Files
ztools/partdesign.md
2026-01-24 15:16:09 -06:00

592 lines
16 KiB
Markdown

# 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', '<<Parameters>>.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*