本記事は生成AIと共同で執筆しています。事実関係は可能な範囲で公式ドキュメント等と照合していますが、誤りが含まれている可能性があります。重要な判断を行う前にご自身でも一次情報をご確認ください。

CAD (computer-aided design) データの長期保存を検討する機会があり、OSS のツールだけでサンプルの CAD データを作成し、Archivematica に投入して AIP (Archival Information Package) 内の METS でフォーマットがどう識別されるかを確認しました。その手順と結果の記録です。

検証環境は Apple Silicon の macOS 上の Archivematica 開発用 Docker スタック (hack/) です。スタックの構築でつまずいた点は 別記事 にまとめています。

CAD データの保存フォーマットの整理

CAD の長期保存では、米国議会図書館の Recommended Formats Statement が STEP・IFC・DXF・PDF/A などを preferred / acceptable なフォーマットとして挙げています。これを踏まえ、本記事では正規化先を次のように整理しました (閲覧用の glTF は Recommended Formats Statement には含まれませんが、Web 配信で広く使われる選択肢として加えています)。

元データ保存用閲覧用
3D CAD (DWG, SLDPRT など)STEP (ISO 10303)STL / glTF
2D 図面 (DWG, DXF)PDF/A + DXF同左
BIM (Building Information Modeling)IFC (ISO 16739)glTF

STEP (Standard for the Exchange of Product model data) は ISO 化された中立フォーマットで、B-rep (境界表現) のジオメトリを保持できます。一方で、フィレット半径やスケッチ拘束のようなパラメトリックな設計履歴は保持されないため、オリジナルのファイルを捨てずに併置するのが基本とされています。

build123d でサンプルパーツを生成する

サンプルデータの作成には build123d を使いました。CAD カーネルの Open CASCADE Technology を Python から操作できるライブラリで、コードでソリッドモデルを記述し、STEP や STL (Standard Tessellation Language) に書き出せます。

uv venv cadtry --python 3.12
VIRTUAL_ENV=$PWD/cadtry uv pip install build123d

取付ブラケット (ベースプレート + ボス + 皿もみ付き取付穴) を次のスクリプトで生成しました。

from build123d import (
    Align, Axis, BuildPart, Box, CounterBoreHole, Cylinder, Hole,
    Locations, fillet, export_step, export_stl,
)

PLATE_W, PLATE_D, PLATE_H = 80, 60, 8
CORNER_R = 10
HOLE_POS = [(30, 20), (-30, 20), (30, -20), (-30, -20)]
BOSS_R, BOSS_H = 16, 22
BORE_R = 8

with BuildPart() as bracket:
    Box(PLATE_W, PLATE_D, PLATE_H)
    fillet(bracket.edges().filter_by(Axis.Z), radius=CORNER_R)

    with Locations((0, 0, PLATE_H / 2)):
        Cylinder(BOSS_R, BOSS_H, align=(Align.CENTER, Align.CENTER, Align.MIN))

    boss_base = bracket.edges().filter_by(Axis.Z, reverse=True).group_by(Axis.Z)[-2]
    fillet(boss_base, radius=3)

    Hole(BORE_R)

    with Locations(*[(x, y, PLATE_H / 2) for x, y in HOLE_POS]):
        CounterBoreHole(radius=3.2, counter_bore_radius=6, counter_bore_depth=3)

export_step(bracket.part, "bracket.step")
export_stl(bracket.part, "bracket.stl", tolerance=0.05)

寸法や穴位置を変数として持っているので、値を書き換えて再実行すれば形状が追従します。生成された STEP のヘッダを見ると、スキーマは AP214 (AUTOMOTIVE_DESIGN { 1 0 10303 214 ... }) でした。

FILE_SCHEMA(('AUTOMOTIVE_DESIGN { 1 0 10303 214 1 1 1 1 }'));

STL をブラウザ確認用の簡易 WebGL ビューアで表示したものが次の画像です。

build123d で生成した取付ブラケットを WebGL ビューアで表示した様子

このスクリプト自体がパラメータと形状定義を含むテキストなので、今回は「オリジナル = Python スクリプト、保存用 = STEP、閲覧用 = STL」という 3 点セットを 1 つのフォルダにまとめて投入対象としました。

cad-bracket-sample/
├── cad_sample.py     # オリジナル (設計パラメータのテキスト表現)
├── bracket.step      # 保存用 (ISO 10303-21, AP214)
└── bracket.stl       # 閲覧用メッシュ

Archivematica への投入

フォルダを transfer source (今回はストレージサービスの /home 以下) に置き、Dashboard の /api/v2beta/package エンドポイントで transfer を開始しました。path は「transfer source の UUID + コロン + 相対パス」を Base64 にした値です。processing configuration に automated を指定すると、承認から AIP 格納までが自動で進みます。

TS=842228fc-8750-489e-9d9b-9f9ccca0f881
REL='archivematica/archivematica-sampledata/cad-bracket-sample'
PATH_B64=$(printf '%s' "${TS}:${REL}" | base64)
curl -s -X POST http://localhost:62080/api/v2beta/package \
  -H "Authorization: ApiKey test:test" \
  -H 'Content-Type: application/json' \
  -d "{\"name\": \"cad-bracket-sample\", \"type\": \"standard\", \"path\": \"$PATH_B64\", \"processing_config\": \"automated\"}"

