From ad24e9669580af091fc5d6e35014cb45a28a2d20 Mon Sep 17 00:00:00 2001 From: Zhaowenlong Date: Mon, 1 Jun 2026 16:29:05 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=A3=80=E6=9F=A5=E5=B8=83=E7=BA=BF?= =?UTF-8?q?=E7=BD=91=E7=BB=9C=E4=BD=BF=E7=94=A8=E6=A1=A5=E6=8E=A5=E5=AE=B9?= =?UTF-8?q?=E5=B7=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/FreeCAD 3D自动布线设计方案.md | 4 +- src/Mod/FreeCADExchange/AutoRouting.py | 8 ++- src/Mod/FreeCADExchange/RoutingNetwork.py | 15 ++++-- .../freecad_exchange_auto_routing_test.py | 52 +++++++++++++++++++ 4 files changed, 72 insertions(+), 7 deletions(-) diff --git a/docs/FreeCAD 3D自动布线设计方案.md b/docs/FreeCAD 3D自动布线设计方案.md index 429d3b3..ade4a06 100644 --- a/docs/FreeCAD 3D自动布线设计方案.md +++ b/docs/FreeCAD 3D自动布线设计方案.md @@ -87,7 +87,7 @@ terminal_uuid 相邻线槽端点允许存在小间隙。默认情况下,两个 `WireDuct` 端点距离不超过 5 mm 时会被视为相邻并自动桥接;自动布线选项 `adjoining_duct_tolerance` 可以按需要调大或调小,用于适配不同建模精度和线槽端部留缝。 -FreeCAD 的 `3D 布线连接` 面板提供“线槽桥接容差 mm”数值框,手动测试时可直接调整这个选项;生成布线路径网络、检查布线路径网络和生成布线连接都会读取当前面板值。 +FreeCAD 的 `3D 布线连接` 面板提供“线槽桥接容差 mm”数值框,手动测试时可直接调整这个选项;生成布线路径网络、检查布线路径网络和生成布线连接都会读取当前面板值。检查通过时,如果存在相邻线槽自动桥接,报告会显示自动桥接段数,便于确认当前容差是否生效。 同一面板还提供“端子接入最大距离 mm”和“端子出线长度 mm”。前者用于控制端子距离最近路由网络超过多少毫米时不再生成 `TerminalAccess`,避免设备还没摆放好时生成超长悬空接入线;后者用于控制端子沿 LCS 出线方向先走出的短线长度,避免导线从设备壳体内部或端子原点直接折返。 @@ -445,7 +445,7 @@ tests/python/freecad_exchange_auto_routing_test.py 27. 批量布线报告会显示一条路径示例,列出首条可追踪导线经过的源对象标签。 28. 线槽源对象支持通过 `QetWireDuctEndMarginMm` 按对象调整中心路径端部缩进距离。 29. 自动布线支持通过 `adjoining_duct_tolerance` 调整相邻线槽端点自动桥接容差,并在网络结果中记录桥接段数量。 -30. `3D 布线连接` 面板提供“线槽桥接容差 mm”设置,面板生成/检查/布线流程会使用该值。 +30. `3D 布线连接` 面板提供“线槽桥接容差 mm”设置,面板生成/检查/布线流程会使用该值;网络检查报告会显示自动桥接段数。 31. `3D 布线连接` 面板提供“端子接入最大距离 mm”和“端子出线长度 mm”设置,用于适配真实机柜里端子离线槽远近不同、设备端子方向不同的情况。 已完成 FreeCAD smoke: diff --git a/src/Mod/FreeCADExchange/AutoRouting.py b/src/Mod/FreeCADExchange/AutoRouting.py index d77ea17..a6125b4 100644 --- a/src/Mod/FreeCADExchange/AutoRouting.py +++ b/src/Mod/FreeCADExchange/AutoRouting.py @@ -1980,6 +1980,7 @@ def generate_eplan_routing_path_network(doc, project_uuid="", options=None, sele selection_ex=selection_ex, terminal_exit_length=float(opts.get("terminal_exit_length", 20.0) or 0.0), terminal_access_max_distance=float(opts.get("terminal_access_max_distance", 1000.0) or 0.0), + adjoining_duct_tolerance=float(opts.get("adjoining_duct_tolerance", 0.0) or 0.0), ) @@ -1999,6 +2000,7 @@ def check_eplan_routing_path_network(doc, project_uuid="", options=None): project_uuid=target_project_uuid, terminal_exit_length=float(opts.get("terminal_exit_length", 20.0) or 0.0), terminal_access_max_distance=float(opts.get("terminal_access_max_distance", 1000.0) or 0.0), + adjoining_duct_tolerance=float(opts.get("adjoining_duct_tolerance", 0.0) or 0.0), ) diagnostic = result.get("diagnostic", {}) if isinstance(result, dict) else {} return { @@ -2054,11 +2056,15 @@ def format_routing_path_network_report(diagnostic): summary = diagnostic.get("summary", {}) if isinstance(diagnostic.get("summary", {}), dict) else {} issues = _dict_items(diagnostic.get("issues", []) or []) if not issues: - return "布线路径网络检查通过:{0} 条 carrier / {1} 段 / {2} 个节点。".format( + message = "布线路径网络检查通过:{0} 条 carrier / {1} 段 / {2} 个节点。".format( summary.get("carriers", 0), summary.get("segments", 0), summary.get("nodes", 0), ) + bridged_segments = int(summary.get("bridged_segments", 0) or 0) + if bridged_segments > 0: + message += " 自动桥接 {0} 段相邻线槽。".format(bridged_segments) + return message message = "布线路径网络检查发现 {0} 类问题。".format(len(issues)) unconnected = _dict_items(diagnostic.get("unconnected_terminals", []) or []) diff --git a/src/Mod/FreeCADExchange/RoutingNetwork.py b/src/Mod/FreeCADExchange/RoutingNetwork.py index 26da3be..c3ea4cb 100644 --- a/src/Mod/FreeCADExchange/RoutingNetwork.py +++ b/src/Mod/FreeCADExchange/RoutingNetwork.py @@ -2193,6 +2193,7 @@ def create_routing_path_network_from_document( selection_ex=None, terminal_exit_length=20.0, terminal_access_max_distance=DEFAULT_TERMINAL_ACCESS_MAX_DISTANCE, + adjoining_duct_tolerance=DEFAULT_ADJOINING_DUCT_TOLERANCE, ): """Generate the EPLAN-style routing path network for the layout space. @@ -2254,7 +2255,10 @@ def create_routing_path_network_from_document( "surface_carriers": len(surfaces), "terminal_access_carriers": len(terminal_access), "layout_space": layout_space, - "network": network_summary(doc), + "network": network_summary( + doc, + adjoining_duct_tolerance=adjoining_duct_tolerance, + ), } @@ -2820,8 +2824,8 @@ def path_points(network, path_keys): return [nodes[key] for key in path_keys or [] if key in nodes] -def network_summary(doc): - network = build_route_graph(doc) +def network_summary(doc, adjoining_duct_tolerance=DEFAULT_ADJOINING_DUCT_TOLERANCE): + network = build_route_graph(doc, adjoining_duct_tolerance=adjoining_duct_tolerance) return _network_summary_from_graph(network) @@ -2927,12 +2931,13 @@ def diagnose_routing_path_network( doc, terminal_exit_length=20.0, terminal_access_max_distance=DEFAULT_TERMINAL_ACCESS_MAX_DISTANCE, + adjoining_duct_tolerance=DEFAULT_ADJOINING_DUCT_TOLERANCE, ): """Inspect the generated routing path network without routing wires.""" if doc is None: raise RoutingNetworkError("No FreeCAD document is available.") - network = build_route_graph(doc) + network = build_route_graph(doc, adjoining_duct_tolerance=adjoining_duct_tolerance) components = _route_graph_components(network) summary = _network_summary_from_graph(network) isolated_components = components if len(components) > 1 else [] @@ -3053,11 +3058,13 @@ def write_routing_path_network_diagnostic( project_uuid="", terminal_exit_length=20.0, terminal_access_max_distance=DEFAULT_TERMINAL_ACCESS_MAX_DISTANCE, + adjoining_duct_tolerance=DEFAULT_ADJOINING_DUCT_TOLERANCE, ): diagnostic = diagnose_routing_path_network( doc, terminal_exit_length=terminal_exit_length, terminal_access_max_distance=terminal_access_max_distance, + adjoining_duct_tolerance=adjoining_duct_tolerance, ) group = WiringObjects.ensure_diagnostic_group(doc, project_uuid) _clear_routing_path_network_diagnostics(doc, group) diff --git a/tests/python/freecad_exchange_auto_routing_test.py b/tests/python/freecad_exchange_auto_routing_test.py index 5276844..e389535 100644 --- a/tests/python/freecad_exchange_auto_routing_test.py +++ b/tests/python/freecad_exchange_auto_routing_test.py @@ -1480,6 +1480,58 @@ class AutoRoutingTest(unittest.TestCase): self.assertIn("(0.0, 0.0, 20.0)", message) self.assertIn("补齐相邻线槽", message) + def test_format_routing_path_network_report_includes_bridged_segment_count(self): + _install_fake_freecad() + _terminal_objects, _wiring_objects, _routing_network, auto_routing = _reload_modules() + diagnostic = { + "summary": { + "carriers": 5, + "segments": 6, + "nodes": 5, + "bridged_segments": 1, + }, + "issues": [], + "ok": True, + } + + message = auto_routing.format_routing_path_network_report(diagnostic) + + self.assertIn("桥接 1 段", message) + + def test_check_routing_path_network_uses_adjoining_duct_tolerance_option(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") + for index, points in enumerate( + ( + [app.Vector(0, 0, 20), app.Vector(44, 0, 20)], + [app.Vector(56, 0, 20), app.Vector(100, 0, 20)], + [app.Vector(100, 0, 20), app.Vector(100, 100, 20)], + [app.Vector(100, 100, 20), app.Vector(0, 100, 20)], + [app.Vector(0, 100, 20), app.Vector(0, 0, 20)], + ), + start=1, + ): + routing_network.create_route_carrier( + doc, + points, + label="线槽{0}".format(index), + project_uuid="project-1", + kind="WireDuct", + ) + + result = auto_routing.check_eplan_routing_path_network( + doc, + project_uuid="project-1", + options={"adjoining_duct_tolerance": 15.0}, + ) + + self.assertTrue(result["ok"]) + self.assertEqual(1, result["diagnostic"]["summary"]["bridged_segments"]) + self.assertEqual([], result["diagnostic"]["possible_breaks"]) + def test_generate_routing_path_network_skips_far_terminal_access_to_protect_view_bbox(self): _install_fake_freecad() terminal_objects, _wiring_objects, _routing_network, _auto_routing = _reload_modules()