Migrating to v2.12 ================== Version 2.12 is the **electrical-harness release**: routed cables can now be consolidated into a single optimizable harness (:doc:`harness_generation`). Existing routing code keeps working — the breaking points are the ``CadMap`` voxelization API, the ``Pack`` API and a handful of removed helpers. Most projects only need the ``voxel_inside`` and ``revoxelize`` fixes below. .. contents:: On this page :local: :depth: 1 New: harness generation ----------------------- The headline addition. One call routes, bundles and optimizes: .. code-block:: python from routing.core.harness import HarnessSettings bundle, history = route_planner.generate_harness(specifications, HarnessSettings()) Nothing in your existing pipeline changes — ``generate`` and ``optimize`` behave as before. See :doc:`harness_generation` for the pipeline, its settings and its results. ``pymoo`` and ``scikit-image`` are new dependencies --------------------------------------------------- The harness optimizer runs on **pymoo** (≥ 0.6) and the skeletonization on **scikit-image**. Both are declared as core dependencies, so ``pip install -U routing`` pulls them in. Only projects that pin their transitive dependency set need to act. ``voxel_inside`` was removed from ``CadMap.from_project_inputs`` ---------------------------------------------------------------- Inside-solid routing is declared where the geometry is declared — on the volume, not on the cadmap. ``RuledVolume.from_volume_model(..., voxel_inside=True)`` is unchanged; the cadmap parameter is gone: .. code-block:: python # Before (v2.11) cadmap = CadMap.from_project_inputs( design_rules=[...], ruled_volumes=[volume], voxel_size=0.02, voxel_inside=True ) .. code-block:: python # After (v2.12) volume = RuledVolume.from_volume_model(volume_model, design_rules=[...], voxel_inside=True) cadmap = CadMap.from_project_inputs( design_rules=[...], ruled_volumes=[volume], voxel_size=0.02 ) See :doc:`../tutorials/routing_inside_volume`. ``to_matrix_based_voxelization`` is now ``revoxelize`` ------------------------------------------------------ Re-voxelizing a cadmap at another resolution is one call, and it returns a :class:`~routing.core.voxels.RoomVoxelization`: .. code-block:: python # Before (v2.11) voxelization = cadmap.to_matrix_based_voxelization(voxel_size=0.01) .. code-block:: python # After (v2.12) voxelization = cadmap.revoxelize(voxel_size=0.01) Two related moves: - Room voxelization itself now belongs to the volume: ``RuledVolume.voxelize_room(...)``. - ``CadMap.update_weights(...)`` is public — reapplying the design rules to the grid no longer means calling a private method. ``RoomVoxelization`` moved to ``routing.core.voxels`` ----------------------------------------------------- The voxel types live in their own module together with ``VoxelVolume``: .. code-block:: python # Before (v2.11) from routing.core.core import RoomVoxelization .. code-block:: python # After (v2.12) from routing.core.voxels import RoomVoxelization The old import still resolves through a deprecated subclass in ``routing.core.core``, so existing code will not break immediately — update it anyway. ``Pack`` construction and stamping changed ------------------------------------------ Packs (the pooled groups returned by ``collect_packs``) were reworked around a fitted cluster axis. Reading a pack is unchanged; **building or stamping one** is not: .. list-table:: :header-rows: 1 :widths: 45 55 * - Before (v2.11) - After (v2.12) * - ``Pack(pipe_lines, vector, crossed_voxels=..., parallel=True)`` - ``Pack(pipe_lines, vector, axis)`` — the tray policy is now a subclass, ``ParallelPack``; ``Pack.from_pipe_line(..., parallel=True)`` dispatches to it * - ``pack.update_coefficients(...)`` + ``pack.update_forbidden_voxels(...)`` - ``pack.stamp(coefficients, forbidden_voxels, pipe_type, pooling_rule, room_voxels, clearance_at)`` — one pass writing both * - ``pack.center_fixed``, ``pack.point_in_bbox``, ``pack.contains_point``, ``pack.point_in_cylinder`` - Removed. Distances are taken to the pack axis; there is no per-voxel containment test left to call * - ``pack.get_axis_voxels(room_voxels)`` - Same contract (voxel 4-tuple → representative 4-tuple), re-derived from the occupancy tube. The historical dictionary-based version stays on ``ParallelPack`` Removed helpers --------------- These methods had no remaining caller inside routing and were deleted. None of them has a one-line replacement; if you relied on one, the geometry it computed is available through the cadmap's voxel and distance fields. .. list-table:: :header-rows: 1 :widths: 40 60 * - Removed - Notes * - ``CadMap.is_point_in_voxels`` - Query the room voxelization directly. * - ``CadMap.to_graph`` / ``CadMap.to_trimesh`` - The routing graph is built by the finders; meshes come from volmdlr. * - ``CadMap.crop_with_bounding_box`` / ``CadMap.crop_and_upscale`` - Cropping is internal to the optimizer windows (``Bundle.attach_local_cadmaps``) and to ``CadMap.from_project_inputs(crop_point=...)``. * - ``CadMap.radii_in_voxel`` - The per-voxel radii cache is gone with the generic pack's per-voxel machinery. * - ``RuledVolume.empty_duplicate`` - Build the volume you need with ``RuledVolume.from_volume_model``. * - ``PipeLine.contains_point_projection`` - Use the pack axis abscissa or ``CadMap.clearance_along``. Behaviour changes without an API change --------------------------------------- Code that compiles unchanged but may produce different numbers: - ``WeightingRule`` **lost its** ``offset`` **parameter** and no longer freezes its calibration on the first distance field it weights: ``coeff`` is recomputed per field, so one rule instance shared by several volumes now calibrates correctly on each. An explicit ``0`` for ``min_value`` / ``max_length`` is honored instead of being replaced by a fallback, and a degenerate band yields a flat ``min_value`` with a warning instead of an infinite slope. - ``ShapedWeightingRule`` **containment is voxel-overlap based** — the shape is voxelized filled on the room lattice instead of being tested with a signed-distance query at each voxel centre. Robust on the non-watertight tessellations that defeated the old test; membership right at a zone boundary can differ. - ``Solution`` **equality is identity** — two cables with identical specifications are two physical cables, so ``==`` and ``data_eq`` no longer report them as equal. Code that de-duplicated solutions by value now keeps both. - ``Solution.input_length`` / ``output_length`` / ``min_straight_length`` **are plain floats defaulting to** ``0.0`` — an explicit ``0`` is honored instead of being coalesced to a fallback length. - **Pooling fields on oblique runs** — a pack whose axis leaves the grid directions no longer crenellates its influence field, so cables that used to thread between the "merlons" of a quasi-45° pack are now pooled as intended. Also new in v2.12 ----------------- - **Cadmap steering and replay** — ``CadMap.repel_zone`` / ``withdraw_zones`` add and remove a repulsive zone over a shape; ``remove_solutions`` / ``restore_solutions`` rebuild the pack state from a recorded solution set. This is what the harness unlock stage uses, and what makes a run replayable (see :doc:`harness_generation`). - **Continuous clearance API** — ``CadMap.cad_distance_field``, ``clearance_at``, ``clearance_along``, ``traversed_weights``: distance to CAD and traversed weights at any world position, not only at voxel centres. - **Cropped cadmaps** — ``CadMap.from_project_inputs(crop_point=...)`` keeps only the navigable component containing that point, which cuts memory on large assemblies. - **Design rules reach the harness** — a rule can constrain the bundled geometry through ``evaluate_on_bundle`` and declare its form with ``RuleEnforcement``; see :ref:`design-rules-on-the-harness`. See Also -------- - :doc:`harness_generation` — the new pipeline in full - :doc:`installation` — updated dependency list - :doc:`migration_v2_11` — the previous upgrade note