674 lines
27 KiB
C#
674 lines
27 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using Autodesk.Navisworks.Api;
|
||
using Autodesk.Navisworks.Api.Plugins;
|
||
|
||
namespace NavisworksTransport
|
||
{
|
||
/// <summary>
|
||
/// 路径点圆形标记渲染插件
|
||
/// 使用Graphics.Circle在3D空间绘制圆形标记
|
||
/// </summary>
|
||
[Plugin("PathPointRenderPlugin", "NavisworksTransport", DisplayName = "路径点圆形标记渲染器")]
|
||
public class PathPointRenderPlugin : RenderPlugin
|
||
{
|
||
private readonly object _lockObject = new object();
|
||
private List<CircleMarker> _circleMarkers = new List<CircleMarker>();
|
||
private bool _isEnabled = true;
|
||
|
||
// 静态实例,用于外部访问
|
||
private static PathPointRenderPlugin _instance;
|
||
|
||
/// <summary>
|
||
/// 构造函数
|
||
/// </summary>
|
||
public PathPointRenderPlugin()
|
||
{
|
||
_instance = this;
|
||
LogManager.WriteLog("[RenderPlugin] PathPointRenderPlugin构造函数被调用");
|
||
}
|
||
|
||
/// <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 MarkerCount
|
||
{
|
||
get
|
||
{
|
||
lock (_lockObject)
|
||
{
|
||
return _circleMarkers.Count;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Navisworks渲染回调方法
|
||
/// </summary>
|
||
/// <param name="view">当前视图</param>
|
||
/// <param name="graphics">图形上下文</param>
|
||
public override void Render(View view, Graphics graphics)
|
||
{
|
||
LogManager.WriteLog($"[Render入口] ✓ Render方法被调用, IsEnabled={_isEnabled}");
|
||
|
||
if (!_isEnabled) return;
|
||
|
||
try
|
||
{
|
||
// 首先检查文档和模型状态
|
||
var activeDoc = Application.ActiveDocument;
|
||
LogManager.WriteLog($"[文档状态] ActiveDocument: {activeDoc?.GetType().Name ?? "null"}");
|
||
|
||
if (activeDoc == null)
|
||
{
|
||
LogManager.WriteLog($"[文档状态] ❌ 没有活动文档,跳过渲染");
|
||
return;
|
||
}
|
||
|
||
if (activeDoc.Models == null || activeDoc.Models.Count == 0)
|
||
{
|
||
LogManager.WriteLog($"[文档状态] ❌ 没有加载的模型,跳过渲染");
|
||
return;
|
||
}
|
||
|
||
LogManager.WriteLog($"[文档状态] ✓ 文档正常,模型数量: {activeDoc.Models.Count}");
|
||
LogManager.WriteLog($"[Graphics状态] Graphics对象: {graphics?.GetType().Name ?? "null"}");
|
||
LogManager.WriteLog($"[Graphics状态] View对象: {view?.GetType().Name ?? "null"}");
|
||
|
||
// 详细的视图和相机诊断信息
|
||
try
|
||
{
|
||
LogManager.WriteLog($"[视图诊断] 开始获取视图信息");
|
||
|
||
// 尝试获取第一个模型的信息
|
||
var firstModel = activeDoc.Models.First();
|
||
LogManager.WriteLog($"[视图诊断] 第一个模型文件名: {firstModel.FileName}");
|
||
|
||
// 尝试获取根项目信息
|
||
var rootItem = firstModel.RootItem;
|
||
if (rootItem != null)
|
||
{
|
||
LogManager.WriteLog($"[视图诊断] 根项目显示名: {rootItem.DisplayName}");
|
||
LogManager.WriteLog($"[视图诊断] 根项目子项数量: {rootItem.Children.Count()}");
|
||
}
|
||
}
|
||
catch (Exception viewEx)
|
||
{
|
||
LogManager.WriteLog($"[视图诊断] 获取视图信息失败: {viewEx.Message}");
|
||
}
|
||
|
||
// 使用BeginModelContext确保正确的渲染上下文
|
||
graphics.BeginModelContext();
|
||
LogManager.WriteLog($"[Graphics状态] BeginModelContext完成");
|
||
|
||
// 超大超明显的测试线段 - 覆盖整个模型范围
|
||
graphics.Color(Color.Red, 0.0);
|
||
graphics.LineWidth(50); // 超粗线条
|
||
|
||
LogManager.WriteLog($"[Graphics状态] Color和LineWidth设置完成");
|
||
|
||
// 视线前方测试:使用正确的Navisworks API获取当前视点
|
||
try
|
||
{
|
||
LogManager.WriteLog($"[视线测试] 开始获取当前视点信息");
|
||
|
||
// 使用正确的API获取当前视点
|
||
var document = Application.ActiveDocument;
|
||
var currentViewpoint = document.CurrentViewpoint.CreateCopy();
|
||
|
||
// 获取相机位置和旋转
|
||
var cameraPosition = currentViewpoint.Position;
|
||
var cameraRotation = currentViewpoint.Rotation;
|
||
|
||
LogManager.WriteLog($"[视线测试] 相机位置: ({cameraPosition.X:F2}, {cameraPosition.Y:F2}, {cameraPosition.Z:F2})");
|
||
|
||
LogManager.WriteLog($"[视线测试] 相机旋转信息获取成功");
|
||
|
||
// 使用最简单的方法:在相机位置周围绘制球体
|
||
graphics.Color(Color.Red, 0.0); // 完全不透明红色
|
||
|
||
// 在相机位置的前、后、左、右、上、下绘制红球
|
||
var offsets = new[]
|
||
{
|
||
new Vector3D(0, 0, -50), // 前方
|
||
new Vector3D(0, 0, 50), // 后方
|
||
new Vector3D(-50, 0, 0), // 左侧
|
||
new Vector3D(50, 0, 0), // 右侧
|
||
new Vector3D(0, 50, 0), // 上方
|
||
new Vector3D(0, -50, 0), // 下方
|
||
};
|
||
|
||
foreach (var offset in offsets)
|
||
{
|
||
var ballPosition = new Point3D(
|
||
cameraPosition.X + offset.X,
|
||
cameraPosition.Y + offset.Y,
|
||
cameraPosition.Z + offset.Z
|
||
);
|
||
|
||
graphics.Sphere(ballPosition, 10.0); // 10单位半径
|
||
LogManager.WriteLog($"[视线测试] 红球位置: ({ballPosition.X:F2}, {ballPosition.Y:F2}, {ballPosition.Z:F2})");
|
||
}
|
||
|
||
LogManager.WriteLog($"[视线测试] ✓ 完成在相机周围绘制 {offsets.Length} 个红球");
|
||
}
|
||
catch (Exception viewEx)
|
||
{
|
||
LogManager.WriteLog($"[视线测试] ❌ 视线测试异常: {viewEx.Message}");
|
||
|
||
// 备用方案:简单位置绘制
|
||
LogManager.WriteLog($"[视线测试] 使用备用方案:固定位置绘制");
|
||
graphics.Color(Color.Red, 0.0);
|
||
var backupPositions = new[]
|
||
{
|
||
new Point3D(0, 0, 0), // 原点
|
||
new Point3D(100, 100, 100), // 正方向
|
||
new Point3D(-100, -100, -100), // 负方向
|
||
};
|
||
|
||
foreach (var pos in backupPositions)
|
||
{
|
||
graphics.Sphere(pos, 20.0);
|
||
LogManager.WriteLog($"[视线测试] 备用红球: ({pos.X}, {pos.Y}, {pos.Z})");
|
||
}
|
||
}
|
||
var sphereCenter = new Point3D(0, 0, 0); // 原点位置
|
||
var sphereRadius = 50000.0; // 超大半径,50米
|
||
|
||
try
|
||
{
|
||
graphics.Sphere(sphereCenter, sphereRadius);
|
||
LogManager.WriteLog($"[球体测试] ✓ 绘制超大红色球体: 中心(0,0,0), 半径={sphereRadius}");
|
||
}
|
||
catch (Exception sphereEx)
|
||
{
|
||
LogManager.WriteLog($"[球体测试] ❌ Sphere调用异常: {sphereEx.Message}");
|
||
}
|
||
|
||
// 再在模型区域绘制一个球体
|
||
var modelCenter = new Point3D(27000.0, -10000.0, 1000.0);
|
||
var modelRadius = 5000.0; // 5米半径
|
||
|
||
try
|
||
{
|
||
graphics.Sphere(modelCenter, modelRadius);
|
||
LogManager.WriteLog($"[球体测试] ✓ 绘制模型区域球体: 中心({modelCenter.X}, {modelCenter.Y}, {modelCenter.Z}), 半径={modelRadius}");
|
||
}
|
||
catch (Exception modelSphereEx)
|
||
{
|
||
LogManager.WriteLog($"[球体测试] ❌ 模型球体调用异常: {modelSphereEx.Message}");
|
||
}
|
||
|
||
// 先绘制测试大圆形 - 验证Graphics.Circle API
|
||
var testCenter = new Point3D(19082.41, -18248.14, 4037.26);
|
||
var testRadius = 200.0; // 200英寸大圆,应该非常明显
|
||
var testColor = new Color(1.0, 0.0, 0.0); // 红色,高对比度
|
||
|
||
graphics.Color(testColor, 0.0); // 完全不透明红色
|
||
graphics.Circle(testCenter, new Vector3D(0, 0, 1), testRadius, true); // 实心圆
|
||
LogManager.WriteLog($"[测试圆形] 绘制测试大圆: 中心({testCenter.X:F2}, {testCenter.Y:F2}, {testCenter.Z:F2}), 半径={testRadius:F2}, 颜色=红色");
|
||
|
||
lock (_lockObject)
|
||
{
|
||
if (_circleMarkers.Count > 0)
|
||
{
|
||
LogManager.WriteLog($"[圆形渲染] 开始渲染 {_circleMarkers.Count} 个圆形标记");
|
||
}
|
||
|
||
// 遍历所有圆形标记并绘制
|
||
foreach (var marker in _circleMarkers)
|
||
{
|
||
// 设置颜色和透明度
|
||
graphics.Color(marker.Color, marker.Transparency);
|
||
|
||
// 绘制圆形标记
|
||
graphics.Circle(marker.Center, marker.Normal, marker.Radius, marker.Filled);
|
||
|
||
LogManager.WriteLog($"[圆形渲染] 绘制圆形: 中心({marker.Center.X:F2}, {marker.Center.Y:F2}, {marker.Center.Z:F2}), 半径={marker.Radius:F2}, 序号={marker.SequenceNumber}");
|
||
}
|
||
}
|
||
|
||
// 结束ModelContext
|
||
graphics.EndModelContext();
|
||
LogManager.WriteLog($"[Graphics状态] EndModelContext完成");
|
||
|
||
LogManager.WriteLog($"[Graphics状态] === 3D渲染完成,如果仍看不到图形,问题可能在Graphics API兼容性 ===");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.WriteLog($"[圆形渲染] 渲染错误: {ex.Message}");
|
||
LogManager.WriteLog($"[圆形渲染] 异常堆栈: {ex.StackTrace}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 2D覆盖层渲染方法
|
||
/// </summary>
|
||
/// <param name="view">当前视图</param>
|
||
/// <param name="graphics">图形上下文</param>
|
||
public override void OverlayRender(View view, Graphics graphics)
|
||
{
|
||
LogManager.WriteLog($"[OverlayRender入口] ✓ OverlayRender方法被调用, IsEnabled={_isEnabled}");
|
||
|
||
if (!_isEnabled) return;
|
||
|
||
try
|
||
{
|
||
// 首先检查文档和模型状态
|
||
var activeDoc = Application.ActiveDocument;
|
||
LogManager.WriteLog($"[OverlayRender] ActiveDocument: {activeDoc?.GetType().Name ?? "null"}");
|
||
|
||
if (activeDoc == null)
|
||
{
|
||
LogManager.WriteLog($"[OverlayRender] ❌ 没有活动文档,跳过2D渲染");
|
||
return;
|
||
}
|
||
|
||
if (activeDoc.Models == null || activeDoc.Models.Count == 0)
|
||
{
|
||
LogManager.WriteLog($"[OverlayRender] ❌ 没有加载的模型,跳过2D渲染");
|
||
return;
|
||
}
|
||
|
||
LogManager.WriteLog($"[OverlayRender] ✓ 文档正常,开始2D渲染");
|
||
|
||
// 检查Graphics对象状态
|
||
LogManager.WriteLog($"[OverlayRender] Graphics对象类型: {graphics?.GetType().Name}");
|
||
LogManager.WriteLog($"[OverlayRender] View对象: {view?.GetType().Name ?? "null"}");
|
||
|
||
// 使用最简单的API测试
|
||
var red = Color.FromByteRGB(255, 0, 0);
|
||
graphics.Color(red, 0.0); // 完全不透明的红色
|
||
LogManager.WriteLog($"[OverlayRender] 设置颜色: R=255, G=0, B=0, Alpha=0.0");
|
||
|
||
graphics.LineWidth(20); // 很粗的线
|
||
LogManager.WriteLog($"[OverlayRender] 设置线宽: 20");
|
||
|
||
// 绘制一条从屏幕左上角到右下角的对角线
|
||
try
|
||
{
|
||
var startPoint = new Point3D(0, 0, 0);
|
||
var endPoint = new Point3D(800, 600, 0);
|
||
graphics.Line(startPoint, endPoint);
|
||
LogManager.WriteLog($"[OverlayRender] ✓ 绘制对角线: (0,0) 到 (800,600)");
|
||
}
|
||
catch (Exception lineEx)
|
||
{
|
||
LogManager.WriteLog($"[OverlayRender] ❌ Line调用异常: {lineEx.Message}");
|
||
}
|
||
|
||
// 尝试绘制一个简单的点
|
||
try
|
||
{
|
||
graphics.Point(new Point3D(100, 100, 0));
|
||
LogManager.WriteLog($"[OverlayRender] ✓ 绘制点: (100,100)");
|
||
}
|
||
catch (Exception pointEx)
|
||
{
|
||
LogManager.WriteLog($"[OverlayRender] ❌ Point调用异常: {pointEx.Message}");
|
||
}
|
||
|
||
// 尝试强制刷新
|
||
try
|
||
{
|
||
if (view != null)
|
||
{
|
||
view.RequestDelayedRedraw(ViewRedrawRequests.Render);
|
||
LogManager.WriteLog($"[OverlayRender] ✓ 请求覆盖层重绘");
|
||
}
|
||
}
|
||
catch (Exception refreshEx)
|
||
{
|
||
LogManager.WriteLog($"[OverlayRender] ❌ 重绘请求异常: {refreshEx.Message}");
|
||
}
|
||
|
||
LogManager.WriteLog($"[OverlayRender] === 2D覆盖层绘制完成 ===");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.WriteLog($"[OverlayRender] 渲染错误: {ex.Message}");
|
||
LogManager.WriteLog($"[OverlayRender] 异常堆栈: {ex.StackTrace}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加圆形标记
|
||
/// </summary>
|
||
/// <param name="center">圆心位置</param>
|
||
/// <param name="pointType">路径点类型</param>
|
||
/// <param name="sequenceNumber">序号</param>
|
||
public void AddCircleMarker(Point3D center, PathPointType pointType, int sequenceNumber)
|
||
{
|
||
try
|
||
{
|
||
var marker = new CircleMarker
|
||
{
|
||
Center = center,
|
||
Normal = new Vector3D(0, 0, 1), // 垂直向上
|
||
Radius = GetRadiusForPointType(pointType),
|
||
Color = GetColorForPointType(pointType),
|
||
Transparency = 0.0, // 完全不透明,更容易看见
|
||
Filled = true, // 实心圆
|
||
PointType = pointType,
|
||
SequenceNumber = sequenceNumber,
|
||
CreatedTime = DateTime.Now
|
||
};
|
||
|
||
lock (_lockObject)
|
||
{
|
||
_circleMarkers.Add(marker);
|
||
}
|
||
|
||
LogManager.WriteLog($"[圆形标记] 添加圆形标记: 类型={pointType}, 序号={sequenceNumber}, 中心=({center.X:F2}, {center.Y:F2}, {center.Z:F2})");
|
||
|
||
// 触发视图刷新
|
||
RequestViewRefresh();
|
||
}
|
||
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>
|
||
/// 清除所有圆形标记
|
||
/// </summary>
|
||
public void ClearAllMarkers()
|
||
{
|
||
try
|
||
{
|
||
int removedCount = 0;
|
||
|
||
lock (_lockObject)
|
||
{
|
||
removedCount = _circleMarkers.Count;
|
||
_circleMarkers.Clear();
|
||
}
|
||
|
||
LogManager.WriteLog($"[圆形标记] 清除所有标记,共移除 {removedCount} 个圆形标记");
|
||
|
||
if (removedCount > 0)
|
||
{
|
||
RequestViewRefresh();
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.WriteLog($"[圆形标记] 清除标记失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取所有标记的副本
|
||
/// </summary>
|
||
/// <returns>标记列表</returns>
|
||
public List<CircleMarker> GetAllMarkers()
|
||
{
|
||
lock (_lockObject)
|
||
{
|
||
return new List<CircleMarker>(_circleMarkers);
|
||
}
|
||
}
|
||
|
||
#region 私有辅助方法
|
||
|
||
/// <summary>
|
||
/// 根据路径点类型和真实文档单位获取适当的半径
|
||
/// 目标:路径点半径为0.5米物理尺寸,起点/终点为0.8米物理尺寸
|
||
/// </summary>
|
||
private double GetRadiusForPointType(PathPointType pointType)
|
||
{
|
||
// 基础半径(米为单位)
|
||
double baseRadiusInMeters = pointType == PathPointType.WayPoint ? 0.5 : 0.8;
|
||
|
||
// 获取真实文档单位转换系数
|
||
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>
|
||
private 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
|
||
{
|
||
if (Application.ActiveDocument?.ActiveView != null)
|
||
{
|
||
Application.ActiveDocument.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.Render);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.WriteLog($"[圆形标记] 视图刷新失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
#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>
|
||
/// 透明度 (0.0-1.0)
|
||
/// </summary>
|
||
public double Transparency { 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}]";
|
||
}
|
||
}
|
||
} |