freecad-scripts

安装量: 468
排名: #4733

安装

npx skills add https://github.com/github/awesome-copilot --skill freecad-scripts

FreeCAD Scripts Expert skill for generating production-quality Python scripts for the FreeCAD CAD application. Interprets shorthand, quasi-code, and natural language descriptions of 3D modeling tasks and translates them into correct FreeCAD Python API calls. When to Use This Skill Writing Python scripts for FreeCAD's built-in console or macro system Creating or manipulating 3D geometry (Part, Mesh, Sketcher, Path, FEM) Building parametric FeaturePython objects with custom properties Developing GUI tools using PySide/Qt within FreeCAD Manipulating the Coin3D scenegraph via Pivy Creating custom workbenches or Gui Commands Automating repetitive CAD operations with macros Converting between mesh and solid representations Scripting FEM analyses, raytracing, or drawing exports Prerequisites FreeCAD installed (0.19+ recommended; 0.21+/1.0+ for latest API) Python 3.x (bundled with FreeCAD) For GUI work: PySide2 (bundled with FreeCAD) For scenegraph: Pivy (bundled with FreeCAD) FreeCAD Python Environment FreeCAD embeds a Python interpreter. Scripts run in an environment where these key modules are available: import FreeCAD

Core module (also aliased as 'App')

import FreeCADGui

GUI module (also aliased as 'Gui') — only in GUI mode

import Part

Part workbench — BRep/OpenCASCADE shapes

import Mesh

Mesh workbench — triangulated meshes

import Sketcher

Sketcher workbench — 2D constrained sketches

import Draft

Draft workbench — 2D drawing tools

import Arch

Arch/BIM workbench

import Path

Path/CAM workbench

import FEM

FEM workbench

import TechDraw

TechDraw workbench (replaces Drawing)

import BOPTools

Boolean operations

import CompoundTools

Compound shape utilities

The FreeCAD Document Model

Create or access a document

doc

FreeCAD . newDocument ( "MyDoc" ) doc = FreeCAD . ActiveDocument

Add objects

box

doc . addObject ( "Part::Box" , "MyBox" ) box . Length = 10.0 box . Width = 10.0 box . Height = 10.0

Recompute

doc . recompute ( )

Access objects

obj

doc . getObject ( "MyBox" ) obj = doc . MyBox

Attribute access also works

Remove objects

doc . removeObject ( "MyBox" ) Core Concepts Vectors and Placements import FreeCAD

Vectors

v1

FreeCAD . Vector ( 1 , 0 , 0 ) v2 = FreeCAD . Vector ( 0 , 1 , 0 ) v3 = v1 . cross ( v2 )

Cross product

d

v1 . dot ( v2 )

Dot product

v4

v1 + v2

Addition

length

v1 . Length

Magnitude

v_norm

FreeCAD . Vector ( v1 ) v_norm . normalize ( )

In-place normalize

Rotations

rot

FreeCAD . Rotation ( FreeCAD . Vector ( 0 , 0 , 1 ) , 45 )

axis, angle(deg)

rot

FreeCAD . Rotation ( 0 , 0 , 45 )

Euler angles (yaw, pitch, roll)

Placements (position + orientation)

placement

FreeCAD . Placement ( FreeCAD . Vector ( 10 , 20 , 0 ) ,

translation

FreeCAD . Rotation ( 0 , 0 , 45 ) ,

rotation

FreeCAD . Vector ( 0 , 0 , 0 )

center of rotation

) obj . Placement = placement

Matrix (4x4 transformation)

import math mat = FreeCAD . Matrix ( ) mat . move ( FreeCAD . Vector ( 10 , 0 , 0 ) ) mat . rotateZ ( math . radians ( 45 ) ) Creating and Manipulating Geometry (Part Module) The Part module wraps OpenCASCADE and provides BRep solid modeling: import FreeCAD import Part

--- Primitive Shapes ---

box

Part . makeBox ( 10 , 10 , 10 )

length, width, height

cyl

Part . makeCylinder ( 5 , 20 )

radius, height

sphere

Part . makeSphere ( 10 )

radius

cone

Part . makeCone ( 5 , 2 , 10 )

r1, r2, height

torus

Part . makeTorus ( 10 , 2 )

major_r, minor_r

--- Wires and Edges ---

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 , 0 , 0 ) ) wire = Part . Wire ( [ edge1 , edge2 , edge3 ] )

Circles and arcs

circle

Part . makeCircle ( 5 )

radius

arc

Part . makeCircle ( 5 , FreeCAD . Vector ( 0 , 0 , 0 ) , FreeCAD . Vector ( 0 , 0 , 1 ) , 0 , 180 )

