using System; using System.Collections.Generic; using System.Linq; using Autodesk.Navisworks.Api; namespace NavisworksTransport { /// /// 3D路径可视化组件 /// 负责在Navisworks 3D视图中绘制路径 /// public class PathVisualizer { private List _routes; private PathRoute _activeRoute; private bool _isVisualizationEnabled; // 可视化样式配置 private readonly Autodesk.Navisworks.Api.Color _startPointColor = Autodesk.Navisworks.Api.Color.Green; private readonly Autodesk.Navisworks.Api.Color _endPointColor = Autodesk.Navisworks.Api.Color.Red; private readonly Autodesk.Navisworks.Api.Color _wayPointColor = Autodesk.Navisworks.Api.Color.Blue; private readonly Autodesk.Navisworks.Api.Color _pathLineColor = Autodesk.Navisworks.Api.Color.Blue; private readonly Autodesk.Navisworks.Api.Color _activeRouteColor = new Autodesk.Navisworks.Api.Color(1.0, 0.5, 0.0); private readonly double _pointSize = 0.5; // 路径点大小(米) private readonly double _lineWidth = 0.1; // 路径线宽度(米) /// /// 是否启用可视化 /// public bool IsVisualizationEnabled { get { return _isVisualizationEnabled; } set { _isVisualizationEnabled = value; if (!_isVisualizationEnabled) { ClearAllVisualizations(); } else { RefreshVisualization(); } } } /// /// 当前活动路径 /// public PathRoute ActiveRoute { get { return _activeRoute; } set { _activeRoute = value; if (_isVisualizationEnabled) { RefreshVisualization(); } } } /// /// 路径点大小 /// public double PointSize { get { return _pointSize; } } /// /// 路径线宽度 /// public double LineWidth { get { return _lineWidth; } } /// /// 构造函数 /// public PathVisualizer() { _routes = new List(); _isVisualizationEnabled = true; } /// /// 添加要可视化的路径 /// /// 路径 public void AddRoute(PathRoute route) { if (route == null) return; if (!_routes.Contains(route)) { _routes.Add(route); if (_isVisualizationEnabled) { VisualizeRoute(route); } } } /// /// 移除路径可视化 /// /// 路径 public void RemoveRoute(PathRoute route) { if (route == null) return; if (_routes.Remove(route)) { if (_isVisualizationEnabled) { ClearRouteVisualization(route); } } } /// /// 清空所有路径 /// public void ClearAllRoutes() { _routes.Clear(); _activeRoute = null; if (_isVisualizationEnabled) { ClearAllVisualizations(); } } /// /// 可视化单个路径 /// /// 路径 public void VisualizeRoute(PathRoute route) { if (route == null || !route.IsValid()) return; try { // 先清除该路径的现有可视化 ClearRouteVisualization(route); var sortedPoints = route.GetSortedPoints(); if (sortedPoints.Count < 2) return; bool isActiveRoute = route == _activeRoute; var lineColor = isActiveRoute ? _activeRouteColor : _pathLineColor; // 绘制路径线条 DrawPathLines(sortedPoints, lineColor); // 绘制路径点 DrawPathPoints(sortedPoints, isActiveRoute); } catch (Exception ex) { // 记录错误但不中断程序 System.Diagnostics.Debug.WriteLine($"可视化路径时发生错误: {ex.Message}"); } } /// /// 绘制路径线条 /// /// 路径点集合 /// 线条颜色 private void DrawPathLines(List points, Autodesk.Navisworks.Api.Color lineColor) { if (points.Count < 2) return; try { // 绘制线段 for (int i = 0; i < points.Count - 1; i++) { var startPoint = points[i].Position; var endPoint = points[i + 1].Position; // 创建线段几何 DrawLine(startPoint, endPoint, lineColor, _lineWidth); } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"绘制路径线条时发生错误: {ex.Message}"); } } /// /// 绘制路径点 /// /// 路径点集合 /// 是否为活动路径 private void DrawPathPoints(List points, bool isActiveRoute) { foreach (var point in points) { try { var pointColor = GetPointColor(point.Type); var pointSize = isActiveRoute ? _pointSize * 1.5 : _pointSize; // 绘制路径点球体 DrawSphere(point.Position, pointSize, pointColor); // 绘制点标签(如果有名称) if (!string.IsNullOrEmpty(point.Name)) { DrawPointLabel(point.Position, point.Name, pointColor); } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"绘制路径点时发生错误: {ex.Message}"); } } } /// /// 绘制线段 /// /// 起点 /// 终点 /// 颜色 /// 宽度 private void DrawLine(Point3D startPoint, Point3D endPoint, Autodesk.Navisworks.Api.Color color, double width) { try { // 计算线段方向和长度 var direction = new Vector3D( 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) return; // 忽略过短的线段 // 标准化方向向量 direction = new Vector3D( direction.X / length, direction.Y / length, direction.Z / length ); // 创建圆柱体几何来表示线段 var cylinderCenter = new Point3D( (startPoint.X + endPoint.X) / 2, (startPoint.Y + endPoint.Y) / 2, (startPoint.Z + endPoint.Z) / 2 ); // 使用临时图形绘制 using (var state = Application.ActiveDocument.State) { // 这里可以使用Navisworks的临时图形API // 由于API限制,我们使用简化的方法 DrawCylinder(cylinderCenter, direction, length, width / 2, color); } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"绘制线段时发生错误: {ex.Message}"); } } /// /// 绘制球体(路径点标记) /// /// 中心点 /// 半径 /// 颜色 public void DrawSphere(Point3D center, double radius, Autodesk.Navisworks.Api.Color color) { try { LogManager.WriteLog($"[PathVisualizer] 开始绘制球体: 中心({center.X:F3}, {center.Y:F3}, {center.Z:F3}), 半径={radius:F3}"); // 使用Navisworks临时几何API绘制球体 // 简化实现:绘制多个圆环来模拟球体 const int segments = 8; // 减少分段数以提高性能 const int rings = 6; // 减少环数以提高性能 var vertices = new List(); // 生成球体的顶点 for (int ring = 0; ring <= rings; ring++) { var phi = Math.PI * ring / rings; // 纬度角 var y = Math.Cos(phi) * radius; var ringRadius = Math.Sin(phi) * radius; for (int segment = 0; segment < segments; segment++) { var theta = 2 * Math.PI * segment / segments; // 经度角 var x = Math.Cos(theta) * ringRadius; var z = Math.Sin(theta) * ringRadius; var vertex = new Point3D(center.X + x, center.Y + y, center.Z + z); vertices.Add(vertex); } } // 绘制纬线(水平圆环) for (int ring = 0; ring <= rings; ring++) { for (int segment = 0; segment < segments; segment++) { var current = ring * segments + segment; var next = ring * segments + ((segment + 1) % segments); if (current < vertices.Count && next < vertices.Count) { DrawLine(vertices[current], vertices[next], color, radius * 0.1); } } } // 绘制经线(垂直线) for (int segment = 0; segment < segments; segment++) { for (int ring = 0; ring < rings; ring++) { var current = ring * segments + segment; var next = (ring + 1) * segments + segment; if (current < vertices.Count && next < vertices.Count) { DrawLine(vertices[current], vertices[next], color, radius * 0.1); } } } LogManager.WriteLog($"[PathVisualizer] 球体绘制完成,共绘制 {vertices.Count} 个顶点"); } catch (Exception ex) { LogManager.WriteLog($"[PathVisualizer] 绘制球体时发生错误: {ex.Message}"); System.Diagnostics.Debug.WriteLine($"绘制球体时发生错误: {ex.Message}"); } } /// /// 绘制圆柱体 /// /// 中心点 /// 方向向量 /// 高度 /// 半径 /// 颜色 private void DrawCylinder(Point3D center, Vector3D direction, double height, double radius, Autodesk.Navisworks.Api.Color color) { try { // 圆柱体绘制的简化实现 // 实际应用中需要使用Navisworks Graphics API const int segments = 12; var halfHeight = height / 2; // 计算圆柱体的两个端点 var startCenter = new Point3D( center.X - direction.X * halfHeight, center.Y - direction.Y * halfHeight, center.Z - direction.Z * halfHeight ); var endCenter = new Point3D( center.X + direction.X * halfHeight, center.Y + direction.Y * halfHeight, center.Z + direction.Z * halfHeight ); // 创建垂直于方向的向量 Vector3D perpendicular1, perpendicular2; CreatePerpendicularVectors(direction, out perpendicular1, out perpendicular2); // 绘制圆柱体侧面 for (int i = 0; i < segments; i++) { var angle1 = 2 * Math.PI * i / segments; var angle2 = 2 * Math.PI * (i + 1) / segments; var cos1 = Math.Cos(angle1); var sin1 = Math.Sin(angle1); var cos2 = Math.Cos(angle2); var sin2 = Math.Sin(angle2); // 计算圆周上的点 var offset1 = new Vector3D( perpendicular1.X * cos1 + perpendicular2.X * sin1, perpendicular1.Y * cos1 + perpendicular2.Y * sin1, perpendicular1.Z * cos1 + perpendicular2.Z * sin1 ); var offset2 = new Vector3D( perpendicular1.X * cos2 + perpendicular2.X * sin2, perpendicular1.Y * cos2 + perpendicular2.Y * sin2, perpendicular1.Z * cos2 + perpendicular2.Z * sin2 ); // 计算四个顶点 var p1 = new Point3D(startCenter.X + offset1.X * radius, startCenter.Y + offset1.Y * radius, startCenter.Z + offset1.Z * radius); var p2 = new Point3D(endCenter.X + offset1.X * radius, endCenter.Y + offset1.Y * radius, endCenter.Z + offset1.Z * radius); var p3 = new Point3D(endCenter.X + offset2.X * radius, endCenter.Y + offset2.Y * radius, endCenter.Z + offset2.Z * radius); var p4 = new Point3D(startCenter.X + offset2.X * radius, startCenter.Y + offset2.Y * radius, startCenter.Z + offset2.Z * radius); // 这里应该使用Graphics API绘制四边形 // 由于API复杂性,使用简化实现 } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"绘制圆柱体时发生错误: {ex.Message}"); } } /// /// 创建垂直向量 /// /// 方向向量 /// 第一个垂直向量 /// 第二个垂直向量 private void CreatePerpendicularVectors(Vector3D direction, out Vector3D perpendicular1, out Vector3D perpendicular2) { // 找到一个与direction不平行的向量 Vector3D temp; if (Math.Abs(direction.X) < 0.9) { temp = new Vector3D(1, 0, 0); } else { temp = new Vector3D(0, 1, 0); } // 计算第一个垂直向量(叉积) perpendicular1 = CrossProduct(direction, temp); perpendicular1 = Normalize(perpendicular1); // 计算第二个垂直向量 perpendicular2 = CrossProduct(direction, perpendicular1); perpendicular2 = Normalize(perpendicular2); } /// /// 向量叉积 /// /// 向量A /// 向量B /// 叉积结果 private Vector3D CrossProduct(Vector3D a, Vector3D b) { return new Vector3D( a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X ); } /// /// 向量标准化 /// /// 向量 /// 标准化后的向量 private Vector3D Normalize(Vector3D vector) { var length = Math.Sqrt(vector.X * vector.X + vector.Y * vector.Y + vector.Z * vector.Z); if (length < 0.001) return new Vector3D(1, 0, 0); return new Vector3D(vector.X / length, vector.Y / length, vector.Z / length); } /// /// 绘制点标签 /// /// 位置 /// 文本 /// 颜色 private void DrawPointLabel(Point3D position, string text, Autodesk.Navisworks.Api.Color color) { try { // 在点的上方偏移位置绘制文本标签 var labelPosition = new Point3D(position.X, position.Y, position.Z + _pointSize * 2); // 这里应该使用Navisworks的文本绘制API // 由于API限制,这里是简化实现 // 实际实现可能需要创建临时的文本几何或使用注释功能 } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"绘制点标签时发生错误: {ex.Message}"); } } /// /// 获取路径点颜色 /// /// 路径点类型 /// 颜色 private Autodesk.Navisworks.Api.Color GetPointColor(PathPointType type) { switch (type) { case PathPointType.StartPoint: return _startPointColor; case PathPointType.EndPoint: return _endPointColor; case PathPointType.WayPoint: return _wayPointColor; default: return _wayPointColor; } } /// /// 清除路径可视化 /// /// 路径 private void ClearRouteVisualization(PathRoute route) { try { // 这里应该清除特定路径的可视化元素 // 由于Navisworks API的限制,可能需要重新绘制所有路径 RefreshVisualization(); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"清除路径可视化时发生错误: {ex.Message}"); } } /// /// 清除所有可视化 /// /// 是否保留通道高亮 private void ClearAllVisualizations(bool preserveChannelHighlight = true) { try { if (!preserveChannelHighlight) { // 只有在明确要求时才清除所有临时材质(包括通道高亮) Application.ActiveDocument.Models.ResetAllTemporaryMaterials(); } // 如果preserveChannelHighlight为true,则不调用ResetAllTemporaryMaterials // 这样可以保留通道的绿色高亮显示 // 刷新视图 Application.ActiveDocument.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.All); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"清除所有可视化时发生错误: {ex.Message}"); } } /// /// 刷新可视化 /// public void RefreshVisualization() { if (!_isVisualizationEnabled) return; try { // 清除现有可视化,但保留通道高亮 ClearAllVisualizations(preserveChannelHighlight: true); // 重新绘制所有路径 foreach (var route in _routes) { VisualizeRoute(route); } // 刷新视图 Application.ActiveDocument.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.All); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"刷新可视化时发生错误: {ex.Message}"); } } /// /// 设置路径可见性 /// /// 路径 /// 是否可见 public void SetRouteVisibility(PathRoute route, bool visible) { if (route == null) return; if (visible) { if (!_routes.Contains(route)) { AddRoute(route); } else if (_isVisualizationEnabled) { VisualizeRoute(route); } } else { RemoveRoute(route); } } /// /// 获取可视化统计信息 /// /// 统计信息 public string GetVisualizationStats() { var totalPoints = _routes.Sum(r => r.Points.Count); var totalLines = _routes.Sum(r => Math.Max(0, r.Points.Count - 1)); return $"可视化路径: {_routes.Count}条\n" + $"路径点: {totalPoints}个\n" + $"路径线段: {totalLines}段\n" + $"可视化状态: {(_isVisualizationEnabled ? "启用" : "禁用")}"; } /// /// 释放资源 /// public void Dispose() { try { // 在释放时清除所有可视化,包括通道高亮 ClearAllVisualizations(preserveChannelHighlight: false); _routes.Clear(); _activeRoute = null; } catch { // 忽略清理错误 } } } }