If you decide to add bolts, nuts, washers, etc, to your assembly, and it is somewhat complicated, you may end spending a lot of time placing this tiny parts all around the 3D space. At least, that has been happening to me from time to time. In this post I introduce you the tool I coded to deal with this situation:
def placeBolts(): sel_obj = FreeCAD.Gui.Selection.getSelectionEx().Object sel_edge = FreeCAD.Gui.Selection.getSelectionEx().SubObjects sel_edge_number = -1 for edge in sel_obj.Shape.Edges: sel_edge_number += 1 if (edge.CenterOfMass - sel_edge.CenterOfMass).Length < 0.001: break parent_folder = None def findParentFolder(): # find the group that sel_obj pertains to for obj in FreeCAD.ActiveDocument.Objects: if obj.TypeId == 'App::DocumentObjectGroup': for sub_obj in obj.Group: if sub_obj.Name == sel_obj.Name: return obj return None parent_folder = findParentFolder() if len( FreeCAD.Gui.Selection.getSelectionEx()) == 2: target_edges = FreeCAD.Gui.Selection.getSelectionEx().SubObjects elif len( FreeCAD.Gui.Selection.getSelectionEx()) > 2: target_edges =  for i in xrange( len( FreeCAD.Gui.Selection.getSelectionEx() ) - 1 ): for sub_object in FreeCAD.Gui.Selection.getSelectionEx()[i+1].SubObjects: target_edges.append( sub_object ) for edge in target_edges: # create new object in document new_obj = FreeCAD.ActiveDocument.addObject( 'Part::Feature', sel_obj.Name + '_copy' ) # assign a shape to the created object new_obj.Shape = sel_obj.Shape.copy() # assign the view object to copy colors new_obj.ViewObject.ShapeColor = sel_obj.ViewObject.ShapeColor new_obj.ViewObject.LineColor = sel_obj.ViewObject.LineColor new_obj.ViewObject.Transparency = sel_obj.ViewObject.Transparency # move this object to a folder if selected object was in a folder if parent_folder: parent_folder.addObject( new_obj ) # place the new object at the desired target VA = new_obj.Shape.Edges[sel_edge_number].Curve.Center VB = edge.Curve.Center DV = VB - VA new_obj.Placement.Base.x += DV.x new_obj.Placement.Base.y += DV.y new_obj.Placement.Base.z += DV.z
This function is called "placeBolts" and has no arguments. To use it, open the python terminal inside FreeCAD and copy-paste the code above, then continue reading.
How to select the objects to place:In the picture there is a rectangular pad with 5 holes on which I want to place the washer (also present in the drawing):
First select the circular arc of the washer that is going to be in contact with the hole in the pad, like this (notice the thin circular edge selected at the bottom of the inner cylinder of the washer in the picture below):
Second select all the edges of the rectangular part that will be in contact with the washer.
Third, copy paste this line at they python terminal:
And its done!
The washers are placed at the selected positions and if the original washer which served as a model was inside a folder, the created copies will be appended within the same folder (this is gold when you are in a big assembly)
Limitations:This tool works for circular edges only, but the vast majority of parts that could benefit from it have them (bolts, nuts, washers, threaded rods... ), so I do not consider it a big drawback.
I may include this as an auxiliary assembly tool in the exploded assembly workbench.