linkcad.plugin
プラグインモジュールは、ツール、形式リーダー、形式ライターを作成するためのフレームワークを提供します。スクリプトとプラグインでは linkcad.v1.plugin を使用してください。これは linkcad.plugin の公開名前空間全体をミラーしたもので、まったく同じ API を公開します。
from linkcad.v1.plugin import ( tool, Tool, Option, TableColumn, format_reader, FormatReader, DrawingContext, CellContext, LayerContext, DrawingBuilder, format_writer, FormatWriter, WriterContext, ShapeInfo, WriterController, DialogSpec, ChoiceItem, EventLog, Phase, LayerFlags, SortOrder, HolesMode, PolygonType, EndCap, FillRule, PluginError, ParseError, WriteError, ValidationError, UNIT_IN_METERS,)作業単位
DrawingContext(インポート)と WriterContext(エクスポート)はどちらも units プロパティを持ちます。一度設定すれば、プラグイン境界を越えるすべての座標と幅がその単位で表現されます——プラグインが独自のスケール表を持つ必要はありません。
drawing.units = "mm" # in a reader: the numbers you hand in are millimetresdrawing.units = "um" # in a writer: the numbers you get back are microns| 使用できる名前 | 別名 |
|---|---|
nm、um、mil、mm、cm、inch、m | nanometer/nanometre、micron/micrometer/micrometre、millimeter/millimetre、centimeter/centimetre、in、meter/metre |
units を未設定のままにする(または None を代入する)と生のデータベース単位になり、このプロパティが存在しなかった頃のプラグインの挙動とまったく同じです。未知の名前、またはデータベース単位を宣言していない図面の場合は ValidationError が送出されます。
UNIT_IN_METERS は唯一の換算表で、どのプラグインも独自の表を抱え込まずに済むようここから公開されています。黙って食い違いうる 2 つ目の表こそ、かつて出荷済みのツールに 1000 倍の配置誤差を持ち込んだ経路でした。
from linkcad.v1.plugin import UNIT_IN_METERS
to_db_units = UNIT_IN_METERS["mm"] * drawing.units # drawing.units is per metreデコレーター
@tool()
クラスをメニューツールとして登録します。ツールデコレーター を参照してください。
@tool(name="My Tool", menu="Tools/Custom")class MyTool(Tool): def run(self, drawing) -> dict: # `drawing` is a linkcad.v1.db.Drawing owned by the application. return {"summary": f"{len(drawing.cells)} cells"}@format_reader()
クラスをファイルインポート形式として登録します。形式デコレーター を参照してください。
@format_reader(name="My Format", extensions=["*.myf"])class MyReader(FormatReader): def read(self, path: Path, drawing: DrawingContext) -> None: ...リーダーは任意で post_process(phase, drawing, resolution) フックを定義できます。これは解析後に LinkCAD が実行する各フェーズごとに呼ばれる、組み込みネイティブリーダーと同じフックです。read() と同じインスタンス上で実行されるため、そこで記録した情報はそのまま利用できます。False を返すとインポートを中止します。
from linkcad.v1.plugin import Phase
class MyReader(FormatReader): def post_process(self, phase, drawing, resolution) -> bool: if phase == Phase.ResolvedRefs: ... # every reference now points at a real cell return TrueFormatReader は LinkCAD が使うネイティブブリッジ parse_file(filepath, builder, file_size, progress_callback) も提供します。ユーザープラグインでは read() を実装し、ブリッジから呼ばせてください。
@format_writer()
クラスをファイルエクスポート形式として登録します。形式デコレーター を参照してください。
@format_writer(name="My Format", extensions=["*.myf"])class MyWriter(FormatWriter): def write(self, path: Path, drawing: WriterContext) -> None: ...FormatWriter は LinkCAD が使うネイティブブリッジ write_file(filepath, controller, set_entity_sink=None) も提供します。ユーザープラグインでは write() を実装し、ブリッジから呼ばせてください。
Option クラス
Option は、型付きで永続化されるオプションを定義するためのファクトリーメソッドを提供します。
| ファクトリー | 結果の型 | UI コントロール |
|---|---|---|
Option.integer(label, default, min, max) | int | スピンボックス |
Option.real(label, default, min, max, decimals) | float | 小数スピンボックス |
Option.boolean(label, default) | bool | チェックボックス |
Option.string(label, default) | str | テキストフィールド |
Option.choice(label, choices, default) | str | ドロップダウン |
Option.path(label, default, file_filter) | str | ファイル選択 |
Option.color(label, default) | str | カラーピッカー |
Option.table(label, columns, default) | list[dict] | 編集可能なグリッド |
Option.cell_choice(label, default) | str | セルのドロップダウン |
すべてのファクトリーは省略可能な tooltip と enabled_when、さらに生成されるオプションキーを上書きするキーワード専用引数 name を受け取ります。
オプションキーはアプリケーション自身の設定と同じ名前空間を共有します。そのため、クラス属性から生成されるキーは単に接頭辞を付けるのではなく区切られます。AsciiWriter の flatten は PyPlugin.AsciiWriter.flatten になります。予約されたルート PyPlugin はプラグインオプションをアプリケーションの名前空間から隔離し、クラス部分は flatten という同名のオプションを持つ 2 つのプラグインを区別します。属性名はそのまま使われるため、キーとそれを読む Python 属性の綴りは一致します。
すべてのプラグインオプションは、このキーでコマンドラインからも設定できます。
linkcad --PyPlugin.AsciiWriter.precision=5 ...コンテキストクラス
DrawingContext
形式リーダー向けの Python らしいビルダーインターフェイスです。
units— 座標の単位。作業単位 を参照cell(name, main=False)—CellContextを返すコンテキストマネージャーiter_lines(path, encoding="utf-8")— 進捗表示付きの行イテレーターiter_binary(path, chunk_size=8192)— 進捗表示付きのバイナリイテレーターprogress—0.0~1.0の進捗の取得/設定
CellContext
DrawingContext.cell() が返します。
layer(name)—LayerContextを返すコンテキストマネージャー
LayerContext
CellContext.layer() が返します。座標は図面の作業単位で指定します。
polygon(vertices)—(x, y)タプルから閉じたポリゴンを作成しますpolyline(width, vertices, closed=False)— ポリラインを作成しますcircle(center, diameter)— 円を作成します
def read(self, path: Path, drawing: DrawingContext) -> None: drawing.units = "um" with drawing.cell(path.stem, main=True) as cell: with cell.layer("METAL1") as layer: layer.polygon([(0, 0), (100, 0), (100, 100), (0, 100)]) # a 100 µm square layer.polyline(2.5, [(0, 0), (200, 200)]) layer.circle((500, 500), 50)WriterContext
形式ライター向けの Python らしい読み取りインターフェイスです。
units— 受け取るジオメトリの単位。作業単位 を参照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の進捗の取得/設定
shapes() とその 2 つのグループ化を除けば、いずれも名詞でありプロパティです。cells() と layers() のジェネレーターは廃止されました。cell_names と layer_names がすでに保持しているのとまったく同じ文字列を返しており、1 つのリストに 2 つの綴りがあるのは正解のない選択だからです。
shapes() は、フラット化の有無にかかわらずジオメトリを走査する唯一の手段です。flatten = False では各セル自身の形状を走査し、参照の処理は呼び出し側に委ねます。flatten = True ではホストコントローラーを通じて階層をレンダリングし、降下しながら変換スタックを適用して途中で曲線をテセレーションします——したがって円弧、円、ドーナツ、NURBS がポリゴンやポリラインとしてライターに届くのはフラット化が有効なときだけです。
def write(self, path: Path, drawing: WriterContext) -> None: drawing.units = "mm" drawing.flatten = True with open(path, "w") as f: for shape in drawing.shapes(): for x, y in shape.vertices: # millimetres f.write(f"{x:.4f} {y:.4f}\n") f.write("\n")フラット化された走査にはホストライターが必要なため、FormatWriter.write() の中でのみ利用できます。手作業で構築した WriterContext は flatten = False しか使えません。
ShapeInfo
WriterContext.shapes() が返すデータクラスです。
layer_name: str— レイヤー名cell_name: str— セル名vertices: list[tuple]— 作業単位での(x, y)座標is_polygon: bool— ポリゴンか、ポリライン的な出力かwidth: int— 作業単位でのポリライン幅is_closed: bool— 形状が閉じているかどうか
ネイティブ形式インターフェイス
ほとんどの形式プラグインは DrawingContext と WriterContext で足ります。LinkCAD の低レベル形式 API と直接対応させたいプラグインのために、ネイティブの DrawingBuilder と WriterController も公開されています。
DrawingBuilder
DrawingBuilder は LinkCAD ランタイムからインポートプラグインに渡されます。ユーザーコードが直接作成することはありません。
| プロパティ | 説明 |
|---|---|
builder.resolution | 曲線テセレーションの設定 |
builder.cell | 現在のセル、または None |
builder.layer | 現在のレイヤー、または None |
builder.cell_object | 直近に作成されたセルオブジェクト、または None |
builder.drawing | 構築中の図面 |
| メソッド群 | メソッド |
|---|---|
| 図面メタデータ | set_drawing_name(name)、set_drawing_modif_time(time)、set_drawing_access_time(time)、set_progress(percent) |
| セル | open_cell(name_or_number, is_main_cell=False, reopen=False)、close_cell()、delete_cell()、set_cell_name(name)、set_cell_modif_time(time)、set_cell_access_time(time)、find_cell(name) |
| レイヤー | select_layer(name_or_number)、select_layer(major, minor)、set_layer_comment(comment)、set_layer_color(rgba)、set_layer_enabled(enabled)、set_layer_z(z)、set_layer_polarity_positive(positive=True)、set_layer_polarity_group(group_name)、set_layer_polarity_sequence(sequence) |
| 形状 | create_polygon(vertices, make_simple=False)、create_polygon_with_bulges(vertices, bulges)、create_rectangle(corner1, corner2)、create_polyline(width, vertices, closed=False, end_cap=EndCap.Round)、create_circle(center, diameter, donut=False)、create_arc(center, radius, width, start_angle=0.0, end_angle=360.0, end_cap=EndCap.Round)、create_donut(center, mean_diameter, width)、create_nurbs(width, degree, knots, control_points, periodic=False)、create_nurbs_weighted(width, degree, knots, control_points, weights, periodic=False) |
| テキスト | create_text()、set_text_position(position)、set_text_height(height)、set_text_stroke_width(width)、set_text_style(flags, mask=TextStyleMask.None_)、set_formatted_text(text)、set_unformatted_text(text)、set_text_font(font_name)、set_text_width_factor(factor)、set_text_obliquing_angle(angle_degrees)、set_text_mirrored_x(mirror=True)、set_text_mirrored_y(mirror=True)、set_text_rotation(angle_degrees, absolute=False)、set_text_box_width(width)、set_text_line_spacing(spacing) |
| 参照 | create_ref(cell_name_or_number)、scale_ref(scale, absolute=False)、mirror_ref_x(negate=True)、mirror_ref_y(negate=True)、rotate_ref(angle_degrees, absolute=False)、translate_ref(position)、set_ref_array_spacing(dx, dy)、set_ref_array_size(cols, rows) |
| コンテキスト | save_context()、enter_context(handle)、leave_context() |
| ログ | log_info(message)、log_warning(message)、log_error(message) |
| プロパティとスタイル | set_entity_layer_style(flags)、set_current_cell_object_real_property(name, value)、set_current_cell_object_bool_property(name, value) |
| フォント | DrawingBuilder.register_odb_fonts(fonts_dir) |
from linkcad.v1.db import EndCap, TextStyle, TextStyleMaskfrom linkcad.v1.geom import Point
builder.open_cell("TOP", is_main_cell=True)builder.select_layer("metal1")builder.create_arc(Point(0, 0), radius=10_000, width=500, end_cap=EndCap.Round)builder.create_text()builder.set_text_position(Point(0, 12_000))builder.set_text_height(1_000)builder.set_text_style(TextStyle.AlignHCenter, TextStyleMask.AlignH)builder.set_unformatted_text("TOP")builder.close_cell()WriterController
WriterController は LinkCAD ランタイムからエクスポートプラグインに渡されます。ユーザーコードが直接作成することはありません。
| プロパティ | 説明 |
|---|---|
controller.file_name | 出力ファイルのパス |
controller.resolution | 曲線テセレーションの設定 |
controller.drawing | エクスポート中の図面 |
controller.main_cell | メインセル |
controller.units_per_meter | メートルあたりのデータベース単位。図面が宣言していなければ 0 |
controller.layers | 有効なすべてのレイヤー(通常順) |
controller.layer_names | 有効なすべてのレイヤーの名前 |
controller.layer_count | 有効なレイヤー数 |
controller.cells | すべてのサブセル(子が先。メインセルは含みません) |
controller.cell_names | メインセルを含むすべてのセルの名前 |
controller.cell_count | メインセルを含むセル数 |
controller.fonts | 図面で使用されているすべてのフォント |
controller.object_count | 処理済みオブジェクト数 |
controller.total_object_count | エクスポート対象オブジェクトの総数 |
controller.fill_rule | 現在の FillRule |
controller.transformation | 座標変換スタックの現在の最上位 |
| メソッド群 | メソッド |
|---|---|
| ログと進捗 | log_info(message)、log_warning(message)、log_error(message)、set_progress(percent)、init_progress_counter(force_flattened=False)、set_object_count(count)、set_total_object_count(count) |
| エクスポート設定 | set_polygon_mode(holes_mode, polygon_type) |
| 絞り込みアクセサー | filtered_layers(sort_order=SortOrder.Regular)、filtered_cells(layer=None) |
| 逐次列挙 | start_enum_layers(sort_order=SortOrder.Regular)、next_layer()、start_enum_cells()、next_cell(layer=None)、start_enum_fonts()、next_font() |
| 変換 | transform_point(point)、transform_distance(distance) |
layers と cells が一般的なケースで、filtered_layers(sort_order) と filtered_cells(layer) はそれらのプロパティが隠しているパラメーターを露出します——cell.shapes / cell.filtered_shapes と同じ組み合わせです。
from linkcad.v1.plugin import SortOrder
for layer in controller.filtered_layers(SortOrder.Reverse): for cell in controller.filtered_cells(layer): ...プッシュ側はフレームワークのもの
LinkCAD はジオメトリを 2 通りの方法でエクスポートします。プラグインが形状を引き出すか、コントローラーがレンダリング済みのエンティティをライターへ押し込むかです。フラット化できるのはプッシュ方向だけです。参照をたどって降下する際に構築される変換スタックを持っているのはコントローラーだけだからです——手動でプッシュ側を操作したプラグインは、配置情報のない形状を受け取り、それを知らせるエラーも出ません。
そのため _render_cell、_render_cell_in_layer_order、_flatten_cell_hierarchy、_get_shapes にはアンダースコアが付いています。これらはフレームワークのものであり、WriterContext が代わりに駆動します。drawing.flatten = True を設定して drawing.shapes() を反復してください。配置がすでに適用された、同じ走査です。
HolesMode と PolygonType は安定したプラグインモジュールから利用でき、WriterController.set_polygon_mode() で使用します。
from linkcad.v1.plugin import HolesMode, PolygonType
controller.set_polygon_mode(HolesMode.Link, PolygonType.AllowComplex)DialogSpec
DialogSpec は形式やツールのオプションダイアログを宣言的に記述します。Rust プラグインのダイアログモデルに対応しており、LinkCAD の UI が読み取る JSON 形式にシリアライズされます。
from linkcad.v1.plugin import DialogSpec, ChoiceItem
spec = ( DialogSpec("Import Options") .group("Geometry") .bool_field("merge", "Merge polygons", True) .int_field("facets", "Minimum facets", 4, 256, 32) .combo_field("units", "Units", ["nm", "um", "mm"], "um") .group_in_row("Layers", row=1) .single_select_list( "layer", "Layer", [ChoiceItem.with_display("metal1", "Metal 1")], ))
json_payload = spec.to_json()| 型 | 目的 |
|---|---|
DialogSpec(title) | 最上位のダイアログ記述子 |
DialogGroup(label, row=None) | 関連するフィールドのグループ。同じ row を持つグループは横並びに配置できます |
UiWidget(option_name, label, kind) | グループ内の単一の UI 要素 |
WidgetKind(kind_type, **kwargs) | ウィジェットの種類と設定 |
ChoiceItem(value, display, description=None) | リスト/コンボボックスの選択肢 |
| ビルダーメソッド | 説明 |
|---|---|
group(label) | グループを開始します |
group_in_row(label, row) | 指定行にグループを開始します |
bool_field(option_name, label, default) | チェックボックス |
int_field(option_name, label, min, max, default) | 整数スピンボックス |
real_field(option_name, label, min, max, default) | 小数スピンボックス |
string_field(option_name, label, default) | テキスト行 |
combo_field(option_name, label, choices, default) | 文字列からのコンボボックス |
single_select_list(option_name, label, static_choices=None, inspection_key=None) | 単一選択リスト |
multi_select_list(option_name, label, static_choices=None, inspection_key=None, value_separator=",") | 複数選択リスト |
note(text) | 表示専用の注記 |
separator() | 水平の区切り線 |
to_json() | JSON にシリアライズします |
ChoiceItem には simple(value)、with_display(value, display)、full(value, display, description) のファクトリーメソッドがあります。
形式メタデータ
リーダーとライターのデコレーターは、プラグインクラスに FormatInfo オブジェクトを付与します。より低レベルの形式制約には linkcad.v1.conv.Format と FormatAttributes を使用してください。linkcad.conv を参照してください。
from linkcad.v1.conv import Format, FormatAttributes
fmt = Format()fmt.attributes = FormatAttributes.LAYER_NAMES | FormatAttributes.CELL_NAMESfmt.layer_max_length = 32例外
| 例外 | 用途 |
|---|---|
PluginError | すべてのプラグインエラーの基底クラス |
ParseError | ファイル解析エラー。キーワード引数 line と path を受け取ります |
WriteError | ファイル書き込みエラー |
ValidationError | オプションの検証エラー |
TableColumn
テーブルオプションの列を定義するデータクラスです。
key: str— 辞書キーlabel: str— 列見出しcol_type: str—string、integer、real、choice、cell_choicedefault: Any— 既定値choices: list[str]—choice列向けdecimals: int—real列向けmin_value/max_value— 数値列向け
列挙型
| 列挙型 | 値 | 用途 |
|---|---|---|
Phase | ParsedFile、ParsedAll、ClosedOpenCells、ResolvedRefs、SelectedMainCell、ResolvedLayersByBlock、AutoNumberedZ | リーダー後処理のフェーズフック |
LayerFlags | Normal、ByLayer、ByBlock | DrawingBuilder.set_entity_layer_style() におけるレイヤー属性の継承 |
SortOrder | Regular、Reverse | WriterController のレイヤー列挙順 |
EndCap | Round、SquareExtended、SquareFlat | ビルダーでの形状作成用に linkcad.v1.db.EndCap を再エクスポート |
FillRule | NonZero、EvenOdd | ライターの塗りつぶし規則用に linkcad.v1.db.FillRule を再エクスポート |
ライターのポリゴンモード列挙型は linkcad.v1.plugin から利用できます。
| 列挙型 | 値 | 用途 |
|---|---|---|
HolesMode | Link、Split、Extract、Keep | ポリゴンエクスポート時の穴の表現方法 |
PolygonType | AllowComplex、ForceSimple | レンダリングされるポリゴンが複雑であってよいか |