NavisworksTransport/PathVisualizer.cs

621 lines
22 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using Autodesk.Navisworks.Api;
namespace NavisworksTransport
{
/// <summary>
/// 3D路径可视化组件
/// 负责在Navisworks 3D视图中绘制路径
/// </summary>
public class PathVisualizer
{
private List<PathRoute> _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; // 路径线宽度(米)
/// <summary>
/// 是否启用可视化
/// </summary>
public bool IsVisualizationEnabled
{
get { return _isVisualizationEnabled; }
set
{
_isVisualizationEnabled = value;
if (!_isVisualizationEnabled)
{
ClearAllVisualizations();
}
else
{
RefreshVisualization();
}
}
}
/// <summary>
/// 当前活动路径
/// </summary>
public PathRoute ActiveRoute
{
get { return _activeRoute; }
set
{
_activeRoute = value;
if (_isVisualizationEnabled)
{
RefreshVisualization();
}
}
}
/// <summary>
/// 路径点大小
/// </summary>
public double PointSize
{
get { return _pointSize; }
}
/// <summary>
/// 路径线宽度
/// </summary>
public double LineWidth
{
get { return _lineWidth; }
}
/// <summary>
/// 构造函数
/// </summary>
public PathVisualizer()
{
_routes = new List<PathRoute>();
_isVisualizationEnabled = true;
}
/// <summary>
/// 添加要可视化的路径
/// </summary>
/// <param name="route">路径</param>
public void AddRoute(PathRoute route)
{
if (route == null) return;
if (!_routes.Contains(route))
{
_routes.Add(route);
if (_isVisualizationEnabled)
{
VisualizeRoute(route);
}
}
}
/// <summary>
/// 移除路径可视化
/// </summary>
/// <param name="route">路径</param>
public void RemoveRoute(PathRoute route)
{
if (route == null) return;
if (_routes.Remove(route))
{
if (_isVisualizationEnabled)
{
ClearRouteVisualization(route);
}
}
}
/// <summary>
/// 清空所有路径
/// </summary>
public void ClearAllRoutes()
{
_routes.Clear();
_activeRoute = null;
if (_isVisualizationEnabled)
{
ClearAllVisualizations();
}
}
/// <summary>
/// 可视化单个路径
/// </summary>
/// <param name="route">路径</param>
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}");
}
}
/// <summary>
/// 绘制路径线条
/// </summary>
/// <param name="points">路径点集合</param>
/// <param name="lineColor">线条颜色</param>
private void DrawPathLines(List<PathPoint> 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}");
}
}
/// <summary>
/// 绘制路径点
/// </summary>
/// <param name="points">路径点集合</param>
/// <param name="isActiveRoute">是否为活动路径</param>
private void DrawPathPoints(List<PathPoint> 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}");
}
}
}
/// <summary>
/// 绘制线段
/// </summary>
/// <param name="startPoint">起点</param>
/// <param name="endPoint">终点</param>
/// <param name="color">颜色</param>
/// <param name="width">宽度</param>
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}");
}
}
/// <summary>
/// 绘制球体
/// </summary>
/// <param name="center">中心点</param>
/// <param name="radius">半径</param>
/// <param name="color">颜色</param>
private void DrawSphere(Point3D center, double radius, Autodesk.Navisworks.Api.Color color)
{
try
{
// 使用Navisworks临时图形API绘制球体
// 这里是简化实现,实际可能需要更复杂的几何创建
// 创建球体的简化表示(多个圆环)
const int segments = 12;
const int rings = 8;
for (int ring = 0; ring < rings; ring++)
{
var angle1 = Math.PI * ring / rings;
var angle2 = Math.PI * (ring + 1) / rings;
var y1 = Math.Cos(angle1) * radius;
var y2 = Math.Cos(angle2) * radius;
var r1 = Math.Sin(angle1) * radius;
var r2 = Math.Sin(angle2) * radius;
for (int segment = 0; segment < segments; segment++)
{
var theta1 = 2 * Math.PI * segment / segments;
var theta2 = 2 * Math.PI * (segment + 1) / segments;
// 创建球面上的点
var points = new Point3D[]
{
new Point3D(center.X + r1 * Math.Cos(theta1), center.Y + y1, center.Z + r1 * Math.Sin(theta1)),
new Point3D(center.X + r2 * Math.Cos(theta1), center.Y + y2, center.Z + r2 * Math.Sin(theta1)),
new Point3D(center.X + r2 * Math.Cos(theta2), center.Y + y2, center.Z + r2 * Math.Sin(theta2)),
new Point3D(center.X + r1 * Math.Cos(theta2), center.Y + y1, center.Z + r1 * Math.Sin(theta2))
};
// 这里应该使用Graphics API绘制四边形
// 由于API复杂性使用简化实现
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"绘制球体时发生错误: {ex.Message}");
}
}
/// <summary>
/// 绘制圆柱体
/// </summary>
/// <param name="center">中心点</param>
/// <param name="direction">方向向量</param>
/// <param name="height">高度</param>
/// <param name="radius">半径</param>
/// <param name="color">颜色</param>
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}");
}
}
/// <summary>
/// 创建垂直向量
/// </summary>
/// <param name="direction">方向向量</param>
/// <param name="perpendicular1">第一个垂直向量</param>
/// <param name="perpendicular2">第二个垂直向量</param>
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);
}
/// <summary>
/// 向量叉积
/// </summary>
/// <param name="a">向量A</param>
/// <param name="b">向量B</param>
/// <returns>叉积结果</returns>
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
);
}
/// <summary>
/// 向量标准化
/// </summary>
/// <param name="vector">向量</param>
/// <returns>标准化后的向量</returns>
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);
}
/// <summary>
/// 绘制点标签
/// </summary>
/// <param name="position">位置</param>
/// <param name="text">文本</param>
/// <param name="color">颜色</param>
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}");
}
}
/// <summary>
/// 获取路径点颜色
/// </summary>
/// <param name="type">路径点类型</param>
/// <returns>颜色</returns>
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;
}
}
/// <summary>
/// 清除路径可视化
/// </summary>
/// <param name="route">路径</param>
private void ClearRouteVisualization(PathRoute route)
{
try
{
// 这里应该清除特定路径的可视化元素
// 由于Navisworks API的限制可能需要重新绘制所有路径
RefreshVisualization();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"清除路径可视化时发生错误: {ex.Message}");
}
}
/// <summary>
/// 清除所有可视化
/// </summary>
private void ClearAllVisualizations()
{
try
{
// 使用Navisworks API清除所有临时图形
Application.ActiveDocument.Models.ResetAllTemporaryMaterials();
// 刷新视图
Application.ActiveDocument.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.All);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"清除所有可视化时发生错误: {ex.Message}");
}
}
/// <summary>
/// 刷新可视化
/// </summary>
public void RefreshVisualization()
{
if (!_isVisualizationEnabled) return;
try
{
// 清除现有可视化
ClearAllVisualizations();
// 重新绘制所有路径
foreach (var route in _routes)
{
VisualizeRoute(route);
}
// 刷新视图
Application.ActiveDocument.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.All);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"刷新可视化时发生错误: {ex.Message}");
}
}
/// <summary>
/// 设置路径可见性
/// </summary>
/// <param name="route">路径</param>
/// <param name="visible">是否可见</param>
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);
}
}
/// <summary>
/// 获取可视化统计信息
/// </summary>
/// <returns>统计信息</returns>
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 ? "" : "")}";
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
try
{
ClearAllVisualizations();
_routes.Clear();
_activeRoute = null;
}
catch
{
// 忽略清理错误
}
}
}
}