Skip to content

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

41 Commits

Folders and files

Repository files navigation

//pub/examples/lego

Assemblies built from the LDraw LEGO parts library.

The parts come from the LDraw library, as served by //pub/universe/lego/ldraw. Nothing is vendored here: this package is the assemblies, and the geometry is meshed from LDraw's own .dat files on demand.

castle

A gothic castle: spired towers along the curtain wall and at its corners, a twin-towered gatehouse over a pointed arch, buttresses with pinnacles between the bays, and a tall turreted keep.

The castle from above The castle from the front

731 parts, nine distinct LDraw parts between them:

part count
Brick:3005 271 1 x 1 brick
Brick:3004 153 1 x 2 brick
Brick:3941 122 2 x 2 round brick
Brick:3010 114 1 x 4 brick
Cone:4589 44 1 x 1 cone — the spires
Cone:3942b 19 2 x 2 cone
Brick:3009 6 1 x 6 brick — the keep's floor
Baseplate:3811 1 32 x 32 baseplate — what it all stands on
Cone:3943b 1 4 x 4 cone — the keep's spire

Everything sits on LEGO's own grid: 8 mm stud pitch, 9.6 mm brick height. The parts arrive standing upright in PartCAD's Z-up world, so front, top, right and iso mean what they say.

pc inspect -a castle
pc render -a -t png --view iso castle

The pieces it is built from

A castle this size repeats itself: four identical corner towers, nine identical spires, sixteen identical buttresses. So castle is not 731 parts in one file - it is ten sub-assemblies under castle/, placed 44 times between them, and the baseplate. Each one is written once and built once, and every further use of it is a cache hit rather than a rebuild; 288 parts are described instead of 731.

sub-assembly parts used
castle/buttress 9 16 a pier stepping out from the wall, capped with a pinnacle
castle/spire 4 9 two 2x2 cones flaring off a tower, then two 1x1 cones to a point
castle/wall 65 3 a stretch of curtain wall between two corner towers
castle/wall-gate 71 1 the same wall with the gateway's pointed arch corbelled through it
castle/tower-corner 15 4 the body of a corner tower
castle/tower-mural 12 3 the body of a tower standing along a wall
castle/tower-gate 13 2 the body of one of the gatehouse pair
castle/keep-courses 14 3 two courses of the keep, the second breaking joint against the first
castle/keep-lancet 36 2 four courses: a lancet, and the course that closes it
castle/keep-top 48 1 the keep's last three courses, its merlons, four bartizans and the spire

Each is a PartCAD assembly in its own right, so any of them can be looked at, rendered or built alone:

pc inspect -a castle/tower-corner
pc render -a -t png --view iso castle/wall

The keep is cut into pairs of courses rather than left whole because its masonry alternates: an even course and the odd one that breaks joint against it, three kinds of pair covering all of it but the last course and the roof. The walls are not split further - the gate wall differs from a plain one in every course, so there is no band of it the two could share.

Joined, not just placed

A brick placed by coordinates is a brick nothing holds up: the file says where it ended up, not what puts it there. Most of these bricks say the other thing instead — which brick they sit on, and which stud of it:

- part: //pub/universe/lego/ldraw/Brick:3010
  name: w_c1_0
  connect:
    with: //pub/universe/lego:anti-stud
    withInstance: c0r0
    name: w_c0_0
    to: //pub/universe/lego:stud
    toInstance: c2r0

//pub/universe/lego declares the pair — a stud on top of a part and an anti-stud underneath — and PartCAD works the coordinates out. Every one of the 288 part nodes is joined that way, in the order they are put together — there is not a single location: left on a part or a piece anywhere in the model.

Which two ports meet is decided by where they are, not by the stud grid the part's name implies, because for several of these parts the grid is not the answer: a Cone 2 x 2 x 2 has four anti-studs under it and a single stud on top, at its centre, and a Cone 3 x 3 x 2 has nine and four. A joint picked by grid index puts such a part half a stud out.

A brick joins downwards to a stud under it or upwards into an anti-stud over it, and that is what keeps the number of coordinates down. A unit's bottom course does not have to go first: put one brick of it down, add the brick above that bridges it to its neighbour, and the neighbour then snaps up into that bridge. So the order is grown rather than given — take whatever can be joined to what is already down.

Each piece's first brick says nothing at all — no coordinates and no joint. It is the piece's own origin, and where that goes is for whatever places the piece to decide, so saying it here would be saying it twice.

