FreeCAD is an open source mechanical design suite. It centers around a feature-based modelling methodology, meaning that complex geometry is built as a sequence of simpler operations, and parametric control, meaning that the shape of an object is determined by underlying code and the parameters it provides. When parameters are altered, the object's code will take care of updating the shape you see on screen. The program runs in graphical user interface or command line mode, and can be made available to other applications as a Python module. Under the hood you'll find open-source libraries: OpenCascade is used as a CAD kernel, Coin3D for model space visualisation, Qt for the user interface and Python for scripting. Extensions to FreeCAD such as a parts library or a range of add-ons and macros can be found on the project's Github page.


When opening FreeCAD you are presented with a welcome screen, and once a document is opened with the main window. The latter contains a model space view (1), construction hierarchy and model tree view (2), a dialog with properties (also referred to as data and view parameters) of currently selected objects (3), a report view where application messages are printed (4), and the Python console (5). The interface is based on the Qt toolkit, which allows for customisation of widgets, menus and toolbars. Arranging the latter in so-called workbenches, chosen from a drop-down at the top of the screen (6), makes relevant commands available when needed.

16ADT 1.jpg

Your mouse offers interaction with the model space, the manner of which being defined by your navigation style (Preference Editor - Display - 3D View). In the 3D view you can select, move around, zoom and rotate. By clicking through to "View - Views - Selection View" you can open an additional window for inspecting currently selected objects and their sub-components. Having adequately moved around your model, it is always possible to return to a standard view, either by use of the icons on the top banner or the numeric area of your keyboard.

Core functionality

As FreeCAD takes a fundamentally modular approach to software development, we'll now take a high-level look at the program by introducing some key modules and the functionality they provide.

The Gui module brings to screen what you see when opening the application. It binds to Qt for visualisation of the user interface (menus, buttons, windows...), and Coin3D for displaying the current model in a 3D view. The model consists in one or more geometric objects, which are stored in the active document.

The App module takes care of creating, saving to disk (in a compressed format) and opening documents. Depending on geometry type it populates the document with appropriate objects, which in their turn are populated by their corresponding geometric modules. It is the content of these objects that is visualised by Coin3D in the model view window. Objects make the parameters available by which they were built, and as such remain fully parametric. These can be found in the properties window (interface, 3) under View and Data tabs. The former pertains to how objects are displayed on screen, the latter to their position and orientation in model space, as well as to parameters used for creating their geometry.

The Part module provides an interface with the OpenCascade kernel and provides the bulk of the application's geometric capabilities. This module builds geometry by first defining primitives (point, line, arc...) which in turn are used to build shapes (vertex, edge, wire, face, shell, solid...). For these shapes to be displayed on screen and stored for later retrieval, they need to be saved in one of the document's objects.

A range of other modules provides additional functionality to the program, and depending on geometry type might require a particular object to be added to the document. With minimal effort you can also add your own modules to the program.


FreeCAD comes with a scripting console featuring syntax highlighting, autocompletion and a class browser. The main programming language is C++, yet most of the application is covered by a Python API, makong it very accessible for scripting. Commands executed by the user are rendered at length in the Python console. When not yet available the Python console is activated by clicking through to "View - Views - Python Console". If commands are not mirrored on the console, enable this feature by going to "FreeCAD - Preferences - General - Macro - Show script commands in Python console".

16ADT 2.jpg

The application is built in a highly modular fashion, meaning that distinct functionality is kept separate in code and only loaded when necessary. You can consult the Python interpreter for a list of available modules, and find out which classes and functions they make available by supplying the "print dir()" command with the module's name. Modules that haven't been loaded are added with the "import" command. A class browser allows you to explore available classes, just type the name of a known class followed by a dot (.) and a list of subclasses and methods is displayed. The "Help" menu at the top of the application window offers another way of reaching information on classes and functions. You can furthermore use the "__doc__" method to retrieve information on classes and methods.

print dir()
print dir(Part)
import Arch
print Part.Line.__doc__

App module