start/end angle

--- Faces ---

face

Part . Face ( wire )

From a closed wire

--- Solids from Faces/Wires ---

extrusion

face . extrude ( FreeCAD . Vector ( 0 , 0 , 10 ) )

Extrude

revolved

face . revolve ( FreeCAD . Vector ( 0 , 0 , 0 ) , FreeCAD . Vector ( 0 , 0 , 1 ) , 360 )

Revolve

--- Boolean Operations ---

fused

box . fuse ( cyl )

Union

cut

box . cut ( cyl )

Subtraction

common

box . common ( cyl )

Intersection

fused_clean

fused . removeSplitter ( )

Clean up seams

--- Fillets and Chamfers ---

filleted

box . makeFillet ( 1.0 , box . Edges )

radius, edges

chamfered

box . makeChamfer ( 1.0 , box . Edges )

dist, edges

--- Loft and Sweep ---

loft

Part . makeLoft ( [ wire1 , wire2 ] , True )

wires, solid

swept

Part . Wire ( [ path_edge ] ) . makePipeShell ( [ profile_wire ] , True , False )

solid, frenet

--- BSpline Curves ---

from FreeCAD import Vector points = [ Vector ( 0 , 0 , 0 ) , Vector ( 1 , 2 , 0 ) , Vector ( 3 , 1 , 0 ) , Vector ( 4 , 3 , 0 ) ] bspline = Part . BSplineCurve ( ) bspline . interpolate ( points ) edge = bspline . toShape ( )

--- Show in document ---

Part . show ( box , "MyBox" )

Quick display (adds to active doc)

Or explicitly:

doc

FreeCAD . ActiveDocument or FreeCAD . newDocument ( ) obj = doc . addObject ( "Part::Feature" , "MyShape" ) obj . Shape = box doc . recompute ( ) Topological Exploration shape = obj . Shape

Access sub-elements

shape . Vertexes

List of Vertex objects

shape . Edges

List of Edge objects

shape . Wires

List of Wire objects

shape . Faces

List of Face objects

shape . Shells

List of Shell objects

shape . Solids

List of Solid objects

Bounding box

bb

shape . BoundBox print ( bb . XMin , bb . XMax , bb . YMin , bb . YMax , bb . ZMin , bb . ZMax ) print ( bb . Center )

Properties

shape . Volume shape . Area shape . Length

For edges/wires

face . Surface

Underlying geometric surface

edge . Curve

Underlying geometric curve

Shape type

shape . ShapeType

"Solid", "Shell", "Face", "Wire", "Edge", "Vertex", "Compound"

Mesh Module import Mesh

Create mesh from vertices and facets

mesh

Mesh . Mesh ( ) mesh . addFacet ( 0.0 , 0.0 , 0.0 ,

vertex 1

1.0 , 0.0 , 0.0 ,

vertex 2

0.0 , 1.0 , 0.0

vertex 3

)

Import/Export

mesh

Mesh . Mesh ( "/path/to/file.stl" ) mesh . write ( "/path/to/output.stl" )

Convert Part shape to Mesh

import Part import MeshPart shape = Part . makeBox ( 1 , 1 , 1 ) mesh = MeshPart . meshFromShape ( Shape = shape , LinearDeflection = 0.1 , AngularDeflection = 0.5 )

Convert Mesh to Part shape

shape

Part . Shape ( ) shape . makeShapeFromMesh ( mesh . Topology , 0.05 )

tolerance

solid

Part . makeSolid ( shape ) Sketcher Module Create a sketch on XY plane sketch = doc.addObject("Sketcher::SketchObject", "MySketch") sketch.Placement = FreeCAD.Placement( FreeCAD.Vector(0, 0, 0), FreeCAD.Rotation(0, 0, 0, 1) ) Add geometry (returns geometry index) idx_line = sketch.addGeometry(Part.LineSegment( FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(10, 0, 0))) idx_circle = sketch.addGeometry(Part.Circle( FreeCAD.Vector(5, 5, 0), FreeCAD.Vector(0, 0, 1), 3)) Add constraints sketch.addConstraint(Sketcher.Constraint("Coincident", 0, 2, 1, 1)) sketch.addConstraint(Sketcher.Constraint("Horizontal", 0)) sketch.addConstraint(Sketcher.Constraint("DistanceX", 0, 1, 0, 2, 10.0)) sketch.addConstraint(Sketcher.Constraint("Radius", 1, 3.0)) sketch.addConstraint(Sketcher.Constraint("Fixed", 0, 1)) Constraint types: Coincident, Horizontal, Vertical, Parallel, Perpendicular, Tangent, Equal, Symmetric, Distance, DistanceX, DistanceY, Radius, Angle, Fixed (Block), InternalAlignment doc.recompute()