Getting to none of them took four things beyond the joints themselves, and each was a fault in the model rather than a limit of the format:

  • The keep's corners did not bond. Every course laid its four sides the same way, so no brick ever spanned a corner and the keep was four stacks that merely touched. The corners alternate now.
  • A course over an opening has to reach past it. A lancet capped by two bricks meeting over the hole ties nothing; the capping course is laid whichever way puts one brick across the opening with a bearing either side, which is not the same way for a four-stud stretch as for a six-stud one. The gateway's lintel got the same treatment and now bears a stud into the wall on each side.
  • No stretch ends with a single stud. Three cells laid greedily come out a two and a one, and that trailing one sits on the corner with nothing reaching across to it.
  • The keep's spire stood on its own open shaft. It has a floor now — the last course laid solid, six bricks the full width, each crossing the ring below at both ends — and a spire built the way the towers' are, since a 3 x 3 cone cannot be centred on a 6 x 6 keep and was sitting half a stud off the grid.

The pieces join each other too, and the whole thing stands on a plate

A piece is placed by coordinates for the same reason a brick was: nothing says what holds it. So each piece externalizes the ports it is joined by, with map::

assemblies:
  castle/spire:
    type: assy
    map:
      spire_s0-anti-c0r0: [spire_s0, //pub/universe/lego:anti-stud, c0r0]

A name of the piece's choosing, against the node inside it, the interface that node implements, and the instance. The interface is not renamed — it is a contract — but the instance name is the piece's to pick.

The walls, towers and buttresses were the hard case: they all stand on the ground side by side, and a stud joins what is above to what is below, so edge to edge there is nothing to join them by. LEGO's own answer is a baseplate, and the library has one big enough — Baseplate 32 x 32 (3811), 1024 studs against a castle covering 30 × 30. Every piece that reaches the ground is joined to it.

So the baseplate says nothing at all: where it goes decides nothing, since every other node is placed relative to it, and where the castle as a whole sits is the container's to say.

The one location: left, and why it stays

name: castle
location: [[0, 0, 0], [0, 0, 1], 0]   # set the offset to [100.0, -100.0, 0.0] to read coordinates off the stud grid

One location: in the whole model, on the container, and as it stands it does nothing. It used to be a quarter turn about X: LDraw draws its parts Y-up and PartCAD's world is Z-up, and no joint can derive that — it is a fact about the parts library, not about the model. The parts library has since taken it on itself and serves every part standing upright, and the turn left behind laid the castle on its side, its baseplate standing up like a wall.

What is left is the offset, and that is a knob rather than a fact, and not free. Left at zero the castle sits at the origin, which is where the default views expect to find it. Set to the figure in the comment it stands where the grid runs on whole studs from a known corner — worth having while reading the numbers by hand, and it costs the rendered views their framing, because they look from a fixed point rather than from one relative to the object.

Jinja2, and why every step is still written down

An ASSY file has to enumerate every step. PartCAD reads the tree it makes to work out the bill of materials, and the assembly instructions are that tree written out a step to a page, so a step that is not in the file is a step nobody is told to take.

The text need not repeat itself, though: every ASSY file is a Jinja2 template, rendered before it is parsed. A run of parts laid out regularly can be written as the loop it is -

{% for i in range(15) %}
- part: //pub/universe/lego/ldraw/Brick:3941
  name: t_c{{ i }}
  location: [[4.0, {{ (9.6 + i * 9.6) | round(3) }}, 4.0], [0, 1, 0], 0]
{% endfor %}
  • and reaches the parser as the fifteen separate nodes it always was. The castle used to be written that way, and is not any more: now that every brick is joined to the stud it sits on rather than placed, there is no arithmetic left to loop over - each joint names its own studs. Between them the eleven files are 332 nodes of YAML for a 731-part model, and every one of those 731 parts is still a step of its own.

f1

A Formula 1 car in LEGO Technic that drives, steers and rides on springs, with its Power Functions electrics and the IR remote control beside it.

The car from the front right, above The car from its right side
The car nose-on The car from above
what does it how
drive Electric:58121 XL motor a 12-tooth double bevel (Technic:32270) on its output turns the crown of a differential (Technic:62821) between two half axles
steering Electric:99498 servo stands behind the front axle, output down; an arm on its output pushes a track rod pinned into both knuckles
power Electric:58119 battery box across the car between the side frames, pinned into both by the four holes in each of its ends
control Electric:58123 IR receiver the airbox, over the motor
Electric:58122 IR remote control beside the car
front suspension double wishbones two Technic Beam 5 a side; a cross block (Technic:6536) on the end of each holds an upright kingpin, and a knuckle (Technic:32557) turns on it, carrying the stub axle in a round hole; a shock absorber from the upper wishbone to a crossbeam
rear suspension a swinging subframe the motor, the differential and both half axles are one subframe, pivoting on an axle across the chassis ahead of the motor and held up by a shock absorber under each of two towers

213 parts, 31 distinct:

pc inspect -a f1                # the car and its remote
pc inspect -a f1/car            # the car alone
pc render -a -t png --view right f1

The first picture above is f1's own, drawn from where PartCAD looks at an assembly when nothing says otherwise: iso, [100, -100, 100], above its front right corner. The other three are f1-front, f1-right and f1-top in partcad.yaml: aliases of f1, each looking at it from a direction of its own ([0, -100, 0] for the front, [100, 0, 0] for the right side, [0, 0, 100] with [0, 1, 0] up from above) - the same directions --view names, written down so that pc render -r draws them with everything else. The castle's two pictures are made the same way: castle's own, and castle-front, an alias of it looking from in front.

It is not small - 44 cm from the back of the rear tyres to the tip of the nose, 19.5 cm across the rear wheels - and that is what fitting a battery box, an XL motor, a servo and a receiver takes, with suspension at both ends.

The pieces it is built from

f1 is the car and the remote beside it; f1/car is the car. The car is split the way it would be built on a bench by several people at once: into sub-systems, each made of blocks that are finished and handled on their own before they are fitted, so that nobody waits for anybody until the last step.

stage 1 - the blocks, all at once parts stage 2 - the sub-systems stage 3
f1/side-frame-left, f1/side-frame-right 7 each f1/tub: the right frame goes onto the battery box's pins, the box onto the left frame; then the pivot axle and its three bushes (4), and the airbox on the rear posts f1/car
f1/battery - the box and the eight pins in its end holes 9
f1/airbox - the IR receiver on a crossbeam, and the cross blocks the posts carry it by 10
f1/front-frame - nose rails, bulkheads, shock crossbeam, servo cradle 43 f1/front-end: everything hangs on the frame; the four pins that join a piece to another piece of it (the tops of the front shocks, the knuckles to the track rod) are its own (4)
f1/front-right, f1/front-left - wishbones, kingpin, knuckle, wheel, shock 15 each
f1/steering - servo, arm, track rod 9
f1/nose - a cross axle, a crossbeam, the cone 12
f1/front-wing - two slats between two endplates, on two pylons 16
f1/motor-unit - XL motor, pinion, the bracket across its face, the spacer beam 13 f1/drivetrain: the subframe's inner beams around the motor unit, the differential, the half axles and wheels, the shocks (23)
f1/rear-wing - an axle through the towers, slats, endplates, pylons 19
f1/sidepod - one panel and its pins 3, used twice

That is 37 in the tub, 114 in the front end, 36 in the drivetrain, 19 in the rear wing and 2 x 3 in the sidepods: 212 for the car, and the remote makes 213.

Only the sidepod occurs twice. The car is symmetric, but the two front corners and the two side frames are mirror images, and a mirror image is not the same assembly turned round.

Pieces are joined to each other through mapped ports, never by reaching into another piece's parts. Each piece's map: in partcad.yaml externalizes the ports a joint outside it uses, and a port that is several levels deep is mapped at every level on the way up: the front end's front-frame-pin-nose-1-l-pin-left is the front frame's pin-nose-1-l-pin-left, which is that pin's left end. A joint between two pieces is written in the lowest piece that holds both, so the front corners are joined to the front frame in f1/front-end, and only the four sub-systems and the sidepods meet in f1/car.

Joined, all of it

Every part of the car is joined through its ports. Nothing in f1/car is placed by coordinates: each part names the port of its own and the port of an earlier part that it is put onto, the way the castle's bricks name the stud they sit on. The left side frame's lower rail is the car's origin, and the car's own location: is that beam's pose turned into PartCAD's Z-up world - which is what puts the ground at z = 0, the nose towards -Y and the car's right towards +X. (It is also what went wrong first: turning the car into Z-up and nothing else leaves it lying the way that beam lies.)

The remote control is the one item placed by coordinates, in f1 beside the car, because nothing joins a handset to the car it drives. PartCAD's connectivity check would rightly refuse it among parts that connect, which is why the car is an assembly of its own.

Which parts need a turn or a push along their axis is what the interfaces allow and nothing else: a pin turns in a round hole (turnZ), an axle slides through one (moveZ), and a stud turns on an anti-stud. An axle hole takes no turn, so a part on an axle takes whatever roll the axle has - fine for a bush or a wheel, and not for a cross block, whose pin hole has to be where the design put it. For those the axle itself is turned, in the round hole it went into.

Three contacts in f1/drivetrain are true of the geometry without being a joint that excuses them, and pc test reports them: the pinion's mesh with the differential's crown (21.979 mm^3; the crown has no gear ports, and the pinion's describe a spur mesh, not a bevel one), the end of the pinion's shaft against the differential (4.220 mm^3), and the right half axle inside the differential that sits on it (11.115 mm^3) - an axle snaps past nothing, so the length of it inside the differential is reported. The bevel gears inside it, which the two half axles would turn, are not modelled.

How it was made, and checked

tools/gen_f1.py writes every file of the car and the f1 block of partcad.yaml; nothing under f1/ is edited by hand. It designs each part at the pose it should have, then looks for a port of the new part and a port of the part it goes onto that are at the same point, facing each other, and have interfaces that mate; that pair becomes the connect:. The pose PartCAD will compute from it - the target port turned around, offset by the joint's parameters, the part's own port undone - is computed there with the same rule, and has to come out exactly where the part was designed to be. A part with no such pair is an error, and the design changes until it has one. The ports come from //pub/universe/lego's own index, so a joint the package does not serve cannot be written.

The result was then checked the way the gen-assembly skill asks: PartCAD instantiated f1, the tree was walked down to its 213 parts composing every transform, and each part's world placement was compared with the generator's as a multiset. All 213 agree, rotations included, through every level of the pieces.

It needed two things from //pub/universe/lego/ldraw that it did not have. One is the axle hole of a cross block: LDraw draws the bush of a cross block as a primitive with the hole inside it, which the package's geometry walk never opens, so Technic:6536, "Cross Block 1 x 2 (Axle/Pin)", came with its pin hole and not its axle hole - and every kingpin, nose block and wing mount here is one. The package reads that primitive now, and 47 parts gained an axle hole. The other is that one end of an axle may carry several parts: a half axle here carries two beams, two bushes and a wheel, each joined to its end at its own moveZ, and PartCAD's connectivity test reported them as crowding one port until technic-axle said multiConnect: true.

Every piece passes pc test -f connect, connectivity, validity, degenerate, solidity, shell and manufacturability on its own as well as inside the car.

What it leaves out

  • The cables. In the real thing the motor's and the servo's leads go to the receiver, and the receiver's to the battery box, routed wherever there is room. Nothing about a port says where that is, and none is placed.
  • Travel. It is a static pose: the wheels straight ahead, the suspension settled. The shocks are LDraw's 10L damped shock compressed (76320-f2), whose eyes are six studs apart, so that each one lands on the stud grid.

A note on interference

A LEGO stud is meant to occupy the part above it, and a Technic pin the hole it is in — that interference is what makes the parts grip. So partcad.test.interference has something true to report about almost every joint in both models, and nowhere to read that it is intended: an overlap which is meant to be there is stated on the joint that causes it, and these joints do not say so.

Nothing here turns the check off. The package is manufacturable: false — nobody is ordering a castle, or this car — and that is what makes interference report what it finds rather than fail on it. Giving it a threshold high enough to swallow a stud would be worse than either: that floor is a rounding tolerance, and making it carry this would be a number pretending to be one.

What makes the check meaningful is the matings in //pub/universe/lego declaring snapIn: true, and for a Technic pin in a round hole they do: its slotted end is squeezed past the lip and springs open behind it. A stud in an anti-stud is the same kind of fit and does not say so yet. It does not need to for the castle: as LDraw draws them, a stud's side lies on the inner face of the wall of the brick above, so stacked bricks touch without overlapping, and with every brick served as a solid the castle reports no interference at all. An axle snaps past nothing, so an axle that overlaps the part it goes through is still reported.

A pin joins two parts, and its connection names one of them; its other end goes into the second part all the same. tools/gen_f1.py finds those ends - a pin end and a round hole facing each other at one point, the test it joins parts by - and says so in interferes:. Within one piece, 15 pins name the second part on their own joint. 25 more have their second part in a different piece - the battery's pins in the side frames, the steering's in the front frame, the sidepods' in the tub - and those are said where the two pieces meet, on the link of one naming the link of the other: the battery's link in f1/tub says interferes: [side-frame-left, side-frame-right]. That excuses any overlap between the two pieces, which is as precise as it can be said until PartCAD can tell an overlap at the joined port from one elsewhere.

PartCAD checks the car the way it is built. Each piece answers for its own inside with its own verdict, cached against the piece, and an assembly looks only at what crosses between the pieces it holds - comparing the box around each piece first, so two pieces that are apart cost one comparison however many parts are in them. A pair whose joint says it overlaps is not measured at all.

What it measures is only as good as the solids it is given, and a part that is not a solid is not measured but reported: a boolean against an open shell returns a number that means nothing - the 12.457 mm^3 once reported between an axle and its cross block was one, where the hole as LDraw draws it is wider than the axle at every corner. //pub/universe/lego/ldraw now serves a part as a solid or not at all. It repairs what LDraw draws as overlapping or short surfaces, and the friction pin, the cross block, the gears, the wheels and the shocks come out solid. Eight more of this car's parts - the knuckle, three panels, the servo, the XL motor, the battery box and the IR remote - have faces LDraw does not draw or draws twice. The plugin's general repairs close the knuckle, the servo and one panel; the rest are closed by patches it keeps to LDraw's own files and applies as it reads them, each pinned to the file it was written against. One of them is authored rather than corrected: the IR remote's top half, which LDraw declares "Inside not modelled", is closed across its rim as a filled envelope. Every part of the car is now served as a solid, and the car, its pieces and the set pass pc test.

Buying the parts

Every part here is a LEGO part, sold as vendor: lego by its LDraw number, and two stores sell them, which the PartCAD index registers at //pub/svc/commerce. This package names them as its suppliers, so pc supply looks for every part of a model at them, in this order, and buys each part from the first that has it:

Store Provider What it needs
LEGO's Pick a Brick //pub/svc/commerce/lego-pick-a-brick:pick-a-brick Nothing
BrickLink //pub/svc/commerce/bricklink:bricklink An account's four OAuth values

Each store's README says how to give it what it needs. One that has not been given it says, quietly, that it has nothing.

pc supply quote castle                                                              # each part where it is first found
pc supply quote -r --provider //pub/svc/commerce/lego-pick-a-brick:pick-a-brick f1  # everything at one store
pc -q supply quote --json --provider //pub/svc/commerce/bricklink:bricklink f1/front-end
python tools/quote.py -r                                                            # every model at every store

A part has no colour - the geometry has none - so a store quotes the cheapest colour it has, unless it is told one:

pc --extra-param '//pub/svc/commerce/lego-pick-a-brick:pick-a-brick.color=Medium Stone Grey' \
  supply quote --provider //pub/svc/commerce/lego-pick-a-brick:pick-a-brick castle

No store sells by the LDraw number alone, and each works out what to buy for it: the LEGO elements Rebrickable's public catalogue says the part has been made as, and the mould LEGO makes in its place where none of those is on sale - the friction pin LDraw draws as 2780 is sold as 61332, the 2L axle 3704 as 32062, the 2 x 2 cone 3942b as 3942c. Pick a Brick is asked for those elements by number, and is not searched. BrickLink sells in lots, each bought whole, so what it quotes is what the lots cost, the pieces over what was asked for included.

What LDraw draws as one part and LEGO makes as several - the front wheels, 41896c01, are a rim with its tyre on - is an assembly in the parts library, with an SKU of its own: the car links its wheels, its shock absorbers, the servo and the battery box as assemblies. pc supply quote asks for each of them whole, as a set or a marketplace may sell it; -r asks for its parts instead, which is how Pick a Brick sells a wheel.

What Pick a Brick's US shop had, asked on 2026-10-18:

Model Parts it had Pieces Price
castle, cheapest colours 9 of 9 731 of 731 $82.01
castle, Medium Stone Grey 7 of 9: not the two cones in grey 711 of 731 $78.00
f1 -r, cheapest colours 25 of 40 204 of 237 $34.24

What it did not have for the car is what LEGO no longer makes: the Power Functions battery box, XL motor, servo, IR receiver and remote, the 10L damped shocks, and the large rims and tyres of the rear wheels. Those are the parts BrickLink, a marketplace, is for. It was not asked: this was run without the credentials it needs.

This README

It is generated, and so is every picture in it: the text is the docs: section of partcad.yaml, and pc render -r writes README.md and the images under images/ - one for each assembly in the list below, the castle and the car among them, and one for each of the aliases that look at those two from elsewhere. They are rendered with reproducible: true, so the same model gives the same file: drawn exactly, from the surfaces, by OpenCASCADE's hidden-line removal.

All but the whole castle, the whole car, the four views of them and the car's front end, which are too big to be drawn that way. The exact algorithm sets memory aside for every pair of edges in the picture before it draws any of them, so what it needs grows with the square of the model: the car has 423,000 edges and would need 45 GB, the castle 248,000 and 15 GB, the front end 199,000 and 10 GB. Those are drawn from a triangulation instead, which comes out the same again on the same kind of machine.

CI installs the latest PartCAD from PyPI on the latest Ubuntu, runs pc test -r and pc render -r, and fails if anything it rendered differs from what is checked in. So a change to a model, to the parts library or to how PartCAD draws shows up as a diff rather than as a README that quietly stopped describing the model. To change this text, edit partcad.yaml and run pc render -r; an edit to README.md itself is overwritten by the next render.

Assemblies

castle

castle A gothic castle built from LDraw LEGO parts.

castle-front (alias to castle)

castle-front A gothic castle built from LDraw LEGO parts.

castle/buttress

castle/buttress A pier stepping out from the wall, capped with a pinnacle

castle/keep-courses

castle/keep-courses Two courses of the keep's masonry, the second breaking joint against the first

castle/keep-lancet

castle/keep-lancet Four courses of the keep, the lancets in them and the course that closes them

castle/keep-top

castle/keep-top What the keep ends with - its last three courses, the merlons, a bartizan at each corner, and the spire

castle/spire

castle/spire A tower's needle roof - two 2x2 cones flaring off the tower, then two 1x1 cones drawing it to a point

castle/tower-corner

castle/tower-corner The body of a corner tower, 15 courses of 2x2 round brick

castle/tower-gate

castle/tower-gate The body of one of the gatehouse pair, 13 courses

castle/tower-mural

castle/tower-mural The body of a tower standing along the wall, 12 courses

castle/wall

castle/wall A stretch of curtain wall between two corner towers, with its lancets and crenellations

castle/wall-gate

castle/wall-gate The same wall with the gateway's pointed arch corbelled through it

f1

f1 A Formula 1 car in LEGO Technic - Power Functions motors, suspension, and the IR remote control.

f1-front (alias to f1)

f1-front A Formula 1 car in LEGO Technic - Power Functions motors, suspension, and the IR remote control.

f1-right (alias to f1)

f1-right A Formula 1 car in LEGO Technic - Power Functions motors, suspension, and the IR remote control.

f1-top (alias to f1)

f1-top A Formula 1 car in LEGO Technic - Power Functions motors, suspension, and the IR remote control.

f1/airbox

f1/airbox The Power Functions IR receiver on a crossbeam, and the cross blocks the rear posts carry it by

f1/battery

f1/battery The Power Functions battery box, with the pins in its end holes that the side frames go onto

f1/car

f1/car The car: every one of its parts joined through its ports, none placed by coordinates

f1/drivetrain

f1/drivetrain The rear subframe: the motor unit, the differential, the half axles and wheels, and the two shocks it hangs from

f1/front-end

f1/front-end Everything ahead of the battery: the front frame, both front corners, the steering, the nose and the front wing

f1/front-frame

f1/front-frame The front frame: the nose rails, the bulkheads the wishbones pivot on, the shock crossbeam and the servo's cradle

f1/front-left

f1/front-left The left front corner: double wishbones, a kingpin, the knuckle, the wheel and a shock

f1/front-right

f1/front-right The right front corner: double wishbones, a kingpin, the knuckle, the wheel and a shock

f1/front-wing

f1/front-wing The front wing: two slats on edge between two endplates, hung from the nose on two pylons

f1/motor-unit

f1/motor-unit The XL motor with its pinion, the bracket across its face and the spacer beam beside it

f1/nose

f1/nose The nose: a cross axle between the nose rails, a crossbeam, and the nose cone

f1/rear-wing

f1/rear-wing The rear wing: an axle through the shock towers, two slats on edge between two endplates, on two pylons

f1/side-frame-left

f1/side-frame-left The left side frame: the two rails, the post at the back and the shock tower over it

f1/side-frame-right

f1/side-frame-right The right side frame: the two rails, the post at the back and the shock tower over it

f1/sidepod

f1/sidepod A sidepod: one smooth panel pinned to the upper side rail

f1/steering

f1/steering The servo, its arm and the track rod

f1/tub

f1/tub The tub: both side frames, the battery box between them, the pivot the drivetrain swings on, and the airbox



Generated by PartCAD

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages