From f653549366e457022ccd549c5c063f9c317e09b4 Mon Sep 17 00:00:00 2001 From: Zhaowenlong Date: Mon, 1 Jun 2026 15:08:21 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=B1=95=E7=A4=BA=E5=B8=83=E7=BA=BF?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E6=BA=90=E5=AF=B9=E8=B1=A1=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/FreeCAD 3D自动布线设计方案.md | 3 ++ src/Mod/FreeCADExchange/AutoRouting.py | 39 +++++++++++++++++++ .../freecad_exchange_auto_routing_test.py | 26 +++++++++++++ 3 files changed, 68 insertions(+) diff --git a/docs/FreeCAD 3D自动布线设计方案.md b/docs/FreeCAD 3D自动布线设计方案.md index d7bd885..50ac511 100644 --- a/docs/FreeCAD 3D自动布线设计方案.md +++ b/docs/FreeCAD 3D自动布线设计方案.md @@ -348,6 +348,8 @@ QetWiringCutOutBridgeExtensionMm = 20.0 生成导线的 `QetRouteTrackJson` 会记录实际经过的 carrier。carrier 如果来自线槽、过线孔、支撑面或端子接入源对象,route track 中还会保留 `source_name`、`source_label`、`source_kind`,用于手动测试时追踪“这段线实际走过哪个 3D 源对象”。 +批量生成布线连接后,面板/控制台报告会从第一条可追踪路径中提取一条“路径示例”,显示导线经过的源对象标签,便于快速确认线路是否进入了预期线槽、过线孔和支撑面。 + ### 5.3 布线连接功能 已完成: @@ -422,6 +424,7 @@ tests/python/freecad_exchange_auto_routing_test.py 24. 自动生成的线槽、过线孔和支撑面 carrier 会在源对象移动、缩放、删除或失效后刷新/清理。 25. `WiringCutOut` 会在穿孔方向外扩虚拟路径,用于桥接开孔两侧附近的线槽或支撑面网络,并支持通过 `QetWiringCutOutBridgeExtensionMm` 按对象调整外扩距离。 26. `QetRouteTrackJson` 会在 carrier 有源对象元数据时保存 `source_name`、`source_label`、`source_kind`,方便核对导线实际走过的线槽、过线孔或支撑面。 +27. 批量布线报告会显示一条路径示例,列出首条可追踪导线经过的源对象标签。 已完成 FreeCAD smoke: diff --git a/src/Mod/FreeCADExchange/AutoRouting.py b/src/Mod/FreeCADExchange/AutoRouting.py index 08ec063..a5836f3 100644 --- a/src/Mod/FreeCADExchange/AutoRouting.py +++ b/src/Mod/FreeCADExchange/AutoRouting.py @@ -1689,6 +1689,42 @@ def _endpoint_pair_text(sample): ) +def _route_source_labels(route_track, limit=5): + labels = [] + seen = set() + if not isinstance(route_track, dict): + return labels + for segment in route_track.get("segments", []) or []: + carrier = segment.get("carrier", {}) if isinstance(segment, dict) else {} + if not isinstance(carrier, dict): + continue + label = ( + str(carrier.get("source_label", "") or "").strip() + or str(carrier.get("source_name", "") or "").strip() + ) + if not label or label in seen: + continue + seen.add(label) + labels.append(label) + if len(labels) >= int(limit or 0): + break + return labels + + +def _route_source_sample_text(report): + for route in report.get("routes", []) or []: + if not isinstance(route, dict): + continue + labels = _route_source_labels(route.get("route_track", {})) + if not labels: + continue + return "路径示例:导线 {0} 经过 {1}。".format( + _wire_sample_text(route), + "、".join(labels), + ) + return "" + + def format_eplan_connection_route_report(report): message = "批量生成布线连接完成:routed={0}, collision_warnings={1}, missing_terminals={2}".format( report.get("routed", 0), @@ -1731,6 +1767,9 @@ def format_eplan_connection_route_report(report): 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) + route_source_sample = _route_source_sample_text(report) + if route_source_sample: + message += "\n{0}".format(route_source_sample) errors = report.get("errors", []) or [] if errors: message += "\n首个错误:{0}".format(str(errors[0])) diff --git a/tests/python/freecad_exchange_auto_routing_test.py b/tests/python/freecad_exchange_auto_routing_test.py index b22b573..1cf7c64 100644 --- a/tests/python/freecad_exchange_auto_routing_test.py +++ b/tests/python/freecad_exchange_auto_routing_test.py @@ -1941,6 +1941,32 @@ class AutoRoutingTest(unittest.TestCase): self.assertEqual(report["total_length_mm"], report["routes"][0]["length_mm"]) self.assertIn("总长度", message) + def test_route_report_includes_route_source_sample_when_available(self): + _install_fake_freecad() + _terminal_objects, _wiring_objects, _routing_network, auto_routing = _reload_modules() + report = { + "routed": 1, + "collision_warnings": 0, + "skipped_missing_terminal": 0, + "routes": [ + { + "wire_label": "N4111", + "route_track": { + "segments": [ + {"carrier": {"kind": "TerminalAccess", "source_label": "QF1:A1"}}, + {"carrier": {"kind": "WireDuct", "source_label": "线槽A"}}, + {"carrier": {"kind": "WiringCutOut", "source_label": "过线孔A"}}, + {"carrier": {"kind": "WireDuct", "source_label": "线槽A"}}, + ] + }, + } + ], + } + + message = auto_routing.format_eplan_connection_route_report(report) + + self.assertIn("路径示例:导线 N4111 经过 QF1:A1、线槽A、过线孔A。", message) + def test_route_eplan_connections_report_keeps_route_identity_and_diagnostics(self): _install_fake_freecad() terminal_objects, _wiring_objects, routing_network, auto_routing = _reload_modules()