Writing a Format Plugin
This tutorial shows how to add custom file format support to LinkCAD using Python.
Format Reader (Import)
A format reader converts an external file format into LinkCAD’s drawing database.
Example: Simple Coordinate File Reader
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): scale = Option.integer("Scale factor", default=1000, min=1, max=1000000) layer_name = Option.string("Layer name", default="imported")
def read(self, path: Path, drawing: DrawingContext) -> None: 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() x = float(parts[0]) * self.scale y = float(parts[1]) * self.scale vertices.append((x, y))
# Don't forget the last polygon if vertices: layer.polygon(vertices)Key Concepts
@format_reader()registers the class as an import formatextensionsdetermines which files the reader handlesDrawingContextprovides a builder API for creating cells, layers, and shapesdrawing.iter_lines()reads lines with automatic progress trackingdrawing.iter_binary()reads binary data with progress tracking
DrawingContext API
| Method | Description |
|---|---|
cell(name, main=False) | Context manager — creates/opens a cell |
iter_lines(path) | Iterate text file lines with progress |
iter_binary(path, chunk_size) | Iterate binary chunks with progress |
progress | Get/set progress (0.0 to 1.0) |
CellContext API
| Method | Description |
|---|---|
layer(name) | Context manager — selects a layer |
LayerContext API
| Method | Description |
|---|---|
polygon(vertices) | Create a polygon from (x, y) tuples |
polyline(width, vertices, closed) | Create a polyline |
circle(center, diameter) | Create a circle |
Format Writer (Export)
A format writer exports LinkCAD geometry to a file.
Example: Simple Text Writer
from pathlib import Pathfrom linkcad.v1.plugin import format_writer, FormatWriter, Option, WriterContext
@format_writer( name="Simple Text", extensions=["*.stxt"],)class SimpleWriter(FormatWriter): separator = Option.choice( "Separator", choices=["Space", "Comma", "Tab"], default="Space", ) precision = Option.integer("Decimal places", default=3, min=0, max=10)
def write(self, path: Path, drawing: WriterContext) -> None: sep = {"Space": " ", "Comma": ", ", "Tab": "\t"}[self.separator]
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")WriterContext API
| Method | Description |
|---|---|
shapes(cell, layer) | Iterate all shapes (optional cell/layer filter) |
shapes_by_layer(cell) | Iterate shapes grouped by layer |
shapes_by_cell(layer) | Iterate shapes grouped by cell |
cells() | Iterate cell names |
layers() | Iterate layer names |
cell_count() | Number of cells |
shape_count() | Total number of shapes |
main_cell_name() | Name of the top cell |
layer_names() | List of all layer names |
flatten | Get/set hierarchy flattening |
progress | Get/set progress (0.0 to 1.0) |
ShapeInfo Properties
| Property | Type | Description |
|---|---|---|
layer_name | str | Layer name |
cell_name | str | Cell name |
vertices | list[tuple] | List of (x, y) coordinates |
is_polygon | bool | True for polygons, False for polylines |
width | int | Polyline width (0 for polygons) |
is_closed | bool | Whether the shape is closed |
Error Handling
Use the built-in exception classes for clear error reporting:
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")Next Steps
- Panel Assembly Tutorial — advanced tool using table options
- Format Decorators Reference — complete decorator API