16 KiB
FreeCAD 1.0.2 PartDesign Workbench Command Reference
Overview
The PartDesign Workbench uses a feature-based parametric methodology where a component is represented by a Body container. Features are cumulative—each builds on the result of preceding features. Most features are based on parametric sketches and are either additive (adding material) or subtractive (removing material).
FreeCAD 1.0 introduced significant improvements including Topological Naming Problem (TNP) mitigation, making parametric models more stable when earlier features are modified.
Structure & Containers
Body
The fundamental container for PartDesign features. Defines a local coordinate system and contains all features that define a single solid component.
body = doc.addObject('PartDesign::Body', 'Body')
Properties:
Tip— The feature representing the current state of the bodyBaseFeature— Optional external solid to build uponOrigin— Contains reference planes (XY, XZ, YZ) and axes (X, Y, Z)
Part Container
Groups multiple Bodies for organization. Not a PartDesign-specific object but commonly used.
part = doc.addObject('App::Part', 'Part')
Sketch Tools
| Command | Description |
|---|---|
| Create Sketch | Creates a new sketch on a selected face or datum plane |
| Attach Sketch | Attaches a sketch to geometry from the active body |
| Edit Sketch | Opens selected sketch for editing |
| Validate Sketch | Verifies tolerance of points and adjusts them |
| Check Geometry | Checks geometry for errors |
# Create sketch attached to XY plane
sketch = body.newObject('Sketcher::SketchObject', 'Sketch')
sketch.AttachmentSupport = [(body.getObject('Origin').getObject('XY_Plane'), '')]
sketch.MapMode = 'FlatFace'
Reference Geometry (Datums)
Datum Plane
Creates a reference plane for sketch attachment or as a mirror/pattern reference.
plane = body.newObject('PartDesign::Plane', 'DatumPlane')
plane.AttachmentSupport = [(face_reference, '')]
plane.MapMode = 'FlatFace'
plane.Offset = App.Vector(0, 0, 10) # Offset along normal
Datum Line
Creates a reference axis for revolutions, grooves, or patterns.
line = body.newObject('PartDesign::Line', 'DatumLine')
line.AttachmentSupport = [(edge_reference, '')]
line.MapMode = 'ObjectXY'
Datum Point
Creates a reference point for geometry attachment.
point = body.newObject('PartDesign::Point', 'DatumPoint')
point.AttachmentSupport = [(vertex_reference, '')]
Local Coordinate System
Creates a local coordinate system (LCS) attached to datum geometry.
lcs = body.newObject('PartDesign::CoordinateSystem', 'LocalCS')
Shape Binder
References geometry from a single parent object.
binder = body.newObject('PartDesign::ShapeBinder', 'ShapeBinder')
binder.Support = [(external_object, ['Face1'])]
SubShapeBinder
References geometry from one or more parent objects (more flexible than ShapeBinder).
subbinder = body.newObject('PartDesign::SubShapeBinder', 'SubShapeBinder')
subbinder.Support = [(obj1, ['Face1']), (obj2, ['Edge2'])]
Clone
Creates a clone of a selected body.
clone = doc.addObject('PartDesign::FeatureBase', 'Clone')
clone.BaseFeature = source_body
Additive Features (Add Material)
Pad
Extrudes a sketch profile to create a solid.
pad = body.newObject('PartDesign::Pad', 'Pad')
pad.Profile = sketch
pad.Length = 20.0
pad.Type = 0 # 0=Dimension, 1=UpToLast, 2=UpToFirst, 3=UpToFace, 4=TwoLengths, 5=UpToShape
pad.Reversed = False
pad.Midplane = False
pad.Symmetric = False
pad.Length2 = 10.0 # For TwoLengths type
pad.UseCustomVector = False
pad.Direction = App.Vector(0, 0, 1)
pad.TaperAngle = 0.0 # Draft angle (new in 1.0)
pad.TaperAngle2 = 0.0
Type Options:
| Value | Mode | Description |
|---|---|---|
| 0 | Dimension | Fixed length |
| 1 | UpToLast | Extends to last face in direction |
| 2 | UpToFirst | Extends to first face encountered |
| 3 | UpToFace | Extends to selected face |
| 4 | TwoLengths | Extends in both directions |
| 5 | UpToShape | Extends to selected shape (new in 1.0) |
Revolution
Creates a solid by revolving a sketch around an axis.
revolution = body.newObject('PartDesign::Revolution', 'Revolution')
revolution.Profile = sketch
revolution.Axis = (body.getObject('Origin').getObject('Z_Axis'), [''])
revolution.Angle = 360.0
revolution.Midplane = False
revolution.Reversed = False
Additive Loft
Creates a solid by transitioning between two or more sketch profiles.
loft = body.newObject('PartDesign::AdditiveLoft', 'AdditiveLoft')
loft.Profile = sketch1
loft.Sections = [sketch2, sketch3]
loft.Ruled = False
loft.Closed = False
Additive Pipe (Sweep)
Creates a solid by sweeping a profile along a path.
pipe = body.newObject('PartDesign::AdditivePipe', 'AdditivePipe')
pipe.Profile = profile_sketch
pipe.Spine = path_sketch # or (object, ['Edge1', 'Edge2'])
pipe.Transition = 0 # 0=Transformed, 1=RightCorner, 2=RoundCorner
pipe.Mode = 0 # 0=Standard, 1=Fixed, 2=Frenet, 3=Auxiliary
pipe.Auxiliary = None # Auxiliary spine for Mode=3
Additive Helix
Creates a solid by sweeping a sketch along a helix.
helix = body.newObject('PartDesign::AdditiveHelix', 'AdditiveHelix')
helix.Profile = sketch
helix.Axis = (body.getObject('Origin').getObject('Z_Axis'), [''])
helix.Pitch = 5.0
helix.Height = 30.0
helix.Turns = 6.0
helix.Mode = 0 # 0=pitch-height, 1=pitch-turns, 2=height-turns
helix.LeftHanded = False
helix.Reversed = False
helix.Angle = 0.0 # Taper angle
helix.Growth = 0.0 # Radius growth per turn
Additive Primitives
Direct primitive creation without sketches.
# Box
box = body.newObject('PartDesign::AdditiveBox', 'Box')
box.Length = 10.0
box.Width = 10.0
box.Height = 10.0
# Cylinder
cyl = body.newObject('PartDesign::AdditiveCylinder', 'Cylinder')
cyl.Radius = 5.0
cyl.Height = 20.0
cyl.Angle = 360.0
# Sphere
sphere = body.newObject('PartDesign::AdditiveSphere', 'Sphere')
sphere.Radius = 10.0
sphere.Angle1 = -90.0
sphere.Angle2 = 90.0
sphere.Angle3 = 360.0
# Cone
cone = body.newObject('PartDesign::AdditiveCone', 'Cone')
cone.Radius1 = 10.0
cone.Radius2 = 5.0
cone.Height = 15.0
cone.Angle = 360.0
# Ellipsoid
ellipsoid = body.newObject('PartDesign::AdditiveEllipsoid', 'Ellipsoid')
ellipsoid.Radius1 = 10.0
ellipsoid.Radius2 = 5.0
ellipsoid.Radius3 = 8.0
# Torus
torus = body.newObject('PartDesign::AdditiveTorus', 'Torus')
torus.Radius1 = 20.0
torus.Radius2 = 5.0
# Prism
prism = body.newObject('PartDesign::AdditivePrism', 'Prism')
prism.Polygon = 6
prism.Circumradius = 10.0
prism.Height = 20.0
# Wedge
wedge = body.newObject('PartDesign::AdditiveWedge', 'Wedge')
wedge.Xmin = 0.0
wedge.Xmax = 10.0
wedge.Ymin = 0.0
wedge.Ymax = 10.0
wedge.Zmin = 0.0
wedge.Zmax = 10.0
wedge.X2min = 2.0
wedge.X2max = 8.0
wedge.Z2min = 2.0
wedge.Z2max = 8.0
Subtractive Features (Remove Material)
Cuts material by extruding a sketch inward.
pocket = body.newObject('PartDesign::Pocket', 'Pocket')
pocket.Profile = sketch
pocket.Length = 15.0
pocket.Type = 0 # Same options as Pad, plus 1=ThroughAll
pocket.Reversed = False
pocket.Midplane = False
pocket.Symmetric = False
pocket.TaperAngle = 0.0
Hole
Creates parametric holes with threading options.
hole = body.newObject('PartDesign::Hole', 'Hole')
hole.Profile = sketch # Sketch with center points
hole.Diameter = 6.0
hole.Depth = 15.0
hole.DepthType = 0 # 0=Dimension, 1=ThroughAll
hole.Threaded = True
hole.ThreadType = 0 # 0=None, 1=ISOMetricCoarse, 2=ISOMetricFine, 3=UNC, 4=UNF, 5=NPT, etc.
hole.ThreadSize = 'M6'
hole.ThreadFit = 0 # 0=Standard, 1=Close
hole.ThreadDirection = 0 # 0=Right, 1=Left
hole.HoleCutType = 0 # 0=None, 1=Counterbore, 2=Countersink
hole.HoleCutDiameter = 10.0
hole.HoleCutDepth = 3.0
hole.HoleCutCountersinkAngle = 90.0
hole.DrillPoint = 0 # 0=Flat, 1=Angled
hole.DrillPointAngle = 118.0
hole.DrillForDepth = False
Thread Types:
- ISO Metric Coarse/Fine
- UNC/UNF (Unified National)
- NPT/NPTF (National Pipe Thread)
- BSW/BSF (British Standard)
- UTS (Unified Thread Standard)
Groove
Creates a cut by revolving a sketch around an axis (subtractive revolution).
groove = body.newObject('PartDesign::Groove', 'Groove')
groove.Profile = sketch
groove.Axis = (body.getObject('Origin').getObject('Z_Axis'), [''])
groove.Angle = 360.0
groove.Midplane = False
groove.Reversed = False
Subtractive Loft
Cuts by transitioning between profiles.
subloft = body.newObject('PartDesign::SubtractiveLoft', 'SubtractiveLoft')
subloft.Profile = sketch1
subloft.Sections = [sketch2]
Subtractive Pipe
Cuts by sweeping a profile along a path.
subpipe = body.newObject('PartDesign::SubtractivePipe', 'SubtractivePipe')
subpipe.Profile = profile_sketch
subpipe.Spine = path_sketch
Subtractive Helix
Cuts by sweeping along a helix (e.g., for threads).
subhelix = body.newObject('PartDesign::SubtractiveHelix', 'SubtractiveHelix')
subhelix.Profile = thread_profile_sketch
subhelix.Axis = (body.getObject('Origin').getObject('Z_Axis'), [''])
subhelix.Pitch = 1.0
subhelix.Height = 10.0
Subtractive Primitives
Same primitives as additive, but subtract material:
PartDesign::SubtractiveBoxPartDesign::SubtractiveCylinderPartDesign::SubtractiveSpherePartDesign::SubtractiveConePartDesign::SubtractiveEllipsoidPartDesign::SubtractiveTorusPartDesign::SubtractivePrismPartDesign::SubtractiveWedge
Transformation Features (Patterns)
Mirrored
Creates a mirror copy of features across a plane.
mirrored = body.newObject('PartDesign::Mirrored', 'Mirrored')
mirrored.Originals = [pad, pocket]
mirrored.MirrorPlane = (body.getObject('Origin').getObject('XZ_Plane'), [''])
Linear Pattern
Creates copies in a linear arrangement.
linear = body.newObject('PartDesign::LinearPattern', 'LinearPattern')
linear.Originals = [pocket]
linear.Direction = (body.getObject('Origin').getObject('X_Axis'), [''])
linear.Length = 100.0
linear.Occurrences = 5
linear.Mode = 0 # 0=OverallLength, 1=Offset
Polar Pattern
Creates copies in a circular arrangement.
polar = body.newObject('PartDesign::PolarPattern', 'PolarPattern')
polar.Originals = [pocket]
polar.Axis = (body.getObject('Origin').getObject('Z_Axis'), [''])
polar.Angle = 360.0
polar.Occurrences = 6
polar.Mode = 0 # 0=OverallAngle, 1=Offset
MultiTransform
Combines multiple transformations (mirrored, linear, polar, scaled).
multi = body.newObject('PartDesign::MultiTransform', 'MultiTransform')
multi.Originals = [pocket]
# Add transformations (created within MultiTransform)
# Typically done via GUI or by setting Transformations property
multi.Transformations = [mirrored_transform, linear_transform]
Scaled
Scales features (only available within MultiTransform).
# Only accessible as part of MultiTransform
scaled = body.newObject('PartDesign::Scaled', 'Scaled')
scaled.Factor = 0.5
scaled.Occurrences = 3
Dress-Up Features (Edge/Face Treatment)
Fillet
Rounds edges with a specified radius.
fillet = body.newObject('PartDesign::Fillet', 'Fillet')
fillet.Base = (pad, ['Edge1', 'Edge5', 'Edge9'])
fillet.Radius = 2.0
Chamfer
Bevels edges.
chamfer = body.newObject('PartDesign::Chamfer', 'Chamfer')
chamfer.Base = (pad, ['Edge2', 'Edge6'])
chamfer.ChamferType = 'Equal Distance' # or 'Two Distances' or 'Distance and Angle'
chamfer.Size = 1.5
chamfer.Size2 = 2.0 # For asymmetric
chamfer.Angle = 45.0 # For 'Distance and Angle'
Draft
Applies angular draft to faces (for mold release).
draft = body.newObject('PartDesign::Draft', 'Draft')
draft.Base = (pad, ['Face2', 'Face4'])
draft.Angle = 3.0 # Degrees
draft.NeutralPlane = (body.getObject('Origin').getObject('XY_Plane'), [''])
draft.PullDirection = App.Vector(0, 0, 1)
draft.Reversed = False
Thickness
Creates a shell by hollowing out a solid, keeping selected faces open.
thickness = body.newObject('PartDesign::Thickness', 'Thickness')
thickness.Base = (pad, ['Face6']) # Faces to remove (open)
thickness.Value = 2.0 # Wall thickness
thickness.Mode = 0 # 0=Skin, 1=Pipe, 2=RectoVerso
thickness.Join = 0 # 0=Arc, 1=Intersection
thickness.Reversed = False
Boolean Operations
Boolean
Imports bodies and applies boolean operations.
boolean = body.newObject('PartDesign::Boolean', 'Boolean')
boolean.Type = 0 # 0=Fuse, 1=Cut, 2=Common (intersection)
boolean.Bodies = [other_body1, other_body2]
Context Menu Commands
| Command | Description |
|---|---|
| Set Tip | Sets selected feature as the body's current state (tip) |
| Move object to other body | Transfers feature to a different body |
| Move object after other object | Reorders features in the tree |
| Appearance | Sets color and transparency |
| Color per face | Assigns different colors to individual faces |
# Set tip programmatically
body.Tip = pocket
# Move feature order
doc.moveObject(feature, body, after_feature)
Additional Tools
Sprocket
Creates a sprocket profile for chain drives.
# Available via Gui.runCommand('PartDesign_Sprocket')
Involute Gear
Creates an involute gear profile.
# Available via Gui.runCommand('PartDesign_InvoluteGear')
Common Properties (All Features)
| Property | Type | Description |
|---|---|---|
Label |
String | User-visible name |
Placement |
Placement | Position and orientation |
BaseFeature |
Link | Feature this builds upon |
Shape |
Shape | Resulting geometry |
Expression Binding
All dimensional properties can be driven by expressions:
pad.setExpression('Length', 'Spreadsheet.plate_height')
fillet.setExpression('Radius', 'Spreadsheet.fillet_r * 0.5')
hole.setExpression('Diameter', '<<Parameters>>.hole_dia')
Best Practices
- Always work within a Body — PartDesign features require a body container
- Use fully constrained sketches — Prevents unexpected behavior when parameters change
- Leverage datum geometry — Creates stable references that survive TNP issues
- Name constraints — Enables expression-based parametric design
- Use spreadsheets — Centralizes parameters for easy modification
- Set meaningful Labels — Internal Names are auto-generated; Labels are user-friendly
- Check isSolid() — Before subtractive operations, verify the body has solid geometry
if not body.isSolid():
raise ValueError("Body must contain solid geometry for subtractive features")
FreeCAD 1.0 Changes
| Change | Description |
|---|---|
| TNP Mitigation | Topological naming more stable |
| UpToShape | New Pad/Pocket type extending to arbitrary shapes |
| Draft Angle | Taper angles on Pad/Pocket |
| Improved Hole | More thread types, better UI |
| Assembly Integration | Native assembly workbench |
| Arch → BIM | Workbench rename |
| Path → CAM | Workbench rename |
Python Module Access
import FreeCAD as App
import FreeCADGui as Gui
import Part
import Sketcher
import PartDesign
import PartDesignGui
# Access feature classes
print(dir(PartDesign))
# ['Additive', 'AdditiveBox', 'AdditiveCone', 'AdditiveCylinder', ...]
Document version: FreeCAD 1.0.2 / January 2026 Reference: FreeCAD Wiki, GitHub FreeCAD-documentation, FreeCAD Forum