Draft Module

```python import Draft import FreeCAD

2D shapes

line = Draft.makeLine(FreeCAD.Vector(0,0,0), FreeCAD.Vector(10,0,0)) circle = Draft.makeCircle(5) rect = Draft.makeRectangle(10, 5) poly = Draft.makePolygon(6, radius=5) # hexagon

Operations

moved = Draft.move(obj, FreeCAD.Vector(10, 0, 0), copy=True) rotated = Draft.rotate(obj, 45, FreeCAD.Vector(0,0,0), axis=FreeCAD.Vector(0,0,1), copy=True) scaled = Draft.scale(obj, FreeCAD.Vector(2,2,2), center=FreeCAD.Vector(0,0,0), copy=True) offset = Draft.offset(obj, FreeCAD.Vector(1,0,0)) array = Draft.makeArray(obj, FreeCAD.Vector(15,0,0), FreeCAD.Vector(0,15,0), 3, 3) Creating Parametric Objects (FeaturePython) FeaturePython objects are custom parametric objects with properties that trigger recomputation: import FreeCAD import Part class MyBox : """A custom parametric box.""" def init ( self , obj ) : obj . Proxy = self obj . addProperty ( "App::PropertyLength" , "Length" , "Dimensions" , "Box length" ) . Length = 10.0 obj . addProperty ( "App::PropertyLength" , "Width" , "Dimensions" , "Box width" ) . Width = 10.0 obj . addProperty ( "App::PropertyLength" , "Height" , "Dimensions" , "Box height" ) . Height = 10.0 def execute ( self , obj ) : """Called on document recompute.""" obj . Shape = Part . makeBox ( obj . Length , obj . Width , obj . Height ) def onChanged ( self , obj , prop ) : """Called when a property changes.""" pass def getstate ( self ) : return None def setstate ( self , state ) : return None class ViewProviderMyBox : """View provider for custom icon and display settings.""" def init ( self , vobj ) : vobj . Proxy = self def getIcon ( self ) : return ":/icons/Part_Box.svg" def attach ( self , vobj ) : self . Object = vobj . Object def updateData ( self , obj , prop ) : pass def onChanged ( self , vobj , prop ) : pass def getstate ( self ) : return None def setstate ( self , state ) : return None

--- Usage ---

doc

FreeCAD . ActiveDocument or FreeCAD . newDocument ( "Test" ) obj = doc . addObject ( "Part::FeaturePython" , "CustomBox" ) MyBox ( obj ) ViewProviderMyBox ( obj . ViewObject ) doc . recompute ( ) Common Property Types Property Type Python Type Description App::PropertyBool bool Boolean App::PropertyInteger int Integer App::PropertyFloat float Float App::PropertyString str String App::PropertyLength float (units) Length with units App::PropertyAngle float (deg) Angle in degrees App::PropertyVector FreeCAD.Vector 3D vector App::PropertyPlacement FreeCAD.Placement Position + rotation App::PropertyLink object ref Link to another object App::PropertyLinkList list of refs Links to multiple objects App::PropertyEnumeration list / str Dropdown selection App::PropertyFile str File path App::PropertyColor tuple RGB color (0.0-1.0) App::PropertyPythonObject any Serializable Python object Creating GUI Tools Gui Commands import FreeCAD import FreeCADGui class MyCommand : """A custom toolbar/menu command.""" def GetResources ( self ) : return { "Pixmap" : ":/icons/Part_Box.svg" , "MenuText" : "My Custom Command" , "ToolTip" : "Creates a custom box" , "Accel" : "Ctrl+Shift+B" } def IsActive ( self ) : return FreeCAD . ActiveDocument is not None def Activated ( self ) :

Command logic here

FreeCAD . Console . PrintMessage ( "Command activated\n" ) FreeCADGui . addCommand ( "My_CustomCommand" , MyCommand ( ) ) PySide Dialogs from PySide2 import QtWidgets , QtCore , QtGui class MyDialog ( QtWidgets . QDialog ) : def init ( self , parent = None ) : super ( ) . init ( parent or FreeCADGui . getMainWindow ( ) ) self . setWindowTitle ( "My Tool" ) self . setMinimumWidth ( 300 ) layout = QtWidgets . QVBoxLayout ( self )

Input fields

self . label = QtWidgets . QLabel ( "Length:" ) self . spinbox = QtWidgets . QDoubleSpinBox ( ) self . spinbox . setRange ( 0.1 , 1000.0 ) self . spinbox . setValue ( 10.0 ) self . spinbox . setSuffix ( " mm" ) form = QtWidgets . QFormLayout ( ) form . addRow ( self . label , self . spinbox ) layout . addLayout ( form )

Buttons

btn_layout

QtWidgets . QHBoxLayout ( ) self . btn_ok = QtWidgets . QPushButton ( "OK" ) self . btn_cancel = QtWidgets . QPushButton ( "Cancel" ) btn_layout . addWidget ( self . btn_ok ) btn_layout . addWidget ( self . btn_cancel ) layout . addLayout ( btn_layout ) self . btn_ok . clicked . connect ( self . accept ) self . btn_cancel . clicked . connect ( self . reject )

Usage

dialog

MyDialog ( ) if dialog . exec_ ( ) == QtWidgets . QDialog . Accepted : length = dialog . spinbox . value ( ) FreeCAD . Console . PrintMessage ( f"Length: { length } \n" ) Task Panel (Recommended for FreeCAD integration) class MyTaskPanel : """Task panel shown in the left sidebar.""" def init ( self ) : self . form = QtWidgets . QWidget ( ) layout = QtWidgets . QVBoxLayout ( self . form ) self . spinbox = QtWidgets . QDoubleSpinBox ( ) self . spinbox . setValue ( 10.0 ) layout . addWidget ( QtWidgets . QLabel ( "Length:" ) ) layout . addWidget ( self . spinbox ) def accept ( self ) :

Called when user clicks OK

length

self . spinbox . value ( ) FreeCAD . Console . PrintMessage ( f"Accepted: { length } \n" ) FreeCADGui . Control . closeDialog ( ) return True def reject ( self ) : FreeCADGui . Control . closeDialog ( ) return True def getStandardButtons ( self ) : return int ( QtWidgets . QDialogButtonBox . Ok | QtWidgets . QDialogButtonBox . Cancel )

Show the panel

panel

MyTaskPanel ( ) FreeCADGui . Control . showDialog ( panel ) Coin3D Scenegraph (Pivy) from pivy import coin import FreeCADGui

Access the scenegraph root

sg

FreeCADGui . ActiveDocument . ActiveView . getSceneGraph ( )

Add a custom separator with a sphere

sep

coin . SoSeparator ( ) mat = coin . SoMaterial ( ) mat . diffuseColor . setValue ( 1.0 , 0.0 , 0.0 )

Red

trans

coin . SoTranslation ( ) trans . translation . setValue ( 10 , 10 , 10 ) sphere = coin . SoSphere ( ) sphere . radius . setValue ( 2.0 ) sep . addChild ( mat ) sep . addChild ( trans ) sep . addChild ( sphere ) sg . addChild ( sep )

Remove later

sg . removeChild ( sep ) Custom Workbench Creation import FreeCADGui class MyWorkbench ( FreeCADGui . Workbench ) : MenuText = "My Workbench" ToolTip = "A custom workbench" Icon = ":/icons/freecad.svg" def Initialize ( self ) : """Called at workbench activation.""" import MyCommands

Import your command module

self . appendToolbar ( "My Tools" , [ "My_CustomCommand" ] ) self . appendMenu ( "My Menu" , [ "My_CustomCommand" ] ) def Activated ( self ) : pass def Deactivated ( self ) : pass def GetClassName ( self ) : return "Gui::PythonWorkbench" FreeCADGui . addWorkbench ( MyWorkbench ) Macro Best Practices

Standard macro header

-- coding: utf-8 --

FreeCAD Macro: MyMacro

Description: Brief description of what the macro does

Author: YourName

Version: 1.0

Date: 2026-04-07

import FreeCAD import Part from FreeCAD import Base

Guard for GUI availability

if FreeCAD . GuiUp : import FreeCADGui from PySide2 import QtWidgets , QtCore def main ( ) : doc = FreeCAD . ActiveDocument if doc is None : FreeCAD . Console . PrintError ( "No active document\n" ) return if FreeCAD . GuiUp : sel = FreeCADGui . Selection . getSelection ( ) if not sel : FreeCAD . Console . PrintWarning ( "No objects selected\n" )

... macro logic ...

doc . recompute ( ) FreeCAD . Console . PrintMessage ( "Macro completed\n" ) if name == "main" : main ( ) Selection Handling

Get selected objects

sel

FreeCADGui . Selection . getSelection ( )

List of objects

sel_ex

FreeCADGui . Selection . getSelectionEx ( )

Extended (sub-elements)

for selobj in sel_ex : obj = selobj . Object for sub in selobj . SubElementNames : print ( f" { obj . Name } . { sub } " ) shape = obj . getSubObject ( sub )

Get sub-shape

Select programmatically

FreeCADGui . Selection . addSelection ( doc . MyBox ) FreeCADGui . Selection . addSelection ( doc . MyBox , "Face1" ) FreeCADGui . Selection . clearSelection ( ) Console Output FreeCAD . Console . PrintMessage ( "Info message\n" ) FreeCAD . Console . PrintWarning ( "Warning message\n" ) FreeCAD . Console . PrintError ( "Error message\n" ) FreeCAD . Console . PrintLog ( "Debug/log message\n" ) Common Patterns Parametric Pad from Sketch doc = FreeCAD . ActiveDocument

Create sketch

sketch

doc . addObject ( "Sketcher::SketchObject" , "Sketch" ) sketch . addGeometry ( Part . LineSegment ( FreeCAD . Vector ( 0 , 0 , 0 ) , FreeCAD . Vector ( 10 , 0 , 0 ) ) ) sketch . addGeometry ( Part . LineSegment ( FreeCAD . Vector ( 10 , 0 , 0 ) , FreeCAD . Vector ( 10 , 10 , 0 ) ) ) sketch . addGeometry ( Part . LineSegment ( FreeCAD . Vector ( 10 , 10 , 0 ) , FreeCAD . Vector ( 0 , 10 , 0 ) ) ) sketch . addGeometry ( Part . LineSegment ( FreeCAD . Vector ( 0 , 10 , 0 ) , FreeCAD . Vector ( 0 , 0 , 0 ) ) )

Close with coincident constraints

for i in range ( 3 ) : sketch . addConstraint ( Sketcher . Constraint ( "Coincident" , i , 2 , i + 1 , 1 ) ) sketch . addConstraint ( Sketcher . Constraint ( "Coincident" , 3 , 2 , 0 , 1 ) )

Pad (PartDesign)

pad

doc . addObject ( "PartDesign::Pad" , "Pad" ) pad . Profile = sketch pad . Length = 5.0 sketch . Visibility = False doc . recompute ( ) Export Shapes

STEP export

Part . export ( [ doc . MyBox ] , "/path/to/output.step" )

STL export (mesh)

import Mesh Mesh . export ( [ doc . MyBox ] , "/path/to/output.stl" )

IGES export

Part . export ( [ doc . MyBox ] , "/path/to/output.iges" )

Multiple formats via importlib

import importlib importlib . import_module ( "importOBJ" ) . export ( [ doc . MyBox ] , "/path/to/output.obj" ) Units and Quantities

FreeCAD uses mm internally

q

FreeCAD . Units . Quantity ( "10 mm" ) q_inch = FreeCAD . Units . Quantity ( "1 in" ) print ( q_inch . getValueAs ( "mm" ) )

25.4

Parse user input with units

q

FreeCAD . Units . parseQuantity ( "2.5 in" ) value_mm = float ( q )

Value in mm (internal unit)

Compensation Rules (Quasi-Coder Integration)
When interpreting shorthand or quasi-code for FreeCAD scripts:
Terminology mapping
"box" →
Part.makeBox()
, "cylinder" →
Part.makeCylinder()
, "sphere" →
Part.makeSphere()
, "merge/combine/join" →
.fuse()
, "subtract/cut/remove" →
.cut()
, "intersect" →
.common()
, "round edges/fillet" →
.makeFillet()
, "bevel/chamfer" →
.makeChamfer()
Implicit document
If no document handling is mentioned, wrap in standard
doc = FreeCAD.ActiveDocument or FreeCAD.newDocument()
Units assumption
Default to millimeters unless stated otherwise
Recompute
Always call
doc.recompute()
after modifications
GUI guard
Wrap GUI-dependent code in
if FreeCAD.GuiUp:
when the script may run headless
Part.show()
Use Part.show(shape, "Name") for quick display, or doc.addObject("Part::Feature", "Name") for named persistent objects References Primary Links Writing Python code Manipulating FreeCAD objects Vectors and Placements Creating and manipulating geometry Creating parametric objects Creating interface tools Python Introduction to Python Python scripting tutorial FreeCAD scripting basics Gui Command Bundled Reference Documents See the references/ directory for topic-organized guides: scripting-fundamentals.md — Core scripting, document model, console geometry-and-shapes.md — Part, Mesh, Sketcher, topology parametric-objects.md — FeaturePython, properties, scripted objects gui-and-interface.md — PySide, dialogs, task panels, Coin3D workbenches-and-advanced.md — Workbenches, macros, FEM, Path, recipes
返回排行榜