At the core of the application the "App" module takes care of general document interaction; it provides methods for opening and closing files, sets documents active, lists their contents, takes care of object creation... It provides object types tailored to hold different kinds of geometry (the Part module for example stores its shapes as B-rep geometry), of which "supportedTypes()" provides a listing. External applications access the App module as "FreeCAD".

# Create objects to hold different types of geometry, and check their respective structures
myMesh = FreeCAD.ActiveDocument.addObject("Mesh::Feature","myMeshName")
myPart = FreeCAD.ActiveDocument.addObject("Part::Feature","myPartName")
print dir(myMesh)
print dir(myPart)
# Create cube, store it in previously created object, then switch with a bigger version
import Part
cube = Part.makeBox(2,2,2)
myPart.Shape = cube
biggercube = Part.makeBox(5,5,5)
myPart.Shape = biggercube
# Check type of object
print FreeCAD.ActiveDocument.myPartName.TypeId

Part module

The Part module takes care of interfacing with the OpenCascade kernel. As FreeCAD relies heavily on the latter, understanding this module's functionality is critical to doing any kind of geometry-related development for the application. The Part module uses a similar design methodology to the OpenCascade kernel, in that it starts from geometric primitives (Geom_* in OpenCascade: point, line, arc...) and uses these to build topological shapes (TopoDS_* in OpenCascade: vertex, edge, wire, face...). Geometric primitives are not meant to be displayed on screen, nor retained very long in memory, which is what shapes are there for. The module uses B-rep geometry, in which shapes are modelled by mathematical curves. In below example you see an object of the appropriate type being added to the document, after which shapes are created with the Part module and loaded in the object.

import Part
doc = App.newDocument()
myShape = doc.addObject("Part::Feature","myShapeObject")
# Create a line and save its shape into previously created object
l = Part.Line()
l.StartPoint = (0.0,0.0,0.0)
l.EndPoint = (1.0,1.0,1.0)
myShape = l.toShape()
# Change your mind, want to add a circle instead
c = Part.Circle()
c.Radius = 10.0
myShape = c.toShape()


A Bezier curve is a smooth curve drawn through provided points, of which the path is further controlled by weights attributed to these points. The curve itself is a geometric primitive, so it needs to be converted into topological shape for display on screen.

from FreeCAD import Base
import Part
point1 = Base.Vector(0,5,0)
point2 = Base.Vector(0,0,0)
point3 = Base.Vector(5,0,0)
curve = Part.Bezier()
curve.setPoles(point1, point2, point3)
edge = curve.toShape()

Boolean Operations

Shapes can affect one another by use of boolean operation: cut, which subtracts one shape from another; common, which retains the volume shared by shapes; fuse, which merges them together; and section, which cuts a solid by a plane.

from FreeCAD import Base
import Part
# Cut
cylinder = Part.makeCylinder(3,10,Base.Vector(0,0,0),Base.Vector(1,0,0)) 
sphere = Part.makeSphere(5,Base.Vector(5,0,0)) 
diff = cylinder.cut(sphere)
# Common
cylinder1 = Part.makeCylinder(3,10,Base.Vector(0,0,0),Base.Vector(1,0,0)) 
cylinder2 = Part.makeCylinder(3,10,Base.Vector(5,0,-5),Base.Vector(0,0,1)) 
common = cylinder1.common(cylinder2)
# Fuse
cylinder1 = Part.makeCylinder(3,10,Base.Vector(0,0,0),Base.Vector(1,0,0)) 
cylinder2 = Part.makeCylinder(3,10,Base.Vector(5,0,-5),Base.Vector(0,0,1)) 
fuse = cylinder1.fuse(cylinder2)
# Section
cylinder1 = Part.makeCylinder(3,10,Base.Vector(0,0,0),Base.Vector(1,0,0)) 
cylinder2 = Part.makeCylinder(3,10,Base.Vector(5,0,-5),Base.Vector(0,0,1)) 
section = cylinder1.section(cylinder2)


