Flattened Network
networks/flat.csv is the 2D drawing. derive is the call a harness script makes. map_instance_to_segments is what the cable mapper calls for one conductor; a harness script calls cable_utils.map_cables_and_conductors_to_segments instead.
Columns
derive writes this header. A harness script leaves the heading columns in the CSV.
| Column | Description |
|---|---|
segment_id |
id of the 3D segment this row flattens |
node_at_end_a |
node id at end A after derive; A is the left end, or the upper end when the segment is vertical |
node_at_end_b |
node id at end B |
length |
arc length of the 3D curve, recomputed on every derive |
length_tolerance |
kept from the previous row with this segment_id; not edited on the 2D page |
angle |
heading in degrees from end A to the first bend; 0 is +X and console Y points down |
angle_constraint |
match name for that first heading; blank means the heading is independent |
subdivisions |
JSON list of {percent, angle, constraint}; percent is in (0, 100) where the next heading starts |
Commands
These functions are already available in build instructions as flattened_network. Use them as written.
flattened_network.derive(network: dict) -> list[dict]
Use this when a harness build needs networks/flat.csv, and the node and segment instances, updated from the chosen network. Skip it when the project does not need the flat drawing.
Build the flattened-network CSV from a chosen network, and update the node and segment instances to match.
The network decides which rows exist and sets segment_id,
node_at_end_a, node_at_end_b, and length. length is the
3D curve length. The 3D page stores each spline_control_points triple
as an offset from end A. spline_length places those stored triples in
the Bezier polygon with the two ends and does not add end A.
length_tolerance, angle, angle_constraint, and
subdivisions already saved for a segment_id are kept. angle
is the heading from end A to the first bend. Each subdivision is a
percent of length where the next heading starts. When the 3D ends come
back swapped versus the saved row, those spans are reversed so the
drawing stays. A first heading in [90, 270) swaps the CSV ends and
adds 180° to each heading, so A is left of B, or above B when the
segment is vertical.
On the instances list, each node receives 2d_translate {x, y},
parent origin / origin, absolute_rotation, and
3d_translate from the network node. A node id with no instance is
created as item_type "node". Each segment is created or updated
as item_type "segment", parented to end A on "origin", with
length rounded to 2 digits.
Args:
- network: Network dict with "segments" and "nodes", such as a chosen network.
Returns:
- list: The flattened rows that were written.
flattened_network.map_instance_to_segments(instance)
Use this when cable routing needs one instance split into a segment instance for each segment between its ends. A harness script calls cable_utils.map_cables_and_conductors_to_segments instead.
Maps a segment-based instance across multiple segments using pathfinding.
Takes an instance that spans between two nodes and creates segment-specific
instances for each segment in the path between those nodes. Uses breadth-first
search to find the path through the segment graph, then creates one
{item_type}-segment instance per segment carrying the direction it is
traversed in and its order along the path.
Note: Cavity endpoints are resolved to the node in the same connector
group. If node_at_end_a / node_at_end_b are already item_type=="node"
instances, they are used directly. When both ends resolve to the same node,
the instance is a loopback: it is mapped out and back on the free stub
leaving that connector, and each hop's length is twice the segment
length.
Args:
instance(dict): Instance dictionary withlocation_type="segment"that hasnode_at_end_aandnode_at_end_bdefined.
Raises:
ValueError: If the instance is not segment-based, if endpoints are missing, if endpoints are not nodes, or if no path is found between the nodes.