Back to work

AI tool · A2

CAD part data extraction, BOM and batch drawing export

Reads a STEP assembly, extracts part data and estimated mass, checks part numbers and materials, and writes the BOM, an issue list and a three-view drawing per part in one run.

Self-initiated projectPublic demo built in October 2026 on a self-made generic modelMethod, requirements and result checks are mine; the code was implemented with AI coding tools and reviewed by meThe equivalent CATIA tools used at work are confidential and not published; this page runs no CATIA

One run

Part types
17
Part instances
32
Drawings
17
Issues found
54 errors · 1 warnings
Total time
3.84s

Sandbox Linux x86_64, 2 vCPUs, Python 3.13.16, OCP 7.8.1.1

Pipeline

  1. STEP assembly

    Neutral STEP AP242. PRODUCT id is the part number, name the nomenclature; materials sit in AP242 material properties.

    input/*.step
  2. Tree traversal

    Expands sub-assemblies recursively per product definition and counts each part’s instances and placements.

    step_reader.py
  3. Properties & mass

    Volume and surface area integrated on the exact B-rep, bounding box; volume × density table gives the estimated mass.

    geometry.py
  4. Rule check

    Part-number pattern and normalisation, missing or unknown material, duplicate part numbers (geometry compared), solid validity.

    rules.py
  5. BOM · drawings · names

    BOM as CSV / XLSX / JSON; A4 three-view drawings by HLR projection; every file named “part number_name”.

    report.py · drawing.py · naming.py

Input: demo assembly

Quarter-section render of the demo robot joint assembly showing the motor, harmonic reducer and bearings
Quarter-section render (STEP surfaces triangulated for display only)

A simplified generic robot joint: hollow motor, harmonic reducer unit, cross-roller bearing, covers and fasteners, with motor and reducer as two sub-assemblies. Sizes are round placeholder values for this demo and match no product. A Python script in the same folder models it with OpenCASCADE and exports STEP.

Four entries in the demo data are wrong on purpose, to test the rule check:

  1. The front cover reuses the rear cover’s part number RJ-STR-002
  2. The driver board’s part number is written rj_elc_002 (case and separators only)
  3. The encoder disc has no material
  4. The M3×8 bolt’s part number is RJ-FST-02 (wrong digit count)

Issue list

Raw rule-check output (issues.csv), sorted by severity. A duplicate part number is listed once for each part.

LevelPart no.NameFinding
ErrorRJ-ELC-001Encoder discNo material; mass not estimated
ErrorRJ-FST-02Hex bolt M3x8Part number “RJ-FST-02” breaks the naming rule and is not changed: with a wrong digit count the intended number is unknown
ErrorRJ-STR-002Front coverPart number RJ-STR-002 is shared by 2 different parts (Rear cover, Front cover)
ErrorRJ-STR-002Rear coverPart number RJ-STR-002 is shared by 2 different parts (Rear cover, Front cover)
WarningRJ-ELC-002Driver boardPart number “rj_elc_002” differed only in case or separators; normalised to RJ-ELC-002

BOM

Summarised BOM, 17 rows. The table reads bom.json only when you ask for it; columns are sortable.

Downloads

Three-view drawings

One A4 sheet (SVG) per part, first-angle projection, named by part number. Lines come from OpenCASCADE hidden-line removal (HLR); only overall sizes are dimensioned. Select a sheet to enlarge it.

Python tool

The tool lives in tools/cad-bom/ of the repository: the geometry kernel is the open-source OpenCASCADE (cadquery-ocp), BOM sheets use openpyxl, and versions are pinned in requirements.txt. The numbers below come from the committed output/run.json; apart from timing, pytest reruns the tool and compares the outputs byte for byte.

Time by stage

Stages
Read STEP and assembly tree0.25
Volume, area, bounding box0.14
Rule check0.00
Summarise BOM0.00
Write CSV / XLSX0.02
Three-view drawings (HLR)2.53
Assembly overview0.91
Manifest and checksums0.00
Total time3.84

Reproduce

cd tools/cad-bom
python -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/python -m cadbom input/robot-joint-demo.step
.venv/bin/python -m pytest

By hand, the same work means opening each part to read its properties, measuring volumes, checking part numbers, then drawing and renaming sheet by sheet; the tool does it in one run, and the result can be checked again at any time.

Core code

Walk the assembly tree (step_reader.py)
def walk(label: TDF_Label, location: TopLoc_Location, depth: int) -> Occurrence:
    node = Occurrence(definition(label), location, depth)
    if XCAFDoc_ShapeTool.IsAssembly_s(label):
        components = TDF_LabelSequence()
        XCAFDoc_ShapeTool.GetComponents_s(label, components, False)
        for i in range(1, components.Length() + 1):
            component = components.Value(i)
            referred = TDF_Label()
            XCAFDoc_ShapeTool.GetReferredShape_s(component, referred)
            placement = location.Multiplied(XCAFDoc_ShapeTool.GetLocation_s(component))
            node.children.append(walk(referred, placement, depth + 1))
    return node
Check and normalise part numbers (rules.py)
def check_part_number(raw: str | None, name: str, pattern: str) -> Checked:
    if raw is None:
        return Checked("", [Issue("PN_AMBIGUOUS", "", name, {})])
    regex = re.compile(pattern)
    if regex.fullmatch(raw):
        return Checked(raw, [])
    fixed = normalize_part_number(raw)
    if regex.fullmatch(fixed):
        return Checked(fixed, [Issue("PN_NORMALIZED", fixed, name, {"raw": raw, "fixed": fixed})])
    return Checked(raw, [Issue("PN_FORMAT", raw, name, {"raw": raw, "pattern": pattern})])
HLR projection of a view (drawing.py)
def project(shape: TopoDS_Shape, view: str, deflection: float = 0.02, hidden: bool = True) -> Projection:
    direction, x_dir = VIEWS[view]
    algo = HLRBRep_Algo()
    algo.Add(shape)
    algo.Projector(HLRAlgo_Projector(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(*direction), gp_Dir(*x_dir))))
    algo.Update()
    algo.Hide()
    result = HLRBRep_HLRToShape(algo)
    visible = _polylines(result.VCompound(), deflection) + _polylines(result.OutLineVCompound(), deflection)
    hidden_lines = []
    if hidden:
        hidden_lines = _polylines(result.HCompound(), deflection) + _polylines(
            result.OutLineHCompound(), deflection)
    return Projection(visible, hidden_lines)

Mapping to CATIA automation

I have built similar tools for CATIA at work (VBA / Python on the CATIA automation API); they are confidential and not published. The table only describes, in words, which CATIA V5 object-model concept each step corresponds to. This page runs no CATIA and contains no CATIA macro code.

This page (STEP + OpenCASCADE)Corresponding CATIA V5 automation concept
XCAF assembly tree, components, placementsProductDocument → Product.Products (instances) and ReferenceProduct
STEP PRODUCT id / nameProduct.PartNumber / Product.Nomenclature
AP242 material and density tableMaterial applied to the part and its density, or user Parameters
BRepGProp volume and areaSPAWorkbench Measurable (Volume, Area) or Product.Analyze
HLR three-view SVGViews generated in a DrawingDocument, exported with ExportData to PDF / DXF
“part number_name” file namesRename and save documents from PartNumber and other properties

Limits

  • The demo assembly is a self-made generic model with simplified geometry (no gear teeth or rolling elements); it represents no product.
  • Mass = volume × nominal density, an estimate; coatings, threads, tolerances and the inside of bought parts are not modelled.
  • The drawings are HLR projections: overall sizes only (bounding box), no tolerances, sections or detail dimensions; not for manufacturing.
  • The demo runs on STEP and OpenCASCADE, not in CATIA; the CATIA interfaces in the table above are a conceptual mapping only.

Project notes

Question
With many parts and inconsistent naming, how do you get a checkable BOM, issue list and drawings from a 3D assembly in one pass?
Method
Walk the STEP assembly tree for part number, name, material and instance count; integrate volume on the B-rep and estimate mass from a density table; check rules with patterns and geometry comparison; project three-view drawings by HLR and name every file “part number_name”.
Takeaway
Demo assembly with 17 part types and 32 instances: one run writes the BOM (CSV / XLSX) and 17 three-view drawings, and finds all four seeded data errors (the duplicate part number involves two parts, five records in total).