A number of shapes provide a shortcut to their creation. For a box you don't need to pass by points, lines and an extrusion, the following method takes care of that for you. You can ask it for the amount of vertexes it contains.

import Part
b = Part.makeBox(100,100,100)


The following code shows a few different ways of defining a circle. As it belongs to the group of geometric primitives, circles need to first be converted to a shape in order to be displayed on screen.

from FreeCAD import Base
import Part
circle1 = Part.makeCircle(10)
# Positioning and orienting along the x-axis
circle2 = Part.makeCircle(10,Base.Vector(10,0,0),Base.Vector(1,0,0))
# Creating an arc of a circle by supplying limits in degrees
arc1 = Part.makeCircle(10,Base.Vector(10,0,0),Base.Vector(1,0,0), 0, 90)
arc2 = Part.makeCircle(10,Base.Vector(10,0,0),Base.Vector(1,0,0), 180, 270)
arc3 = Part.Arc(circle1, 0, 180)
edge = arc3.toShape()


Direct code entry in the Python console is great for experimenting with functionality; once you have something that works, organising it in a class facilitates use and further development. The class in below example waits for a user to click a point (by creating a Pivy callback for a mouse event), and in response calls the "getpoint" function. There we filter for a button being pushed, and get the coordinates in question for defining a point. Once the stack contains two points, a line is drawn and the Pivy callback removed.

import FreeCADGui, Part
from pivy.coin import *
# Creating and initialising a class named line
class line:
 "this class will create a line after the user clicked 2 points on the screen"
 def __init__(self):
   self.view = FreeCADGui.ActiveDocument.ActiveView
   self.stack = []
   self.callback = self.view.addEventCallbackPivy(SoMouseButtonEvent.getClassTypeId(),self.getpoint)  
# Core function
 def getpoint(self,event_cb):
  event = event_cb.getEvent()
  if event.getState() == SoMouseButtonEvent.DOWN:
   pos = event.getPosition()
   point = self.view.getPoint(pos[0],pos[1])
   if len(self.stack) == 2:
    l = Part.Line(self.stack[0],self.stack[1])
    shape = l.toShape()

The python interpreter looks through known script directories, which are the system's Python installation paths, the FreeCAD bin directory, and the FreeCAD Mod directory. You could for example create "Mod/MyScripts" and save above script there as "". If you subsequently make changes to the script, reload it for them to take effect.

import exercise
# Test
# Reload
reload exercise


This function offers a quick way to create a cone, and accepts at least top and bottom radii as well as height. Optionally one can supply vectors for position and orientation, as well as an angle in case a full rotation is not what is required.

from FreeCAD import Base
import Part
cone = Part.makeCone(10,0,20) 
semicone = Part.makeCone(10,0,20,Base.Vector(20,0,0),Base.Vector(0,0,1),180)


This is a shortcut function to creating a cylinder, which requires at minimum values for radius and height. Optionally one can provide vectors for position and orientation, and well as an angle in case less than a full revolution is desired.

from FreeCAD import Base
import Part
cylinder = Part.makeCylinder(5,20) 
partCylinder = Part.makeCylinder(5,20,Base.Vector(20,0,0),Base.Vector(0,0,1),180)


An "Edge" is the topological shape created from geometric primitive "line", which in turn is defined using two points. Once created, different kinds of information can be requested from the Edge shape.

from FreeCAD import Base
import Part
myEdge = Part.makeLine((0,0,0),(10,0,0))
# Update 3D view in order to display shape


This is a geometric primitive for creating an ellipse, which below is supplied with center, as well as major and minor radii. Before being able to be displayed, it needs to be converted into a shape.

from FreeCAD import Base
import Part
eli = Part.Ellipse(Base.Vector(0,0,0),10,5) 


In the realm of shapes, solids contain faces, faces contain wires, wires contain edges, and edges contain vertexes. Following commands allow access to the sub-shapes of a gives shape.

import Part
b = Part.makeBox(100,100,100)
w = b.Wires[0]

