Batch Engineering Drawings with FreeCAD Python
Automating the creation of 2D technical drawings from 3D CAD models saves significant engineering time and eliminates repetitive manual drafting. This article explains how to use FreeCAD's headless Python environment and the TechDraw workbench to batch-process 3D models (such as STEP or native FCStd files), apply standard drawing templates, insert projected orthographic views, and export production-ready PDF or DXF drawings automatically.
Understanding the FreeCAD TechDraw API
FreeCAD includes a dedicated drawing module called TechDraw. When driving FreeCAD via Python, the core components required to generate a drawing include:
TechDraw::DrawPage: The container object representing the sheet.TechDraw::DrawSVGTemplate: The title block and sheet border loaded from an SVG file.TechDraw::DrawProjGrouporTechDraw::DrawViewPart: Objects that calculate 2D hidden-line-removal (HLR) projections from 3D geometry.
Preparing the Automation Environment
FreeCAD can execute scripts without launching the graphical interface
using the freecadcmd binary (or FreeCADCmd.exe
on Windows). Ensure your system paths point to FreeCAD's
bin and lib directories so Python can import
the FreeCAD, Part, and TechDraw
modules.
The Batch Drawing Script
The following script iterates through a folder of 3D models, loads each part, applies an SVG drawing template, generates standard third-angle projection views (Front, Top, Right, and Isometric), and saves the result as a PDF.
import os
import FreeCAD
import Part
import TechDraw
# Configuration
INPUT_DIR = "/path/to/cad_models"
OUTPUT_DIR = "/path/to/output_drawings"
TEMPLATE_PATH = "/usr/share/freecad/Mod/TechDraw/Templates/A4_Landscape_TD.svg"
os.makedirs(OUTPUT_DIR, exist_ok=True)
def process_file(file_path):
filename = os.path.basename(file_path)
base_name, ext = os.path.splitext(filename)
# Create a fresh FreeCAD document
doc = FreeCAD.newDocument(base_name)
# Load 3D geometry
if ext.lower() in ['.step', '.stp']:
shape = Part.read(file_path)
part_feature = doc.addObject("Part::Feature", "ImportedPart")
part_feature.Shape = shape
elif ext.lower() == '.fcstd':
doc.restore(file_path)
# Find the first solid feature in the file
part_feature = None
for obj in doc.Objects:
if hasattr(obj, "Shape") and obj.Shape.Solids:
part_feature = obj
break
if not part_feature:
print(f"Skipping {filename}: No solid geometry found.")
FreeCAD.closeDocument(doc.Name)
return
else:
FreeCAD.closeDocument(doc.Name)
return
doc.recompute()
# Create TechDraw Page
page = doc.addObject('TechDraw::DrawPage', 'Page')
template = doc.addObject('TechDraw::DrawSVGTemplate', 'Template')
template.Template = TEMPLATE_PATH
page.Template = template
# Create Projection Group (Multi-view)
proj_group = doc.addObject('TechDraw::DrawProjGroup', 'ProjGroup')
page.addView(proj_group)
proj_group.Source = [part_feature]
proj_group.ProjectionType = "ThirdAngle"
# Define Views: Front, Top, Right, Isometric
proj_group.addProjectionType("Front")
proj_group.addProjectionType("Top")
proj_group.addProjectionType("Right")
proj_group.addProjectionType("Iso")
# Layout configuration
proj_group.ScaleType = "Automatic"
proj_group.X = 140.0
proj_group.Y = 100.0
doc.recompute()
# Export Drawing to PDF
output_pdf = os.path.join(OUTPUT_DIR, f"{base_name}.pdf")
TechDraw.writePageAsPdf(page, output_pdf)
# Optional DXF Export:
# TechDraw.writePageAsDxf(page, os.path.join(OUTPUT_DIR, f"{base_name}.dxf"))
print(f"Generated drawing: {output_pdf}")
FreeCAD.closeDocument(doc.Name)
def run_batch():
valid_extensions = ('.step', '.stp', '.fcstd')
files = [f for f in os.listdir(INPUT_DIR) if f.lower().endswith(valid_extensions)]
for f in files:
full_path = os.path.join(INPUT_DIR, f)
process_file(full_path)
if __name__ == "__main__":
run_batch()Running the Automation Headless
To run the automation script headlessly from the terminal or a continuous integration (CI) pipeline, execute:
freecadcmd batch_drawings.pyOn Windows, use:
"C:\Program Files\FreeCAD 0.21\bin\FreeCADCmd.exe" batch_drawings.pyCustomizing Output Parameters
- Drawing Scale: By default, setting
proj_group.ScaleType = "Automatic"allows FreeCAD to fit components to the sheet. For fixed scale (such as 1:2), setproj_group.ScaleType = "Custom"followed byproj_group.Scale = 0.5. - Hidden Lines: Toggle hidden line rendering on views
using
proj_group.HardHidden = Trueor accessing individual sub-views viaproj_group.views['Front'].HardHidden = True. - Title Block Metadata: Modify template text fields
dynamically by accessing template editable texts through
template.setEditableText("Author", "Automated Script").