User Guide: Multi-Scale and Multi-Grid Routing#
For large or complex assemblies you can split the routing space into multiple CadMap grids. This gives you two capabilities:
Multi-scale routing: one coarse grid for open space + one or more fine grids near critical areas. Faster voxelization while preserving accuracy where it matters.
Multi-grid routing (mono-scale): decompose the routing space into independent sub-regions and route pipes across them. Useful for very large assemblies that would exhaust memory as a single grid.
Both scenarios use MultiCadMap as the routing container
and pass it to RoutePlanner exactly like a regular
CadMap.
MultiCadMap#
MultiCadMap is a container for a list of
CadMap objects. The router treats them as a unified space
with implicit connections at shared boundaries.
from routing.core.cadmap import MultiCadMap
Key properties:
multi_cadmap.main_cadmap— the primary grid (cad_maps[0])multi_cadmap.voxel_sizes— set of unique voxel sizes (length > 1 → multi-scale)multi_cadmap.nbytes— total memory across all gridsmulti_cadmap.is_multi_scale—Trueif grids have different voxel sizes
Creating a MultiCadMap#
Three factory methods are available:
1. From an existing CadMap (most common):
from routing.core.cadmap import CadMap, MultiCadMap
# Build a regular CadMap first
cadmap = CadMap.from_project_inputs(
design_rules=design_rules,
ruled_volumes=[outer_volume, border_volume],
bounding_box=bounding_box,
voxel_size=0.021,
exact_distances=True,
)
# Wrap it into a MultiCadMap (mono-scale: auto-decompose into sub-regions)
multi_cadmap = MultiCadMap.from_cad_map(cadmap, multi_scale=False)
# Or: multi-scale (adds a finer grid at size_factor× resolution)
multi_cadmap = MultiCadMap.from_cad_map(
cadmap,
multi_scale=True,
size_factor=3, # fine grid = voxel_size / 3 ≈ 7 mm
bounding_box=cadmap.bounding_box.bounding_box,
)
Parameters of from_cad_map:
Parameter |
Default |
Description |
|---|---|---|
|
required |
The existing |
|
|
If |
|
|
Resolution multiplier for the fine grid ( |
|
|
Optional bounding box to restrict fine-grid creation. Pass
|
2. Directly from project inputs (combines CadMap.from_project_inputs and wrapping):
multi_cadmap = MultiCadMap.from_project_inputs(
design_rules=design_rules,
ruled_volumes=[outer_volume, border_volume],
bounding_box=bounding_box,
voxel_size=0.021,
exact_distances=True,
multi_scale=True,
size_factor=3,
)
3. From a list of pre-built CadMaps (same voxel size required):
multi_cadmap = MultiCadMap.from_cad_maps([cadmap_region_A, cadmap_region_B])
All CadMaps in the list must share the same voxel_size.
Using MultiCadMap with RoutePlanner#
Pass a MultiCadMap to RoutePlanner exactly like
a single CadMap:
from routing.core.finders import SmartFinder
from routing.core.route_planner import RoutePlanner
finder = SmartFinder("AStar", "manhattan", "never")
route_planner = RoutePlanner(multi_cadmap, finder)
result = route_planner.generate(specifications=specifications, n_iterations=1)
Visualizing the Multi-Grid Layout#
You can inspect the grid decomposition before routing:
from volmdlr.model import VolumeModel
# Show all sub-grid boundaries and their connections
VolumeModel(multi_cadmap.voxel_meshes(show_connections=True)).babylonjs()
Complete Multi-Scale Example#
from volmdlr.model import VolumeModel
from volmdlr.step import Step
from routing.core.cadmap import CadMap, MultiCadMap
from routing.core.core import Port, PipeType, RuledVolume, Specification
from routing.core.design_rules import TurnPenalizer, WeightingRule
from routing.core.finders import SmartFinder
from routing.core.optimizer import Costs, Settings
from routing.core.route_planner import RoutePlanner
from piping_3d import piping
# --- Load CAD ---
model = Step.from_file("data/step/Cas_test_windows_V5.step")
volume_model = model.to_volume_model()
weighting_rule = WeightingRule("linear", 0.0, 0.2, min_value=1, max_value=10)
outer_volume = RuledVolume.from_volume_model(
VolumeModel([volume_model.primitives[1]]), [weighting_rule], name="outer"
)
border_volume = RuledVolume.from_volume_model(
VolumeModel([volume_model.primitives[0]]), [weighting_rule], name="border"
)
# --- Build coarse CadMap ---
voxel_size = 0.021
bounding_box = CadMap.build_bounding_volume(
[outer_volume, border_volume], [], voxel_size, voxel_margin=1
)
cadmap = CadMap.from_project_inputs(
design_rules=[TurnPenalizer(cost=3.0)],
ruled_volumes=[outer_volume, border_volume],
bounding_box=bounding_box,
voxel_size=voxel_size,
exact_distances=True,
weights_operator="min_distance",
)
# --- Wrap into multi-scale MultiCadMap ---
multi_cadmap = MultiCadMap.from_cad_map(
cadmap,
multi_scale=True,
size_factor=3, # adds a ~7 mm fine grid
bounding_box=cadmap.bounding_box.bounding_box,
)
# --- Route ---
pipe_type = PipeType(
section=piping.Section(radius_equivalent=0.015),
name="PipeA",
radius_of_curvature_ratio_min=1.5,
color=(0, 150, 200),
type_="TypeA",
)
spec = Specification(
Port((0.05, -0.4, 0.1), (0, 1, 0), length=0.1),
Port((0.05, 0.8, 0.1), (0, -1, 0), length=0.1),
pipe_type, "route_A",
)
route_planner = RoutePlanner(multi_cadmap, SmartFinder("AStar", "manhattan", "never"))
result = route_planner.generate(specifications=[spec], n_iterations=1)
# --- Optimize ---
costs = Costs(length=1000, sideways=100, short_line=5000, gravity=5000,
bend=250, constraints=5000, interferences=1e8)
settings = Settings(voxel_size=0.006, max_shift=0.1, stabilization_threshold=1.0,
n_iterations=3, max_iter=1000)
result = route_planner.optimize(costs=costs, settings=settings, picked_path="best")
result.specific_packs_cad_view(result.collect_packs(only_optimized=True))
When to Use Multi-Scale vs Multi-Grid#
Scenario |
Recommended approach |
Why |
|---|---|---|
Large assembly, uniform complexity |
|
Auto-decomposes into sub-regions; no memory explosion |
Assembly with a few critical tight spots |
|
Coarse grid for open space, fine grid for tight areas |
Assembly with distinct disconnected zones |
|
Build separate CadMaps per zone; combine manually |
Single small assembly |
Plain |
Simpler; |
Next Steps#
Tutorial: Routing Pipes Through a CAD Assembly — full routing tutorial with a single CadMap
User Guide: Path Geometry Optimization — tune the geometry optimizer
User Guide: Pipe Pooling (Bundling) — pipe bundling across multi-grid setups