形式プラグインの作成
このチュートリアルでは、Python を使って LinkCAD にカスタムファイル形式のサポートを追加する方法を説明します。
形式リーダー(インポート)
形式リーダーは、外部のファイル形式を LinkCAD の図面データベースに変換します。
例: 単純な座標ファイルリーダー
from pathlib import Pathfrom linkcad.v1.plugin import format_reader, FormatReader, Option, DrawingContext
@format_reader( name="Coordinate File", extensions=["*.xyz", "*.coord"], description="Simple X Y coordinate files",)class CoordReader(FormatReader): units = Option.choice( "Units", choices=["nm", "um", "mil", "mm", "cm", "inch", "m"], default="um", tooltip="Physical units of the coordinate values in the file", ) layer_name = Option.string("Layer name", default="imported")
def read(self, path: Path, drawing: DrawingContext) -> None: # Name the unit once and LinkCAD converts every coordinate you hand it. drawing.units = self.units
with drawing.cell(path.stem, main=True) as cell: with cell.layer(self.layer_name) as layer: vertices = [] for line in drawing.iter_lines(path): line = line.strip() if not line or line.startswith("#"): # Blank line = end of polygon if vertices: layer.polygon(vertices) vertices = [] continue parts = line.split() vertices.append((float(parts[0]), float(parts[1])))
# Don't forget the last polygon if vertices: layer.polygon(vertices)主要な概念
@format_reader()はクラスをインポート形式として登録しますextensionsはリーダーが扱うファイルを決めますDrawingContextはセル、レイヤー、形状を作成するためのビルダー API を提供しますdrawing.unitsは座標の単位を宣言するもので、これにより手作業でのスケーリングが不要になりますdrawing.iter_lines()は進捗表示付きで行を読み込みますdrawing.iter_binary()は進捗表示付きでバイナリデータを読み込みます
作業単位
drawing.units を一度設定すれば、渡すすべての座標と幅がその単位として解釈されます。使用できる名前は nm、um、mil、mm、cm、inch、m と、micron、millimetre、in などの別名です。
未設定のままならば座標は生のデータベース単位になり、このプロパティが存在しなかった頃とまったく同じ挙動になります。未知の名前、またはデータベース単位を宣言していない図面の場合は ValidationError が送出されます。
独自のスケール表で座標を乗算しているリーダーは古い書き方です。表を削除し、単位を宣言してください。
DrawingContext API
| プロパティ / メソッド | 説明 |
|---|---|
units | 座標の単位。None は生のデータベース単位 |
cell(name, main=False) | コンテキストマネージャー——セルを作成/オープンします |
iter_lines(path, encoding="utf-8") | 進捗表示付きでテキスト行を反復します |
iter_binary(path, chunk_size=8192) | 進捗表示付きでバイナリチャンクを反復します |
progress | 進捗の取得/設定(0.0~1.0) |
CellContext API
| メソッド | 説明 |
|---|---|
layer(name) | コンテキストマネージャー——レイヤーを選択します |
LayerContext API
座標は図面の作業単位で指定します。
| メソッド | 説明 |
|---|---|
polygon(vertices) | (x, y) タプルから閉じたポリゴンを作成します |
polyline(width, vertices, closed=False) | ポリラインを作成します |
circle(center, diameter) | 円を作成します |
後処理フック
リーダーは任意で post_process() を定義し、LinkCAD が解析後に実行する各フェーズに参加できます——組み込みのネイティブリーダーが使うのと同じフックです。read() と同じインスタンス上で実行されるため、そこで記録した情報はそのまま利用できます。False を返すとインポートを中止します。
from linkcad.v1.plugin import Phase
class CoordReader(FormatReader): def post_process(self, phase, drawing, resolution) -> bool: if phase == Phase.ResolvedRefs: ... # every reference now points at a real cell return Trueフェーズは次の順で到達します: ParsedFile、ParsedAll、ClosedOpenCells、ResolvedRefs、SelectedMainCell、ResolvedLayersByBlock、AutoNumberedZ。
形式ライター(エクスポート)
形式ライターは LinkCAD のジオメトリをファイルに書き出します。
例: 単純なテキストライター
from pathlib import Pathfrom linkcad.v1.plugin import format_writer, FormatWriter, Option, WriterContext
@format_writer( name="Simple Text", extensions=["*.stxt"],)class SimpleWriter(FormatWriter): units = Option.choice( "Output units", choices=["nm", "um", "mil", "mm", "cm", "inch", "m"], default="um", ) separator = Option.choice( "Separator", choices=["Space", "Comma", "Tab"], default="Space", ) precision = Option.integer("Decimal places", default=3, min=0, max=10) flatten = Option.boolean("Flatten hierarchy", default=False)
def write(self, path: Path, drawing: WriterContext) -> None: sep = {"Space": " ", "Comma": ", ", "Tab": "\t"}[self.separator]
# Name the unit once and every coordinate arrives already converted. drawing.units = self.units drawing.flatten = self.flatten
with open(path, "w") as f: for layer_name, shapes in drawing.shapes_by_layer(): f.write(f"# Layer: {layer_name}\n") for shape in shapes: for x, y in shape.vertices: f.write(f"{x:.{self.precision}f}{sep}" f"{y:.{self.precision}f}\n") f.write("\n")作業単位とフラット化
drawing.units はリーダーと同じように、ただし逆方向に働きます。設定すれば shapes() から受け取る座標と幅はすべてその単位に変換済みです。独自のスケール表で割っているライターは古い書き方です。
drawing.flatten は走査方法を選びます。反復を始める前に設定してください。
flatten = Falseは各セル自身の形状のみを走査し、セル参照の処理は呼び出し側に委ねます。曲線は頂点を持たずに返されます。曲線のテセレーションにはホストが必要だからです。flatten = Trueはホストコントローラーを通じて階層をレンダリングします。ホストは降下しながら変換スタックを適用し、途中で曲線をテセレーションします。したがって円弧、円、ドーナツ、NURBS がポリゴンやポリラインとしてライターに届くのはフラット化が有効なときだけです。
いずれの場合も shapes() が唯一の走査手段です。フラット化専用のイテレーターは存在しません。
WriterContext API
| プロパティ / メソッド | 説明 |
|---|---|
units | 受け取るジオメトリの単位。None は生のデータベース単位 |
flatten | 階層のフラット化の取得/設定。反復前に設定します |
shapes(cell=None, layer=None) | 形状を反復します(セル/レイヤーフィルター任意) |
shapes_by_layer(cell=None) | レイヤーごとにグループ化して反復します |
shapes_by_cell(layer=None) | セルごとにグループ化して反復します |
cell_names / layer_names | すべてのセル名/レイヤー名のリスト |
cell_count | セル数 |
shape_count | 形状の総数 |
main_cell_name | トップセルの名前 |
progress | 進捗の取得/設定(0.0~1.0) |
ShapeInfo のプロパティ
| プロパティ | 型 | 説明 |
|---|---|---|
layer_name | str | レイヤー名 |
cell_name | str | セル名 |
vertices | list[tuple] | 作業単位での (x, y) 座標 |
is_polygon | bool | ポリゴンなら True、ポリラインなら False |
width | int | 作業単位でのポリライン幅(ポリゴンは 0) |
is_closed | bool | 形状が閉じているかどうか |
エラー処理
明確なエラー報告のために、組み込みの例外クラスを使用してください。
from linkcad.v1.plugin import ParseError, WriteError, ValidationError
# In a reader:raise ParseError("Invalid coordinate", line=42, path=path)
# In a writer:raise WriteError("Cannot write to locked file")
# In option validation:raise ValidationError("Scale must be positive")次のステップ
- パネルアセンブリチュートリアル——テーブルオプションを使う応用的なツール
- 形式デコレーターリファレンス——完全なデコレーター API