補足として、zsh で "$TS:archivematica/..." のように変数直後にコロンを書くと、:a が修飾子 (絶対パス化) として展開されてパスが壊れました。${TS} と波括弧で区切る必要があります。

transfer と ingest の状態はそれぞれ /api/transfer/status/<uuid>/api/ingest/status/<uuid> で追えます。今回のデータでは数十秒で COMPLETE になり、AIP は 7-Zip 形式 (約 293 KB、元データ約 1.2 MB) で格納されました。

Archivematica の Ingest タブで cad-bracket-sample の全マイクロサービスが完了した様子

METS でのフォーマット識別結果

格納された AIP から、Storage Service の extract_file API で METS を取り出しました。

SIP=378bd654-4de9-4817-8e8f-028f72c11fe9
curl -s -H "Authorization: ApiKey test:test" \
  "http://localhost:62081/api/v2/file/$SIP/extract_file/?relative_path_to_file=cad-bracket-sample-$SIP/data/METS.$SIP.xml" \
  -o aip-mets.xml

METS 内の PREMIS を見ると、3 ファイルとも PRONOM の PUID (PRONOM Unique Identifier) 付きで識別されていました。

ファイル識別されたフォーマットPUID
bracket.stepStandard for the Exchange of Product model datafmt/698
bracket.stlSTL (Standard Tessellation Language) Binaryfmt/865
cad_sample.pyPython Script Filefmt/938

表のフォーマット名は METS に記録された値をそのまま示しています。PRONOM の現行レジストリでは fmt/938 の名称は Python Source Code File に更新されていますが、Archivematica は内部の FPR に登録された名称で PREMIS に書き込むため、METS 上は Python Script File となっています。

実際の METS の該当箇所も抜粋しておきます。bracket.step の premis:objectCharacteristics には、チェックサムとサイズに続いて、フォーマット名と PUID が記録されています。

<premis:objectCharacteristics>
  <premis:compositionLevel>0</premis:compositionLevel>
  <premis:fixity>
    <premis:messageDigestAlgorithm>sha256</premis:messageDigestAlgorithm>
    <premis:messageDigest>1e0eb4c6b9bfc14524e6252a875a285eb0a2d57dab2d56265b1a5cc32ecdf9ec</premis:messageDigest>
  </premis:fixity>
  <premis:size>101689</premis:size>
  <premis:format>
    <premis:formatDesignation>
      <premis:formatName>Standard for the Exchange of Product model data</premis:formatName>
    </premis:formatDesignation>
    <premis:formatRegistry>
      <premis:formatRegistryName>PRONOM</premis:formatRegistryName>
      <premis:formatRegistryKey>fmt/698</premis:formatRegistryKey>
    </premis:formatRegistry>
  </premis:format>
</premis:objectCharacteristics>

format identification の PREMIS イベントには、識別ツールが Siegfried 1.11.2 であることと判定結果が記録されています (linkingAgent は Archivematica-1.18)。

<premis:eventType>format identification</premis:eventType>
<premis:eventDateTime>2026-07-03T20:58:13.501712+00:00</premis:eventDateTime>
<premis:eventDetailInformation>
  <premis:eventDetail>program="Siegfried"; version="1.11.2"</premis:eventDetail>
</premis:eventDetailInformation>
<premis:eventOutcomeInformation>
  <premis:eventOutcome>Positive</premis:eventOutcome>
  <premis:eventOutcomeDetail>
    <premis:eventOutcomeDetailNote>fmt/698</premis:eventOutcomeDetailNote>
  </premis:eventOutcomeDetail>
</premis:eventOutcomeInformation>

PREMIS イベントは各ファイルに対して format identification / virus check / message digest calculation / ingestion の 4 種で、normalization イベントはありませんでした。つまり、デフォルトの FPR (Format Policy Registry) には CAD 系フォーマットの正規化ルールがなく、原本が無変換のまま AIP に保存されます。STEP を投入前に用意しておく今回の方式では、これは望ましい挙動といえます。

投入前に正規化する構成

今回の確認から、CAD の保存は次の整理ができそうです。

  • STEP・STL・Python スクリプトのような中立フォーマットで投入すれば、Archivematica 側の追加設定は不要で、METS には PUID 付きの識別結果が記録される
  • METS に PUID が残るので、将来フォーマットの陳腐化が問題になった場合も、PUID を手がかりに対象 AIP を特定して再変換する運用が可能
  • DWG のようなベンダー固有フォーマットを受け入れる場合は変換が必要になるが、FPR にカスタムルールを足す方法のほかに、投入前のパイプライン側で STEP などへ変換して併置する方法もある。調査した限り、OSS の LibreDWG は DWG の読み込みは全バージョンに対応する一方 (R2010 以降の一部の高度なオブジェクトは読み飛ばされます)、書き込みは R2004 以前のみ安定という制約があり、現時点では ODA File Converter (無償配布ですが ODA 非会員は非商用利用限定・非 OSS) を併用する事例が多いようです

今回使った build123d の実行環境 (Open CASCADE) は、そのまま STEP の読み書きや STL 化のエンジンとしても使えるため、投入前正規化をコンテナ化する際の部品としても選択肢になると考えています。

今回のサンプル一式 (build123d スクリプト・STEP・STL・AIP から取り出した METS) は nakamura196/archivematica-cad-sample に CC0 で公開しています。同じ transfer を投入してフォーマット識別を再現する検証などにご利用ください。