Layout¶
Diagram layout engine for positioning devices and routing wires.
New in v0.15.0: The layout system has been refactored into a modular package structure for better maintainability:
layout.engine- MainLayoutEngineorchestratorlayout.positioning-DevicePositionerfor multi-tier device placementlayout.routing-WireRouterfor smooth Bezier curve routinglayout.sizing-CanvasSizerfor calculating canvas dimensionslayout.types-LayoutConfig,LayoutResult, and constantslayout.utils- Utility functions (e.g.,create_bezier_path)
The public API remains unchanged - import from pinviz.layout as before.
layout ¶
Layout engine for positioning components and routing wires.
This package provides modular layout functionality split into focused components: - types: Layout data types and configuration - engine: Main LayoutEngine orchestrator - positioning: Device positioning logic - routing: Wire routing logic - sizing: Canvas size calculation - utils: Utility functions (create_bezier_path)
For backward compatibility, all public classes are re-exported at the package level.
CanvasSizer ¶
Calculates canvas dimensions to fit all diagram components.
Determines the minimum canvas size needed to display the board, all devices, all wire paths, and optional legend/GPIO diagram without clipping or overlap.
Initialize canvas sizer.
| PARAMETER | DESCRIPTION |
|---|---|
config
|
Layout configuration parameters
TYPE:
|
board_margin_top
|
Top margin for the board
TYPE:
|
Source code in src/pinviz/layout/sizing.py
calculate_canvas_size ¶
Calculate required canvas size to fit all components.
Determines the minimum canvas dimensions needed to display the board, all devices, all wire paths, and optional legend/GPIO diagram without clipping or overlap. Accounts for multi-tier device layouts.
| PARAMETER | DESCRIPTION |
|---|---|
diagram
|
The diagram containing board, devices, and configuration
TYPE:
|
routed_wires
|
List of wires with calculated routing paths
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
tuple[float, float]
|
Tuple of (canvas_width, canvas_height) in SVG units |
Note
Adds extra margin for the legend and GPIO reference diagram if enabled.
Source code in src/pinviz/layout/sizing.py
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | |
DevicePositioner ¶
Positions devices across horizontal tiers based on connection depth.
Handles multi-tier layout where devices are arranged in columns (tiers) based on their hierarchical level in the connection graph. Within each tier, devices are stacked vertically with smart positioning based on their pin connections.
Initialize device positioner.
| PARAMETER | DESCRIPTION |
|---|---|
config
|
Layout configuration parameters
TYPE:
|
board_margin_top
|
Top margin for the board
TYPE:
|
Source code in src/pinviz/layout/positioning.py
position_devices ¶
Position all devices in the diagram across horizontal tiers.
Calculates device levels from connection graph, assigns X positions for each tier, then positions devices vertically within each tier.
| PARAMETER | DESCRIPTION |
|---|---|
diagram
|
The diagram containing devices and connections
TYPE:
|
Note
This method mutates the position attribute of each device.
Source code in src/pinviz/layout/positioning.py
LayoutConfig
dataclass
¶
LayoutConfig(
board_margin_left: float = 40.0,
board_margin_top_base: float = 40.0,
title_height: float = 40.0,
title_margin: float = 50.0,
device_area_left: float = 450.0,
device_spacing_vertical: float = 20.0,
device_margin_top: float = 60.0,
rail_offset: float = 40.0,
wire_spacing: float = 8.0,
bundle_spacing: float = 4.0,
corner_radius: float = 5.0,
canvas_padding: float = 40.0,
legend_margin: float = 20.0,
legend_width: float = 150.0,
legend_height: float = 120.0,
pin_number_y_offset: float = 12.0,
gpio_diagram_width: float = 125.0,
gpio_diagram_margin: float = 40.0,
specs_table_top_margin: float = 30.0,
tier_spacing: float = 200.0,
min_canvas_width: float = 400.0,
min_canvas_height: float = 300.0,
max_canvas_width: float = 5000.0,
max_canvas_height: float = 3000.0,
warn_connections: int = 30,
warn_devices: int = 20,
max_connections: int | None = None,
max_devices: int | None = None,
)
Configuration parameters for diagram layout.
Controls spacing, margins, and visual parameters for the diagram layout engine. All measurements are in SVG units (typically pixels).
| ATTRIBUTE | DESCRIPTION |
|---|---|
board_margin_left |
Left margin before board (default: 40.0)
TYPE:
|
board_margin_top_base |
Base top margin before board (default: 80.0)
TYPE:
|
title_height |
Height reserved for title text (default: 40.0)
TYPE:
|
title_margin |
Margin below title before wires can start (default: 50.0)
TYPE:
|
device_area_left |
X position where devices start (default: 450.0)
TYPE:
|
device_spacing_vertical |
Vertical space between stacked devices (default: 20.0)
TYPE:
|
device_margin_top |
Top margin for first device (default: 60.0)
TYPE:
|
rail_offset |
Horizontal distance from board to wire routing rail (default: 40.0)
TYPE:
|
wire_spacing |
Minimum vertical spacing between parallel wires (default: 8.0)
TYPE:
|
bundle_spacing |
Spacing between wire bundles (default: 4.0)
TYPE:
|
corner_radius |
Radius for wire corner rounding (default: 5.0)
TYPE:
|
canvas_padding |
Uniform padding around all content (default: 40.0)
TYPE:
|
legend_margin |
Margin around legend box (default: 20.0)
TYPE:
|
legend_width |
Width of legend box (default: 150.0)
TYPE:
|
legend_height |
Height of legend box (default: 120.0)
TYPE:
|
pin_number_y_offset |
Vertical offset for pin number circles (default: 12.0)
TYPE:
|
gpio_diagram_width |
Width of GPIO reference diagram (default: 125.0)
TYPE:
|
gpio_diagram_margin |
Margin around GPIO reference diagram (default: 40.0)
TYPE:
|
specs_table_top_margin |
Margin above specs table from bottom element (default: 30.0)
TYPE:
|
tier_spacing |
Horizontal spacing between device tiers (default: 200.0)
TYPE:
|
min_canvas_width |
Minimum canvas width (default: 400.0)
TYPE:
|
min_canvas_height |
Minimum canvas height (default: 300.0)
TYPE:
|
max_canvas_width |
Maximum canvas width (default: 5000.0)
TYPE:
|
max_canvas_height |
Maximum canvas height (default: 3000.0)
TYPE:
|
warn_connections |
Threshold for connection count warning (default: 30)
TYPE:
|
warn_devices |
Threshold for device count warning (default: 20)
TYPE:
|
max_connections |
Hard limit for connection count, None = unlimited (default: None)
TYPE:
|
max_devices |
Hard limit for device count, None = unlimited (default: None)
TYPE:
|
get_board_margin_top ¶
Calculate actual board top margin based on whether title is shown.
Source code in src/pinviz/layout/types.py
LayoutConstants
dataclass
¶
LayoutConstants(
Y_POSITION_TOLERANCE: float = 50.0,
FROM_Y_POSITION_TOLERANCE: float = 100.0,
RAIL_SPACING_MULTIPLIER: float = 3.0,
VERTICAL_SPACING_MULTIPLIER: float = 4.5,
MIN_SEPARATION_MULTIPLIER: float = 1.5,
SAMPLE_POSITIONS: tuple[float, ...] = (
0.0,
0.25,
0.5,
0.75,
1.0,
),
CONFLICT_ADJUSTMENT_DIVISOR: float = 2.0,
MAX_ADJUSTMENT: float = 50.0,
STRAIGHT_SEGMENT_LENGTH: float = 15.0,
WIRE_PIN_EXTENSION: float = 2.0,
SIMILAR_Y_THRESHOLD: float = 50.0,
GENTLE_ARC_CTRL1_RAIL_RATIO: float = 0.3,
GENTLE_ARC_CTRL1_START_RATIO: float = 0.7,
GENTLE_ARC_CTRL1_OFFSET_RATIO: float = 0.8,
GENTLE_ARC_CTRL2_RAIL_RATIO: float = 0.7,
GENTLE_ARC_CTRL2_END_RATIO: float = 0.3,
GENTLE_ARC_CTRL2_OFFSET_RATIO: float = 0.3,
S_CURVE_CTRL1_RATIO: float = 0.4,
S_CURVE_CTRL1_OFFSET_RATIO: float = 0.9,
S_CURVE_CTRL2_RATIO: float = 0.4,
S_CURVE_CTRL2_OFFSET_RATIO: float = 0.3,
)
Algorithm constants for wire routing and path calculation.
These constants control the behavior of the wire routing algorithm, including grouping, spacing, and curve generation. They are separate from LayoutConfig as they represent algorithmic tuning parameters rather than user-configurable layout settings.
LayoutEngine ¶
Calculate positions and wire routing for diagram components.
The layout engine orchestrates the algorithmic placement of devices and routing of wires between board pins and device pins. It coordinates three specialized components: - DevicePositioner: Handles device placement across tiers - WireRouter: Routes wires with smooth curves - CanvasSizer: Calculates canvas dimensions
Wire routing features
- Automatic offset for parallel wires from the same pin
- Rounded corners for professional appearance
- Multiple routing styles (orthogonal, curved, mixed)
- Optimized path calculation to minimize overlaps
Initialize layout engine with optional configuration.
| PARAMETER | DESCRIPTION |
|---|---|
config
|
Layout configuration parameters. If None, uses default LayoutConfig.
TYPE:
|
Source code in src/pinviz/layout/engine.py
layout_diagram ¶
Calculate layout for a complete diagram.
Returns a LayoutResult containing all layout information including canvas dimensions, device positions, and routed wires. This immutable result can be passed to the renderer without further diagram mutation.
| PARAMETER | DESCRIPTION |
|---|---|
diagram
|
The diagram to layout
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
LayoutResult
|
LayoutResult with complete layout information |
Note
For backward compatibility, this method still mutates device.position on the diagram's devices. Future versions will remove this mutation.
Source code in src/pinviz/layout/engine.py
validate_layout ¶
Validate calculated layout for issues.
Checks for: - Device overlaps - Devices positioned at negative coordinates - Devices extending beyond canvas bounds
| PARAMETER | DESCRIPTION |
|---|---|
diagram
|
The diagram with positioned devices
TYPE:
|
canvas_width
|
Canvas width
TYPE:
|
canvas_height
|
Canvas height
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[str]
|
List of validation warnings/errors (empty if no issues) |
Source code in src/pinviz/layout/engine.py
LayoutResult
dataclass
¶
LayoutResult(
canvas_width: float,
canvas_height: float,
board_position: Point,
device_positions: dict[str, Point],
routed_wires: list[RoutedWire],
board_margin_top: float,
)
Complete layout information for a diagram.
Contains all calculated layout data including canvas dimensions, positioned devices, and routed wires. This is the immutable output of the layout engine that gets passed to the renderer.
This decouples layout calculation from rendering, enabling: - Independent testing of layout logic - Alternative layout algorithms - Layout result caching - Thread-safe parallel rendering
| ATTRIBUTE | DESCRIPTION |
|---|---|
canvas_width |
Calculated canvas width in SVG units
TYPE:
|
canvas_height |
Calculated canvas height in SVG units
TYPE:
|
board_position |
Absolute position of the board on canvas
TYPE:
|
device_positions |
Mapping of device names to their absolute positions
TYPE:
|
routed_wires |
List of wires with calculated routing paths
TYPE:
|
board_margin_top |
Top margin of the board (needed for pin positioning)
TYPE:
|
RoutedWire
dataclass
¶
RoutedWire(
connection: Connection,
path_points: list[Point],
color: str,
from_pin_pos: Point,
to_pin_pos: Point,
)
A wire connection with calculated routing path.
Contains the complete routing information for a wire, including all waypoints along its path. This is the result of the layout engine's wire routing algorithm.
| ATTRIBUTE | DESCRIPTION |
|---|---|
connection |
The original connection specification
TYPE:
|
path_points |
List of points defining the wire path (min 2 points)
TYPE:
|
color |
Wire color as hex code (from connection or auto-assigned)
TYPE:
|
from_pin_pos |
Absolute position of source pin on board
TYPE:
|
to_pin_pos |
Absolute position of destination pin on device
TYPE:
|
WireData
dataclass
¶
WireData(
connection: Connection,
from_pos: Point,
to_pos: Point,
color: str,
device: Device,
source_device: Device | None = None,
is_source_right_side: bool = False,
is_target_right_side: bool = False,
)
Intermediate wire data collected during routing.
Stores all information needed to route a single wire before path calculation. Used internally by the layout engine during the wire routing algorithm.
| ATTRIBUTE | DESCRIPTION |
|---|---|
connection |
The original connection specification
TYPE:
|
from_pos |
Absolute position of source pin on board
TYPE:
|
to_pos |
Absolute position of destination pin on device
TYPE:
|
color |
Wire color as hex code (from connection or auto-assigned)
TYPE:
|
device |
The target device for this wire
TYPE:
|
source_device |
The source device (None for board-to-device connections)
TYPE:
|
is_source_right_side |
True if source pin is on right side of device
TYPE:
|
is_target_right_side |
True if target pin is on right side of device
TYPE:
|
WireRouter ¶
Routes wires between board pins and device pins.
Implements device-based routing lanes where each device gets its own vertical "rail" for routing wires. This prevents wire crossings and maintains visual clarity similar to Fritzing diagrams.
Features: - Automatic offset for parallel wires from the same pin - Smooth Bezier curves for professional appearance - Conflict detection and resolution - Support for device-to-device connections
Initialize wire router.
| PARAMETER | DESCRIPTION |
|---|---|
config
|
Layout configuration parameters
TYPE:
|
board_margin_left
|
Left margin for the board
TYPE:
|
board_margin_top
|
Top margin for the board
TYPE:
|
Source code in src/pinviz/layout/routing.py
route_wires ¶
Route all wires using device-based routing lanes to prevent crossings.
This is the main wire routing orchestration method. It coordinates the multi-step routing algorithm: 1. Collect wire data (pins, positions, colors) 2. Sort wires for optimal visual flow 3. Group wires by starting position for offset calculation 4. Assign routing rails to each device 5. Calculate initial wire paths with offsets 6. Detect and resolve any remaining conflicts 7. Generate final routed wires
Strategy: - Assign each device a vertical routing zone based on its Y position - Wires to the same device route through that device's zone - Wires to different devices use different zones, preventing crossings - Similar to Fritzing's approach where wires don't cross
| PARAMETER | DESCRIPTION |
|---|---|
diagram
|
The diagram containing all connections, board, and devices
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[RoutedWire]
|
List of RoutedWire objects with calculated paths |
Source code in src/pinviz/layout/routing.py
create_bezier_path ¶
Create an SVG path string with smooth Bezier curves.
Creates organic, flowing curves through the points using cubic Bezier curves, similar to the classic Fritzing diagram style.
| PARAMETER | DESCRIPTION |
|---|---|
points
|
List of points defining the path (including control points)
TYPE:
|
corner_radius
|
Not used, kept for API compatibility
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
str
|
SVG path d attribute string with smooth curves |