增加了修改提升点来调整上升高度的功能,重构了吊装路径的坐标约束
This commit is contained in:
parent
da89105269
commit
b09564c4aa
@ -2255,7 +2255,158 @@ namespace NavisworksTransport
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新吊装路径点位置(专用方法)
|
||||
/// 更新路径点位置(带约束的公共方法)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 根据路径类型智能处理坐标更新:
|
||||
/// - 吊装路径:
|
||||
/// - 空中路径点(提升点、下降点、中间路径点):只更新XY坐标,保留原有Z坐标(吊装高度)
|
||||
/// - 地面路径点(起吊点、落地点):更新完整XYZ坐标
|
||||
/// - 其他路径类型:更新完整XYZ坐标
|
||||
/// </remarks>
|
||||
/// <param name="route">路径</param>
|
||||
/// <param name="pointIndex">路径点索引</param>
|
||||
/// <param name="newPosition">新位置</param>
|
||||
/// <returns>是否成功更新</returns>
|
||||
public bool UpdatePathPointWithConstraints(PathRoute route, int pointIndex, Point3D newPosition)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (route == null || pointIndex < 0 || pointIndex >= route.Points.Count)
|
||||
{
|
||||
LogManager.Error($"UpdatePathPointWithConstraints: 无效的参数,route={route}, pointIndex={pointIndex}");
|
||||
return false;
|
||||
}
|
||||
|
||||
var pointToUpdate = route.Points[pointIndex];
|
||||
|
||||
// 吊装路径:智能处理Z坐标
|
||||
if (route.PathType == PathType.Hoisting)
|
||||
{
|
||||
bool isLiftPoint = pointToUpdate.Name == "提升点";
|
||||
bool isDescendPoint = pointToUpdate.Name == "下降点";
|
||||
bool isStartPoint = pointToUpdate.Name == "起吊点";
|
||||
bool isEndPoint = pointToUpdate.Name == "落地点";
|
||||
|
||||
// 🔥 新功能:允许修改提升点和下降点的Z坐标来调整吊装高度
|
||||
if (isLiftPoint || isDescendPoint)
|
||||
{
|
||||
// 修改提升点或下降点的Z坐标,同步更新所有空中路径点的Z坐标
|
||||
double newHoistingHeight = newPosition.Z;
|
||||
double originalZ = pointToUpdate.Position.Z;
|
||||
double heightDelta = newHoistingHeight - originalZ;
|
||||
|
||||
// 更新当前点的XY和Z坐标
|
||||
pointToUpdate.Position = new Point3D(
|
||||
newPosition.X,
|
||||
newPosition.Y,
|
||||
newHoistingHeight
|
||||
);
|
||||
|
||||
// 同步更新所有空中路径点的Z坐标
|
||||
foreach (var point in route.Points)
|
||||
{
|
||||
// 只更新空中路径点(提升点、下降点、中间路径点)
|
||||
// 跳过当前正在修改的点,避免重复更新
|
||||
if (point.Name != "起吊点" && point.Name != "落地点" && point != pointToUpdate)
|
||||
{
|
||||
point.Position = new Point3D(
|
||||
point.Position.X,
|
||||
point.Position.Y,
|
||||
point.Position.Z + heightDelta
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 🔥 更新路径的提升高度属性(转换为米)
|
||||
double hoistingHeightMeters = CalculateHoistingHeight(route);
|
||||
route.LiftHeightMeters = hoistingHeightMeters;
|
||||
LogManager.Info($"[更新路径点] 吊装路径 {pointToUpdate.Name},提升高度已调整为: {hoistingHeightMeters:F3}米");
|
||||
|
||||
// 使用路径的 LiftHeightMeters 属性显示提升高度
|
||||
RaiseStatusChanged($"吊装高度: {route.LiftHeightMeters:F3}米", PathPlanningStatusType.Info);
|
||||
}
|
||||
// 空中路径点(非提升点、下降点):只更新XY坐标,保持原有吊装高度
|
||||
else if (!isStartPoint && !isEndPoint)
|
||||
{
|
||||
double originalZ = pointToUpdate.Position.Z;
|
||||
pointToUpdate.Position = new Point3D(
|
||||
newPosition.X,
|
||||
newPosition.Y,
|
||||
originalZ // 保留原有Z坐标(吊装高度)
|
||||
);
|
||||
LogManager.Info($"[更新路径点] 吊装路径空中点 {pointToUpdate.Name},保留原有高度: {originalZ:F3}");
|
||||
}
|
||||
// 起吊点/落地点:更新完整位置
|
||||
else
|
||||
{
|
||||
pointToUpdate.Position = newPosition;
|
||||
LogManager.Info($"[更新路径点] 吊装路径地面点 {pointToUpdate.Name},更新完整位置");
|
||||
}
|
||||
|
||||
// 吊装路径:自动更新关联点(仅当修改起吊点或落地点时)
|
||||
// 注意:修改提升点/下降点时,已经在上面同步更新了所有空中路径点,不需要再次调用
|
||||
if (isStartPoint || isEndPoint)
|
||||
{
|
||||
UpdateAerialPathRelatedPoints(route, pointIndex);
|
||||
}
|
||||
|
||||
// 吊装路径:优化路径点(处理斜线和清除多余点)
|
||||
OptimizeRightAnglePathPoints(route);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 其他路径类型:更新完整位置
|
||||
pointToUpdate.Position = newPosition;
|
||||
LogManager.Info($"[更新路径点] {route.PathType}路径点 {pointToUpdate.Name},更新完整位置");
|
||||
}
|
||||
|
||||
// 调用统一更新函数
|
||||
route.RecalculateAndSaveRoute($"更新路径点 {pointToUpdate.Name} 位置");
|
||||
|
||||
// 保存到数据库
|
||||
SavePathToDatabase(route);
|
||||
|
||||
// 触发路径点列表更新事件
|
||||
RaisePathPointsListUpdated(route, "路径点更新完成");
|
||||
|
||||
LogManager.Info($"路径点更新完成: {pointToUpdate.Name}");
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"UpdatePathPointWithConstraints 失败: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算吊装路径的提升高度
|
||||
/// </summary>
|
||||
/// <param name="route">吊装路径</param>
|
||||
/// <returns>提升高度(从起吊点到提升点的高度差)</returns>
|
||||
private double CalculateHoistingHeight(PathRoute route)
|
||||
{
|
||||
if (route == null || route.PathType != PathType.Hoisting || route.Points.Count < 2)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// 找到起吊点和提升点
|
||||
var startPoint = route.Points.FirstOrDefault(p => p.Name == "起吊点");
|
||||
var liftPoint = route.Points.FirstOrDefault(p => p.Name == "提升点");
|
||||
|
||||
if (startPoint == null || liftPoint == null)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// 计算高度差(提升点Z - 起吊点Z)
|
||||
return liftPoint.Position.Z - startPoint.Position.Z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新吊装路径点位置(专用方法,用于3D修改流程)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 智能处理吊装路径点的坐标更新:
|
||||
@ -2276,69 +2427,39 @@ namespace NavisworksTransport
|
||||
return false;
|
||||
}
|
||||
|
||||
// 更新路径点位置(吊装路径:智能处理Z坐标)
|
||||
var pointToUpdate = CurrentRoute.Points[_editingPointIndex];
|
||||
|
||||
// 空中路径点只更新XY坐标,保持原有吊装高度
|
||||
if (pointToUpdate.Name != "起吊点" && pointToUpdate.Name != "落地点")
|
||||
// 调用公共方法处理
|
||||
bool success = UpdatePathPointWithConstraints(CurrentRoute, _editingPointIndex, _editingPreviewPoint.Position);
|
||||
|
||||
if (success)
|
||||
{
|
||||
double originalZ = pointToUpdate.Position.Z;
|
||||
pointToUpdate.Position = new Point3D(
|
||||
_editingPreviewPoint.Position.X,
|
||||
_editingPreviewPoint.Position.Y,
|
||||
originalZ // 保留原有Z坐标(吊装高度)
|
||||
);
|
||||
LogManager.Info($"[修改吊装路径点] 空中路径点 {pointToUpdate.Name},保留原有高度: {originalZ:F3}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 起吊点/落地点使用完整位置
|
||||
pointToUpdate.Position = _editingPreviewPoint.Position;
|
||||
LogManager.Info($"[修改吊装路径点] 地面路径点 {pointToUpdate.Name},更新完整位置");
|
||||
// 添加历史记录
|
||||
var pointToUpdate = CurrentRoute.Points[_editingPointIndex];
|
||||
var historyEntry = new PathHistoryEntry(
|
||||
CurrentRoute.Id,
|
||||
PathHistoryOperationType.Edited,
|
||||
CurrentRoute,
|
||||
$"修改吊装路径点 {pointToUpdate.Name} 位置");
|
||||
_historyManager.AddHistoryEntry(historyEntry);
|
||||
|
||||
// 清理修改预览可视化(会自动清除预览并重新渲染正常路径)
|
||||
ClearEditingPreviewVisualization();
|
||||
|
||||
// 清理修改状态
|
||||
ClearEditingState();
|
||||
|
||||
// 切换回查看状态
|
||||
PathEditState = PathEditState.Viewing;
|
||||
|
||||
// 停用ToolPlugin
|
||||
DeactivateToolPlugin();
|
||||
|
||||
// 更新可视化
|
||||
DrawRouteVisualization(CurrentRoute, isAutoPath: false);
|
||||
|
||||
RaiseStatusChanged($"吊装路径点 {pointToUpdate.Name} 修改完成", PathPlanningStatusType.Success);
|
||||
}
|
||||
|
||||
// 吊装路径:自动更新关联点
|
||||
UpdateAerialPathRelatedPoints(CurrentRoute, _editingPointIndex);
|
||||
|
||||
// 吊装路径:优化路径点(处理斜线和清除多余点)
|
||||
OptimizeRightAnglePathPoints(CurrentRoute);
|
||||
|
||||
// 核心修复:调用统一更新函数
|
||||
CurrentRoute.RecalculateAndSaveRoute($"修改吊装路径点 {pointToUpdate.Name} 位置");
|
||||
|
||||
// 添加历史记录
|
||||
var historyEntry = new PathHistoryEntry(
|
||||
CurrentRoute.Id,
|
||||
PathHistoryOperationType.Edited,
|
||||
CurrentRoute,
|
||||
$"修改吊装路径点 {pointToUpdate.Name} 位置");
|
||||
_historyManager.AddHistoryEntry(historyEntry);
|
||||
|
||||
// 清理修改预览可视化(会自动清除预览并重新渲染正常路径)
|
||||
ClearEditingPreviewVisualization();
|
||||
|
||||
// 清理修改状态
|
||||
ClearEditingState();
|
||||
|
||||
// 切换回查看状态
|
||||
PathEditState = PathEditState.Viewing;
|
||||
|
||||
// 停用ToolPlugin
|
||||
DeactivateToolPlugin();
|
||||
|
||||
// 更新可视化
|
||||
DrawRouteVisualization(CurrentRoute, isAutoPath: false);
|
||||
|
||||
// 立即保存到数据库
|
||||
SavePathToDatabase(CurrentRoute);
|
||||
|
||||
// 触发路径点列表更新事件
|
||||
RaisePathPointsListUpdated(CurrentRoute, "路径点修改完成");
|
||||
|
||||
RaiseStatusChanged($"吊装路径点 {pointToUpdate.Name} 修改完成", PathPlanningStatusType.Success);
|
||||
LogManager.Info($"吊装路径点修改完成: {pointToUpdate.Name}");
|
||||
|
||||
return true;
|
||||
return success;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@ -1180,48 +1180,51 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
// 创建并显示对话框
|
||||
// 注意:在Navisworks插件的ViewModel中,不设置Owner
|
||||
// 因为Application.Current.MainWindow在Navisworks环境中不可用
|
||||
var dialog = new EditCoordinatesWindow(point.X, point.Y, point.Z);
|
||||
|
||||
var dialog = new EditCoordinatesWindow(point.X, point.Y, point.Z, point.Name, point.Type.ToString());
|
||||
|
||||
if (dialog.ShowDialog() == true)
|
||||
{
|
||||
// 更新ViewModel中的坐标
|
||||
point.X = dialog.X;
|
||||
point.Y = dialog.Y;
|
||||
point.Z = dialog.Z;
|
||||
|
||||
LogManager.Info($"[坐标编辑] 修改点: {point.Name}, 类型: {point.Type}, 索引: {point.Index}");
|
||||
|
||||
// 吊装路径:自动更新关联点(UI层)
|
||||
UpdateAerialPathRelatedPoints(SelectedPathRoute, point.Index);
|
||||
|
||||
// 同步更新到底层数据模型
|
||||
if (_pathPlanningManager != null)
|
||||
{
|
||||
var coreRoute = _pathPlanningManager.Routes.FirstOrDefault(r => r.Id == SelectedPathRoute.Id);
|
||||
if (coreRoute != null)
|
||||
{
|
||||
var corePoint = coreRoute.Points.FirstOrDefault(p => p.Id == point.Id);
|
||||
if (corePoint != null)
|
||||
// 验证索引是否有效
|
||||
if (point.Index < 0 || point.Index >= coreRoute.Points.Count)
|
||||
{
|
||||
corePoint.X = point.X;
|
||||
corePoint.Y = point.Y;
|
||||
corePoint.Z = point.Z;
|
||||
LogManager.Error($"[坐标编辑] 索引错误: point.Index={point.Index}, coreRoute.Points.Count={coreRoute.Points.Count}");
|
||||
System.Windows.MessageBox.Show($"路径点索引错误", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
// 吊装路径:自动更新关联点(Core层)
|
||||
UpdateAerialPathRelatedPointsCore(coreRoute, point.Index);
|
||||
var corePoint = coreRoute.Points[point.Index];
|
||||
LogManager.Info($"[坐标编辑] Core路径点: {corePoint.Name}, 索引: {point.Index}, 位置: ({corePoint.Position.X:F3}, {corePoint.Position.Y:F3}, {corePoint.Position.Z:F3})");
|
||||
|
||||
// 保存更改到数据库
|
||||
_pathPlanningManager.UpdateRoute(coreRoute);
|
||||
// 使用公共方法更新路径点(自动处理吊装路径约束)
|
||||
var newPosition = new Point3D(dialog.X, dialog.Y, dialog.Z);
|
||||
bool success = _pathPlanningManager.UpdatePathPointWithConstraints(coreRoute, point.Index, newPosition);
|
||||
|
||||
// 触发路径点列表更新事件,确保UI刷新
|
||||
_pathPlanningManager.RaisePathPointsListUpdated(coreRoute, "编辑坐标");
|
||||
if (success)
|
||||
{
|
||||
// 更新ViewModel中的坐标(从Core数据同步)
|
||||
corePoint = coreRoute.Points[point.Index];
|
||||
point.X = corePoint.Position.X;
|
||||
point.Y = corePoint.Position.Y;
|
||||
point.Z = corePoint.Position.Z;
|
||||
|
||||
// 刷新视图
|
||||
UpdatePathVisualization();
|
||||
|
||||
LogManager.Info($"已更新路径点 {point.Name} 的坐标为 ({point.X:F3}, {point.Y:F3}, {point.Z:F3})");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Error($"更新路径点失败: {point.Name}");
|
||||
System.Windows.MessageBox.Show($"更新路径点失败", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1240,8 +1243,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
{
|
||||
var points = new List<PathPointViewModel>();
|
||||
|
||||
foreach (var corePoint in coreRoute.Points)
|
||||
for (int i = 0; i < coreRoute.Points.Count; i++)
|
||||
{
|
||||
var corePoint = coreRoute.Points[i];
|
||||
var wpfPoint = new PathPointViewModel
|
||||
{
|
||||
Id = corePoint.Id,
|
||||
@ -1249,7 +1253,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
X = corePoint.X,
|
||||
Y = corePoint.Y,
|
||||
Z = corePoint.Z,
|
||||
Type = corePoint.Type
|
||||
Type = corePoint.Type,
|
||||
Index = i // 🔥 设置正确的索引
|
||||
};
|
||||
points.Add(wpfPoint);
|
||||
}
|
||||
@ -1891,24 +1896,23 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
|
||||
await _uiStateManager.ExecuteUIUpdateAsync(() =>
|
||||
{
|
||||
// 4. 起点和终点的特殊处理逻辑
|
||||
// 4. 禁止删除起点和终点
|
||||
if (corePoint != null)
|
||||
{
|
||||
int pointIndex = coreRoute.Points.IndexOf(corePoint);
|
||||
|
||||
if (corePoint.Type == PathPointType.StartPoint && coreRoute.Points.Count > 1)
|
||||
if (corePoint.Type == PathPointType.StartPoint)
|
||||
{
|
||||
// 删除起点:下一个点变为起点
|
||||
var nextPoint = coreRoute.Points[pointIndex + 1];
|
||||
nextPoint.Type = PathPointType.StartPoint;
|
||||
LogManager.Info($"起点被删除,下一个路径点 {nextPoint.Name} 已设为新的起点");
|
||||
LogManager.Warning($"不能删除路径的起点");
|
||||
UpdateMainStatus($"❌ 无法删除:{corePoint.Name} 是路径的起点");
|
||||
return;
|
||||
}
|
||||
else if (corePoint.Type == PathPointType.EndPoint && coreRoute.Points.Count > 1)
|
||||
|
||||
if (corePoint.Type == PathPointType.EndPoint)
|
||||
{
|
||||
// 删除终点:上一个点变为终点
|
||||
var prevPoint = coreRoute.Points[pointIndex - 1];
|
||||
prevPoint.Type = PathPointType.EndPoint;
|
||||
LogManager.Info($"终点被删除,上一个路径点 {prevPoint.Name} 已设为新的终点");
|
||||
LogManager.Warning($"不能删除路径的终点");
|
||||
UpdateMainStatus($"❌ 无法删除:{corePoint.Name} 是路径的终点");
|
||||
return;
|
||||
}
|
||||
|
||||
// 吊装路径:禁止删除关键点(提升点、下降点)
|
||||
@ -3160,6 +3164,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
Index = i
|
||||
};
|
||||
pathViewModel.Points.Add(pointViewModel);
|
||||
LogManager.Debug($"[路径点列表更新] 索引{i}: {point.Name}, Id={point.Id}, 位置=({point.Position.X:F2}, {point.Position.Y:F2}, {point.Position.Z:F2})");
|
||||
}
|
||||
LogManager.Info($"已更新路径点列表,当前点数: {pathViewModel.Points.Count}");
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<Window x:Class="NavisworksTransport.UI.WPF.Views.EditCoordinatesWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="编辑路径点坐标" Height="320" Width="400"
|
||||
Title="编辑路径点坐标" Height="380" Width="400"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
@ -33,6 +33,28 @@
|
||||
<!-- 输入区域 -->
|
||||
<Border Grid.Row="1" Padding="20,15">
|
||||
<StackPanel>
|
||||
<!-- 路径点信息 -->
|
||||
<Border Background="#FFF0F7FF" BorderBrush="#FFD4E7FF" BorderThickness="1" Padding="12,10" Margin="0,0,0,15">
|
||||
<StackPanel>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" Text="路径点:" FontSize="10" Foreground="#FF666666" VerticalAlignment="Center"/>
|
||||
<TextBlock Grid.Column="1" Text="{Binding PointName}" FontSize="10" FontWeight="SemiBold" Foreground="#FF2B579A" VerticalAlignment="Center" Margin="5,0,0,0"/>
|
||||
</Grid>
|
||||
<Grid Margin="0,5,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" Text="类型:" FontSize="10" Foreground="#FF666666" VerticalAlignment="Center"/>
|
||||
<TextBlock Grid.Column="1" Text="{Binding PointType}" FontSize="10" Foreground="#FF666666" VerticalAlignment="Center" Margin="5,0,0,0"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- X坐标 -->
|
||||
<Grid Margin="0,0,0,12">
|
||||
<Grid.ColumnDefinitions>
|
||||
|
||||
@ -9,8 +9,10 @@ namespace NavisworksTransport.UI.WPF.Views
|
||||
public double X { get; set; }
|
||||
public double Y { get; set; }
|
||||
public double Z { get; set; }
|
||||
public string PointName { get; set; }
|
||||
public string PointType { get; set; }
|
||||
|
||||
public EditCoordinatesWindow(double x, double y, double z)
|
||||
public EditCoordinatesWindow(double x, double y, double z, string pointName = "", string pointType = "")
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -18,6 +20,8 @@ namespace NavisworksTransport.UI.WPF.Views
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
PointName = pointName;
|
||||
PointType = pointType;
|
||||
DataContext = this;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user