Skip to content

Inter-section dispatch table

Inter-section edges, running port or junction to port or junction, are routed by _route_inter_section in routing/inter_section_handlers.py. It chooses the route’s shape from a declarative table, _INTER_SECTION_RULES, rather than from a hand-written if-ladder. Before emission, every inter-section member is classified from one _InterFacts snapshot. The route system freezes that family ID, calls the family once to build an immutable RouteMemberGeometryPlan, then emits a fresh copy of that exact template. Production never takes a second pass through this table.

Every rule’s handler builds its route from a centerline through the bundle builder, meaning build_concentric_bundle or build_tapered_bundle. No handler assembles per-line points or corner radii by hand. The runtime curve guard is a backstop rather than the mechanism that keeps the routes correct.

_InterFacts resolves the geometry and topology each rule keys on:

  • Relative position: the source and target grid columns and rows (src_col/row, tgt_col/row), plus the derived same_y, same_x, same_col, cross_row, and needs_bypass. The last of these means a multi-column hop with an intervening section in the source or target row.
  • Exit side: whether the source is a LEFT or RIGHT exit port, a TOP or BOTTOM perpendicular exit (is_perp_exit), a TB BOTTOM exit (is_tb_bottom_exit, or is_tb_perp_exit_against_flow when it feeds an entry the flow-direction drop cannot reach), or a junction.
  • Entry side: entry_side is the target entry port’s side, one of LEFT, RIGHT, TOP, or BOTTOM, or None when the target is a junction. merge_ep is the resolved entry-port station when the target is a merge junction.
  • Spatial queries: section coordinates and horizontal and vertical crossing checks are resolved through the snapshot, which keeps every predicate and route builder on the same endpoint facts.

The source claims appear in their canonical classification order. Construction subtracts every earlier claim from each later predicate. Every row therefore owns an exclusive region of the fact space. The runtime rule table is therefore pairwise disjoint and can be reordered without changing which family owns an edge. If no predicate matches, the standard L-shape is the fall-through. Planned template construction resolves its frozen family through the same table’s stable rule ID without evaluating the predicates again, and production emission does not revisit the table or call the family.

