diff --git a/src/Core/Animation/PathAnimationManager.cs b/src/Core/Animation/PathAnimationManager.cs
index 78234c2..b7c86da 100644
--- a/src/Core/Animation/PathAnimationManager.cs
+++ b/src/Core/Animation/PathAnimationManager.cs
@@ -2838,7 +2838,7 @@ namespace NavisworksTransport.Core.Animation
}
// 包含路径边的摘要信息(区分不同的曲线化结果)
- if (route?.Edges != null)
+ if (route?.Edges != null && route.Edges.Count > 0)
{
foreach (var edge in route.Edges)
{
@@ -2853,6 +2853,9 @@ namespace NavisworksTransport.Core.Animation
}
}
+ // 包含路径最后修改时间(确保路径修改后重新生成动画)
+ sb.Append($"LastModified:{route?.LastModified:yyyyMMddHHmmss}");
+
// 计算哈希
using (var md5 = System.Security.Cryptography.MD5.Create())
{
diff --git a/src/Core/PathPlanningManager.cs b/src/Core/PathPlanningManager.cs
index 86d906e..d88cb19 100644
--- a/src/Core/PathPlanningManager.cs
+++ b/src/Core/PathPlanningManager.cs
@@ -511,7 +511,7 @@ namespace NavisworksTransport
if (route != null && route.Points.Count >= 2 && generationMethod != RouteGenerationMethod.Manual)
{
// 使用统一的曲线化和保存方法
- RecalculateAndSaveRoute(route, $"RouteGenerated({generationMethod})");
+ route.RecalculateAndSaveRoute($"RouteGenerated({generationMethod})");
}
else if (generationMethod == RouteGenerationMethod.Manual)
{
@@ -631,7 +631,7 @@ namespace NavisworksTransport
if (needRecalculate)
{
// 使用统一的曲线化和保存方法
- RecalculateAndSaveRoute(route, $"PathPointsListUpdated({updateReason})");
+ route.RecalculateAndSaveRoute($"PathPointsListUpdated({updateReason})");
}
var eventArgs = new PathPointsListUpdatedEventArgs(route, updateReason, _managerId);
@@ -1771,7 +1771,7 @@ namespace NavisworksTransport
UpdateAerialPathRelatedPoints(CurrentRoute, _editingPointIndex);
// 核心修复:调用统一更新函数
- CurrentRoute.UpdatePathDataComplete($"修改路径点 {pointToUpdate.Name} 位置");
+ CurrentRoute.RecalculateAndSaveRoute($"修改路径点 {pointToUpdate.Name} 位置");
// 添加历史记录
var historyEntry = new PathHistoryEntry(
@@ -3249,59 +3249,6 @@ namespace NavisworksTransport
///
/// 重新计算曲线化路径并保存到数据库
///
- /// 要计算的路径
- /// 上下文信息(用于日志)
- private void RecalculateAndSaveRoute(PathRoute route, string context)
- {
- if (route == null || route.Points.Count < 2)
- {
- LogManager.Info($"跳过曲线化计算(路径点不足): {context}");
- return;
- }
-
- try
- {
- // 空中路径不进行曲线化,直接保存
- if (route.PathType == PathType.Aerial)
- {
- string aerialSubTypeName = route.AerialSubType == AerialSubType.Rail ? "空轨" : "吊装";
- LogManager.Info($"{aerialSubTypeName}路径跳过曲线化,直接保存: {route.Name}");
- SavePathToDatabase(route);
- LogManager.Info($"{aerialSubTypeName}路径已保存到数据库: {route.Name}");
- return;
- }
-
- // 地面路径进行曲线化
- double samplingStep = ConfigManager.Instance.Current.PathEditing.ArcSamplingStep;
- route.TurnRadius = ConfigManager.Instance.Current.PathEditing.DefaultPathTurnRadius;
- List warnings;
- PathCurveEngine.ApplyCurvatureToRoute(route, samplingStep, out warnings);
- LogManager.Info($"路径曲线化完成({context}): {route.Name}, 转弯半径: {route.TurnRadius:F2}m, 边数: {route.Edges.Count}");
-
- // 如果有警告,显示到状态栏
- if (warnings != null && warnings.Count > 0)
- {
- // 只显示第一个警告(避免刷屏)
- string firstWarning = warnings[0];
- if (warnings.Count > 1)
- {
- firstWarning += $"(还有 {warnings.Count - 1} 个类似问题)";
- }
-
- // 通过StatusChanged事件发送警告
- RaiseStatusChanged(firstWarning, PathPlanningStatusType.Warning);
- LogManager.Warning($"路径曲线化警告: {firstWarning}");
- }
-
- // 曲线化计算完成后,立即保存数据库
- SavePathToDatabase(route);
- LogManager.Info($"路径曲线化后已保存到数据库: {route.Name}");
- }
- catch (Exception ex)
- {
- LogManager.Error($"路径曲线化和保存失败({context}): {ex.Message}", ex);
- }
- }
#endregion
@@ -3323,7 +3270,7 @@ namespace NavisworksTransport
if (route == null) return;
// 使用统一的曲线化和保存方法
- RecalculateAndSaveRoute(route, "UpdateRoute");
+ route.RecalculateAndSaveRoute("UpdateRoute");
}
#endregion
@@ -4144,7 +4091,7 @@ namespace NavisworksTransport
///
/// 保存路径时同时保存到数据库
///
- private void SavePathToDatabase(PathRoute route)
+ public void SavePathToDatabase(PathRoute route)
{
try
{
diff --git a/src/Core/PathPlanningModels.cs b/src/Core/PathPlanningModels.cs
index 33e7a65..28aecf1 100644
--- a/src/Core/PathPlanningModels.cs
+++ b/src/Core/PathPlanningModels.cs
@@ -662,7 +662,7 @@ namespace NavisworksTransport
{
Points.Add(point);
// 调用统一更新函数(内部会重新设置索引)
- UpdatePathDataComplete("添加路径点");
+ RecalculateAndSaveRoute("添加路径点");
}
///
@@ -674,7 +674,7 @@ namespace NavisworksTransport
{
Points.Insert(insertIndex, point);
// 调用统一更新函数(内部会重新设置索引)
- UpdatePathDataComplete("插入路径点");
+ RecalculateAndSaveRoute("插入路径点");
}
///
@@ -687,7 +687,7 @@ namespace NavisworksTransport
if (removed)
{
// 调用统一更新函数(内部会重新设置索引)
- UpdatePathDataComplete("移除路径点");
+ RecalculateAndSaveRoute("移除路径点");
}
return removed;
}
@@ -716,7 +716,7 @@ namespace NavisworksTransport
Edges.Clear();
IsCurved = false;
// 调用统一更新函数
- UpdatePathDataComplete("清空路径点");
+ RecalculateAndSaveRoute("清空路径点");
}
///
@@ -781,50 +781,78 @@ namespace NavisworksTransport
}
///
- /// 完整更新路径数据(坐标点、边、曲线、长度)
- /// 根据路径类型自动决定是否重新计算曲线
+ /// 重新计算路径数据并保存到数据库
+ /// 统一的路径数据更新入口:重新设置索引、更新长度、计算曲线、保存到数据库
///
- /// 更新原因(用于日志)
- public void UpdatePathDataComplete(string updateReason = "路径数据更新")
+ /// 上下文信息(用于日志)
+ public void RecalculateAndSaveRoute(string context = "路径数据更新")
{
- // 1. 重新设置路径点索引
- for (int i = 0; i < Points.Count; i++)
+ if (Points.Count < 2)
{
- Points[i].Index = i;
+ LogManager.Info($"跳过路径数据更新(路径点不足): {Name}, 原因: {context}");
+ return;
}
- // 2. 根据路径类型决定是否重新计算曲线
- if (PathType == PathType.Ground)
+ try
{
- // 地面路径:需要曲线化
- double samplingStep = ConfigManager.Instance.Current.PathEditing.ArcSamplingStep;
- double turnRadius = ConfigManager.Instance.Current.PathEditing.DefaultPathTurnRadius;
+ // 1. 重新设置路径点索引
+ for (int i = 0; i < Points.Count; i++)
+ {
+ Points[i].Index = i;
+ }
- PathCurveEngine.ApplyCurvatureToRoute(this, samplingStep, out _);
- LogManager.Info($"[路径更新] 地面路径已重新曲线化: {Name}");
+ // 2. 根据路径类型决定是否重新计算曲线
+ if (PathType == PathType.Aerial)
+ {
+ // 空中路径:使用直线,不需要曲线化
+ Edges.Clear();
+ IsCurved = false;
+ UpdateTotalLength();
+ string aerialSubTypeName = AerialSubType == AerialSubType.Rail ? "空轨" : "吊装";
+ LogManager.Info($"{aerialSubTypeName}路径已更新(直线模式): {Name}, 原因: {context}");
+ }
+ else if (PathType == PathType.Ground)
+ {
+ // 地面路径:进行曲线化
+ double samplingStep = ConfigManager.Instance.Current.PathEditing.ArcSamplingStep;
+ TurnRadius = ConfigManager.Instance.Current.PathEditing.DefaultPathTurnRadius;
+ List warnings;
+ PathCurveEngine.ApplyCurvatureToRoute(this, samplingStep, out warnings);
+ LogManager.Info($"地面路径已曲线化: {Name}, 原因: {context}, 转弯半径: {TurnRadius:F2}m, 边数: {Edges.Count}");
+
+ // 如果有警告,记录日志
+ if (warnings != null && warnings.Count > 0)
+ {
+ foreach (var warning in warnings)
+ {
+ LogManager.Warning($"路径曲线化警告: {warning}");
+ }
+ }
+ }
+ else
+ {
+ // 未知路径类型:使用直线
+ Edges.Clear();
+ IsCurved = false;
+ UpdateTotalLength();
+ LogManager.Warning($"未知路径类型,使用直线模式: {Name}, 原因: {context}");
+ }
+
+ // 3. 更新最后修改时间
+ LastModified = DateTime.Now;
+
+ // 4. 保存到数据库(通过PathPlanningManager)
+ var pathPlanningManager = PathPlanningManager.Instance;
+ if (pathPlanningManager != null)
+ {
+ pathPlanningManager.SavePathToDatabase(this);
+ LogManager.Info($"路径数据已保存到数据库: {Name}, 原因: {context}, 总长度: {TotalLength:F2}米");
+ }
}
- else if (PathType == PathType.Aerial)
+ catch (Exception ex)
{
- // 吊装/空轨路径:使用直线,不需要曲线化
- // 清空Edges,使用Points直接计算
- Edges.Clear();
- IsCurved = false;
- UpdateTotalLength();
- LogManager.Info($"[路径更新] 空中路径已更新(直线模式): {Name}");
+ LogManager.Error($"路径数据更新和保存失败({context}): {ex.Message}", ex);
}
- else
- {
- // 未知路径类型:使用直线
- Edges.Clear();
- IsCurved = false;
- UpdateTotalLength();
- LogManager.Warning($"[路径更新] 未知路径类型,使用直线模式: {Name}");
- }
-
- // 3. 更新最后修改时间
- LastModified = DateTime.Now;
-
- LogManager.Info($"[路径更新] 路径数据完整更新完成: {Name}, 原因: {updateReason}, 总长度: {TotalLength:F2}米");
}
///
diff --git a/src/Core/PathPointRenderPlugin.cs b/src/Core/PathPointRenderPlugin.cs
index 2e6a4ce..959393a 100644
--- a/src/Core/PathPointRenderPlugin.cs
+++ b/src/Core/PathPointRenderPlugin.cs
@@ -2149,143 +2149,6 @@ namespace NavisworksTransport
return lineRadiusInMeters * UnitsConverter.GetMetersToUnitsConversionFactor();
}
- ///
- /// 添加路径点到指定路径
- ///
- /// 路径ID
- /// 新的路径点
- /// 插入位置索引,-1表示添加到末尾
- public void AddPointToPath(string pathId, PathPoint newPoint, int insertIndex = -1)
- {
- var visualization = GetPathVisualization(pathId);
- if (visualization == null)
- {
- 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);
- RequestViewRefresh();
- }
- catch (Exception ex)
- {
- LogManager.Error($"[路径编辑] 添加路径点失败: {ex.Message}", ex);
- }
- }
-
- ///
- /// 从指定路径移除路径点
- ///
- /// 路径ID
- /// 要移除的点索引
- public void RemovePointFromPath(string pathId, int pointIndex)
- {
- var visualization = GetPathVisualization(pathId);
- if (visualization == null)
- {
- 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);
- RequestViewRefresh();
- }
- else
- {
- LogManager.Warning($"[路径编辑] 未找到索引为 {pointIndex} 的路径点");
- }
- }
- catch (Exception ex)
- {
- LogManager.Error($"[路径编辑] 移除路径点失败: {ex.Message}", ex);
- }
- }
-
- ///
- /// 更新指定路径中的路径点
- ///
- /// 路径ID
- /// 要更新的点索引
- /// 更新后的路径点
- public void UpdatePointInPath(string pathId, int pointIndex, PathPoint updatedPoint)
- {
- var visualization = GetPathVisualization(pathId);
- if (visualization == null)
- {
- 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);
- RequestViewRefresh();
- }
- else
- {
- LogManager.Warning($"[路径编辑] 未找到索引为 {pointIndex} 的路径点");
- }
- }
- catch (Exception ex)
- {
- LogManager.Error($"[路径编辑] 更新路径点失败: {ex.Message}", ex);
- }
- }
-
- ///
- /// 重新分配路径点索引
- ///
- /// 路径对象
- private void ReindexPoints(PathRoute pathRoute)
- {
- // 按照当前在List中的位置重新分配连续索引
- for (int i = 0; i < pathRoute.Points.Count; i++)
- {
- pathRoute.Points[i].Index = i;
- }
- }
-
///
/// 获取路径可视化对象
///
diff --git a/src/PathPlanning/PathOptimizer.cs b/src/PathPlanning/PathOptimizer.cs
index 0aaafda..b82bb5e 100644
--- a/src/PathPlanning/PathOptimizer.cs
+++ b/src/PathPlanning/PathOptimizer.cs
@@ -477,8 +477,8 @@ namespace NavisworksTransport.PathPlanning
optimizedRoute.Points.Add(point);
}
- // 重新计算路径长度
- optimizedRoute.RecalculateLength();
+ // 重新计算路径数据并保存到数据库
+ optimizedRoute.RecalculateAndSaveRoute("路径优化");
return optimizedRoute;
}
diff --git a/src/UI/WPF/ViewModels/PathEditingViewModel.cs b/src/UI/WPF/ViewModels/PathEditingViewModel.cs
index d095b80..6b4d984 100644
--- a/src/UI/WPF/ViewModels/PathEditingViewModel.cs
+++ b/src/UI/WPF/ViewModels/PathEditingViewModel.cs
@@ -1832,6 +1832,16 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
var pointCount = SelectedPathRoute.Points.Count;
+ // 清空 Core 层的路径点
+ var coreRoute = _pathPlanningManager?.Routes?.FirstOrDefault(r => r.Name == SelectedPathRoute.Name);
+ if (coreRoute != null)
+ {
+ coreRoute.Points.Clear();
+ coreRoute.RecalculateAndSaveRoute("清空路径");
+ LogManager.Info($"已清空Core路径: {coreRoute.Name}");
+ }
+
+ // 清空 UI 层的路径点
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
SelectedPathRoute.Points.Clear();