NavisworksTransport/src/Core/PathPointRenderPlugin.cs

1004 lines
35 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.Linq;
using Autodesk.Navisworks.Api;
using Autodesk.Navisworks.Api.Plugins;
using NavisworksTransport.Core;
namespace NavisworksTransport
{
/// <summary>
/// 连线标记,用于渲染路径点之间的连接线
/// </summary>
public class LineMarker
{
/// <summary>
/// 连线起点
/// </summary>
public Point3D StartPoint { get; set; }
/// <summary>
/// 连线终点
/// </summary>
public Point3D EndPoint { get; set; }
/// <summary>
/// 连线颜色
/// </summary>
public Color Color { get; set; }
/// <summary>
/// 连线半径
/// </summary>
public double Radius { get; set; }
/// <summary>
/// 起点在路径中的索引
/// </summary>
public int FromIndex { get; set; }
/// <summary>
/// 终点在路径中的索引
/// </summary>
public int ToIndex { get; set; }
public override string ToString()
{
return $"LineMarker[{FromIndex}->{ToIndex}, 起点=({StartPoint.X:F2},{StartPoint.Y:F2},{StartPoint.Z:F2}), 终点=({EndPoint.X:F2},{EndPoint.Y:F2},{EndPoint.Z:F2})]";
}
}
/// <summary>
/// 路径可视化数据,包含一个完整路径的所有可视化元素
/// </summary>
public class PathVisualization
{
/// <summary>
/// 路径唯一标识
/// </summary>
public string PathId { get; set; }
/// <summary>
/// 路径数据引用
/// </summary>
public PathRoute PathRoute { get; set; }
/// <summary>
/// 点标记集合
/// </summary>
public List<CircleMarker> PointMarkers { get; set; }
/// <summary>
/// 连线标记集合
/// </summary>
public List<LineMarker> LineMarkers { get; set; }
/// <summary>
/// 最后更新时间
/// </summary>
public DateTime LastUpdated { get; set; }
/// <summary>
/// 构造函数
/// </summary>
public PathVisualization()
{
PointMarkers = new List<CircleMarker>();
LineMarkers = new List<LineMarker>();
LastUpdated = DateTime.Now;
}
public override string ToString()
{
return $"PathVisualization[PathId={PathId}, 点数={PointMarkers.Count}, 连线数={LineMarkers.Count}]";
}
}
/// <summary>
/// 路径点圆形标记渲染插件
/// 使用Graphics.Circle在3D空间绘制圆形标记
/// </summary>
[Plugin("PathPointRenderPlugin", "NavisworksTransport", DisplayName = "路径点圆形标记渲染器")]
public class PathPointRenderPlugin : RenderPlugin
{
private readonly object _lockObject = new object();
private Dictionary<string, PathVisualization> _pathVisualizations = new Dictionary<string, PathVisualization>();
private bool _isEnabled = true;
// 为向后兼容保留的旧字段
private List<CircleMarker> _circleMarkers = new List<CircleMarker>();
// 静态实例,用于外部访问
private static PathPointRenderPlugin _instance;
/// <summary>
/// 构造函数
/// </summary>
public PathPointRenderPlugin()
{
_instance = this;
}
/// <summary>
/// 获取静态实例
/// </summary>
public static PathPointRenderPlugin Instance => _instance;
/// <summary>
/// 是否启用渲染
/// </summary>
public bool IsEnabled
{
get { return _isEnabled; }
set
{
_isEnabled = value;
// 触发视图刷新
if (Application.ActiveDocument?.ActiveView != null)
{
Application.ActiveDocument.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.Render);
}
}
}
/// <summary>
/// 当前路径总数
/// </summary>
public int PathCount
{
get
{
lock (_lockObject)
{
return _pathVisualizations.Count;
}
}
}
/// <summary>
/// 当前点标记总数
/// </summary>
public int MarkerCount
{
get
{
lock (_lockObject)
{
return _pathVisualizations.Values.Sum(v => v.PointMarkers.Count);
}
}
}
/// <summary>
/// Navisworks渲染回调方法
/// </summary>
/// <param name="view">当前视图</param>
/// <param name="graphics">图形上下文</param>
public override void Render(View view, Graphics graphics)
{
if (!_isEnabled) return;
try
{
// 快速检查避免频繁的API调用
var activeDoc = Application.ActiveDocument;
if (activeDoc?.Models == null || activeDoc.Models.Count == 0)
{
return; // 静默返回,避免日志泛滥
}
// 检查是否有路径需要渲染
int pathCount;
lock (_lockObject)
{
pathCount = _pathVisualizations.Count;
}
if (pathCount == 0) return;
// 使用BeginModelContext确保正确的渲染上下文
graphics.BeginModelContext();
lock (_lockObject)
{
foreach (var visualization in _pathVisualizations.Values)
{
// 渲染所有点标记
foreach (var pointMarker in visualization.PointMarkers)
{
graphics.Color(pointMarker.Color, pointMarker.Alpha);
graphics.Sphere(pointMarker.Center, pointMarker.Radius);
}
// 渲染所有连线
LogManager.WriteLog($"[渲染连线] 路径 {visualization.PathId} 有 {visualization.LineMarkers.Count} 条连线");
foreach (var lineMarker in visualization.LineMarkers)
{
graphics.Color(lineMarker.Color, 1.0);
graphics.Cylinder(lineMarker.StartPoint, lineMarker.EndPoint, lineMarker.Radius);
LogManager.WriteLog($"[渲染连线] 绘制连线 {lineMarker.FromIndex}->{lineMarker.ToIndex}, 半径={lineMarker.Radius:F3}");
}
}
}
graphics.EndModelContext();
}
catch (Exception ex)
{
// 渲染异常应该静默处理避免影响Navisworks主程序
LogManager.WriteLog($"[渲染异常] {ex.Message}");
// 不输出堆栈信息,避免日志过量
}
}
#region
/// <summary>
/// 渲染完整路径
/// </summary>
/// <param name="pathRoute">路径数据</param>
public void RenderPath(PathRoute pathRoute)
{
if (pathRoute == null)
{
LogManager.WriteLog("[路径渲染] 路径数据为空");
return;
}
try
{
var visualization = new PathVisualization
{
PathId = pathRoute.Id,
PathRoute = pathRoute
};
BuildVisualization(visualization);
lock (_lockObject)
{
_pathVisualizations[pathRoute.Id] = visualization;
}
LogManager.WriteLog($"[路径渲染] 渲染路径: {pathRoute.Name}, 点数: {pathRoute.Points.Count}");
RequestViewRefresh();
}
catch (Exception ex)
{
LogManager.WriteLog($"[路径渲染] 渲染路径失败: {ex.Message}");
}
}
/// <summary>
/// 只渲染点标记,不绘制连线(用于自动路径规划的起终点显示)
/// </summary>
public void RenderPointOnly(PathRoute pathRoute)
{
if (pathRoute == null)
{
LogManager.WriteLog("[点标记渲染] 路径数据为空");
return;
}
try
{
var visualization = new PathVisualization
{
PathId = pathRoute.Id,
PathRoute = pathRoute
};
// 只构建点标记,不构建连线
BuildPointMarkersOnly(visualization);
lock (_lockObject)
{
_pathVisualizations[pathRoute.Id] = visualization;
}
LogManager.WriteLog($"[点标记渲染] 渲染点标记: {pathRoute.Name}, 点数: {pathRoute.Points.Count}");
RequestViewRefresh();
}
catch (Exception ex)
{
LogManager.WriteLog($"[点标记渲染] 渲染点标记失败: {ex.Message}");
}
}
/// <summary>
/// 只构建点标记,不构建连线
/// </summary>
private void BuildPointMarkersOnly(PathVisualization visualization)
{
// 清空现有标记
visualization.PointMarkers.Clear();
visualization.LineMarkers.Clear(); // 确保没有连线
var points = visualization.PathRoute.Points;
if (points.Count == 0) return;
// 按索引排序点
var sortedPoints = points.OrderBy(p => p.Index).ToList();
// 只构建点标记,不构建连线
foreach (var point in sortedPoints)
{
var pointMarker = CreatePointMarker(point);
visualization.PointMarkers.Add(pointMarker);
}
visualization.LastUpdated = DateTime.Now;
LogManager.WriteLog($"[点标记构建] 已构建 {visualization.PointMarkers.Count} 个点标记,无连线");
}
/// <summary>
/// 刷新路径可视化
/// </summary>
/// <param name="pathId">路径ID</param>
public void RefreshPath(string pathId)
{
lock (_lockObject)
{
if (_pathVisualizations.TryGetValue(pathId, out var visualization))
{
BuildVisualization(visualization);
LogManager.WriteLog($"[路径刷新] 刷新路径: {pathId}");
RequestViewRefresh();
}
}
}
/// <summary>
/// 移除路径
/// </summary>
/// <param name="pathId">路径ID</param>
public void RemovePath(string pathId)
{
lock (_lockObject)
{
if (_pathVisualizations.Remove(pathId))
{
LogManager.WriteLog($"[路径移除] 移除路径: {pathId}");
RequestViewRefresh();
}
}
}
/// <summary>
/// 清空所有路径
/// </summary>
public void ClearAllPaths()
{
lock (_lockObject)
{
var count = _pathVisualizations.Count;
_pathVisualizations.Clear();
LogManager.WriteLog($"[路径清空] 清空所有路径,共{count}个");
RequestViewRefresh();
}
}
/// <summary>
/// 构建路径可视化
/// </summary>
/// <param name="visualization">路径可视化对象</param>
private void BuildVisualization(PathVisualization visualization)
{
// 清空现有标记
visualization.PointMarkers.Clear();
visualization.LineMarkers.Clear();
var points = visualization.PathRoute.Points;
if (points.Count == 0) return;
// 按索引排序点
var sortedPoints = points.OrderBy(p => p.Index).ToList();
// 构建点标记
foreach (var point in sortedPoints)
{
var pointMarker = CreatePointMarker(point);
visualization.PointMarkers.Add(pointMarker);
}
// 构建连线标记(按排序后的顺序连接)
for (int i = 0; i < sortedPoints.Count - 1; i++)
{
var currentPoint = sortedPoints[i];
var nextPoint = sortedPoints[i + 1];
var lineMarker = new LineMarker
{
StartPoint = currentPoint.Position,
EndPoint = nextPoint.Position,
Color = GetLineColor(),
Radius = GetLineRadius(),
FromIndex = currentPoint.Index,
ToIndex = nextPoint.Index
};
visualization.LineMarkers.Add(lineMarker);
LogManager.WriteLog($"[连线构建] 创建连线: {currentPoint.Index} -> {nextPoint.Index}, " +
$"起点({currentPoint.Position.X:F2}, {currentPoint.Position.Y:F2}, {currentPoint.Position.Z:F2}) -> " +
$"终点({nextPoint.Position.X:F2}, {nextPoint.Position.Y:F2}, {nextPoint.Position.Z:F2})");
}
visualization.LastUpdated = DateTime.Now;
}
/// <summary>
/// 创建点标记
/// </summary>
/// <param name="point">路径点</param>
/// <returns>圆形标记</returns>
private CircleMarker CreatePointMarker(PathPoint point)
{
return new CircleMarker
{
Center = point.Position,
Normal = new Vector3D(0, 0, 1),
Radius = GetRadiusForPointType(point.Type),
Color = GetColorForPointType(point.Type),
Alpha = 1.0,
Filled = true,
PointType = point.Type,
SequenceNumber = point.Index, // 使用Index而不是任意序号
CreatedTime = DateTime.Now
};
}
/// <summary>
/// 获取连线颜色(统一使用橙色)
/// </summary>
/// <returns>连线颜色</returns>
private Color GetLineColor()
{
return Color.FromByteRGB(255, 165, 0); // 统一使用橙色连线
}
/// <summary>
/// 获取连线半径
/// </summary>
/// <returns>连线半径</returns>
private double GetLineRadius()
{
double lineRadiusInMeters = 0.2;
return lineRadiusInMeters * GetMetersToModelUnitsConversionFactor();
}
/// <summary>
/// 添加路径点到指定路径
/// </summary>
/// <param name="pathId">路径ID</param>
/// <param name="newPoint">新的路径点</param>
/// <param name="insertIndex">插入位置索引,-1表示添加到末尾</param>
public void AddPointToPath(string pathId, PathPoint newPoint, int insertIndex = -1)
{
var visualization = GetPathVisualization(pathId);
if (visualization == null)
{
LogManager.WriteLog($"[路径编辑] 未找到路径: {pathId}");
return;
}
try
{
var pathRoute = visualization.PathRoute;
if (insertIndex == -1)
{
// 添加到末尾
newPoint.Index = pathRoute.Points.Count;
pathRoute.Points.Add(newPoint);
}
else
{
// 插入到指定位置
pathRoute.Points.Insert(insertIndex, newPoint);
// 重新分配所有点的索引
ReindexPoints(pathRoute);
}
// 重建可视化
BuildVisualization(visualization);
LogManager.WriteLog($"[路径编辑] 添加路径点: {newPoint.Name} 到路径 {pathId}");
RequestViewRefresh();
}
catch (Exception ex)
{
LogManager.WriteLog($"[路径编辑] 添加路径点失败: {ex.Message}");
}
}
/// <summary>
/// 从指定路径移除路径点
/// </summary>
/// <param name="pathId">路径ID</param>
/// <param name="pointIndex">要移除的点索引</param>
public void RemovePointFromPath(string pathId, int pointIndex)
{
var visualization = GetPathVisualization(pathId);
if (visualization == null)
{
LogManager.WriteLog($"[路径编辑] 未找到路径: {pathId}");
return;
}
try
{
var pathRoute = visualization.PathRoute;
var pointToRemove = pathRoute.Points.FirstOrDefault(p => p.Index == pointIndex);
if (pointToRemove != null)
{
pathRoute.Points.Remove(pointToRemove);
// 重新分配索引
ReindexPoints(pathRoute);
// 重建可视化
BuildVisualization(visualization);
LogManager.WriteLog($"[路径编辑] 移除路径点: 索引 {pointIndex} 从路径 {pathId}");
RequestViewRefresh();
}
else
{
LogManager.WriteLog($"[路径编辑] 未找到索引为 {pointIndex} 的路径点");
}
}
catch (Exception ex)
{
LogManager.WriteLog($"[路径编辑] 移除路径点失败: {ex.Message}");
}
}
/// <summary>
/// 更新指定路径中的路径点
/// </summary>
/// <param name="pathId">路径ID</param>
/// <param name="pointIndex">要更新的点索引</param>
/// <param name="updatedPoint">更新后的路径点</param>
public void UpdatePointInPath(string pathId, int pointIndex, PathPoint updatedPoint)
{
var visualization = GetPathVisualization(pathId);
if (visualization == null)
{
LogManager.WriteLog($"[路径编辑] 未找到路径: {pathId}");
return;
}
try
{
var pathRoute = visualization.PathRoute;
var existingPoint = pathRoute.Points.FirstOrDefault(p => p.Index == pointIndex);
if (existingPoint != null)
{
// 保持索引不变
updatedPoint.Index = pointIndex;
// 替换点
var index = pathRoute.Points.IndexOf(existingPoint);
pathRoute.Points[index] = updatedPoint;
// 重建可视化
BuildVisualization(visualization);
LogManager.WriteLog($"[路径编辑] 更新路径点: 索引 {pointIndex} 在路径 {pathId}");
RequestViewRefresh();
}
else
{
LogManager.WriteLog($"[路径编辑] 未找到索引为 {pointIndex} 的路径点");
}
}
catch (Exception ex)
{
LogManager.WriteLog($"[路径编辑] 更新路径点失败: {ex.Message}");
}
}
/// <summary>
/// 重新分配路径点索引
/// </summary>
/// <param name="pathRoute">路径对象</param>
private void ReindexPoints(PathRoute pathRoute)
{
// 按照当前在List中的位置重新分配连续索引
for (int i = 0; i < pathRoute.Points.Count; i++)
{
pathRoute.Points[i].Index = i;
}
}
/// <summary>
/// 获取路径可视化对象
/// </summary>
/// <param name="pathId">路径ID</param>
/// <returns>路径可视化对象如果不存在返回null</returns>
private PathVisualization GetPathVisualization(string pathId)
{
lock (_lockObject)
{
_pathVisualizations.TryGetValue(pathId, out var visualization);
return visualization;
}
}
#endregion
#region
/// <summary>
/// [已过时] 添加球体标记 - 请使用RenderPath方法代替
/// </summary>
/// <param name="center">圆心位置</param>
/// <param name="pointType">路径点类型</param>
/// <param name="sequenceNumber">序号</param>
[Obsolete("此方法已过时请使用RenderPath方法进行统一的路径可视化", false)]
public void AddCircleMarker(Point3D center, PathPointType pointType, int sequenceNumber)
{
LogManager.WriteLog($"[兼容性警告] 使用了已过时的AddCircleMarker方法建议使用RenderPath方法");
try
{
// 为了兼容性,创建一个临时路径
var tempPath = new PathRoute($"TempPath_{Guid.NewGuid().ToString("N").Substring(0, 8)}")
{
Id = $"temp_{sequenceNumber}_{DateTime.Now.Ticks}"
};
var pathPoint = new PathPoint(center, $"Point_{sequenceNumber}", pointType)
{
Index = 0
};
tempPath.Points.Add(pathPoint);
// 使用新的渲染方法
RenderPath(tempPath);
}
catch (Exception ex)
{
LogManager.WriteLog($"[兼容性标记] 添加标记失败: {ex.Message}");
}
}
/// <summary>
/// 移除指定位置的球体标记
/// </summary>
/// <param name="position">位置</param>
/// <param name="tolerance">容差距离(米)</param>
/// <returns>是否成功移除</returns>
public bool RemoveMarkerAt(Point3D position, double tolerance = 1.0)
{
bool removed = false;
try
{
lock (_lockObject)
{
for (int i = _circleMarkers.Count - 1; i >= 0; i--)
{
var marker = _circleMarkers[i];
var distance = CalculateDistance(marker.Center, position);
if (distance <= tolerance)
{
_circleMarkers.RemoveAt(i);
removed = true;
LogManager.WriteLog($"[球体标记] 移除标记: 序号={marker.SequenceNumber}, 距离={distance:F2}m");
}
}
}
if (removed)
{
RequestViewRefresh();
}
}
catch (Exception ex)
{
LogManager.WriteLog($"[球体标记] 移除标记失败: {ex.Message}");
}
return removed;
}
/// <summary>
/// [已过时] 清除所有球体标记 - 请使用ClearAllPaths方法代替
/// </summary>
[Obsolete("此方法已过时请使用ClearAllPaths方法", false)]
public void ClearAllMarkers()
{
LogManager.WriteLog($"[兼容性警告] 使用了已过时的ClearAllMarkers方法建议使用ClearAllPaths方法");
ClearAllPaths();
}
/// <summary>
/// [已过时] 清除所有自动路径标记 - 请使用ClearAllPaths方法代替
/// </summary>
[Obsolete("此方法已过时请使用ClearAllPaths方法", false)]
public void ClearAutoPathMarkers()
{
LogManager.WriteLog($"[兼容性警告] 使用了已过时的ClearAutoPathMarkers方法建议使用ClearAllPaths方法");
ClearAllPaths();
}
/// <summary>
/// [已过时] 清除手动路径标记 - 请使用ClearAllPaths方法代替
/// </summary>
[Obsolete("此方法已过时请使用ClearAllPaths方法", false)]
public void ClearManualPathMarkers()
{
LogManager.WriteLog($"[兼容性警告] 使用了已过时的ClearManualPathMarkers方法建议使用ClearAllPaths方法");
ClearAllPaths();
}
/// <summary>
/// [已过时] 获取所有球体标记的副本 - 此方法不再适用于新的路径系统
/// </summary>
/// <returns>空列表</returns>
[Obsolete("此方法已过时,新的路径系统不使用独立的标记概念", false)]
public List<CircleMarker> GetAllMarkers()
{
LogManager.WriteLog($"[兼容性警告] 使用了已过时的GetAllMarkers方法新系统不再支持独立标记");
return new List<CircleMarker>();
}
/// <summary>
/// [已过时] 根据序号更新一个已存在的球体标记 - 请使用UpdatePointInPath方法代替
/// </summary>
[Obsolete("此方法已过时请使用UpdatePointInPath方法更新路径中的点", false)]
public void UpdateMarker(int sequenceNumber, Color newColor, double newRadius)
{
LogManager.WriteLog($"[兼容性警告] 使用了已过时的UpdateMarker方法请使用UpdatePointInPath方法");
// 由于新系统没有直接的序号对应关系,这个方法不再有效
}
#endregion
#region
/// <summary>
/// 根据路径点类型和真实文档单位获取适当的半径
/// 目标路径点半径为0.5米物理尺寸,起点/终点为0.8米物理尺寸
/// </summary>
public double GetRadiusForPointType(PathPointType pointType)
{
// 基础半径米为单位起点和终点为0.5米路径点为0.4米
double baseRadiusInMeters = pointType == PathPointType.WayPoint ? 0.4 : 0.5;
// 获取真实文档单位转换系数
double metersToModelUnits = GetMetersToModelUnitsConversionFactor();
// 转换为模型单位
double radiusInModelUnits = baseRadiusInMeters * metersToModelUnits;
//LogManager.WriteLog($"[半径计算] 类型={pointType}, 基础半径={baseRadiusInMeters}m, 转换系数={metersToModelUnits:F2}, 最终半径={radiusInModelUnits:F2}");
return radiusInModelUnits;
}
/// <summary>
/// 获取米转换为文档单位的转换系数
/// 使用Navisworks API直接获取真实文档单位而不是猜测
/// </summary>
private double GetMetersToModelUnitsConversionFactor()
{
try
{
var units = Application.ActiveDocument.Units;
//LogManager.WriteLog($"[单位检测] API返回的文档单位: {units}");
switch (units)
{
case Units.Millimeters:
//LogManager.WriteLog("[单位检测] 确认为毫米单位,转换系数=1000");
return 1000.0; // 1米 = 1000毫米
case Units.Centimeters:
//LogManager.WriteLog("[单位检测] 确认为厘米单位,转换系数=100");
return 100.0; // 1米 = 100厘米
case Units.Meters:
//LogManager.WriteLog("[单位检测] 确认为米单位,转换系数=1");
return 1.0; // 1米 = 1米
case Units.Inches:
//LogManager.WriteLog("[单位检测] 确认为英寸单位,转换系数=39.37");
return 39.37; // 1米 = 39.37英寸
case Units.Feet:
//LogManager.WriteLog("[单位检测] 确认为英尺单位,转换系数=3.281");
return 3.281; // 1米 = 3.281英尺
case Units.Kilometers:
//LogManager.WriteLog("[单位检测] 确认为公里单位,转换系数=0.001");
return 0.001; // 1米 = 0.001公里
case Units.Micrometers:
//LogManager.WriteLog("[单位检测] 确认为微米单位,转换系数=1000000");
return 1000000.0; // 1米 = 1000000微米
case Units.Microinches:
//LogManager.WriteLog("[单位检测] 确认为微英寸单位,转换系数=39370078.74");
return 39370078.74; // 1米 = 39370078.74微英寸
case Units.Mils:
//LogManager.WriteLog("[单位检测] 确认为密尔单位,转换系数=39370.08");
return 39370.08; // 1米 = 39370.08密尔
case Units.Yards:
//LogManager.WriteLog("[单位检测] 确认为码单位,转换系数=1.094");
return 1.094; // 1米 = 1.094码
case Units.Miles:
//LogManager.WriteLog("[单位检测] 确认为英里单位,转换系数=0.000621");
return 0.000621; // 1米 = 0.000621英里
default:
//LogManager.WriteLog($"[单位检测] 未知单位类型: {units},使用默认米单位,转换系数=1");
return 1.0;
}
}
catch (Exception ex)
{
LogManager.WriteLog($"[单位检测] API调用失败: {ex.Message}");
LogManager.WriteLog("[单位检测] 使用默认米单位,转换系数=1");
return 1.0;
}
}
/// <summary>
/// 根据路径点类型获取颜色
/// </summary>
public Color GetColorForPointType(PathPointType pointType)
{
switch (pointType)
{
case PathPointType.StartPoint:
return Color.Green; // 起点绿色
case PathPointType.EndPoint:
return Color.Red; // 终点红色
case PathPointType.WayPoint:
default:
return new Color(1.0, 0.0, 1.0); // 路径点洋红色RGB(1,0,1) - 高对比度避免与蓝色通道冲突
}
}
/// <summary>
/// 计算两点间距离
/// </summary>
private double CalculateDistance(Point3D point1, Point3D point2)
{
var dx = point1.X - point2.X;
var dy = point1.Y - point2.Y;
var dz = point1.Z - point2.Z;
return Math.Sqrt(dx * dx + dy * dy + dz * dz);
}
/// <summary>
/// 请求视图刷新(带防抖机制)
/// </summary>
private void RequestViewRefresh()
{
try
{
// 使用静态变量实现简单的防抖机制
var now = DateTime.Now;
if ((now - _lastRefreshTime).TotalMilliseconds < 50) // 最小间隔50ms
{
return; // 忽略过于频繁的刷新请求
}
_lastRefreshTime = now;
if (Application.ActiveDocument?.ActiveView != null)
{
Application.ActiveDocument.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.Render);
}
}
catch (Exception ex)
{
LogManager.WriteLog($"[视图刷新] 失败: {ex.Message}");
}
}
private static DateTime _lastRefreshTime = DateTime.MinValue;
#endregion
#region
/// <summary>
/// 清除路径标记(兼容性方法)
/// </summary>
public void ClearPathMarkers()
{
ClearAllMarkers();
}
/// <summary>
/// 移除路径点标记(兼容性方法)
/// </summary>
/// <param name="pathPoint">路径点</param>
/// <returns>是否成功移除</returns>
public bool RemovePathPointMarker(PathPoint pathPoint)
{
if (pathPoint?.Position != null)
{
return RemoveMarkerAt(pathPoint.Position, 1.0);
}
return false;
}
/// <summary>
/// 移除路径点标记(兼容性方法)
/// </summary>
/// <param name="marker">路径点标记</param>
/// <returns>是否成功移除</returns>
public bool RemovePathPointMarker(PathPointMarker marker)
{
if (marker?.PathPoint?.Position != null)
{
return RemoveMarkerAt(marker.PathPoint.Position, 1.0);
}
return false;
}
#endregion
#region
/// <summary>
/// 清理资源
/// </summary>
public void CleanUp()
{
ClearAllMarkers();
}
#endregion
}
/// <summary>
/// 圆形标记数据结构
/// </summary>
public class CircleMarker
{
/// <summary>
/// 圆心坐标
/// </summary>
public Point3D Center { get; set; }
/// <summary>
/// 圆面法向量
/// </summary>
public Vector3D Normal { get; set; }
/// <summary>
/// 圆形半径
/// </summary>
public double Radius { get; set; }
/// <summary>
/// 圆形颜色
/// </summary>
public Color Color { get; set; }
/// <summary>
/// 不透明度 (1.0 = 完全不透明, 0.0 = 完全透明)
/// </summary>
public double Alpha { get; set; }
/// <summary>
/// 是否填充
/// </summary>
public bool Filled { get; set; }
/// <summary>
/// 路径点类型
/// </summary>
public PathPointType PointType { get; set; }
/// <summary>
/// 序号
/// </summary>
public int SequenceNumber { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreatedTime { get; set; }
public override string ToString()
{
return $"CircleMarker[序号={SequenceNumber}, 类型={PointType}, 中心=({Center.X:F2},{Center.Y:F2},{Center.Z:F2}), 半径={Radius:F2}]";
}
}
}