# 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. ```python body = doc.addObject('PartDesign::Body', 'Body') ``` **Properties:** - `Tip` — The feature representing the current state of the body - `BaseFeature` — Optional external solid to build upon - `Origin` — 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. ```python 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 | ```python # 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. ```python 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. ```python line = body.newObject('PartDesign::Line', 'DatumLine') line.AttachmentSupport = [(edge_reference, '')] line.MapMode = 'ObjectXY' ``` ### Datum Point Creates a reference point for geometry attachment. ```python point = body.newObject('PartDesign::Point', 'DatumPoint') point.AttachmentSupport = [(vertex_reference, '')] ``` ### Local Coordinate System Creates a local coordinate system (LCS) attached to datum geometry. ```python lcs = body.newObject('PartDesign::CoordinateSystem', 'LocalCS') ``` ### Shape Binder References geometry from a single parent object. ```python binder = body.newObject('PartDesign::ShapeBinder', 'ShapeBinder') binder.Support = [(external_object, ['Face1'])] ``` ### SubShapeBinder References geometry from one or more parent objects (more flexible than ShapeBinder). ```python subbinder = body.newObject('PartDesign::SubShapeBinder', 'SubShapeBinder') subbinder.Support = [(obj1, ['Face1']), (obj2, ['Edge2'])] ``` ### Clone Creates a clone of a selected body. ```python clone = doc.addObject('PartDesign::FeatureBase', 'Clone') clone.BaseFeature = source_body ``` --- ## Additive Features (Add Material) ### Pad Extrudes a sketch profile to create a solid. ```python 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. ```python 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. ```python 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. ```python 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. ```python 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. ```python # 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) ### Pocket Cuts material by extruding a sketch inward. ```python 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. ```python 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). ```python 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. ```python subloft = body.newObject('PartDesign::SubtractiveLoft', 'SubtractiveLoft') subloft.Profile = sketch1 subloft.Sections = [sketch2] ``` ### Subtractive Pipe Cuts by sweeping a profile along a path. ```python 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). ```python 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::SubtractiveBox` - `PartDesign::SubtractiveCylinder` - `PartDesign::SubtractiveSphere` - `PartDesign::SubtractiveCone` - `PartDesign::SubtractiveEllipsoid` - `PartDesign::SubtractiveTorus` - `PartDesign::SubtractivePrism` - `PartDesign::SubtractiveWedge` --- ## Transformation Features (Patterns) ### Mirrored Creates a mirror copy of features across a plane. ```python 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. ```python 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. ```python 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). ```python 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). ```python # 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. ```python fillet = body.newObject('PartDesign::Fillet', 'Fillet') fillet.Base = (pad, ['Edge1', 'Edge5', 'Edge9']) fillet.Radius = 2.0 ``` ### Chamfer Bevels edges. ```python 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). ```python 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. ```python 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. ```python 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 | ```python # 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. ```python # Available via Gui.runCommand('PartDesign_Sprocket') ``` ### Involute Gear Creates an involute gear profile. ```python # 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: ```python pad.setExpression('Length', 'Spreadsheet.plate_height') fillet.setExpression('Radius', 'Spreadsheet.fillet_r * 0.5') hole.setExpression('Diameter', '<>.hole_dia') ``` --- ## Best Practices 1. **Always work within a Body** — PartDesign features require a body container 2. **Use fully constrained sketches** — Prevents unexpected behavior when parameters change 3. **Leverage datum geometry** — Creates stable references that survive TNP issues 4. **Name constraints** — Enables expression-based parametric design 5. **Use spreadsheets** — Centralizes parameters for easy modification 6. **Set meaningful Labels** — Internal Names are auto-generated; Labels are user-friendly 7. **Check isSolid()** — Before subtractive operations, verify the body has solid geometry ```python 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 ```python 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*