|
|
|
|
@ -140,6 +140,32 @@ def _with_axis(point, axis, value):
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _lane_payload(route_index, options):
|
|
|
|
|
opts = options or {}
|
|
|
|
|
lane_axis = (opts.get("lane_axis") or "y").lower()
|
|
|
|
|
if lane_axis not in {"x", "y", "z"}:
|
|
|
|
|
lane_axis = "y"
|
|
|
|
|
lane_index = int(route_index or 0)
|
|
|
|
|
lane_spacing = float(opts.get("lane_spacing", 0.0) or 0.0)
|
|
|
|
|
return {
|
|
|
|
|
"index": lane_index,
|
|
|
|
|
"axis": lane_axis,
|
|
|
|
|
"spacing_mm": lane_spacing,
|
|
|
|
|
"offset_mm": float(lane_index) * lane_spacing,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _apply_lane_offset(points, lane):
|
|
|
|
|
offset = float((lane or {}).get("offset_mm", 0.0) or 0.0)
|
|
|
|
|
if abs(offset) <= 0.000001:
|
|
|
|
|
return list(points or [])
|
|
|
|
|
axis = (lane or {}).get("axis", "y")
|
|
|
|
|
return [
|
|
|
|
|
_with_axis(point, axis, _axis_value(point, axis) + offset)
|
|
|
|
|
for point in list(points or [])
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _orthogonal_points(start_point, end_point, preferred_axis=None):
|
|
|
|
|
if _vector_close(start_point, end_point):
|
|
|
|
|
return [start_point]
|
|
|
|
|
@ -528,6 +554,7 @@ def _route_payload(route_data, collisions, wire_style_id=""):
|
|
|
|
|
"algorithm": route_data.get("algorithm", ""),
|
|
|
|
|
"length_mm": _route_length(points),
|
|
|
|
|
"wire_style_id": str(wire_style_id or "").strip(),
|
|
|
|
|
"lane": route_data.get("lane", {}),
|
|
|
|
|
"points": [_point_payload(point) for point in points],
|
|
|
|
|
"collision_count": len(collisions),
|
|
|
|
|
"collisions": collisions,
|
|
|
|
|
@ -581,20 +608,17 @@ def build_orthogonal_route(start_terminal, end_terminal, route_index=0, options=
|
|
|
|
|
clearance_axis = (opts.get("clearance_axis") or "z").lower()
|
|
|
|
|
if clearance_axis not in {"x", "y", "z"}:
|
|
|
|
|
clearance_axis = "z"
|
|
|
|
|
lane_axis = (opts.get("lane_axis") or "y").lower()
|
|
|
|
|
if lane_axis not in {"x", "y", "z"}:
|
|
|
|
|
lane_axis = "y"
|
|
|
|
|
lane = _lane_payload(route_index, opts)
|
|
|
|
|
|
|
|
|
|
clearance_value = max(
|
|
|
|
|
_axis_value(start_exit, clearance_axis),
|
|
|
|
|
_axis_value(end_exit, clearance_axis),
|
|
|
|
|
) + float(opts.get("clearance", 0.0) or 0.0)
|
|
|
|
|
|
|
|
|
|
lane_offset = float(route_index or 0) * float(opts.get("lane_spacing", 0.0) or 0.0)
|
|
|
|
|
lane_point = _with_axis(start_exit, clearance_axis, clearance_value)
|
|
|
|
|
lane_point = _with_axis(lane_point, lane_axis, _axis_value(lane_point, lane_axis) + lane_offset)
|
|
|
|
|
lane_point = _with_axis(lane_point, lane["axis"], _axis_value(lane_point, lane["axis"]) + lane["offset_mm"])
|
|
|
|
|
end_lane = _with_axis(end_exit, clearance_axis, clearance_value)
|
|
|
|
|
end_lane = _with_axis(end_lane, lane_axis, _axis_value(end_lane, lane_axis) + lane_offset)
|
|
|
|
|
end_lane = _with_axis(end_lane, lane["axis"], _axis_value(end_lane, lane["axis"]) + lane["offset_mm"])
|
|
|
|
|
|
|
|
|
|
points = []
|
|
|
|
|
_append_unique(points, start_origin)
|
|
|
|
|
@ -608,6 +632,7 @@ def build_orthogonal_route(start_terminal, end_terminal, route_index=0, options=
|
|
|
|
|
"algorithm": "orthogonal-v1",
|
|
|
|
|
"points": points,
|
|
|
|
|
"network": {},
|
|
|
|
|
"lane": lane,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -655,6 +680,8 @@ def build_network_route(start_terminal, end_terminal, route_index=0, options=Non
|
|
|
|
|
carrier_points = RoutingNetwork.path_points(network, path_keys)
|
|
|
|
|
if not carrier_points:
|
|
|
|
|
return None
|
|
|
|
|
lane = _lane_payload(route_index, opts)
|
|
|
|
|
carrier_points = _apply_lane_offset(carrier_points, lane)
|
|
|
|
|
|
|
|
|
|
points = []
|
|
|
|
|
_append_unique(points, start_origin)
|
|
|
|
|
@ -677,6 +704,7 @@ def build_network_route(start_terminal, end_terminal, route_index=0, options=Non
|
|
|
|
|
"exit_distance": float(end_distance or 0.0),
|
|
|
|
|
"obstacle_aware": bool(obstacle_aware),
|
|
|
|
|
},
|
|
|
|
|
"lane": lane,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
use_obstacle_avoidance = bool(opts.get("avoid_obstacles", True))
|
|
|
|
|
@ -989,6 +1017,8 @@ def route_between_terminals(
|
|
|
|
|
"algorithm": route_data.get("algorithm", ""),
|
|
|
|
|
"network": route_data.get("network", {}),
|
|
|
|
|
"points": points,
|
|
|
|
|
"lane": route_data.get("lane", {}),
|
|
|
|
|
"length_mm": _route_length(points),
|
|
|
|
|
"collision_count": len(collisions),
|
|
|
|
|
"collisions": collisions,
|
|
|
|
|
}
|
|
|
|
|
@ -1069,6 +1099,7 @@ def route_all_from_payload(doc, payload, options=None):
|
|
|
|
|
"auto_terminal_binding_warnings": terminal_binding_report["warnings"],
|
|
|
|
|
"routed": 0,
|
|
|
|
|
"collision_warnings": 0,
|
|
|
|
|
"total_length_mm": 0.0,
|
|
|
|
|
"skipped_missing_terminal": 0,
|
|
|
|
|
"skipped_invalid": 0,
|
|
|
|
|
"missing_endpoint_uuids": [],
|
|
|
|
|
@ -1129,11 +1160,14 @@ def route_all_from_payload(doc, payload, options=None):
|
|
|
|
|
if result["route_status"] == "CollisionWarning":
|
|
|
|
|
report["collision_warnings"] += 1
|
|
|
|
|
report["routed"] += 1
|
|
|
|
|
route_length = float(result.get("length_mm", 0.0) or 0.0)
|
|
|
|
|
report["total_length_mm"] += route_length
|
|
|
|
|
report["routes"].append(
|
|
|
|
|
{
|
|
|
|
|
"wire_uuid": _wire_item_value(item, "wire_id", "wire_uuid", "id"),
|
|
|
|
|
"algorithm": result["algorithm"],
|
|
|
|
|
"route_status": result["route_status"],
|
|
|
|
|
"length_mm": route_length,
|
|
|
|
|
"collision_count": result["collision_count"],
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
@ -1155,6 +1189,9 @@ def format_route_all_report(report):
|
|
|
|
|
prepared_layout.get("surface_carriers", 0),
|
|
|
|
|
prepared_layout.get("terminal_access_carriers", 0),
|
|
|
|
|
)
|
|
|
|
|
total_length_mm = float(report.get("total_length_mm", 0.0) or 0.0)
|
|
|
|
|
if total_length_mm > 0.0:
|
|
|
|
|
message += "\n自动布线总长度:{0:.1f} mm。".format(total_length_mm)
|
|
|
|
|
errors = report.get("errors", []) or []
|
|
|
|
|
if errors:
|
|
|
|
|
message += "\n首个错误:{0}".format(str(errors[0]))
|
|
|
|
|
|