diff --git a/docs/FreeCAD 3D自动布线设计方案.md b/docs/FreeCAD 3D自动布线设计方案.md index 2965f04..541ac09 100644 --- a/docs/FreeCAD 3D自动布线设计方案.md +++ b/docs/FreeCAD 3D自动布线设计方案.md @@ -85,6 +85,8 @@ terminal_uuid 构图时不要求所有 carrier 都提前手工打断。系统会识别轴向线段之间的几何相交和同线重叠,把交点/重叠端点自动切成图节点。这样多条线槽中心路径只要在空间中相交,就可以在交点处换向,Dijkstra 才能得到符合工程布线习惯的折线路径。 +相邻线槽端点允许存在小间隙。默认情况下,两个 `WireDuct` 端点距离不超过 5 mm 时会被视为相邻并自动桥接;自动布线选项 `adjoining_duct_tolerance` 可以按需要调大或调小,用于适配不同建模精度和线槽端部留缝。 + ### 2.1 路由优先级 当前版本按下面优先级处理: @@ -429,6 +431,7 @@ tests/python/freecad_exchange_auto_routing_test.py 26. `QetRouteTrackJson` 会在 carrier 有源对象元数据时保存 `source_name`、`source_label`、`source_kind`,方便核对导线实际走过的线槽、过线孔或支撑面。 27. 批量布线报告会显示一条路径示例,列出首条可追踪导线经过的源对象标签。 28. 线槽源对象支持通过 `QetWireDuctEndMarginMm` 按对象调整中心路径端部缩进距离。 +29. 自动布线支持通过 `adjoining_duct_tolerance` 调整相邻线槽端点自动桥接容差,并在网络结果中记录桥接段数量。 已完成 FreeCAD smoke: diff --git a/src/Mod/FreeCADExchange/AutoRouting.py b/src/Mod/FreeCADExchange/AutoRouting.py index a5836f3..d77ea17 100644 --- a/src/Mod/FreeCADExchange/AutoRouting.py +++ b/src/Mod/FreeCADExchange/AutoRouting.py @@ -29,6 +29,7 @@ DEFAULT_OPTIONS = { # 线槽网络相关参数。 "use_routing_network": True, "network_entry_max_distance": 1000.0, + "adjoining_duct_tolerance": RoutingNetwork.DEFAULT_ADJOINING_DUCT_TOLERANCE, "bend_penalty": 25.0, # EPLAN/SOLIDWORKS 风格:线槽/路由路径最优先,辅助面域只作为过渡/兜底区域。 "carrier_kind_cost_factors": { @@ -824,6 +825,7 @@ def build_network_route(start_terminal, end_terminal, route_index=0, options=Non "network": { "carriers": int(network.get("carrier_count", 0)), "segments": int(network.get("segment_count", 0)), + "bridged_segments": int(network.get("bridged_segment_count", 0)), "blocked_segments": int(network.get("blocked_segment_count", 0)), "nodes": len(network.get("nodes", {})), "entry_distance": float(start_distance or 0.0), @@ -843,12 +845,19 @@ def build_network_route(start_terminal, end_terminal, route_index=0, options=Non blocked_bboxes = [obstacle["bbox"] for obstacle in obstacles if obstacle.get("bbox")] if blocked_bboxes: - obstacle_aware_network = RoutingNetwork.build_route_graph(doc, blocked_bboxes=blocked_bboxes) + obstacle_aware_network = RoutingNetwork.build_route_graph( + doc, + blocked_bboxes=blocked_bboxes, + adjoining_duct_tolerance=float(opts.get("adjoining_duct_tolerance", 0.0) or 0.0), + ) route_data = route_on_network(obstacle_aware_network, obstacle_aware=True) if route_data is not None: return route_data - network = RoutingNetwork.build_route_graph(doc) + network = RoutingNetwork.build_route_graph( + doc, + adjoining_duct_tolerance=float(opts.get("adjoining_duct_tolerance", 0.0) or 0.0), + ) return route_on_network(network, obstacle_aware=False) diff --git a/tests/python/freecad_exchange_auto_routing_test.py b/tests/python/freecad_exchange_auto_routing_test.py index b2ab08d..bc9283e 100644 --- a/tests/python/freecad_exchange_auto_routing_test.py +++ b/tests/python/freecad_exchange_auto_routing_test.py @@ -743,6 +743,37 @@ class AutoRoutingTest(unittest.TestCase): self.assertEqual("network-dijkstra-v1", result["algorithm"]) self.assertEqual("Routed", result["route_status"]) + def test_auto_routing_respects_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") + 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)) + routing_network.create_route_carrier( + doc, + [app.Vector(0, 0, 20), app.Vector(44, 0, 20)], + project_uuid="project-1", + kind="WireDuct", + ) + routing_network.create_route_carrier( + doc, + [app.Vector(56, 0, 20), app.Vector(100, 0, 20)], + project_uuid="project-1", + kind="WireDuct", + ) + + result = auto_routing.route_eplan_connection_between_terminals( + doc, + start, + end, + options={"adjoining_duct_tolerance": 15.0}, + ) + + self.assertEqual("Routed", result["route_status"]) + self.assertEqual(1, result["network"]["bridged_segments"]) + def test_connect_point_to_network_replaces_bridged_edge_without_stale_reverse_edge(self): _install_fake_freecad() _terminal_objects, _wiring_objects, routing_network, _auto_routing = _reload_modules()