修复了路径编辑的事件分发问题。

This commit is contained in:
tian 2025-08-20 14:33:47 +08:00
parent 0e20be9e86
commit 3012e4752f
5 changed files with 448 additions and 130 deletions

View File

@ -184,11 +184,21 @@ namespace NavisworksTransport.Core.Animation
var doc = NavisApplication.ActiveDocument;
var modelItems = new ModelItemCollection { _animatedObject };
// 计算从部件原始中心到路径起点的偏移
// 获取物体的包围盒
var boundingBox = _animatedObject.BoundingBox();
// 计算物体底面中心点(而不是整体中心点)
var objectBottomCenter = new Point3D(
_originalCenter.X,
_originalCenter.Y,
boundingBox.Min.Z // 使用包围盒的最小Z值作为底面
);
// 计算从物体底面中心到路径起点的偏移
var startOffset = new Vector3D(
_pathPoints[0].X - _originalCenter.X,
_pathPoints[0].Y - _originalCenter.Y,
_pathPoints[0].Z - _originalCenter.Z
_pathPoints[0].X - objectBottomCenter.X,
_pathPoints[0].Y - objectBottomCenter.Y,
_pathPoints[0].Z - objectBottomCenter.Z
);
// 创建变换并应用
@ -198,9 +208,12 @@ namespace NavisworksTransport.Core.Animation
// 更新当前位置为路径起点
_currentPosition = _pathPoints[0];
LogManager.Info($"部件已移动到路径起点,偏移: ({startOffset.X:F2},{startOffset.Y:F2},{startOffset.Z:F2})");
LogManager.Info($"物体已移动到路径起点,底面对齐地面");
LogManager.Info($"物体包围盒: Min=({boundingBox.Min.X:F2},{boundingBox.Min.Y:F2},{boundingBox.Min.Z:F2}), Max=({boundingBox.Max.X:F2},{boundingBox.Max.Y:F2},{boundingBox.Max.Z:F2})");
LogManager.Info($"物体原始中心: ({_originalCenter.X:F2},{_originalCenter.Y:F2},{_originalCenter.Z:F2})");
LogManager.Info($"物体底面中心: ({objectBottomCenter.X:F2},{objectBottomCenter.Y:F2},{objectBottomCenter.Z:F2})");
LogManager.Info($"路径起点坐标: ({_pathPoints[0].X:F2},{_pathPoints[0].Y:F2},{_pathPoints[0].Z:F2})");
LogManager.Info($"原始中心坐标: ({_originalCenter.X:F2},{_originalCenter.Y:F2},{_originalCenter.Z:F2})");
LogManager.Info($"应用的偏移量: ({startOffset.X:F2},{startOffset.Y:F2},{startOffset.Z:F2})");
}
catch (Exception ex)
{

View File

@ -40,6 +40,9 @@ namespace NavisworksTransport
// ToolPlugin 集成
private bool _isToolPluginActive = false;
// 自动路径规划模式标志
private bool _isInAutoPathMode = false;
// 路径点3D标记管理
private List<PathPointMarker> _pathPointMarkers;
@ -147,7 +150,7 @@ namespace NavisworksTransport
public bool IsInEditableState
{
get { return _pathEditState == PathEditState.Creating || _pathEditState == PathEditState.Editing; }
get { return _pathEditState == PathEditState.Creating || _pathEditState == PathEditState.Editing || _pathEditState == PathEditState.AddingPoints; }
}
public PathRoute CurrentRoute
@ -177,6 +180,14 @@ namespace NavisworksTransport
get { return _currentPointType; }
private set { _currentPointType = value; }
}
/// <summary>
/// 是否在自动路径规划模式
/// </summary>
public bool IsInAutoPathMode
{
get { return _isInAutoPathMode; }
private set { _isInAutoPathMode = value; }
}
public ChannelBounds CombinedChannelBounds => _combinedChannelBounds;
@ -618,9 +629,14 @@ namespace NavisworksTransport
try
{
CurrentPointType = pointType;
ActivateToolPlugin();
// 检查是否在自动路径模式 - 如果是则不订阅PathPlanningManager的事件
bool shouldSubscribeToEvents = !IsInAutoPathMode;
LogManager.Info($"StartClickTool - 自动路径模式: {IsInAutoPathMode}, 订阅事件: {shouldSubscribeToEvents}");
ActivateToolPlugin(shouldSubscribeToEvents);
PathEditState = PathEditState.AddingPoints;
LogManager.Info($"点击工具已启动,类型: {pointType}");
LogManager.Info($"点击工具已启动,类型: {pointType},事件订阅: {shouldSubscribeToEvents}");
}
catch (Exception ex)
{
@ -676,8 +692,7 @@ namespace NavisworksTransport
LogManager.WriteLog($"[事件清理] 额外清理过程异常: {cleanupEx.Message}");
}
// 3. 更新状态
PathEditState = PathEditState.None;
// 注意移除了PathEditState设置StopClickTool只管理工具插件状态不修改业务逻辑状态
LogManager.WriteLog("[事件清理] ===== StopClickTool执行完成所有事件订阅已清理 =====");
}
catch (Exception ex)
@ -687,6 +702,47 @@ namespace NavisworksTransport
}
}
/// <summary>
/// 禁用鼠标处理(用于自动路径规划模式)
/// </summary>
public void DisableMouseHandling()
{
try
{
LogManager.Info("禁用PathPlanningManager鼠标处理进入自动路径规划模式");
IsInAutoPathMode = true;
// 取消PathPlanningManager的鼠标事件订阅
PathClickToolPlugin.MouseClicked -= OnToolPluginMouseClicked;
LogManager.Info("已取消PathPlanningManager的鼠标事件订阅");
}
catch (Exception ex)
{
LogManager.Error($"禁用鼠标处理失败: {ex.Message}", ex);
}
}
/// <summary>
/// 启用鼠标处理(用于手动路径编辑模式)
/// </summary>
public void EnableMouseHandling()
{
try
{
LogManager.Info("启用PathPlanningManager鼠标处理退出自动路径规划模式");
IsInAutoPathMode = false;
// 重新订阅PathPlanningManager的鼠标事件
PathClickToolPlugin.MouseClicked -= OnToolPluginMouseClicked; // 先取消避免重复
PathClickToolPlugin.MouseClicked += OnToolPluginMouseClicked;
LogManager.Info("已重新订阅PathPlanningManager的鼠标事件");
}
catch (Exception ex)
{
LogManager.Error($"启用鼠标处理失败: {ex.Message}", ex);
}
}
/// <summary>
/// 自动路径规划(完整实现)
/// </summary>
@ -1631,18 +1687,27 @@ namespace NavisworksTransport
/// <summary>
/// 激活自定义ToolPlugin进行精确点击检测
/// </summary>
private bool ActivateToolPlugin()
/// <param name="subscribeToEvents">是否订阅鼠标事件</param>
private bool ActivateToolPlugin(bool subscribeToEvents = true)
{
// 如果已经激活,直接返回成功
// 如果已经激活,检查是否需要订阅事件
if (_isToolPluginActive)
{
LogManager.WriteLog("[ToolPlugin] ToolPlugin已激活无需重复激活");
LogManager.WriteLog("[ToolPlugin] ToolPlugin已激活检查事件订阅状态");
if (subscribeToEvents)
{
// 确保事件订阅(避免重复订阅)
PathClickToolPlugin.MouseClicked -= OnToolPluginMouseClicked;
PathClickToolPlugin.MouseClicked += OnToolPluginMouseClicked;
LogManager.WriteLog("[ToolPlugin] 已确保PathPlanningManager事件订阅");
}
return true;
}
try
{
LogManager.WriteLog("[ToolPlugin] ===== 开始激活ToolPlugin =====");
LogManager.WriteLog($"[ToolPlugin] 订阅事件: {subscribeToEvents}");
LogManager.WriteLog($"[ToolPlugin] 当前应用程序状态: {Application.IsAutomated}");
LogManager.WriteLog($"[ToolPlugin] 当前文档状态: {Application.ActiveDocument?.Title ?? "NULL"}");
@ -1681,10 +1746,17 @@ namespace NavisworksTransport
Application.MainDocument.Tool.SetCustomToolPlugin(loadedPlugin);
LogManager.WriteLog("[ToolPlugin] ✓ 工具设置成功");
// 5. 订阅点击事件
LogManager.WriteLog("[ToolPlugin] 步骤5: 订阅点击事件");
PathClickToolPlugin.MouseClicked += OnToolPluginMouseClicked;
LogManager.WriteLog("[ToolPlugin] ✓ 事件订阅成功");
// 5. 根据参数决定是否订阅点击事件
if (subscribeToEvents)
{
LogManager.WriteLog("[ToolPlugin] 步骤5: 订阅点击事件");
PathClickToolPlugin.MouseClicked += OnToolPluginMouseClicked;
LogManager.WriteLog("[ToolPlugin] ✓ PathPlanningManager事件订阅成功");
}
else
{
LogManager.WriteLog("[ToolPlugin] 步骤5: 跳过事件订阅(由外部组件管理)");
}
_isToolPluginActive = true;
LogManager.WriteLog("[ToolPlugin] ===== ToolPlugin激活完成 =====");
@ -1708,85 +1780,17 @@ namespace NavisworksTransport
LogManager.WriteLog("[ToolPlugin事件-V2] ===== 收到精确点击坐标 =====");
LogManager.WriteLog($"[ToolPlugin事件-V2] 精确坐标: ({pickResult.Point.X:F3}, {pickResult.Point.Y:F3}, {pickResult.Point.Z:F3})");
LogManager.WriteLog($"[ToolPlugin事件-V2] 选中对象: {pickResult.ModelItem?.DisplayName ?? "NULL"}");
LogManager.WriteLog($"[ToolPlugin事件-V2] 当前点类型: {CurrentPointType}");
// 检查当前选中的通道状态
LogManager.WriteLog($"[ToolPlugin事件-V2] 当前_selectedChannels状态: {(_selectedChannels == null ? "NULL" : $"{_selectedChannels.Count}")}");
// 如果没有选中的通道,尝试实时搜索
if (_selectedChannels == null || _selectedChannels.Count == 0)
// 如果在自动路径规划模式则跳过处理应该由PathEditingViewModel处理
if (IsInAutoPathMode)
{
LogManager.WriteLog("[ToolPlugin事件] 没有预选通道,开始实时搜索可通行的物流模型");
try
{
var document = Application.ActiveDocument;
if (document?.Models != null)
{
// 使用Search API实时搜索
var logisticsItems = SearchLogisticsItemsUsingSearchAPI();
LogManager.WriteLog($"[ToolPlugin事件] 实时搜索找到 {logisticsItems.Count} 个物流模型");
if (logisticsItems.Count > 0)
{
// 筛选出可通行的物流模型
var modelCollection = new ModelItemCollection();
modelCollection.AddRange(logisticsItems);
var traversableItems = CategoryAttributeManager.FilterTraversableItems(modelCollection);
LogManager.WriteLog($"[ToolPlugin事件] 筛选出 {traversableItems.Count} 个可通行的物流模型");
// 临时设置为选中通道
if (_selectedChannels == null) _selectedChannels = new List<ModelItem>();
_selectedChannels.Clear();
foreach (ModelItem item in traversableItems)
{
_selectedChannels.Add(item);
LogManager.WriteLog($"[ToolPlugin事件] 添加可通行模型: '{item.DisplayName}'");
}
}
}
}
catch (Exception searchEx)
{
LogManager.WriteLog($"[ToolPlugin事件] 实时搜索失败: {searchEx.Message}");
}
LogManager.WriteLog("[ToolPlugin事件] 当前在自动路径规划模式跳过PathPlanningManager处理");
return;
}
// 检查是否在可通行的物流模型内
if (_selectedChannels != null && _selectedChannels.Any())
{
bool isInTraversableLogisticsModel = IsItemInSelectedChannels(pickResult.ModelItem) ||
IsItemChildOfSelectedChannels(pickResult.ModelItem);
LogManager.WriteLog($"[ToolPlugin事件] 在可通行的物流模型内: {isInTraversableLogisticsModel}");
if (isInTraversableLogisticsModel)
{
// 不再传递点类型让AddPathPointIn3D方法内部自动判断
LogManager.WriteLog("[ToolPlugin事件] 调用AddPathPointIn3D添加路径点");
var pathPoint = AddPathPointIn3D(pickResult.Point);
if (pathPoint != null)
{
LogManager.WriteLog($"[ToolPlugin事件] ✓ 路径点添加成功: {pathPoint.Name}");
}
else
{
LogManager.WriteLog("[ToolPlugin事件] ✗ 路径点添加失败");
}
}
else
{
LogManager.WriteLog("[ToolPlugin事件] ✗ 点击位置不在可通行的物流模型内");
// 可以考虑给用户一个提示
OnStatusChanged("点击位置不是可通行的物流模型,请在可通行的物流模型上点击");
}
}
else
{
LogManager.WriteLog("[ToolPlugin事件] ✗ 没有可通行的物流模型");
OnStatusChanged("没有找到任何可通行的物流模型,请先为模型设置可通行的物流属性");
}
// 手动路径编辑处理
ProcessManualPathEditing(pickResult);
}
catch (Exception ex)
{
@ -1795,6 +1799,98 @@ namespace NavisworksTransport
}
}
/// <summary>
/// 处理手动路径编辑的鼠标点击
/// </summary>
private void ProcessManualPathEditing(PickItemResult pickResult)
{
// 检查当前选中的通道状态
LogManager.WriteLog($"[手动编辑] 当前_selectedChannels状态: {(_selectedChannels == null ? "NULL" : $"{_selectedChannels.Count}")}");
// 如果没有选中的通道,尝试实时搜索
if (_selectedChannels == null || _selectedChannels.Count == 0)
{
LogManager.WriteLog("[手动编辑] 没有预选通道,开始实时搜索可通行的物流模型");
SearchAndSetTraversableChannels();
}
// 检查是否在可通行的物流模型内并添加路径点
if (_selectedChannels != null && _selectedChannels.Any())
{
bool isInTraversableLogisticsModel = IsItemInSelectedChannels(pickResult.ModelItem) ||
IsItemChildOfSelectedChannels(pickResult.ModelItem);
LogManager.WriteLog($"[手动编辑] 在可通行的物流模型内: {isInTraversableLogisticsModel}");
if (isInTraversableLogisticsModel)
{
// 手动路径编辑 - 添加路径点并绘制
LogManager.WriteLog("[手动编辑] 调用AddPathPointIn3D添加路径点");
var pathPoint = AddPathPointIn3D(pickResult.Point);
if (pathPoint != null)
{
LogManager.WriteLog($"[手动编辑] ✓ 路径点添加成功: {pathPoint.Name}");
}
else
{
LogManager.WriteLog("[手动编辑] ✗ 路径点添加失败");
}
}
else
{
LogManager.WriteLog("[手动编辑] ✗ 点击位置不在可通行的物流模型内");
OnStatusChanged("点击位置不是可通行的物流模型,请在可通行的物流模型上点击");
}
}
else
{
LogManager.WriteLog("[手动编辑] ✗ 没有可通行的物流模型");
OnStatusChanged("没有找到任何可通行的物流模型,请先为模型设置可通行的物流属性");
}
}
/// <summary>
/// 搜索并设置可通行的通道
/// </summary>
private void SearchAndSetTraversableChannels()
{
try
{
var document = Application.ActiveDocument;
if (document?.Models != null)
{
// 使用Search API实时搜索
var logisticsItems = SearchLogisticsItemsUsingSearchAPI();
LogManager.WriteLog($"[搜索通道] 实时搜索找到 {logisticsItems.Count} 个物流模型");
if (logisticsItems.Count > 0)
{
// 筛选出可通行的物流模型
var modelCollection = new ModelItemCollection();
modelCollection.AddRange(logisticsItems);
var traversableItems = CategoryAttributeManager.FilterTraversableItems(modelCollection);
LogManager.WriteLog($"[搜索通道] 筛选出 {traversableItems.Count} 个可通行的物流模型");
// 临时设置为选中通道
if (_selectedChannels == null) _selectedChannels = new List<ModelItem>();
_selectedChannels.Clear();
foreach (ModelItem item in traversableItems)
{
_selectedChannels.Add(item);
LogManager.WriteLog($"[搜索通道] 添加可通行模型: '{item.DisplayName}'");
}
}
}
}
catch (Exception searchEx)
{
LogManager.WriteLog($"[搜索通道] 实时搜索失败: {searchEx.Message}");
}
}
/// <summary>
/// 使用Navisworks Search API高效搜索具有物流属性的模型项
/// </summary>

