作品一覧へ戻る

AI ツール · A2

CAD 部品情報の抽出、BOM 整理と図面の一括出力

STEP アセンブリを読み込み、部品情報の抽出と質量の推定、部品番号と材料のチェックを行い、BOM、指摘一覧、部品ごとの三面図を 1 回の実行で出力する。

個人プロジェクト(自主制作)2026年10月に作成した公開デモ。自作の汎用モデルを使用手法と要件の定義、結果の確認は本人が担当し、コードは AI コーディングツールで実装して本人が確認した業務で作成した CATIA 向けの同種ツールは機密のため公開しておらず、本ページでも CATIA は実行していない

1 回の実行結果

部品の種類
17
部品インスタンス
32
三面図
17
検出した指摘
5エラー 4 件 · 警告 1 件
総処理時間
3.84s

サンドボックス Linux x86_64、vCPU 2 個、Python 3.13.16、OCP 7.8.1.1

処理の流れ

  1. STEP アセンブリ

    中間ファイル形式 STEP AP242。PRODUCT の id を部品番号、name を名称とし、材料は AP242 の材料プロパティに記述する。

    input/*.step
  2. アセンブリツリーの走査

    製品定義ごとにサブアセンブリを再帰的に展開し、部品ごとのインスタンス数と配置を集計する。

    step_reader.py
  3. プロパティと質量

    厳密な B-rep 上で体積と表面積を積分し、バウンディングボックスを求める。体積 × 密度表で質量を推定する。

    geometry.py
  4. ルールチェック

    部品番号の正規表現と正規化、材料の未設定・密度表にない材料、部品番号の重複(形状を比較)、ソリッドの妥当性。

    rules.py
  5. BOM · 三面図 · ファイル名

    BOM を CSV / XLSX / JSON で出力し、HLR 投影で A4 三面図を作成する。ファイル名は「部品番号_名称」に統一する。

    report.py · drawing.py · naming.py

入力:デモ用アセンブリ

デモ用ロボット関節アセンブリの 1/4 カットレンダリング。モータ、波動歯車減速機、軸受が見える
1/4 カットのレンダリング(STEP の曲面を三角形分割して表示用に描画)

汎用ロボット関節の簡略構造。中空モータ、波動歯車減速機ユニット、クロスローラベアリング、カバー、締結部品からなり、モータと減速機の 2 つのサブアセンブリを含む。寸法はデモ用の切りのよい仮の値で、いずれの製品とも無関係である。同じフォルダの Python スクリプトで OpenCASCADE によりパラメトリックにモデリングし、STEP に出力した。

ルールチェックを確かめるため、デモデータには意図的に 4 か所の誤りを入れた。

  1. フロントカバーがリアカバーの部品番号 RJ-STR-002 を流用している
  2. ドライバ基板の部品番号が rj_elc_002 になっている(大文字小文字と区切り文字のみの違い)
  3. エンコーダディスクに材料が設定されていない
  4. M3×8 ボルトの部品番号が RJ-FST-02 になっている(桁数の誤り)

指摘一覧

ルールチェックの出力(issues.csv)をそのまま重大度順に並べた。部品番号の重複は該当する 2 部品それぞれに 1 件ずつ記録する。

区分部品番号名称内容
エラーRJ-ELC-001エンコーダディスク材料が未設定のため、質量を推定していない
エラーRJ-FST-02六角ボルト M3×8部品番号「RJ-FST-02」は命名規則に合わず、自動修正しない。桁数が誤っている場合、正しい番号を判断できないため人が確認する
エラーRJ-STR-002フロントカバー部品番号 RJ-STR-002 を形状の異なる 2 部品が共用している(リアカバー、フロントカバー)
エラーRJ-STR-002リアカバー部品番号 RJ-STR-002 を形状の異なる 2 部品が共用している(リアカバー、フロントカバー)
警告RJ-ELC-002ドライバ基板部品番号「rj_elc_002」は大文字小文字と区切り文字のみが不統一のため、RJ-ELC-002 に正規化した

BOM

集計 BOM(17 行)。表はボタンを押したときに bom.json を読み込み、列見出しで並べ替えできる。

ダウンロード

三面図

部品ごとに A4 図面 1 枚(SVG)を第一角法で作成し、ファイル名は部品番号に基づく。線は OpenCASCADE の隠線処理(HLR)による投影で、外形寸法のみ記入した。図面を選ぶと拡大表示する。

Python ツール

ツールはリポジトリの tools/cad-bom/ にある。形状カーネルはオープンソースの OpenCASCADE(cadquery-ocp)、BOM の表計算ファイルは openpyxl で作成し、依存バージョンは requirements.txt に固定した。以下の数値はコミットした output/run.json による。処理時間を除き、pytest がツールを再実行して出力をバイト単位で照合する。

処理段階ごとの時間

処理段階秒
STEP とアセンブリツリーの読み込み0.25
体積、表面積、バウンディングボックス0.14
ルールチェック0.00
BOM の集計0.00
CSV / XLSX の書き出し0.02
三面図(HLR)2.53
アセンブリ全体図0.91
マニフェストとチェックサム0.00
総処理時間3.84

再現手順

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

比較:同じ作業を手作業で行うと、部品を 1 つずつ開いてプロパティを確認し、体積を測り、部品番号を照合したうえで、図面を 1 枚ずつ作成して名前を付け直す必要がある。ツールは 1 回の実行で完了し、結果を何度でも照合できる。

主要コード

アセンブリツリーの走査(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
部品番号のチェックと正規化(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 による投影図の作成(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)

CATIA 自動化との対応

業務では CATIA 向けの同種ツール(VBA / Python で CATIA のオートメーション API を呼び出すもの)を作成したが、機密のため公開していない。下表は本ページの各処理が CATIA V5 のオブジェクトモデルのどの概念に対応するかを文章で示すだけであり、本ページでは CATIA を実行しておらず、CATIA マクロのコードも掲載していない。

本ページ(STEP + OpenCASCADE)CATIA V5 オートメーションで対応する概念
XCAF のアセンブリツリー、コンポーネントと配置ProductDocument → Product.Products(インスタンス)と ReferenceProduct
STEP PRODUCT の id / nameProduct.PartNumber / Product.Nomenclature
AP242 の材料と密度表部品に適用した材料とその密度、またはユーザー定義の Parameters
BRepGProp による体積・表面積SPAWorkbench の Measurable(Volume、Area)または Product.Analyze
HLR による三面図 SVGDrawingDocument でビューを作成し、ExportData で PDF / DXF に出力
「部品番号_名称」のファイル名PartNumber などのプロパティからファイル名を付けて保存

制約

  • デモ用アセンブリは自作の汎用モデルで、形状を簡略化している(歯形や転動体はモデル化していない)。いずれの製品も表していない。
  • 質量は体積 × 公称密度による推定値で、めっき・塗装、ねじ、公差、購入部品の内部構造は考慮していない。
  • 三面図は HLR による投影の模式図で、外形寸法(バウンディングボックス)のみを記入し、公差、断面、詳細寸法はない。加工には使えない。
  • デモは STEP と OpenCASCADE に基づき、CATIA では実行していない。上表の CATIA のインタフェースは概念上の対応を示すだけである。

プロジェクトの要点

問い
部品点数が多く命名が不統一なとき、3D アセンブリから照合可能な BOM、指摘一覧、図面を一度に得るにはどうするか。
手法
STEP のアセンブリツリーを走査して部品番号、名称、材料、インスタンス数を取得し、B-rep 上で体積を積分して密度表から質量を推定する。正規表現と形状比較でルールをチェックし、HLR 投影で三面図を一括作成して「部品番号_名称」で命名する。
結果
デモ用アセンブリ(部品 17 種類、インスタンス 32 個)に対し、1 回の実行で BOM(CSV / XLSX)と三面図 17 枚を出力し、意図的に入れた 4 か所の誤りをすべて検出した(部品番号の重複は 2 部品に関わり、計 5 件)。