Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Introduction to Lattice workbench
What is placement
Placement describes how a solid object can be moved in free air.
Placement is translation and reorientation.
Translation (aka position, aka movement) is lateral translation of an object without changing its orientation. Rotation (aka orientation) is rotation of the object as a solid. Placement is the combination of two.
In FreeCAD, most objects have a Placement property. This property is changed when the object is moved around. In Edit->Placement, Edit->Alignment, Draft Move, and other commands that move objects do that by altering Placement properties of objects.
Placement is a transformation
Placement property sets the extra transformation applied to the object compared to what was yielded by the operation that made the object (1). Placement of zero doesn't mean that the actual object is at the origin (centered, or started, or whatever) - it can still be anywhere. Placement is additional transformation.
Since placement is a transformation, it is convenient to write it as a mathematical transformation function:
placed_object = Placement(original_object)
Translation is applied after rotation
As was noted before, a placement is a combination of translation and rotation. In FreeCAD, translation is applied after orientation, like so:
placed_object = Translate(Rotate(original_object))
To avoid writing tons of parenthesis, matematicians often use the notion of operators and products, so the above equation is written as:
placed_object = Translation*Rotation*original_object
It is convenient to read such expressions back-to-front to simplify understanding them: original_object is first rotated, then translated, which yields the placed object.
Order of application matters
Note that the product in the above equation cannot be rearranged like product of numbers. It is not allowed to mix the terms order in the equation (2). Just remember that Translation*Rotation*original_object actually means Translate(Rotate(original_object)).
(1) Not always so; this is the situation in Part workbench. PartDesign handles placement differently, Draft Clone also doesn't really obey this rule. (2) Translations actually can be mixed: Translation1*Translation2*Rotation is the same as Translation2*Translation1*Rotation, but is not the same as Translation1*Rotation*Translation2.
Placement defines local coordinate system
Applying placement to an object is equivalent to reconstructing the object in local coordinate system. Location of the origin of that local coordinate system is the Translation part of Placement, and the way axes directions change is described by Rotation part of placement.
A vector (a point) in local coordinate system and the same vector (point) in global coordinate system are written by the same equations:
vector_in_global = Translate(Rotate(vector_in_local))
vector_in_global = Translation*Rotation*vector_in_local
To show placements in 3d view, Lattice workbench uses placement markers.
You may have guessed, coordinate system can be used as a natural marker. Yes it can, but there are a few bad things about it: the model is heavy on faces, if thick arrows are used; it is not easy to remember the axes by their colors; it can be hard to figure out the orientation without rotating the view. So, a different shape was chosen for placement marker.
The default marker is shown on the picture above. The marker is a small non-manifold shell looking like a toy plane folded from a sheet of paper. The plane is oriented along X axis. Z axis is upwards, Y axis is to the left (from the point of view of plane's pilot). The origin is at the center vertex of the tail of the plane. Wing faces are on XY plane; fuselage face is XZ plane.
Such a marker solves all the problems listed above: just three faces, easy to remember axes directions, relatively easy to catch the orientation by looking at it. The faces on standard XY and XZ planes are useful for attachment of sketches.
This is merely the default marker. There is a property that allows one to choose marker from a few built-in ones; any shape in the document can be made to be a marker.
So, the marker shows local coordinate system inside the placement. The transform is - moving the marker from the origin to where it is displayed. It is recommended to drop a dummy zero placement to always show the origin, because it is a global reference point for all markers.
Chaining placements, inverse placement
Like translation and rotation parts of placements are just a chain of transformations, placements can be chained as well. And in that chaining, order is impotant.
However, there is one interesting case, where the order doesn't matter - with inverse placements.
What is an inverse placement? An inverse placement is a transformation that undoes the transformation that the original placement does. Like this:
same_object = inverse_placement(placement(object))
Inverse transformation of a placement is just another placement. However, inverse placement has an interesting property: it commutes with the original placement (it is a general property of any inverse transformation, btw). That is, we can apply int inverse placement fisrt, and still get no transformation in the end. That is,
same_object = placement(inverse_placement(object))
Here is a picture of how an inverse placement looks as a marker.
Populating a placement
Consider we've created a placement in FreeCAD. Now what? How does one use that placement to drive a placement of an object? Lattice workbench has two tools to apply placements: Lattice PopulateCopies, and Lattice PopulateChildren.
The first one, Lattice PopulateCopies, makes a copy (clone) of the object to be placed, transformed by the placement. If an array of placements is supplied, each of the placements is populated with a copy of the object, thansformed by the placement. The original object is hidden, which is a typical way many features of FreeCAD work.
The second one, PopulateChildren, is a bit smarter. It expects a compound to populate placements. It takes children of the compound, and populates the array with different children: child1 goes to placement1, child2 to placement2, and so on. This way, we can bend shapestrings to follow curved paths, for example.
Unfortunately, due to the way FreeCAD is organized, a placement cannot be forced to an existing object, unless that object supports it. One type of an object that supports linked placement is Sketch.
Sketches can be attached to faces, in particular, to faces of placement markers. I highly recommend to rip a single placement off an array with ArrayFilter before attaching a sketch to it. If you don't, sketch origin will be a projection of array's overall placement base, which is usually the origin. If you do, sketch placement will fully match the placement represented by the marker.
Because PopulateCopies and PopulateChildren copy only the Shape of Part::Feature-derived objects, they are useless with a multitude of FreeCAD objects that don't have a shape, or a shape isn't everything about it. Meshes, labels, dimensions fall into these, unsupported sorts of objects.