View File

@ -268,6 +268,68 @@ namespace NavisworksTransport
}
}
/// <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>

View File

@ -357,8 +357,16 @@ namespace NavisworksTransport.UI.WPF.ViewModels
PathRoutes.Add(newPathViewModel);
SelectedPathRoute = newPathViewModel;
// 强制重新初始化ToolPlugin以确保获得鼠标焦点新建路径需要订阅事件
if (!ForceReinitializeToolPlugin(subscribeToEvents: true))
{
AutoPathStatus = "ToolPlugin初始化失败请重试";
LogManager.Error("新建路径ToolPlugin初始化失败");
return;
}
AutoPathStatus = $"已进入新建路径模式: {newRoute.Name} - 请在3D视图中点击设置路径点";
LogManager.Info($"开始新建路径: {newRoute.Name}");
LogManager.Info($"开始新建路径: {newRoute.Name}已强制重新初始化ToolPlugin获取鼠标焦点");
// 不再显示对话框,状态文本已提供足够的反馈
}
@ -458,21 +466,27 @@ namespace NavisworksTransport.UI.WPF.ViewModels
IsSelectingEndPoint = false;
AutoPathStatus = "请在3D视图中点击选择起点...";
// 强制重新初始化ToolPlugin以确保获得鼠标焦点
if (!ForceReinitializeToolPlugin())
// 进入自动路径规划模式 - 动态事件订阅
LogManager.Info("进入自动路径规划模式,启用动态事件订阅");
// 1. 禁用PathPlanningManager的鼠标处理
_pathPlanningManager.DisableMouseHandling();
// 2. 启用PathEditingViewModel的事件订阅
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked; // 先取消避免重复
PathClickToolPlugin.MouseClicked += OnAutoPathMouseClicked;
LogManager.Info("已启用PathEditingViewModel的鼠标事件订阅");
// 强制重新初始化ToolPlugin以确保获得鼠标焦点自动路径不需要PathPlanningManager订阅事件
if (!ForceReinitializeToolPlugin(subscribeToEvents: false))
{
AutoPathStatus = "ToolPlugin初始化失败请重试";
return;
}
// 订阅PathClickToolPlugin的鼠标点击事件来获取自动路径规划的起点
LogManager.Info("订阅PathClickToolPlugin.MouseClicked事件");
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
PathClickToolPlugin.MouseClicked += OnAutoPathMouseClicked;
// 在STA线程中调用Navisworks API
_pathPlanningManager.StartClickTool(PathPointType.StartPoint);
LogManager.Info("=== 选择起点命令设置完成,ToolPlugin已重新激活并获得鼠标焦点,等待用户点击 ===");
LogManager.Info("=== 选择起点命令设置完成,已启用动态事件订阅,等待用户点击 ===");
}, "选择起点");
}
@ -494,21 +508,27 @@ namespace NavisworksTransport.UI.WPF.ViewModels
IsSelectingEndPoint = true;
AutoPathStatus = "请在3D视图中点击选择终点...";
// 强制重新初始化ToolPlugin以确保获得鼠标焦点
if (!ForceReinitializeToolPlugin())
// 进入自动路径规划模式 - 动态事件订阅
LogManager.Info("进入自动路径规划模式,启用动态事件订阅");
// 1. 禁用PathPlanningManager的鼠标处理
_pathPlanningManager.DisableMouseHandling();
// 2. 启用PathEditingViewModel的事件订阅
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked; // 先取消避免重复
PathClickToolPlugin.MouseClicked += OnAutoPathMouseClicked;
LogManager.Info("已启用PathEditingViewModel的鼠标事件订阅");
// 强制重新初始化ToolPlugin以确保获得鼠标焦点自动路径不需要PathPlanningManager订阅事件
if (!ForceReinitializeToolPlugin(subscribeToEvents: false))
{
AutoPathStatus = "ToolPlugin初始化失败请重试";
return;
}
// 订阅PathClickToolPlugin的鼠标点击事件来获取自动路径规划的终点
LogManager.Info("订阅PathClickToolPlugin.MouseClicked事件");
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
PathClickToolPlugin.MouseClicked += OnAutoPathMouseClicked;
// 在STA线程中调用Navisworks API
_pathPlanningManager.StartClickTool(PathPointType.EndPoint);
LogManager.Info("=== 选择终点命令设置完成,ToolPlugin已重新激活并获得鼠标焦点,等待用户点击 ===");
LogManager.Info("=== 选择终点命令设置完成,已启用动态事件订阅,等待用户点击 ===");
}, "选择终点");
}
@ -568,6 +588,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
_pathPlanningManager.StopClickTool();
}
// 清理临时的起点和终点标记
ClearTemporaryAutoPathMarkers();
// 不在这里直接操作UI让RouteGenerated事件处理UI更新
// 这避免了重复的路径添加和UI更新冲突
@ -576,15 +599,28 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
else
{
AutoPathStatus = "❌ 路径规划失败,未找到可行路径";
LogManager.Warning("自动路径规划失败:未找到可行路径");
// 检查是否已经通过ErrorOccurred事件设置了详细错误信息
if (!AutoPathStatus.Contains("❌ 自动路径规划失败"))
{
// 如果没有详细错误信息,则设置通用错误提示
AutoPathStatus = "❌ 路径规划失败,未找到可行路径";
LogManager.Warning("自动路径规划失败:未找到可行路径");
}
else
{
// 如果已有详细错误信息,保留不覆盖
LogManager.Info("保留ErrorOccurred事件设置的详细错误信息不覆盖AutoPathStatus");
}
// 失败情况下也要清理事件订阅
// 失败情况下也要清理事件订阅和临时标记
CleanupAutoPathEventSubscriptions();
if (_pathPlanningManager != null)
{
_pathPlanningManager.StopClickTool();
}
// 清理临时的起点和终点标记
ClearTemporaryAutoPathMarkers();
}
}, "自动路径规划");
}
@ -603,25 +639,26 @@ namespace NavisworksTransport.UI.WPF.ViewModels
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
}
// 清除所有路径可视化使用新的统一API
// 清除所有路径的可视化显示(与新建路径按钮保持一致
if (PathPointRenderPlugin.Instance != null)
{
try
{
// 清除所有路径可视化,包括自动路径和手动路径
PathPointRenderPlugin.Instance.ClearAllPaths();
LogManager.Info("重置参数:已清除所有路径可视化显示");
}
catch (Exception ex)
{
LogManager.Error($"重置参数:清除路径可视化失败: {ex.Message}", ex);
throw; // 重新抛出异常,让上层处理
// 不抛出异常,继续执行状态重置
}
}
// 强制重新初始化ToolPlugin以重新获得鼠标焦点
// 强制重新初始化ToolPlugin以重新获得鼠标焦点,重置时不需要订阅事件
if (_pathPlanningManager != null)
{
ForceReinitializeToolPlugin();
ForceReinitializeToolPlugin(subscribeToEvents: false);
}
// 重置所有状态
@ -638,7 +675,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 通知Can Execute属性更改
OnPropertyChanged(nameof(CanExecuteAutoPlanPath));
LogManager.Info("自动路径规划参数和3D标记已完全重置ToolPlugin已重新初始化");
LogManager.Info("自动路径规划参数和起终点标记已完全重置ToolPlugin已重新初始化");
}, "重置自动路径规划");
}
@ -820,7 +857,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
SetAutoPathStartPoint(point3D);
await SafeExecuteAsync(() =>
{
// 退出自动路径规划模式 - 恢复事件订阅
LogManager.Info("起点选择完成,恢复正常事件订阅状态");
CleanupAutoPathEventSubscriptions();
_pathPlanningManager?.EnableMouseHandling(); // 恢复PathPlanningManager的鼠标处理
_pathPlanningManager?.StopClickTool();
}, "停止起点选择工具");
}
@ -830,7 +870,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
SetAutoPathEndPoint(point3D);
await SafeExecuteAsync(() =>
{
// 退出自动路径规划模式 - 恢复事件订阅
LogManager.Info("终点选择完成,恢复正常事件订阅状态");
CleanupAutoPathEventSubscriptions();
_pathPlanningManager?.EnableMouseHandling(); // 恢复PathPlanningManager的鼠标处理
_pathPlanningManager?.StopClickTool();
}, "停止终点选择工具");
}
@ -838,6 +881,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
LogManager.WriteLog("[自动路径事件] 非选择状态,直接清理事件订阅");
CleanupAutoPathEventSubscriptions();
_pathPlanningManager?.EnableMouseHandling(); // 恢复PathPlanningManager的鼠标处理
}
}
catch (Exception ex)
@ -848,10 +892,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
IsSelectingStartPoint = false;
IsSelectingEndPoint = false;
// 异常情况下也要清理事件订阅
// 异常情况下也要清理事件订阅并恢复状态
try
{
CleanupAutoPathEventSubscriptions();
_pathPlanningManager?.EnableMouseHandling(); // 恢复PathPlanningManager的鼠标处理
_pathPlanningManager?.StopClickTool();
}
catch (Exception cleanupEx)
@ -868,9 +913,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
await SafeExecuteAsync(() =>
{
// 如果已有起点,先移除之前的可视化
if (_hasStartPoint && PathPointRenderPlugin.Instance != null)
{
PathPointRenderPlugin.Instance.RemoveMarkerAt(_startPoint3D, 2.0);
// 移除之前的起点路径可视化
PathPointRenderPlugin.Instance.RemovePath("AutoPathStartPoint");
}
_startPoint3D = point;
@ -881,9 +928,24 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 通知Can Execute属性更改
OnPropertyChanged(nameof(CanExecuteAutoPlanPath));
// 使用新的RenderPointOnly API只渲染起点标记
if (PathPointRenderPlugin.Instance != null)
{
PathPointRenderPlugin.Instance.AddCircleMarker(point, PathPointType.StartPoint, -100);
// 创建临时路径只包含起点
var startPointPathRoute = new PathRoute("AutoPathStartPoint")
{
Description = "自动路径规划起点"
};
var startPathPoint = new PathPoint
{
Name = "起点",
Position = point,
Type = PathPointType.StartPoint
};
startPointPathRoute.AddPoint(startPathPoint);
// 使用新的只渲染点的API不绘制连线
PathPointRenderPlugin.Instance.RenderPointOnly(startPointPathRoute);
}
if (_hasEndPoint)
@ -906,9 +968,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
await SafeExecuteAsync(() =>
{
// 如果已有终点,先移除之前的可视化
if (_hasEndPoint && PathPointRenderPlugin.Instance != null)
{
PathPointRenderPlugin.Instance.RemoveMarkerAt(_endPoint3D, 2.0);
// 移除之前的终点路径可视化
PathPointRenderPlugin.Instance.RemovePath("AutoPathEndPoint");
}
_endPoint3D = point;
@ -919,9 +983,24 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 通知Can Execute属性更改
OnPropertyChanged(nameof(CanExecuteAutoPlanPath));
// 使用新的RenderPointOnly API只渲染终点标记
if (PathPointRenderPlugin.Instance != null)
{
PathPointRenderPlugin.Instance.AddCircleMarker(point, PathPointType.EndPoint, -200);
// 创建临时路径只包含终点
var endPointPathRoute = new PathRoute("AutoPathEndPoint")
{
Description = "自动路径规划终点"
};
var endPathPoint = new PathPoint
{
Name = "终点",
Position = point,
Type = PathPointType.EndPoint
};
endPointPathRoute.AddPoint(endPathPoint);
// 使用新的只渲染点的API不绘制连线
PathPointRenderPlugin.Instance.RenderPointOnly(endPointPathRoute);
}
if (_hasStartPoint)
@ -1003,6 +1082,33 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
/// <summary>
/// 清理临时的自动路径起点和终点标记
/// </summary>
private void ClearTemporaryAutoPathMarkers()
{
try
{
LogManager.WriteLog("[临时标记清理] 开始清理自动路径临时标记");
if (PathPointRenderPlugin.Instance != null)
{
// 清除临时的起点和终点标记
PathPointRenderPlugin.Instance.RemovePath("AutoPathStartPoint");
PathPointRenderPlugin.Instance.RemovePath("AutoPathEndPoint");
LogManager.WriteLog("[临时标记清理] 已清除AutoPathStartPoint和AutoPathEndPoint临时标记");
}
else
{
LogManager.WriteLog("[临时标记清理] PathPointRenderPlugin实例为null无法清理标记");
}
}
catch (Exception ex)
{
LogManager.Error($"[临时标记清理] 清理临时标记失败: {ex.Message}");
}
}
#endregion
#region PathPlanningManager事件处理
@ -1037,7 +1143,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 订阅路径生成事件(用于处理自动路径)
_pathPlanningManager.RouteGenerated += OnRouteGenerated;
LogManager.Info("*** PathEditingViewModel已成功订阅PathPlanningManager事件包括RouteGenerated ***");
// 添加错误事件订阅 - 用于处理自动路径规划失败等错误
_pathPlanningManager.ErrorOccurred += OnPathPlanningError;
LogManager.Info("*** PathEditingViewModel已成功订阅PathPlanningManager事件包括RouteGenerated和ErrorOccurred ***");
// 验证事件订阅是否成功
var routeGeneratedField = _pathPlanningManager.GetType().GetEvent("RouteGenerated");
@ -1070,8 +1179,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
_pathPlanningManager.CurrentRouteChanged -= OnCurrentRouteChanged;
_pathPlanningManager.EditStateChanged -= OnEditStateChanged;
_pathPlanningManager.RouteGenerated -= OnRouteGenerated;
_pathPlanningManager.ErrorOccurred -= OnPathPlanningError;
LogManager.Info("PathEditingViewModel已取消订阅PathPlanningManager事件");
LogManager.Info("PathEditingViewModel已取消订阅PathPlanningManager事件包括ErrorOccurred");
}
catch (Exception ex)
{
@ -1337,6 +1447,41 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
/// <summary>
/// 处理路径规划错误事件
/// </summary>
/// <summary>
/// 处理路径规划错误事件
/// </summary>
/// <summary>
/// 处理路径规划错误事件
/// </summary>
private async void OnPathPlanningError(object sender, PathPlanningErrorOccurredEventArgs e)
{
LogManager.Info($"*** OnPathPlanningError被调用Sender: {sender?.GetType().Name}, Error: {e?.ErrorMessage} ***");
try
{
await SafeExecuteAsync(async () =>
{
LogManager.Error($"自动路径规划失败: {e.ErrorMessage}");
// 使用UIStateManager确保UI更新在主线程执行
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
// 更新自动路径状态显示错误信息
AutoPathStatus = $"❌ 自动路径规划失败: {e.ErrorMessage}";
LogManager.Info($"*** AutoPathStatus已更新为: {AutoPathStatus} ***");
});
}, "处理路径规划错误事件");
}
catch (Exception ex)
{
LogManager.Error($"*** OnPathPlanningError异常: {ex.Message} ***", ex);
}
}
#endregion
#region
@ -1344,10 +1489,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
/// <summary>
/// 强制重新初始化ToolPlugin以确保获得鼠标焦点
/// </summary>
/// <param name="subscribeToEvents">是否订阅鼠标事件新建路径需要true自动路径选点需要false</param>
/// <returns>初始化是否成功</returns>
private bool ForceReinitializeToolPlugin()
private bool ForceReinitializeToolPlugin(bool subscribeToEvents = false)
{
LogManager.Info("开始强制重新初始化ToolPlugin以确保获得鼠标焦点");
LogManager.Info($"开始强制重新初始化ToolPlugin以确保获得鼠标焦点,订阅事件: {subscribeToEvents}");
try
{
// 使用反射调用私有方法强制重新激活ToolPlugin
@ -1368,13 +1514,14 @@ namespace NavisworksTransport.UI.WPF.ViewModels
LogManager.Info("已重置ToolPlugin激活状态标志");
}
// 重新激活ToolPlugin
// 重新激活ToolPlugin,根据参数决定是否订阅事件
var activateMethod = _pathPlanningManager.GetType().GetMethod("ActivateToolPlugin",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if (activateMethod != null)
{
var result = activateMethod.Invoke(_pathPlanningManager, null);
LogManager.Info($"ToolPlugin重新激活结果: {result}");
// 调用带参数的方法传递subscribeToEvents参数
var result = activateMethod.Invoke(_pathPlanningManager, new object[] { subscribeToEvents });
LogManager.Info($"ToolPlugin重新激活结果事件订阅: {subscribeToEvents}: {result}");
if (!(bool)result)
{
LogManager.Error("ToolPlugin激活失败");