Edges allow for deeper exploration. For one, you can walk an edge by its length, and perform analysis at a given value.

import Part 
box = Part.makeBox(100,100,100) 
anEdge = box.Edges[0] 
print anEdge.Length
# Tangent
# Points
# Derivatives
# Curvature
# Normal


Shapes can be extruded in order to add an extra dimension to them. As such, a vertex becomes an edge, an edge becomes a face, and a face becomes a solid. In each case the vector provides direction and distance for the extrusion.

from FreeCAD import Base
import Part
# Hollow tube, extrusion from edge
circle = Part.makeCircle(10) 
tube = circle.extrude(Base.Vector(0,0,2))
# Full cylinder, extrusion from face
wire = Part.Wire(circle) 
disc = Part.Face(wire) 
cylinder = disc.extrude(Base.Vector(0,0,2))


A face can be created from a closed wire. In the following example, a rectangle and inscribed circle are defined and their faces created, after which the circular face is subtracted from the rectangular face. The resulting face is extruded to create a solid. Again, a number of methods allow getting shape information.

from FreeCAD import Base
import Part
# Defining a rectangular face
x = 40
y = 50
edge1 = Part.makeLine((-x/2,y/2,0),(x/2,y/2,0))
edge2 = Part.makeLine((x/2,y/2,0),(x/2,-y/2,0))
edge3 = Part.makeLine((x/2,-y/2,0),(-x/2,-y/2,0))
edge4 = Part.makeLine((-x/2,-y/2,0),(-x/2,y/2,0))
wire1 = Part.Wire([edge1,edge2,edge3,edge4])
rectangle = Part.Face(wire1)
# Defining a circular face
radius = 15
edge5 = Part.makeCircle(radius)
wire2 = Part.Wire(edge5)
circle = Part.Face(wire2)
# Cutting circle from rectangle
diff = rectangle.cut(circle)
# Extrude along z-axis and update 3D view
extrusion = diff.extrude(Base.Vector(0,0,20))
# Getting information from faces


The following piece of code finds the vector normal to a selected surface, which it then draws on screen. It first goes to getting selected surface and edge, discretises the edge into points, and finds them on the surface in order to create their normals.

# Get surface from selection
face = FreeCADGui.Selection.getSelectionEx()[0].SubObjects[1]
# Copy edge from selection and discretise
edge = FreeCADGui.Selection.getSelectionEx()[0].SubObjects[0].copy()
points = edge.discretize(3.0)
# Iterate through points, find points on surface and get their normals
for pp in points:
 pt = FreeCAD.Base.Vector(pp.x,pp.y,pp.z)
 uv = face.Surface.parameter(pt)
 u = uv[0]
 v = uv[1]
 normal = face.normalAt(u,v)
 print normal
 line = Part.makeLine((pp.x,pp.y,pp.z),(normal.x,normal.y,normal.z))

OCC Bottle

The following code implements OpenCascade's bottle example, which it mostly does using the same strategy; with the exception of creating the second half of the base shape, which it does by rotation instead of mirroring, and the absent thread around the neck.

import Part, FreeCAD, math
from FreeCAD import Base
# Dimensions
# Points
# Arc and line segments for half the base
aArcOfCircle = Part.Arc(aPnt2,aPnt3,aPnt4)
# Edges and wire
# Duplicating wire, and joining with original
# Creating a face, and extruding along z-axis
# Filleting all edges
# Creating the neck
myNeckRadius = myThickness / 4.
myNeckHeight = myHeight / 10
myNeck = Part.makeCylinder(myNeckRadius,myNeckHeight,neckLocation,neckNormal)	
# Fusing body and neck
myBody = myBody.fuse(myNeck)
# Removing top face from neck
faceToRemove = 0
zMax = -1.0
for xp in myBody.Faces:
  surf = xp.Surface
  if type(surf) == Part.Plane:
   z = surf.Position.z
    if z > zMax:
     zMax = z
     faceToRemove = xp
