将网格点可视化从球和立方体,改为圆形和正方形

This commit is contained in:
tian 2025-10-18 16:43:17 +08:00
parent 9c97633411
commit 55fbcbdb48
3 changed files with 105 additions and 110 deletions

View File

@ -34,14 +34,14 @@ namespace NavisworksTransport
Sphere,
/// <summary>
/// 立方体
/// 正方形
/// </summary>
Cube,
Rectangle,
/// <summary>
///
///
/// </summary>
Point
Circle
}
@ -291,13 +291,13 @@ namespace NavisworksTransport
private readonly object _lockObject = new object();
private Dictionary<string, PathVisualization> _pathVisualizations = new Dictionary<string, PathVisualization>();
private bool _isEnabled = true;
// 预览点标记
private CircleMarker _previewMarker = null;
// 预览连线标记
private List<LineMarker> _previewLines = new List<LineMarker>();
// 当前网格大小(米),用于自适应点大小计算
private double _currentGridSizeInMeters;
@ -305,7 +305,7 @@ namespace NavisworksTransport
private PathVisualizationMode _visualizationMode = PathVisualizationMode.StandardLine;
// 网格点类型配置
private GridPointType _gridPointType = GridPointType.Cube;
private GridPointType _gridPointType = GridPointType.Rectangle;
// 车辆参数必须通过SetVehicleParameters方法设置
private double _vehicleLength;
@ -364,8 +364,8 @@ namespace NavisworksTransport
public bool IsEnabled
{
get { return _isEnabled; }
set
{
set
{
_isEnabled = value;
// 触发视图刷新
if (Application.ActiveDocument?.ActiveView != null)
@ -380,8 +380,8 @@ namespace NavisworksTransport
/// </summary>
public int PathCount
{
get
{
get
{
lock (_lockObject)
{
return _pathVisualizations.Count;
@ -394,8 +394,8 @@ namespace NavisworksTransport
/// </summary>
public int MarkerCount
{
get
{
get
{
lock (_lockObject)
{
return _pathVisualizations.Values.Sum(v => v.PointMarkers.Count);
@ -409,7 +409,7 @@ namespace NavisworksTransport
/// <param name="view">当前视图</param>
/// <param name="graphics">图形上下文</param>
public override void Render(View view, Graphics graphics)
{
{
if (!_isEnabled) return;
try
@ -420,7 +420,7 @@ namespace NavisworksTransport
{
return; // 静默返回,避免日志泛滥
}
// 检查是否有路径或预览点需要渲染
int pathCount;
bool hasPreviewPoint;
@ -429,9 +429,9 @@ namespace NavisworksTransport
pathCount = _pathVisualizations.Count;
hasPreviewPoint = _previewMarker != null;
}
if (pathCount == 0 && !hasPreviewPoint) return;
// 使用BeginModelContext确保正确的渲染上下文
graphics.BeginModelContext();
@ -461,14 +461,14 @@ namespace NavisworksTransport
RenderVehicleSpace(graphics, vehicleSpaceMarker);
}
}
// 渲染预览点(灰色)
if (_previewMarker != null && _previewMarker.IsVisible)
{
graphics.Color(_previewMarker.Color, 0.7); // 使用半透明效果
RenderPointMarker(graphics, _previewMarker);
}
// 渲染预览连线(灰色)
if (_previewLines.Count > 0)
{
@ -479,7 +479,7 @@ namespace NavisworksTransport
}
}
}
graphics.EndModelContext();
}
catch (Exception ex)
@ -544,7 +544,7 @@ namespace NavisworksTransport
pathRoute.Id == "grid_visualization_door" ||
pathRoute.Id == "grid_visualization_unknown" ||
pathRoute.Id == "grid_visualization_obstacle";
var visualization = new PathVisualization
{
PathId = pathRoute.Id,
@ -558,7 +558,7 @@ namespace NavisworksTransport
{
_pathVisualizations[pathRoute.Id] = visualization;
}
RequestViewRefresh();
}
catch (Exception ex)
@ -724,7 +724,7 @@ namespace NavisworksTransport
var excludedSet = new HashSet<string>(excludedPathIds.Where(id => !string.IsNullOrEmpty(id)));
var toRemove = _pathVisualizations.Keys.Where(id => !excludedSet.Contains(id)).ToList();
// 检查排除的路径是否实际存在
var existingExcluded = excludedSet.Where(id => _pathVisualizations.ContainsKey(id)).ToList();
var nonExistingExcluded = excludedSet.Where(id => !_pathVisualizations.ContainsKey(id)).ToList();
@ -737,7 +737,7 @@ namespace NavisworksTransport
removedCount++;
}
}
if (removedCount > 0)
{
RequestViewRefresh();
@ -909,7 +909,7 @@ namespace NavisworksTransport
gridStyle = new RenderStyle(gridStyle.Color, 0.5);
}
}
return new CircleMarker
{
Center = point.Position,
@ -1230,7 +1230,7 @@ namespace NavisworksTransport
IsVisible = true,
PathPoint = previewPoint
};
// 请求刷新视图
RequestViewRefresh();
}
@ -1254,7 +1254,7 @@ namespace NavisworksTransport
{
_previewMarker = null;
_previewLines.Clear();
// 请求刷新视图
RequestViewRefresh();
}
@ -1284,14 +1284,14 @@ namespace NavisworksTransport
{
// 清除旧的预览连线
_previewLines.Clear();
// 找到预览点应该插入的最近线段
var nearestSegment = FindNearestLineSegment(previewPoint.Position, pathPoints);
if (nearestSegment.HasValue)
{
var (prevPoint, nextPoint) = nearestSegment.Value;
// 创建两条预览连线
// 1. 前一个点 -> 预览点
var line1 = new LineMarker
@ -1302,7 +1302,7 @@ namespace NavisworksTransport
Radius = GetLineRadius() // 使用与正常连线相同的直径
};
_previewLines.Add(line1);
// 2. 预览点 -> 后一个点
var line2 = new LineMarker
{
@ -1312,13 +1312,13 @@ namespace NavisworksTransport
Radius = GetLineRadius()
};
_previewLines.Add(line2);
}
else
{
LogManager.Warning("[预览连线渲染] 未找到合适的线段插入预览点");
}
// 请求刷新视图
RequestViewRefresh();
}
@ -1341,7 +1341,7 @@ namespace NavisworksTransport
if (_previewLines.Count > 0)
{
_previewLines.Clear();
// 请求刷新视图
RequestViewRefresh();
}
@ -1375,7 +1375,7 @@ namespace NavisworksTransport
// 找到预览点及其索引
var previewPointIndex = -1;
PathPoint previewPoint = null;
for (int i = 0; i < previewRoute.Points.Count; i++)
{
if (previewRoute.Points[i].Name.Contains("_预览"))
@ -1385,12 +1385,12 @@ namespace NavisworksTransport
break;
}
}
if (previewPoint != null && previewPointIndex >= 0)
{
// 只渲染预览点
RenderPreviewPoint(previewPoint);
// 只渲染与预览点相关的连线
// 连接前一个点到预览点
if (previewPointIndex > 0)
@ -1405,7 +1405,7 @@ namespace NavisworksTransport
};
_previewLines.Add(line1);
}
// 连接预览点到下一个点
if (previewPointIndex < previewRoute.Points.Count - 1)
{
@ -1418,7 +1418,7 @@ namespace NavisworksTransport
Radius = GetLineRadius()
};
_previewLines.Add(line2);
}
}
}
else
{
@ -1469,7 +1469,7 @@ namespace NavisworksTransport
{
// 起点尺寸为网格大小的100%,并限制在合理范围内
double standardRadius = _currentGridSizeInMeters * 1.0;
// 边界限制最小0.1米最大0.5米
return Math.Max(0.1, Math.Min(0.5, standardRadius));
}
@ -1607,13 +1607,13 @@ namespace NavisworksTransport
{
switch (pointMarker.GridPointType)
{
case GridPointType.Cube:
case GridPointType.Rectangle:
// 渲染立方体
RenderCubeMarker(graphics, pointMarker);
break;
case GridPointType.Point:
// 渲染
graphics.Point(pointMarker.Center);
case GridPointType.Circle:
// 渲染
RenderCircleMarker(graphics, pointMarker);
break;
case GridPointType.Sphere:
default:
@ -1630,23 +1630,40 @@ namespace NavisworksTransport
/// <param name="pointMarker">点标记</param>
private void RenderCubeMarker(Graphics graphics, CircleMarker pointMarker)
{
// 计算立方体的边长(直径的一半
double halfSide = pointMarker.Radius;
// 计算正方形的边长(直径
double sideLength = pointMarker.Radius * 2;
// 定义立方体的三个轴向量沿X、Y、Z轴
var xVector = new Vector3D(halfSide * 2, 0, 0);
var yVector = new Vector3D(0, halfSide * 2, 0);
var zVector = new Vector3D(0, 0, halfSide * 2);
// 定义正方形的两个轴向量沿X、Y轴
var xVector = new Vector3D(sideLength, 0, 0);
var yVector = new Vector3D(0, sideLength, 0);
// 计算立方体原点(中心点减去各轴向量的一半)
// 计算正方形原点(中心点减去各轴向量的一半),略微抬高以避免与模型重叠
var origin = new Point3D(
pointMarker.Center.X - halfSide,
pointMarker.Center.Y - halfSide,
pointMarker.Center.Z - halfSide
pointMarker.Center.X - pointMarker.Radius,
pointMarker.Center.Y - pointMarker.Radius,
pointMarker.Center.Z + 0.01
);
// 使用Cuboid API渲染立方体
graphics.Cuboid(origin, xVector, yVector, zVector, pointMarker.Filled);
// 使用Rectangle API渲染正方形
graphics.Rectangle(origin, xVector, yVector, pointMarker.Filled);
}
/// <summary>
/// 渲染圆形标记
/// </summary>
/// <param name="graphics">图形上下文</param>
/// <param name="pointMarker">点标记</param>
private void RenderCircleMarker(Graphics graphics, CircleMarker pointMarker)
{
// 调整中心点位置,略微抬高以避免与模型重叠
Point3D adjustCenterPoint = new Point3D(
pointMarker.Center.X,
pointMarker.Center.Y,
pointMarker.Center.Z + 0.01
);
// 使用Circle API渲染圆形
graphics.Circle(adjustCenterPoint, pointMarker.Normal, pointMarker.Radius, true);
}
/// <summary>
@ -1690,7 +1707,7 @@ namespace NavisworksTransport
// 按索引排序路径点
var sortedPoints = pathPoints.OrderBy(p => p.Index).ToList();
double minDistance = double.MaxValue;
(PathPoint prevPoint, PathPoint nextPoint)? nearestSegment = null;
@ -1699,10 +1716,10 @@ namespace NavisworksTransport
{
var currentPoint = sortedPoints[i];
var nextPoint = sortedPoints[i + 1];
// 计算预览点到线段的距离
var distance = CalculatePointToLineSegmentDistance(previewPosition, currentPoint.Position, nextPoint.Position);
if (distance < minDistance)
{
minDistance = distance;
@ -1724,36 +1741,36 @@ namespace NavisworksTransport
{
// 线段向量
var lineVector = new Point3D(lineEnd.X - lineStart.X, lineEnd.Y - lineStart.Y, lineEnd.Z - lineStart.Z);
// 点到线段起点的向量
var pointVector = new Point3D(point.X - lineStart.X, point.Y - lineStart.Y, point.Z - lineStart.Z);
// 计算线段长度的平方
var lineLengthSquared = lineVector.X * lineVector.X + lineVector.Y * lineVector.Y + lineVector.Z * lineVector.Z;
if (lineLengthSquared == 0)
{
// 线段退化为点,返回点到点的距离
return CalculateDistance(point, lineStart);
}
// 计算投影参数t
var t = (pointVector.X * lineVector.X + pointVector.Y * lineVector.Y + pointVector.Z * lineVector.Z) / lineLengthSquared;
// 将t限制在[0,1]范围内
t = Math.Max(0, Math.Min(1, t));
// 计算线段上最近点
var closestPoint = new Point3D(
lineStart.X + t * lineVector.X,
lineStart.Y + t * lineVector.Y,
lineStart.Z + t * lineVector.Z
);
// 返回点到最近点的距离
return CalculateDistance(point, closestPoint);
}
private static DateTime _lastRefreshTime = DateTime.MinValue;
#endregion
@ -1821,10 +1838,10 @@ namespace NavisworksTransport
/// <summary>
/// 位置Center的别名用于预览点兼容性
/// </summary>
public Point3D Position
{
get { return Center; }
set { Center = value; }
public Point3D Position
{
get { return Center; }
set { Center = value; }
}
/// <summary>
@ -1837,4 +1854,4 @@ namespace NavisworksTransport
return $"CircleMarker[序号={SequenceNumber}, 类型={PointType}, 中心=({Center.X:F2},{Center.Y:F2},{Center.Z:F2}), 半径={Radius:F2}]";
}
}
}
}

View File

@ -27,7 +27,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private bool _showDoorGrid = false;
// 网格点类型字段
private GridPointType _gridPointType = GridPointType.Cube;
private GridPointType _gridPointType = GridPointType.Rectangle;
private ObservableCollection<GridPointType> _gridPointTypes;
// 路径可视化模式字段
@ -121,9 +121,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (SetProperty(ref _gridPointType, value))
{
// 通知相关的单选按钮属性更新
OnPropertyChanged(nameof(IsCubePointType));
OnPropertyChanged(nameof(IsSpherePointType));
OnPropertyChanged(nameof(IsPointPointType));
OnPropertyChanged(nameof(IsRectanglePointType));
OnPropertyChanged(nameof(IsCirclePointType));
OnGridPointTypeChanged();
}
}
@ -132,29 +131,14 @@ namespace NavisworksTransport.UI.WPF.ViewModels
/// <summary>
/// 是否使用立方体点类型
/// </summary>
public bool IsCubePointType
public bool IsRectanglePointType
{
get => _gridPointType == GridPointType.Cube;
get => _gridPointType == GridPointType.Rectangle;
set
{
if (value)
{
GridPointType = GridPointType.Cube;
}
}
}
/// <summary>
/// 是否使用球形点类型
/// </summary>
public bool IsSpherePointType
{
get => _gridPointType == GridPointType.Sphere;
set
{
if (value)
{
GridPointType = GridPointType.Sphere;
GridPointType = GridPointType.Rectangle;
}
}
}
@ -162,14 +146,14 @@ namespace NavisworksTransport.UI.WPF.ViewModels
/// <summary>
/// 是否使用点状点类型
/// </summary>
public bool IsPointPointType
public bool IsCirclePointType
{
get => _gridPointType == GridPointType.Point;
get => _gridPointType == GridPointType.Circle;
set
{
if (value)
{
GridPointType = GridPointType.Point;
GridPointType = GridPointType.Circle;
}
}
}
@ -547,7 +531,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
SelectedLogLevel = currentLevel.ToString();
// 设置默认网格点类型
GridPointType = GridPointType.Cube;
GridPointType = GridPointType.Rectangle;
// 初始化系统信息
PluginVersion = "v1.0";

View File

@ -173,23 +173,17 @@ NavisworksTransport 系统管理页签视图 - 采用与其他页签一致的Nav
Orientation="Horizontal"
VerticalAlignment="Center"
Margin="5,0,0,0">
<RadioButton Content="立方体"
<RadioButton Content="正方形"
GroupName="GridPointType"
IsChecked="{Binding IsCubePointType}"
IsChecked="{Binding IsRectanglePointType}"
Margin="0,0,20,0"
VerticalAlignment="Center"
ToolTip="显示立方体网格点"/>
<RadioButton Content="球形"
<RadioButton Content=""
GroupName="GridPointType"
IsChecked="{Binding IsSpherePointType}"
Margin="0,0,20,0"
IsChecked="{Binding IsCirclePointType}"
VerticalAlignment="Center"
ToolTip="显示球形网格点"/>
<RadioButton Content="点"
GroupName="GridPointType"
IsChecked="{Binding IsPointPointType}"
VerticalAlignment="Center"
ToolTip="显示点状网格点"/>
ToolTip="显示圆形网格点"/>
</StackPanel>
</Grid>
</StackPanel>