From 4b40e2f81d6135bd78336a860d313c937d61f3c9 Mon Sep 17 00:00:00 2001 From: Zhaowenlong Date: Sun, 31 May 2026 14:43:55 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=87=AA=E5=8A=A8=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E5=B8=83=E7=BA=BF=E9=94=99=E5=BC=80=E6=96=B9=E5=90=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Mod/FreeCADExchange/AutoRouting.py | 27 ++++++++-- .../freecad_exchange_auto_routing_test.py | 49 +++++++++++++++++++ 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/src/Mod/FreeCADExchange/AutoRouting.py b/src/Mod/FreeCADExchange/AutoRouting.py index 83af255..d87e7ce 100644 --- a/src/Mod/FreeCADExchange/AutoRouting.py +++ b/src/Mod/FreeCADExchange/AutoRouting.py @@ -23,7 +23,7 @@ import WiringObjects DEFAULT_OPTIONS = { # 端子出来先走一小段,避免导线贴着设备外壳起步。 "terminal_exit_length": 20.0, - "lane_axis": "y", + "lane_axis": "auto", "lane_spacing": 10.0, # 线槽网络相关参数。 "use_routing_network": True, @@ -139,9 +139,30 @@ def _with_axis(point, axis, value): ) -def _lane_payload(route_index, options): +def _auto_lane_axis(route_points): + points = [_vector(point) for point in route_points or []] + if len(points) < 2: + return "y" + extents = {"x": 0.0, "y": 0.0, "z": 0.0} + for index in range(len(points) - 1): + start = points[index] + end = points[index + 1] + extents["x"] += abs(float(end.x) - float(start.x)) + extents["y"] += abs(float(end.y) - float(start.y)) + extents["z"] += abs(float(end.z) - float(start.z)) + dominant_axis = max(extents, key=lambda axis: extents[axis]) + if dominant_axis == "y": + return "x" + if dominant_axis == "x": + return "y" + return "x" + + +def _lane_payload(route_index, options, route_points=None): opts = options or {} lane_axis = (opts.get("lane_axis") or "y").lower() + if lane_axis == "auto": + lane_axis = _auto_lane_axis(route_points) if lane_axis not in {"x", "y", "z"}: lane_axis = "y" lane_index = max(int(route_index or 0), 0) @@ -778,7 +799,7 @@ 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) + lane = _lane_payload(route_index, opts, route_points=carrier_points) carrier_points = _apply_lane_offset(carrier_points, lane) points = [] diff --git a/tests/python/freecad_exchange_auto_routing_test.py b/tests/python/freecad_exchange_auto_routing_test.py index 43d8aaf..0c86ca8 100644 --- a/tests/python/freecad_exchange_auto_routing_test.py +++ b/tests/python/freecad_exchange_auto_routing_test.py @@ -1918,6 +1918,55 @@ class AutoRoutingTest(unittest.TestCase): ][0] self.assertTrue(any(abs(point.y - 10.0) <= 0.001 for point in second_wire.Points[1:-1])) + def test_route_eplan_connections_auto_lane_axis_offsets_perpendicular_to_shared_segment(self): + _install_fake_freecad() + terminal_objects, _wiring_objects, routing_network, auto_routing = _reload_modules() + app = sys.modules["FreeCAD"] + doc = FakeDocument() + terminal_objects.ensure_root_group(doc, "project-1") + _terminal(doc, terminal_objects, "TerminalStartA", "terminal-start-a", app.Vector(0, 0, 0)) + _terminal(doc, terminal_objects, "TerminalEndA", "terminal-end-a", app.Vector(0, 100, 0)) + _terminal(doc, terminal_objects, "TerminalStartB", "terminal-start-b", app.Vector(0, 0, 0)) + _terminal(doc, terminal_objects, "TerminalEndB", "terminal-end-b", app.Vector(0, 100, 0)) + routing_network.create_route_carrier( + doc, + [app.Vector(0, 0, 20), app.Vector(0, 100, 20)], + project_uuid="project-1", + kind="WireDuct", + ) + payload = { + "project_uuid": "project-1", + "wires": [ + { + "wire_id": "wire-a", + "start_terminal_uuid": "terminal-start-a", + "end_terminal_uuid": "terminal-end-a", + }, + { + "wire_id": "wire-b", + "start_terminal_uuid": "terminal-start-b", + "end_terminal_uuid": "terminal-end-b", + }, + ], + } + + report = auto_routing.route_eplan_connections_from_payload( + doc, + payload, + options={"lane_spacing": 10.0}, + ) + + self.assertEqual(1, report["routes"][1]["lane"]["index"]) + self.assertEqual("x", report["routes"][1]["lane"]["axis"]) + routed_group = doc.getObject("QETWiring_04_Routed") + second_wire = [ + wire + for wire in list(getattr(routed_group, "Group", []) or []) + if getattr(wire, "QetWireUuid", "") == "wire-b" + ][0] + self.assertTrue(any(abs(point.x - 10.0) <= 0.001 for point in second_wire.Points[1:-1])) + self.assertFalse(all(abs(point.x) <= 0.001 for point in second_wire.Points[1:-1])) + def test_route_eplan_connections_report_includes_collision_samples(self): _install_fake_freecad() terminal_objects, _wiring_objects, routing_network, auto_routing = _reload_modules()