This post will describe how to shrink a FreeCAD model to any size for 3D printing. I want to build a model of an old ore car but I want to 3d print it at many different scales. What I don’t want to do is create a different FreeCAD model for each scale. The solution is to design the FreeCAD model as a 1:1 drawing (i.e. full size) and then use a python script to clone the model and rescale it. The complete python script will be explained below.
The python code described in this post also illustrates several generic operations you might use in any FreeCAD python script including:
- how to use Gui.runCommand in FreeCAD to cut/copy/paste objects between models
- how to select and hide objects in a FreeCAD model using python
- how to clone and scale a FreeCAD body using python
- how to use the “ViewFit” command to center and zoom a model
FreeCAD is built from the ground up to be scripted using Python. You can see the python scripting docs here.
If you’re new to FreeCAD you might want to check out my Getting Started post.
FreeCAD Model
First, I create a FreeCAD model at full size, i.e. each measurement on the CAD drawing reflects the actual real world dimension of the object. As you can see in the tree view at the left, the model is made up of a bunch of “bodies”. I also have a few “parts” that contain a “body”.
This is a screenshot of the FreeCAD model of the wooden frame that exists on each end of the ore car. It is modeled at full size, i.e. 1:1. It is about 5 feet wide and 5 feet long.
The challenge now is to create an STL file that I can 3D print at a specific scaled down size. In Blender this would be easy as the STL export function allows you to specify a scale but FreeCAD does not. The answer is to use a python script to copy and scale the model before we export the STL file.
Python Script
The following is the entire python script. We will break it down and explain each of the sections of code.
import FreeCAD as App
import Part
# input parameters
# output model name
scaleModel = 'testscale'
# input model name
baseModel = r'C:/Users/jsing/OneDrive - SingerLinks/PERSONAL/large scale/gilpin ore cars/FREECAD/MODELS/FRAME/ORECAR-FRAME.FCStd'
#baseModel = r'C:/Users/jsing/OneDrive - SingerLinks/PERSONAL/large scale/TRUCK/FREECAD/MODELS/TRUCK.FCStd'
#baseModel = r'C:/Users/jsing/OneDrive - SingerLinks/PERSONAL/large scale/gilpin ore cars/FREECAD/Coupler.FCStd'
print("Start Clone and Scale - {}".format(baseModel), end = "\r\n")
# scale factor
scaleFactor = u'0.07291600000000001'
# open the base model
App.openDocument(baseModel)
# select and copy all the objects in the base model
Gui.runCommand("Std_SelectAll")
Gui.runCommand("Std_Copy")
# open a new document to store the copied model
NewModel = App.newDocument(scaleModel)
# paste all the copied objects into the new model
Gui.runCommand("Std_Paste")
NewModel.recompute()
# make the copy of original model invisible
Gui.Selection.clearSelection()
for obj in FreeCAD.ActiveDocument.Objects:
Gui.Selection.addSelection(obj)
Gui.runCommand('Std_HideSelection',0)
# clone all the bodies and adjust scale
Gui.activateWorkbench("DraftWorkbench")
import PartDesignGui
import Draft
bodys = App.ActiveDocument.findObjects("PartDesign::Body")
for body in bodys:
print ("Cloning Object: {} Label: {} Name: {}".format(body,body.Label,body.Name))
clone = Draft.make_clone(body)
clone.setExpression('.Scale.x', scaleFactor)
clone.setExpression('.Scale.y', scaleFactor)
clone.setExpression('.Scale.z', scaleFactor)
clone.Placement.Base.scale(float(scaleFactor),
float(scaleFactor),float(scaleFactor))
NewModel.recompute()
print("Finished", end = "\r\n")
# center model on UI
Gui.SendMsgToActiveView("ViewFit")
This is the entire script. Copy and paste this into a macro in FreeCAD.
Input Variables
# output model name
scaleModel = 'testscale'
# input model name
baseModel = r'C:/Users/jsing/OneDrive - SingerLinks/PERSONAL/large scale/gilpin ore cars/FREECAD/MODELS/FRAME/ORECAR-FRAME.FCStd'
# scale factor
scaleFactor = u'0.07291600000000001'
First we set some input variables.
- scaleModel – this is the output model of the script. the script does not modify your original model, instead it creates a copy and modifies that one.
- baseModel – this is the model you want to clone and scale. It should be closed when you run the script.
- scaleFactor = u’0.07291600000000001′ – this is the factor I want to use to scale the full size model down to the size I want to print.
Open and Copy The Base Model
# open the base model
App.openDocument(baseModel)
# select and copy all the objects in the base model
Gui.runCommand("Std_SelectAll")
Gui.runCommand("Std_Copy")
# open a new document to store the copied model
NewModel = App.newDocument(scaleModel)
# paste all the copied objects into the new model
Gui.runCommand("Std_Paste")
NewModel.recompute()
This section of code opens the base model and does a copy/paste operation into a new model. The openDocument method opens “baseModel” which is your original full size FreeCAD model. The Gui.runCommand allows you to do the select all and copy operation. This selects and copies everything in the treeview of the FreeCAD model. Next the code creates a new FreeCAD model using the “scaleModel” variable as the name. Then it does a paste operation to copy all the objects in the clip board into the new model.
This code shows how to use Gui.runCommand in FreeCAD to cut/copy/paste objects between models.
Hide The Full Size Objects In The FreeCAD model
Now we have a copy of the base model but it is still full size. First let’s hide the full size model so we only see the scaled down version.
# make the copy of original model invisible
Gui.Selection.clearSelection()
for obj in FreeCAD.ActiveDocument.Objects:
Gui.Selection.addSelection(obj)
Gui.runCommand('Std_HideSelection',0)
This section of code shows how to select and hide objects in a FreeCAD model. First we clear the clipboard using the clearSelection method. Next, we iterate through all the objects in the active document. As we iterate through, we add each object to the selection. This is the same as manually shift/clicking each item in the treeview. Finally, we run the Std_HideSelection command which is the same as hitting the spacebar which hides the objects from view.
Clone and Scale the FreeCAD Objects
Now we are ready to clone and scale the model.
import PartDesignGui
import Draft
bodys = App.ActiveDocument.findObjects("PartDesign::Body")
for body in bodys:
print ("Cloning Object: {} Label: {} Name: {}".format(body,body.Label,body.Name))
clone = Draft.make_clone(body)
clone.setExpression('.Scale.x', scaleFactor)
clone.setExpression('.Scale.y', scaleFactor)
clone.setExpression('.Scale.z', scaleFactor)
clone.Placement.Base.scale(float(scaleFactor),
float(scaleFactor),float(scaleFactor))
This is where the magic occurs. First, we do some imports as we will use the Draft workbench. Then we use the “findObjects” method to find all the bodies and put them into a list. Using the python ‘for’ statement we iterate through the list so we can operate on each body one at a time. The print statement shows you the name and label of each body. The Draft.make_clone method makes the clone of the body and puts it in the “clone” variable. The clone has scale properties that we then set using the setExpression method. The “scaleFactor” variable value is assigned to the Scale.x, Scale.y, and Scale.z properties of the clone object. This will scale the body to the size we want.
The final step is to scale any changes we made to the object’s placement. This is accomplished using the Placement.Base.scale method. Notice that this method expects floats so we have to convert the string variable scaleFactor to a float.
This python code illustrated how to clone and scale a FreeCAD body using python.
End Result
One last thing needs to be done. We need to center the cloned and scaled objects on the screen so we can see everything.
# center model on UI
Gui.SendMsgToActiveView("ViewFit")
This final bit of code demonstrates how to use the “ViewFit” command to center and zoom a model.
Here is a screenshot of the final result. It looks exactly like the original model which is what we want. If you look at the clones you will see their sizes are all scaled down. Now all we need to do is select the clones we want and do an Export STL command and we can 3D print our model!
And Finally…
Thanks for reading this post where I described how to shrink a FreeCAD model to any size for 3D printing. If you’re interested in more maker space related posts check out the categories on the right.