From ec3ef5b30e527628090e7967b8bd1f8b9ebcd7b0 Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Sun, 4 Jan 2026 11:59:50 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=B8=A6=E7=8A=B6=E8=BF=9E?= =?UTF-8?q?=E7=BA=BF=E9=A3=8E=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/PathPointRenderPlugin.cs | 158 ++++++++++++++---- src/UI/WPF/ViewModels/PathEditingViewModel.cs | 104 +++++++++++- src/UI/WPF/Views/PathEditingView.xaml | 39 +++-- 3 files changed, 256 insertions(+), 45 deletions(-) diff --git a/src/Core/PathPointRenderPlugin.cs b/src/Core/PathPointRenderPlugin.cs index bd1e8e1..cebae8c 100644 --- a/src/Core/PathPointRenderPlugin.cs +++ b/src/Core/PathPointRenderPlugin.cs @@ -17,6 +17,11 @@ namespace NavisworksTransport /// StandardLine, + /// + /// 带状连线模式 - 长方体连线 + /// + RibbonLine, + /// /// 车辆通行空间模式 - 矩形通道 /// @@ -239,6 +244,11 @@ namespace NavisworksTransport /// public List SampledPoints { get; set; } + /// + /// 带状连线高度(仅用于 RibbonLine 模式) + /// + public double Height { get; set; } + public override string ToString() { return $"LineMarker[{FromIndex}->{ToIndex}, 类型={SegmentType}, 起点=({StartPoint.X:F2},{StartPoint.Y:F2},{StartPoint.Z:F2}), 终点=({EndPoint.X:F2},{EndPoint.Y:F2},{EndPoint.Z:F2})]"; @@ -717,6 +727,18 @@ namespace NavisworksTransport } } + /// + /// 获取所有路径可视化对象 + /// + /// 所有路径可视化对象的列表 + public List GetAllPathVisualizations() + { + lock (_lockObject) + { + return _pathVisualizations.Values.ToList(); + } + } + /// /// 判断是否为网格可视化路径 /// @@ -981,6 +1003,9 @@ namespace NavisworksTransport } } + // 计算带状连线的高度(比切点标记低:GetLineRadius() * 0.2) + double ribbonHeight = GetLineRadius() * 0.2; + // 3. 构建路径连线(Edges包含直线段和圆弧段) foreach (var edge in edges) { @@ -996,7 +1021,8 @@ namespace NavisworksTransport Color = GetRenderStyle(RenderStyleName.Line).Color, Radius = GetLineRadius(), SegmentType = PathSegmentType.Straight, - SampledPoints = edge.SampledPoints + SampledPoints = edge.SampledPoints, + Height = ribbonHeight // 设置带状连线高度 }; visualization.PathLineMarkers.Add(lineMarker); } @@ -1012,7 +1038,8 @@ namespace NavisworksTransport Radius = GetLineRadius(), SegmentType = PathSegmentType.Arc, Trajectory = edge.Trajectory, - SampledPoints = edge.SampledPoints + SampledPoints = edge.SampledPoints, + Height = ribbonHeight // 设置带状连线高度 }; visualization.PathLineMarkers.Add(arcMarker); @@ -1749,22 +1776,27 @@ namespace NavisworksTransport } /// - /// 渲染车辆通行空间(矩形通道)- 使用Cuboid API简化实现 + /// 渲染长方体标记(通用方法) /// /// 图形上下文 - /// 车辆通行空间标记 - private void RenderVehicleSpace(Graphics graphics, VehicleSpaceMarker vehicleSpace) + /// 起点 + /// 终点 + /// 宽度 + /// 高度 + /// 颜色 + /// 透明度 + private void RenderCuboidMarker(Graphics graphics, Point3D startPoint, Point3D endPoint, double width, double height, Color color, double alpha) { try { - // 计算通道方向向量 + // 计算方向向量 var direction = new Vector3D( - vehicleSpace.EndPoint.X - vehicleSpace.StartPoint.X, - vehicleSpace.EndPoint.Y - vehicleSpace.StartPoint.Y, - vehicleSpace.EndPoint.Z - vehicleSpace.StartPoint.Z + endPoint.X - startPoint.X, + endPoint.Y - startPoint.Y, + endPoint.Z - startPoint.Z ); - // 计算通道长度 + // 计算长度 var length = Math.Sqrt(direction.X * direction.X + direction.Y * direction.Y + direction.Z * direction.Z); if (length < 0.001) // 避免零长度线段 @@ -1789,33 +1821,72 @@ namespace NavisworksTransport right = new Vector3D(right.X / rightLength, right.Y / rightLength, right.Z / rightLength); } - // 计算通道的边界框和向量 - var halfWidth = vehicleSpace.Width / 2.0; + // 计算长方体的边界框和向量 + var halfWidth = width / 2.0; // 计算立方体原点(起点左下角) var origin = new Point3D( - vehicleSpace.StartPoint.X - halfWidth * right.X, - vehicleSpace.StartPoint.Y - halfWidth * right.Y, - vehicleSpace.StartPoint.Z + startPoint.X - halfWidth * right.X, + startPoint.Y - halfWidth * right.Y, + startPoint.Z ); // 定义立方体的三个轴向量 var xVector = new Vector3D(direction.X * length, direction.Y * length, direction.Z * length); // 长度方向 - var yVector = new Vector3D(right.X * vehicleSpace.Width, right.Y * vehicleSpace.Width, right.Z * vehicleSpace.Width); // 宽度方向 - var zVector = new Vector3D(0, 0, vehicleSpace.Height); // 高度方向 + var yVector = new Vector3D(right.X * width, right.Y * width, right.Z * width); // 宽度方向 + var zVector = new Vector3D(0, 0, height); // 高度方向 // 设置颜色和透明度 - graphics.Color(vehicleSpace.Color, vehicleSpace.Alpha); + graphics.Color(color, alpha); - // 使用Cuboid API渲染长方体通道 + // 使用Cuboid API渲染长方体 graphics.Cuboid(origin, xVector, yVector, zVector, true); } catch (Exception ex) { - LogManager.Error($"[车辆空间渲染] 渲染车辆通行空间失败: {ex.Message}", ex); + LogManager.Error($"[长方体渲染] 渲染长方体失败: {ex.Message}", ex); } } + /// + /// 渲染车辆通行空间(矩形通道)- 使用Cuboid API简化实现 + /// + /// 图形上下文 + /// 车辆通行空间标记 + private void RenderVehicleSpace(Graphics graphics, VehicleSpaceMarker vehicleSpace) + { + var style = GetRenderStyle(RenderStyleName.VehicleSpace); + RenderCuboidMarker( + graphics, + vehicleSpace.StartPoint, + vehicleSpace.EndPoint, + vehicleSpace.Width, + vehicleSpace.Height, + vehicleSpace.Color, + vehicleSpace.Alpha + ); + } + + /// + /// 渲染带状连线(长方体) + /// + /// 图形上下文 + /// 连线标记 + private void RenderRibbonLineMarker(Graphics graphics, LineMarker lineMarker) + { + // 计算带状连线的宽度(直径) + var width = lineMarker.Radius * 2; + RenderCuboidMarker( + graphics, + lineMarker.StartPoint, + lineMarker.EndPoint, + width, + lineMarker.Height, + lineMarker.Color, + 1.0 // 带状连线使用不透明 + ); + } + /// /// 渲染点标记 @@ -1922,20 +1993,51 @@ namespace NavisworksTransport /// 连线标记 private void RenderLineMarker(Graphics graphics, LineMarker lineMarker) { - if (lineMarker.SegmentType == PathSegmentType.Arc && - lineMarker.SampledPoints != null && - lineMarker.SampledPoints.Count >= 2) + if (_visualizationMode == PathVisualizationMode.RibbonLine) { - // 圆弧段:多段圆柱体 - for (int i = 0; i < lineMarker.SampledPoints.Count - 1; i++) + // 带状连线模式:使用长方体渲染 + if (lineMarker.SegmentType == PathSegmentType.Arc && + lineMarker.SampledPoints != null && + lineMarker.SampledPoints.Count >= 2) { - graphics.Cylinder(lineMarker.SampledPoints[i], lineMarker.SampledPoints[i + 1], lineMarker.Radius); + // 圆弧段:多段长方体拼接 + for (int i = 0; i < lineMarker.SampledPoints.Count - 1; i++) + { + var segmentMarker = new LineMarker + { + StartPoint = lineMarker.SampledPoints[i], + EndPoint = lineMarker.SampledPoints[i + 1], + Radius = lineMarker.Radius, + Height = lineMarker.Height, + Color = lineMarker.Color + }; + RenderRibbonLineMarker(graphics, segmentMarker); + } + } + else + { + // 直线段:单个长方体 + RenderRibbonLineMarker(graphics, lineMarker); } } else { - // 直线段:单个圆柱体 - graphics.Cylinder(lineMarker.StartPoint, lineMarker.EndPoint, lineMarker.Radius); + // 标准连线模式:使用圆柱体渲染 + if (lineMarker.SegmentType == PathSegmentType.Arc && + lineMarker.SampledPoints != null && + lineMarker.SampledPoints.Count >= 2) + { + // 圆弧段:多段圆柱体 + for (int i = 0; i < lineMarker.SampledPoints.Count - 1; i++) + { + graphics.Cylinder(lineMarker.SampledPoints[i], lineMarker.SampledPoints[i + 1], lineMarker.Radius); + } + } + else + { + // 直线段:单个圆柱体 + graphics.Cylinder(lineMarker.StartPoint, lineMarker.EndPoint, lineMarker.Radius); + } } } diff --git a/src/UI/WPF/ViewModels/PathEditingViewModel.cs b/src/UI/WPF/ViewModels/PathEditingViewModel.cs index 91064e1..2c627c3 100644 --- a/src/UI/WPF/ViewModels/PathEditingViewModel.cs +++ b/src/UI/WPF/ViewModels/PathEditingViewModel.cs @@ -9,6 +9,7 @@ using System.Linq; using System.IO; using Microsoft.Win32; using Autodesk.Navisworks.Api; +using NavisApplication = Autodesk.Navisworks.Api.Application; using NavisworksTransport.Core; using NavisworksTransport.Core.Config; using NavisworksTransport.Commands; @@ -81,7 +82,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels private bool _showDoorGrid = false; private GridPointType _gridPointType = GridPointType.Rectangle; private bool _isStandardLineMode = true; + private bool _isRibbonLineMode = false; private bool _isVehicleSpaceMode = false; + private bool _showControlVisualization = true; // 默认显示控制点 // 路径策略参数 private PathStrategyOption _selectedPathStrategy; @@ -491,6 +494,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels { if (value) { + IsRibbonLineMode = false; IsVehicleSpaceMode = false; OnPathVisualizationModeChanged(); } @@ -511,12 +515,48 @@ namespace NavisworksTransport.UI.WPF.ViewModels if (value) { IsStandardLineMode = false; + IsRibbonLineMode = false; OnPathVisualizationModeChanged(); } } } } + /// + /// 是否使用带状连线模式 + /// + public bool IsRibbonLineMode + { + get => _isRibbonLineMode; + set + { + if (SetProperty(ref _isRibbonLineMode, value)) + { + if (value) + { + IsStandardLineMode = false; + IsVehicleSpaceMode = false; + OnPathVisualizationModeChanged(); + } + } + } + } + + /// + /// 是否显示控制点可视化(用户意图) + /// + public bool ShowControlVisualization + { + get => _showControlVisualization; + set + { + if (SetProperty(ref _showControlVisualization, value)) + { + OnControlVisualizationChanged(); + } + } + } + #endregion /// @@ -2364,10 +2404,27 @@ namespace NavisworksTransport.UI.WPF.ViewModels var renderPlugin = PathPointRenderPlugin.Instance; if (renderPlugin != null) { - var mode = IsVehicleSpaceMode ? PathVisualizationMode.VehicleSpace : PathVisualizationMode.StandardLine; - renderPlugin.VisualizationMode = mode; + PathVisualizationMode mode; + string modeName; - LogManager.Info($"路径可视化模式已更改: {(IsVehicleSpaceMode ? "车辆通行空间" : "标准连线")}"); + if (IsVehicleSpaceMode) + { + mode = PathVisualizationMode.VehicleSpace; + modeName = "车辆通行空间"; + } + else if (IsRibbonLineMode) + { + mode = PathVisualizationMode.RibbonLine; + modeName = "带状连线"; + } + else + { + mode = PathVisualizationMode.StandardLine; + modeName = "柱形连线"; + } + + renderPlugin.VisualizationMode = mode; + LogManager.Info($"路径可视化模式已更改: {modeName}"); UpdateMainStatus("路径可视化模式已更新"); } else @@ -2382,6 +2439,47 @@ namespace NavisworksTransport.UI.WPF.ViewModels } } + /// + /// 控制点可视化变更事件处理 + /// + private void OnControlVisualizationChanged() + { + try + { + var renderPlugin = PathPointRenderPlugin.Instance; + if (renderPlugin != null) + { + // 更新所有路径的 ShowControlVisualization 属性 + lock (typeof(PathPointRenderPlugin)) + { + var allVisualizations = renderPlugin.GetAllPathVisualizations(); + foreach (var visualization in allVisualizations) + { + visualization.ShowControlVisualization = ShowControlVisualization; + } + } + + // 触发视图刷新 + if (NavisApplication.ActiveDocument?.ActiveView != null) + { + NavisApplication.ActiveDocument.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.Render); + } + + LogManager.Info($"控制点可视化已更改: {(ShowControlVisualization ? "显示" : "隐藏")}"); + UpdateMainStatus("控制点可视化已更新"); + } + else + { + LogManager.Warning("无法获取PathPointRenderPlugin实例"); + } + } + catch (Exception ex) + { + LogManager.Error($"应用控制点可视化设置失败: {ex.Message}", ex); + UpdateMainStatus("控制点可视化设置失败"); + } + } + /// /// 清理自动路径相关的事件订阅 /// diff --git a/src/UI/WPF/Views/PathEditingView.xaml b/src/UI/WPF/Views/PathEditingView.xaml index c494c22..9f78557 100644 --- a/src/UI/WPF/Views/PathEditingView.xaml +++ b/src/UI/WPF/Views/PathEditingView.xaml @@ -445,22 +445,33 @@ NavisworksTransport 路径编辑页签视图 - 采用与动画控制和分层管 VerticalAlignment="Center"/> - - - - + + + + +