From ea0e0a701d059b740f6844d789acdcd74d9f0af0 Mon Sep 17 00:00:00 2001 From: Zhaowenlong Date: Mon, 1 Jun 2026 14:50:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=AE=B0=E5=BD=95=E5=B8=83=E7=BA=BF?= =?UTF-8?q?=E8=BD=A8=E8=BF=B9=E6=BA=90=E5=AF=B9=E8=B1=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/FreeCAD 3D自动布线设计方案.md | 3 ++ src/Mod/FreeCADExchange/RoutingNetwork.py | 12 +++++++- .../freecad_exchange_auto_routing_test.py | 28 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/docs/FreeCAD 3D自动布线设计方案.md b/docs/FreeCAD 3D自动布线设计方案.md index f759dff..d7bd885 100644 --- a/docs/FreeCAD 3D自动布线设计方案.md +++ b/docs/FreeCAD 3D自动布线设计方案.md @@ -346,6 +346,8 @@ QetWiringCutOutBridgeExtensionMm = 20.0 自动生成的 carrier 会随源对象生命周期刷新:源对象仍有效时更新几何;安装板尺寸变化时同步增删 `RoutingRange` 网格线;源对象被删除或不再满足线槽/支撑面规则时,下一次生成布线路径网络会删除对应自动 carrier,并撤销该源对象的穿越/支撑面障碍模式。用户手工创建、没有源对象元数据的 carrier 不会被这一步自动删除。 +生成导线的 `QetRouteTrackJson` 会记录实际经过的 carrier。carrier 如果来自线槽、过线孔、支撑面或端子接入源对象,route track 中还会保留 `source_name`、`source_label`、`source_kind`,用于手动测试时追踪“这段线实际走过哪个 3D 源对象”。 + ### 5.3 布线连接功能 已完成: @@ -419,6 +421,7 @@ tests/python/freecad_exchange_auto_routing_test.py 23. 导线会保存 routing track;网络检查会生成 `RoutingPathNetwork` 诊断对象。 24. 自动生成的线槽、过线孔和支撑面 carrier 会在源对象移动、缩放、删除或失效后刷新/清理。 25. `WiringCutOut` 会在穿孔方向外扩虚拟路径,用于桥接开孔两侧附近的线槽或支撑面网络,并支持通过 `QetWiringCutOutBridgeExtensionMm` 按对象调整外扩距离。 +26. `QetRouteTrackJson` 会在 carrier 有源对象元数据时保存 `source_name`、`source_label`、`source_kind`,方便核对导线实际走过的线槽、过线孔或支撑面。 已完成 FreeCAD smoke: diff --git a/src/Mod/FreeCADExchange/RoutingNetwork.py b/src/Mod/FreeCADExchange/RoutingNetwork.py index 2bb141f..bbe6427 100644 --- a/src/Mod/FreeCADExchange/RoutingNetwork.py +++ b/src/Mod/FreeCADExchange/RoutingNetwork.py @@ -2643,11 +2643,21 @@ def connect_point_to_network(network, point): def _carrier_track_payload(carrier): - return { + payload = { "name": getattr(carrier, "Name", ""), "label": getattr(carrier, "Label", ""), "kind": (getattr(carrier, "QetRouteCarrierKind", "") or "").strip() or ROUTE_CARRIER_KIND, } + source_fields = ( + ("source_name", "QetRouteSourceName"), + ("source_label", "QetRouteSourceLabel"), + ("source_kind", "QetRouteSourceKind"), + ) + for payload_key, property_name in source_fields: + value = (getattr(carrier, property_name, "") or "").strip() + if value: + payload[payload_key] = value + return payload def _segment_usage_key(carrier, from_key, to_key): diff --git a/tests/python/freecad_exchange_auto_routing_test.py b/tests/python/freecad_exchange_auto_routing_test.py index a52709b..b22b573 100644 --- a/tests/python/freecad_exchange_auto_routing_test.py +++ b/tests/python/freecad_exchange_auto_routing_test.py @@ -281,6 +281,34 @@ class AutoRoutingTest(unittest.TestCase): self.assertEqual("WireDuct", payload["route_track"]["segments"][0]["carrier"]["kind"]) self.assertTrue(json.loads(wire.QetRouteTrackJson)["carrier_names"]) + def test_route_track_preserves_generated_carrier_source_metadata(self): + _install_fake_freecad() + terminal_objects, _wiring_objects, _routing_network, auto_routing = _reload_modules() + auto_routing_panel = importlib.import_module("AutoRoutingPanel") + app = sys.modules["FreeCAD"] + doc = FakeDocument() + app.ActiveDocument = doc + terminal_objects.ensure_root_group(doc, "project-1") + start = _terminal(doc, terminal_objects, "TerminalStart", "terminal-start", app.Vector(0, 0, 0)) + end = _terminal(doc, terminal_objects, "TerminalEnd", "terminal-end", app.Vector(100, 0, 0)) + duct = doc.addObject("Part::Feature", "WireDuctA") + duct.Label = "线槽A" + duct.Shape = FakeShape(FakeBoundBox(0, 100, -5, 5, 15, 25)) + + auto_routing_panel.AutoRoutingController().generate_routing_paths() + result = auto_routing.route_eplan_connection_between_terminals(doc, start, end) + route_track = json.loads(result["wire"].QetRouteTrackJson) + wire_duct_carriers = [ + segment["carrier"] + for segment in route_track["segments"] + if segment["carrier"]["kind"] == "WireDuct" + ] + + self.assertTrue(wire_duct_carriers) + self.assertEqual("WireDuctA", wire_duct_carriers[0].get("source_name")) + self.assertEqual("线槽A", wire_duct_carriers[0].get("source_label")) + self.assertEqual("WireDuct", wire_duct_carriers[0].get("source_kind")) + def test_network_eplan_connection_route_offsets_lane_by_route_index(self): _install_fake_freecad() terminal_objects, _wiring_objects, routing_network, auto_routing = _reload_modules()