From 556241bae3cf533b4305144a64f06c344ec68498 Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Sun, 8 Mar 2026 22:18:33 -0700 Subject: [PATCH] more bend-related work --- DOCS.md | 25 ++++++++++++ examples/04_sbends_and_radii.py | 1 - examples/sbends_radii.png | Bin 40027 -> 39585 bytes inire/tests/test_components.py | 68 +++++++++++++++++++++++++++++++- 4 files changed, 92 insertions(+), 2 deletions(-) diff --git a/DOCS.md b/DOCS.md index fe585ea..4b0b693 100644 --- a/DOCS.md +++ b/DOCS.md @@ -51,3 +51,28 @@ The `CostEvaluator` defines the "goodness" of a path. - **Coordinates**: Micrometers (µm). - **Grid Snapping**: The router internally operates on a **1nm** grid for final ports and a **1µm** lattice for expansion moves. - **Search Space**: Assumptions are optimized for design areas up to **20mm x 20mm**. + +--- + +## 5. Best Practices & Tuning Advice + +### Speed vs. Optimality +The `greedy_h_weight` is your primary lever for search performance. +- **`1.0`**: Dijkstra-like behavior. Guarantees the shortest path but is very slow. +- **`1.1` to `1.2`**: Recommended range. Balances wire length with fast convergence. +- **`> 1.5`**: Extremely fast "greedy" search. May produce zig-zags or suboptimal detours. + +### Avoiding "Zig-Zags" +If the router produces many small bends instead of a long straight line: +1. Increase `bend_penalty` (e.g., set to `100.0` or higher). +2. Ensure `straight_lengths` includes larger values like `25.0` or `100.0`. +3. Decrease `greedy_h_weight` closer to `1.0`. + +### Handling Congestion +In multi-net designs, if nets are overlapping: +1. Increase `congestion_penalty` in `CostEvaluator`. +2. Increase `max_iterations` in `PathFinder`. +3. If a solution is still not found, check if the `clearance` is physically possible given the design's narrowest bottlenecks. + +### S-Bend Usage +Parametric S-bends are triggered by the `sbend_offsets` list. If you need a specific lateral shift (e.g., 5.86µm for a 45° switchover), add it to `sbend_offsets`. The router will only use an S-bend if it can reach a state that is exactly on the lattice or the target. diff --git a/examples/04_sbends_and_radii.py b/examples/04_sbends_and_radii.py index 2234878..44c3d46 100644 --- a/examples/04_sbends_and_radii.py +++ b/examples/04_sbends_and_radii.py @@ -3,7 +3,6 @@ from shapely.geometry import Polygon from inire.geometry.collision import CollisionEngine from inire.geometry.primitives import Port from inire.router.astar import AStarRouter -from inire.router.config import CostConfig, RouterConfig from inire.router.cost import CostEvaluator from inire.router.danger_map import DangerMap from inire.router.pathfinder import PathFinder diff --git a/examples/sbends_radii.png b/examples/sbends_radii.png index 1a8f9c59c73c25f70b8bb4b4f6c0c46013bd71d7..a736212c547e1b4783f60933ff4568327cc8fa69 100644 GIT binary patch literal 39585 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 literal 40027 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 diff --git a/inire/tests/test_components.py b/inire/tests/test_components.py index ffb43a4..37da884 100644 --- a/inire/tests/test_components.py +++ b/inire/tests/test_components.py @@ -1,7 +1,9 @@ +import numpy as np import pytest +from shapely.geometry import Point from inire.geometry.components import Bend90, SBend, Straight -from inire.geometry.primitives import Port +from inire.geometry.primitives import Port, rotate_port, translate_port def test_straight_generation() -> None: @@ -90,3 +92,67 @@ def test_sbend_collision_models() -> None: res_arc = SBend.generate(start, offset, radius, width, collision_type="arc") assert res_bbox.geometry[0].area > res_arc.geometry[0].area + + +def test_sbend_continuity() -> None: + # Verify SBend endpoints and continuity math + start = Port(10, 20, 90) # Starting facing up + offset = 4.0 + radius = 20.0 + width = 1.0 + + res = SBend.generate(start, offset, radius, width) + + # Target orientation should be same as start + assert abs(res.end_port.orientation - 90.0) < 1e-6 + + # For a port at 90 deg, +offset is a shift in -x direction + assert abs(res.end_port.x - (10.0 - offset)) < 1e-6 + + # Geometry should be connected (unary_union results in 1 polygon) + assert len(res.geometry) == 1 + assert res.geometry[0].is_valid + + +def test_arc_sagitta_precision() -> None: + # Verify that requested sagitta actually controls segment count + start = Port(0, 0, 0) + radius = 100.0 # Large radius to make sagitta significant + width = 2.0 + + # Coarse: 1um sagitta + res_coarse = Bend90.generate(start, radius, width, sagitta=1.0) + # Fine: 0.01um (10nm) sagitta + res_fine = Bend90.generate(start, radius, width, sagitta=0.01) + + # Number of segments should be significantly higher for fine + # Exterior points = (segments + 1) * 2 + pts_coarse = len(res_coarse.geometry[0].exterior.coords) + pts_fine = len(res_fine.geometry[0].exterior.coords) + + assert pts_fine > pts_coarse * 2 + + +def test_component_transform_invariance() -> None: + # Verify that generating at (0,0) then transforming + # is same as generating at the transformed port. + start0 = Port(0, 0, 0) + radius = 10.0 + width = 2.0 + + res0 = Bend90.generate(start0, radius, width, direction="CCW") + + # Transform: Translate (10, 10) then Rotate 90 + dx, dy = 10.0, 5.0 + angle = 90.0 + + # 1. Transform the generated geometry + p_end_transformed = rotate_port(translate_port(res0.end_port, dx, dy), angle) + + # 2. Generate at transformed start + start_transformed = rotate_port(translate_port(start0, dx, dy), angle) + res_transformed = Bend90.generate(start_transformed, radius, width, direction="CCW") + + assert abs(res_transformed.end_port.x - p_end_transformed.x) < 1e-6 + assert abs(res_transformed.end_port.y - p_end_transformed.y) < 1e-6 + assert abs(res_transformed.end_port.orientation - p_end_transformed.orientation) < 1e-6