# Creating wall thickness
myBody = myBody.makeThickness([faceToRemove],-myThickness/50 , 1.e-3)
# Update screen


A plane is a flat rectangular surface created by providing values for size in two directions, as well as optional vectors for position and orientation. The plane is created perpendicular to the orientation vector.

from FreeCAD import Base
import Part
plane = Part.makePlane(2,2)
plane = Part.makePlane(2,2,Base.Vector(3,0,0),Base.Vector(0,1,0))


This function offers a shortcut for creating a closed wire through provided points. The polygon in question can but does not need to be of regular type.

from FreeCAD import Base
import Part
point1 = Base.Vector(0,5,0)
point2 = Base.Vector(0,0,0)
point3 = Base.Vector(5,0,0)
wire1 = Part.makePolygon(point1, point2, point3)


Objects selected in the 3D view can be retrieved and used in your code. This capability is offered by the Gui module, and forms the cornerstone of graphical user interaction. In following example you would of course wait for the user to make a selection before iterating through selected objects.

import Part,100,100)) 
Gui.SendMsgToActiveView(" ViewFit" )
# Going through selected objects
for o in Gui.Selection.getSelectionEx():
 print o.ObjectName
for s in o.SubElementNames:
 print " name: " ,s 
for s in o.SubObjects:
 print " object: " ,s
# Measuring total edge length
length = 0.0 
for o in Gui.Selection.getSelectionEx(): 
 for s in o.SubObjects: 
  length += s.Length 
print " Length of the selected edges:" ,length


Following function creates a full or partial sphere, and requires a radius as well as an optional set of angles.

from FreeCAD import Base
import Part
sphere = Part.makeSphere(10) 
hemisphere = Part.makeSphere(10,Base.Vector(0,0,0),Base.Vector(0,0,1),-90,90,180)


The following example shows how to create a slot using the Part module. It first defines geometric primitives (first points, followed by arcs and line segments), which are used to create a single topological shape. Edges of this shape are used to create a wire, and the wire in turn to create an extrusion.

from FreeCAD import Base
import Part
# Create points in XY-plane
V1 = Base.Vector(0,10,0)
V2 = Base.Vector(30,10,0)
V3 = Base.Vector(30,-10,0)
V4 = Base.Vector(0,-10,0)
VC1 = Base.Vector(-10,0,0)
VC2 = Base.Vector(40,0,0)
# Create arcs and line segments
C1 = Part.Arc(V1,VC1,V4)
C2 = Part.Arc(V2,VC2,V3)
L1 = Part.Line(V1,V2)
L2 = Part.Line(V3,V4)
# Make shape from lines and arcs
S1 = Part.Shape([C1,C2,L1,L2])
# Create wire and extrude along Z-axis
W = Part.Wire(S1.Edges)
P = W.extrude(Base.Vector(0,0,10))


This is a shortcut function for creating a solid shaped like a donut, the torus. It is created by sweeping a small circle along a big circle, the radii of which are both supplied to the command. Optionally one can provide vectors for position and orientation, as well as angles for the beginning and end of the sweep.

from FreeCAD import Base
import Part
torus = Part.makeTorus(10, 2) 
torus = Part.makeTorus(10,5,Base.Vector(0,0,0),Base.Vector(0,0,1),0,180)


Once created a shape can easily be translated, rotated and scaled using available methods. A translation just needs to be supplied with a vector; a rotation requires center of rotation, axis around which to rotate, and angle; a scaling operation needs scaling factors for each of the three axis. One can define a matrix for a complex transformation, and apply the former to the object in question.

from FreeCAD import Base
import Part, math
myShape = Part.makeBox(2,2,2)
# Move shape 2 units along the x-axis
# Rotate shape by defining center of rotation, axis and angle
# Define a transformation using a matrix
myMat = Base.Matrix() 
# Scaling by use of a matrix
myMat = Base.Matrix() 


You can create a mesh from your B-rep model, maybe for use in Blender or to perform some kind of surface analysis on it (like FEM). Triangulation of the model, which more accurately is called tessellation, is done with the help of an OpenCascade function and the Mesh module.