#Stable familyRuleFires whenRoute
1PERP_EXIT_FAR_SIDE_WRAPperp-exit -> far-side entry wrapA TOP/BOTTOM exit feeds a far-side LEFT/RIGHT entry._route_perp_exit_farside_entry_wrap continues through the row gap and enters from the port’s outward side.
2PERP_EXITperp-exitThe source is a TOP/BOTTOM exit on a horizontal section._route_perp_exit uses a column drop or up-and-over route.
3TB_PERP_EXIT_OVERTB perp-exit overA TB/BT trailing exit feeds an entry against its flow._route_perp_exit_over uses the opposite-side corridor.
4SAME_Y_STRAIGHTsame-Y straightEndpoints share Y, need no bypass, and neither entry is approached from its far side._route_straight_connector emits a horizontal run.
5TB_BOTTOM_EXIT_AROUND_STACKTB bottom exit around stackA TB bottom-exit drop crosses sections stacked between source and target._route_around_stack diverts through a clear gap.
6TB_BOTTOM_EXITTB bottom exitThe source is a TB/BT bottom exit._route_tb_bottom_exit emits the ordinary drop or jog.
7TOP_ENTRY_L_SHAPETOP entry L-shapeThe target entry side is TOP._route_top_entry_l_shape supplies the required horizontal lead-in.
8BOTTOM_ENTRY_L_SHAPEBOTTOM entry L-shapeThe target entry side is BOTTOM._route_bottom_entry_l_shape supplies the mirrored lead-in.
9SAME_X_VERTICAL_DROPsame-X vertical dropEndpoints share X and are not stacked same-side exceptions._route_straight_connector emits a vertical run.
10BOTTOM_EXIT_JUNCTION_RIGHT_LANDINGSbottom-exit junction right landingsA fan plan owns the junction’s right-side landings._route_bottom_exit_junction_right_landings emits the fan landing template.
11BOTTOM_EXIT_JUNCTION_VIA_GAPbottom-exit junction via gapThe plain junction route crosses a section and a gap detour is available._route_bottom_exit_junction_via_gap_leaf emits the detour.
12BOTTOM_EXIT_JUNCTIONbottom-exit junctionThe source is a bottom-exit junction using the plain shape._route_bottom_exit_junction emits the drop-then-turn route.
13MERGE_TRUNK_AROUND_BELOWmerge trunk around belowA primary merge trunk has no target-side channel._route_merge_trunk_around_below loops under the target.
14MERGE_TRUNKmerge trunkMerge classification names this feeder as the primary trunk._route_merge_trunk emits the U-shaped trunk.
15MERGE_BRANCHmerge branchMerge classification names this feeder as a non-trunk branch._route_merge_branch_feeder joins the trunk channel.
16LEFT_ENTRY_CORRIDORLEFT entry corridorA cross-row LEFT entry needs the clear corridor leaf._route_left_entry_corridor emits the corridor route.
17BYPASS_L_SHAPEbypass L-shapeA bypass-classified hop resolves to its L-shaped leaf._route_l_shape emits the leaf directly.
18BYPASS_LEFT_ENTRYbypass LEFT entryA bypass reaches the ordinary LEFT-entry wrap leaf._route_left_entry_family emits the wrap.
19BYPASS_LEFT_EXIT_AROUND_BELOWbypass LEFT exit around belowA bypassing LEFT exit must loop below a far-side LEFT entry._route_left_exit_around_below_left_entry emits the loop.
20BYPASS_CELLMATE_GAP_DROPbypass cell-mate gap dropA cell-mate blocks the source-row bypass._route_bypass_cellmate_gap_drop uses the gap drop.
21BYPASS_PACKED_CELL_SAME_ROWbypass packed-cell same rowA packed cell-mate stands on a same-row hop’s source or target Y._route_bypass_packed_cell_same_row shares the sibling corridor, or takes the row-top one.
22BYPASS_RIGHT_ENTRY_CROSS_ROWbypass RIGHT entry cross-rowA bypass reaches the cross-row RIGHT-entry leaf._route_right_entry_cross_row emits the wrap.
23BYPASS_FAMILYbypass familyThe member needs the ordinary U-shaped bypass._route_u_bypass_family emits the U route.
24NEAR_VERTICAL_JUNCTIONnear-vertical same-col junctionA junction drops almost straight into a same-column entry._route_near_vertical_junction preserves the near-vertical channel.
25RIGHT_ENTRY_WRAPRIGHT entry wrapA RIGHT entry is fed from the left, or a stacked RIGHT exit feeds it._route_right_entry_wrap travels over or around the target’s right side.
26LEFT_ENTRY_WRAPLEFT entry wrap familyA LEFT entry is approached leftward across rows._route_left_entry_family selects its remaining named wrap construction.
27SERPENTINE_LEFTserpentine LEFT exit -> LEFT entryA LEFT exit feeds a stacked same-column LEFT entry._route_left_exit_left_entry_drop leads out to a clear left channel.
28LEFT_EXIT_FAR_SIDE_WRAPLEFT exit -> far-side LEFT entry wrapA LEFT exit reaches a LEFT entry from its far side without a bypass obstacle._route_left_exit_around_below_left_entry enters from the outward side.
29MERGE_ENTRY_STRAIGHTmerge entry straightA merge feeder is nearly collinear with its entry port._route_merge_entry_straight emits the straight leaf.
30MERGE_ENTRY_CORRIDORmerge entry corridorA merge feeder must cross a section and a corridor is viable._route_merge_entry_corridor emits the corridor leaf.
31MERGE_ENTRY_AROUND_BELOWmerge entry around belowA merge feeder must cross a section and has no viable corridor._route_merge_entry_around_below loops below the row.
32MERGE_ENTRY_PERPENDICULARmerge entry perpendicularThe resolved merge entry port is TOP or BOTTOM._route_merge_entry_perpendicular emits the staircase leaf.
33MERGE_ENTRYmerge entry familyThe target resolves through the ordinary merge-entry L-shape._route_merge_entry_family emits the L-shaped remainder.
34RIGHT_ENTRY_PLOUGH_BYPASSRIGHT entry plough -> bypassA higher-row route to a RIGHT entry would cross an intervening section._route_right_entry_plough_bypass deflects through the bypass.
35RIGHT_ENTRY_CROSS_ROW_WRAPRIGHT entry cross-row wrapA source above and right of a RIGHT entry travels left with no bypass obstacle._route_right_entry_cross_row uses the target-side band or around-below route.
-STANDARD_L_SHAPEfall-throughNo rule matches._route_l_shape emits the standard construction.

The promoted bottom-exit, bypass, and merge-entry leaves each have a stable family ID. Classification, source-turn planning, and production emission therefore all name the same geometry.

The table first runs in classification mode, then its selected families build non-convergence member templates in canonical order. Their gap slots are materialized together, and their occupied vertical channels are frozen before convergence planning. The convergence planner uses those channels as fixed external inputs while it freezes every supported merge trunk, feeder join, continuation, and endpoint owner. It may construct canonical trial routes for the convergence members it owns, but it does not route other members again. Rules 9 and 14 consume those convergence decisions. A continuation covered by a named feeder is suppressed before production emission, with the carrier recorded in the route-system binding. Merge landing and covered-hop cleanup are therefore unnecessary.

The table is the complete inter-section handler inventory. The emission ownership inventory, covering emitters, fallbacks, and validators, is route emission inventory.

assert_render_curve_invariants (routing/invariants.py) runs on every render, and the stage-boundary checks run under validate=True. Every rule in the table builds its route through the centerline bundle builder, which makes a flipped, pinched, or collinear bundle impossible by construction. These checks are therefore a thin safety net, and they never fire in normal operation.