import Mesh
faces = []
shape = FreeCAD.ActiveDocument.ActiveObject.Shape
# Create triangles by tessellation, precision is set to 1
triangles = shape.tesselate(1)
for tri in triangles[1]:
 face = []
 for i in range(3):
  vindex = tri[i]
# Create mesh from faces
m = Mesh.Mesh(faces)


Vectors are used extensively in geometry design, defining points, direction... The following defines a vector, uses it to create its shape counterpart, a vertex, then extracts the vector back from the shape.

from FreeCAD import Base
import Part
# Create vector at coordinates x=3, y=2, z=0
myVector = Base.Vector(3,2,0)
myVertex = myVector.toShape()
print myVertex.Point


A wire is created as a combination of edges. Again, a number of methods are available to get information from it.

from FreeCAD import Base
import Part
edge1 = Part.makeLine((0,0,0), (10,0,0))
edge2 = Part.makeLine((10,0,0), (10,10,0))
edge3 = Part.makeLine((10,10,0), (0,10,0))
edge4 = Part.makeLine((0,10,0), (0,0,0))
# Combine edges into wires
wire1 = Part.Wire([edge1,edge2]) 
wire2 = Part.Wire([edge3,edge4])
wire3 = Part.Wire([wire1,wire2])
# Access information from wires

Drawing module

The drawing module creates 2D projections from your model to be used as plans. It does so by adding a Page object to the document, and defining a number of views to be projected on this page. Placement of these views are adjusted to appropriately positions them on the page.

import FreeCAD, Part, Drawing
# Create basic features
b1 = Part.makeBox(100,100,100)
b2 = Part.makeBox(90,40,100)
b3 = Part.makeBox(20,85,100).toShape()
c1 = Part.makeCylinder(80,100).toShape()
# Fuse and cut shapes, add result to object
fusion = b2
fusion = fusion.fuse(b3)
fusion = fusion.fuse(c1)
myShape = b1.cut(fusion)
Shape = App.ActiveDocument.addObject("Part::Feature","Shape")
Shape = myShape.toShape()
# Create some direct projections from the model
[visibleG0,visibleG1,hiddenG0,hiddenG1] = Drawing.project(myShape)
[visibleG0,visibleG1,hiddenG0,hiddenG1] = Drawing.project(myShape,App.Vector(1,1,1))
# Project and format as SVG
resultSVG = Drawing.projectToSVG(myShape,App.Vector(1,1,1))
print resultSVG
# Insert Page object and provide template
App.ActiveDocument.Page.Template = App.getResourceDir()+'Mod/Drawing/Templates/A3_Landscape.svg' 
# Insert object View and add to Page
App.ActiveDocument.View.Source = App.ActiveDocument.Shape
App.ActiveDocument.View.Direction = (0.0,0.0,1.0)
App.ActiveDocument.View.X = 10.0
App.ActiveDocument.View.Y = 10.0
App.ActiveDocument.View.Scale = 1.0
App.ActiveDocument.View.Rotation = 90.0

Sketch module

In a typical design flow using this module you will find yourself setting up a sketch plane, creating flat geometry, then generating a volumetric shape using tools like extrusion and rotation. For some operations you don't need to create this geometry yourself, as they take it straight from the model (filleting and chamfering tools for example use existing edges).

Elements offered by the sketching environment are point, line, polygon, arc, fillet, circle, slot, ellipse and hyperbola, some of which can be projected onto the sketch plane from other model features. They can be toggled between regular and construction geometry, of which only the former figures in the resulting feature. By applying a combination of coincident, parallel, perpendicular, tangent, equal, symmetric, vertical and horizontal constraints, sketch geometry is made to behave as one desires. Then it can be sized appropriately using linear and angular dimensions.


© 2015–2018 Inatics.
Inatics is a proud member of the Smart cooperative. The contents of this document, unless otherwise expressly stated, are licensed under the CC-BY-SA-3.0 license.