1144 lines
48 KiB
C#
1144 lines
48 KiB
C#
using Autodesk.Navisworks.Api;
|
||
using Autodesk.Navisworks.Api.Plugins;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.ComponentModel;
|
||
using System.Drawing;
|
||
using System.Windows.Forms;
|
||
using NavisApplication = Autodesk.Navisworks.Api.Application;
|
||
|
||
namespace NavisworksTransport
|
||
{
|
||
/// <summary>
|
||
/// 全局异常处理工具类
|
||
/// </summary>
|
||
public static class GlobalExceptionHandler
|
||
{
|
||
private static bool _isInitialized = false;
|
||
|
||
/// <summary>
|
||
/// 初始化全局异常处理器
|
||
/// </summary>
|
||
public static void Initialize()
|
||
{
|
||
if (_isInitialized) return;
|
||
|
||
try
|
||
{
|
||
// 捕获未处理的异常
|
||
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
|
||
System.Windows.Forms.Application.ThreadException += OnThreadException;
|
||
_isInitialized = true;
|
||
|
||
LogManager.Info("[全局异常] 全局异常处理器已初始化");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"[全局异常] 初始化异常处理器失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理未捕获的异常
|
||
/// </summary>
|
||
private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||
{
|
||
try
|
||
{
|
||
Exception ex = e.ExceptionObject as Exception;
|
||
string message = ex?.Message ?? "未知异常";
|
||
string stackTrace = ex?.StackTrace ?? "无堆栈信息";
|
||
|
||
LogManager.Error($"[全局异常] 未处理异常: {message}");
|
||
LogManager.Error($"[全局异常] 堆栈信息: {stackTrace}");
|
||
LogManager.Error($"[全局异常] 异常类型: {ex?.GetType().Name ?? "Unknown"}");
|
||
LogManager.Error($"[全局异常] 是否终止: {e.IsTerminating}");
|
||
|
||
// 显示用户友好的错误信息
|
||
ShowErrorDialog("程序发生未预期的错误", message, ex);
|
||
|
||
// 尝试恢复关键组件
|
||
TryRecoverComponents();
|
||
}
|
||
catch
|
||
{
|
||
// 异常处理中的异常,保持静默
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理线程异常
|
||
/// </summary>
|
||
private static void OnThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
|
||
{
|
||
try
|
||
{
|
||
Exception ex = e.Exception;
|
||
LogManager.Error($"[全局异常] 线程异常: {ex.Message}");
|
||
LogManager.Error($"[全局异常] 堆栈信息: {ex.StackTrace}");
|
||
LogManager.Error($"[全局异常] 异常类型: {ex.GetType().Name}");
|
||
|
||
// 显示用户友好的错误信息
|
||
ShowErrorDialog("程序发生线程错误", ex.Message, ex);
|
||
|
||
// 尝试恢复关键组件
|
||
TryRecoverComponents();
|
||
}
|
||
catch
|
||
{
|
||
// 异常处理中的异常,保持静默
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 安全执行方法,捕获所有异常
|
||
/// </summary>
|
||
public static T SafeExecute<T>(Func<T> action, T defaultValue = default(T), string operationName = "操作")
|
||
{
|
||
try
|
||
{
|
||
return action();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"[安全执行] {operationName}失败: {ex.Message}");
|
||
LogManager.Error($"[安全执行] 堆栈信息: {ex.StackTrace}");
|
||
LogManager.Error($"[安全执行] 异常类型: {ex.GetType().Name}");
|
||
|
||
// 对于用户操作,显示简短的错误提示
|
||
if (!string.IsNullOrEmpty(operationName) && operationName != "操作")
|
||
{
|
||
ShowErrorToast($"{operationName}失败: {ex.Message}");
|
||
}
|
||
|
||
return defaultValue;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 安全执行方法(无返回值)
|
||
/// </summary>
|
||
public static void SafeExecute(Action action, string operationName = "操作")
|
||
{
|
||
SafeExecute(() => { action(); return true; }, false, operationName);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示错误对话框
|
||
/// </summary>
|
||
private static void ShowErrorDialog(string title, string message, Exception ex = null)
|
||
{
|
||
try
|
||
{
|
||
string detailMessage = message;
|
||
if (ex != null)
|
||
{
|
||
detailMessage += $"\n\n技术详情: {ex.GetType().Name}";
|
||
if (!string.IsNullOrEmpty(ex.Message))
|
||
{
|
||
detailMessage += $"\n错误信息: {ex.Message}";
|
||
}
|
||
}
|
||
|
||
MessageBox.Show(detailMessage, title, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
catch
|
||
{
|
||
// 如果连错误对话框都显示不了,就保持静默
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示简短的错误提示
|
||
/// </summary>
|
||
private static void ShowErrorToast(string message)
|
||
{
|
||
try
|
||
{
|
||
MessageBox.Show(message, "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||
}
|
||
catch
|
||
{
|
||
// 保持静默
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 尝试恢复关键组件
|
||
/// </summary>
|
||
private static void TryRecoverComponents()
|
||
{
|
||
try
|
||
{
|
||
LogManager.Info("[全局异常] 尝试恢复关键组件...");
|
||
|
||
// 尝试重置路径编辑模式
|
||
var activeManager = PathPlanningManager.GetActivePathManager();
|
||
if (activeManager != null && activeManager.IsPathEditMode)
|
||
{
|
||
activeManager.ExitPathEditMode();
|
||
LogManager.Info("[全局异常] 已退出路径编辑模式");
|
||
}
|
||
|
||
// 尝试清除临时高亮
|
||
if (NavisApplication.ActiveDocument?.Models != null)
|
||
{
|
||
NavisApplication.ActiveDocument.Models.ResetAllTemporaryMaterials();
|
||
LogManager.Info("[全局异常] 已清除临时材质");
|
||
}
|
||
|
||
LogManager.Info("[全局异常] 组件恢复完成");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"[全局异常] 组件恢复失败: {ex.Message}");
|
||
}
|
||
}
|
||
}
|
||
|
||
[PluginAttribute("Basic", "Tian", ToolTip = "Transport Plugin", DisplayName = "Transport Plugin")]
|
||
[AddInPlugin(AddInLocation.AddIn)] // 将插件显示在Navisworks的"附加模块"选项卡中
|
||
public class Main : AddInPlugin
|
||
{
|
||
/// <summary>
|
||
/// 会话初始化标志,用于确保在同一Navisworks会话中只清空一次日志
|
||
/// </summary>
|
||
private static bool _isSessionInitialized = false;
|
||
|
||
public override int Execute(params string[] parameters)
|
||
{
|
||
return GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
// 初始化全局异常处理器
|
||
GlobalExceptionHandler.Initialize();
|
||
|
||
// 根据会话状态决定日志处理方式
|
||
if (!_isSessionInitialized)
|
||
{
|
||
// 首次启动:清空旧日志
|
||
LogManager.ClearLog();
|
||
LogManager.Info("=== NavisworksTransport 插件启动 ===");
|
||
LogManager.Info("=== 路径点计算日志功能已加载 ===");
|
||
_isSessionInitialized = true;
|
||
}
|
||
else
|
||
{
|
||
// 后续打开:添加会话分隔符,保留历史记录
|
||
LogManager.WriteSessionSeparator();
|
||
LogManager.Info("=== 重新打开插件界面 ===");
|
||
}
|
||
|
||
// 显示类别选择对话框
|
||
ShowCategorySelectionDialog();
|
||
|
||
return 0;
|
||
}, -1, "插件初始化");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示主控制面板
|
||
/// </summary>
|
||
private void ShowCategorySelectionDialog()
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
// 获取当前选中的模型项数量
|
||
int selectedCount = NavisApplication.ActiveDocument.CurrentSelection.SelectedItems.Count;
|
||
|
||
// 创建对话框
|
||
Form dialog = new Form
|
||
{
|
||
Text = "物流路径规划插件 - 3D交互模式",
|
||
Size = new Size(380, 700), // 增加高度以容纳新的详情显示区域
|
||
StartPosition = FormStartPosition.CenterParent,
|
||
FormBorderStyle = FormBorderStyle.FixedDialog,
|
||
MaximizeBox = false,
|
||
MinimizeBox = false
|
||
};
|
||
|
||
// 创建主面板,启用自动滚动
|
||
Panel mainPanel = new Panel
|
||
{
|
||
Dock = DockStyle.Fill,
|
||
Padding = new Padding(15),
|
||
AutoScroll = true
|
||
};
|
||
dialog.Controls.Add(mainPanel);
|
||
|
||
int currentY = 0;
|
||
|
||
// 状态信息标签
|
||
Label statusLabel = new Label
|
||
{
|
||
Text = $"当前选中: {selectedCount} 个模型项",
|
||
Font = new Font("微软雅黑", 9, FontStyle.Bold),
|
||
ForeColor = selectedCount > 0 ? System.Drawing.Color.Blue : System.Drawing.Color.Red,
|
||
AutoSize = true,
|
||
Location = new Point(0, currentY)
|
||
};
|
||
mainPanel.Controls.Add(statusLabel);
|
||
currentY += 35;
|
||
|
||
// 创建类别设置GroupBox
|
||
GroupBox categoryGroupBox = new GroupBox
|
||
{
|
||
Text = "★ 类别设置",
|
||
Location = new Point(0, currentY),
|
||
Size = new Size(320, 65),
|
||
Font = new Font("微软雅黑", 9, FontStyle.Bold)
|
||
};
|
||
mainPanel.Controls.Add(categoryGroupBox);
|
||
CreateCategoryDropdown(categoryGroupBox);
|
||
currentY += 85;
|
||
|
||
// 创建3D交互模式GroupBox
|
||
GroupBox mode3DGroupBox = new GroupBox
|
||
{
|
||
Text = "★ 3D路径编辑",
|
||
Location = new Point(0, currentY),
|
||
Size = new Size(320, 300), // 减少高度20像素
|
||
Font = new Font("微软雅黑", 9, FontStyle.Bold),
|
||
BackColor = System.Drawing.Color.LightBlue
|
||
};
|
||
mainPanel.Controls.Add(mode3DGroupBox);
|
||
Create3DInteractionControls(mode3DGroupBox);
|
||
currentY += 320; // 调整间距以适应减少的GroupBox高度
|
||
|
||
// 创建可见性控制GroupBox
|
||
GroupBox visibilityGroupBox = new GroupBox
|
||
{
|
||
Text = "可见性控制",
|
||
Location = new Point(0, currentY),
|
||
Size = new Size(320, 85),
|
||
Font = new Font("微软雅黑", 9, FontStyle.Bold)
|
||
};
|
||
mainPanel.Controls.Add(visibilityGroupBox);
|
||
CreateVisibilityControls(visibilityGroupBox);
|
||
currentY += 105;
|
||
|
||
// 创建路径管理GroupBox
|
||
GroupBox pathManagementGroupBox = new GroupBox
|
||
{
|
||
Text = "路径管理",
|
||
Location = new Point(0, currentY),
|
||
Size = new Size(320, 85),
|
||
Font = new Font("微软雅黑", 9, FontStyle.Bold)
|
||
};
|
||
mainPanel.Controls.Add(pathManagementGroupBox);
|
||
CreatePathManagementControls(pathManagementGroupBox);
|
||
currentY += 105;
|
||
|
||
// 创建关闭按钮
|
||
Button closeButton = new Button
|
||
{
|
||
Text = "关闭",
|
||
Size = new Size(80, 30),
|
||
Location = new Point(240, currentY),
|
||
DialogResult = DialogResult.OK,
|
||
Font = new Font("微软雅黑", 9)
|
||
};
|
||
mainPanel.Controls.Add(closeButton);
|
||
|
||
// 显示对话框
|
||
dialog.ShowDialog();
|
||
}, "显示主控制面板");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建3D交互控制界面
|
||
/// </summary>
|
||
/// <param name="parent">父容器</param>
|
||
private void Create3DInteractionControls(GroupBox parent)
|
||
{
|
||
// 进入3D编辑模式按钮
|
||
Button enterEditModeButton = new Button
|
||
{
|
||
Text = "进入路径编辑",
|
||
Location = new Point(20, 25),
|
||
Size = new Size(110, 30),
|
||
Font = new Font("微软雅黑", 9),
|
||
BackColor = System.Drawing.Color.LightGreen,
|
||
UseVisualStyleBackColor = false
|
||
};
|
||
|
||
// 退出3D编辑模式按钮
|
||
Button exitEditModeButton = new Button
|
||
{
|
||
Text = "退出路径编辑",
|
||
Location = new Point(140, 25),
|
||
Size = new Size(110, 30),
|
||
Font = new Font("微软雅黑", 9),
|
||
BackColor = System.Drawing.Color.LightCoral,
|
||
UseVisualStyleBackColor = false,
|
||
Enabled = false
|
||
};
|
||
|
||
// 检查全局编辑模式状态并更新按钮状态
|
||
bool isGlobalEditMode = PathPlanningManager.GlobalIsPathEditMode;
|
||
enterEditModeButton.Enabled = !isGlobalEditMode;
|
||
exitEditModeButton.Enabled = isGlobalEditMode;
|
||
|
||
// 当前状态显示
|
||
Label statusLabel = new Label
|
||
{
|
||
Text = "状态: 未进入编辑模式",
|
||
Location = new Point(20, 65),
|
||
Size = new Size(200, 20),
|
||
Font = new Font("微软雅黑", 9),
|
||
ForeColor = System.Drawing.Color.Gray
|
||
};
|
||
|
||
// 下一个点类型显示
|
||
Label nextPointTypeLabel = new Label
|
||
{
|
||
Text = "下一个点: 起点",
|
||
Location = new Point(230, 65),
|
||
Size = new Size(80, 20),
|
||
Font = new Font("微软雅黑", 9),
|
||
ForeColor = System.Drawing.Color.Blue
|
||
};
|
||
|
||
// 路径点列表
|
||
Label pointListLabel = new Label
|
||
{
|
||
Text = "路径点列表:",
|
||
Location = new Point(20, 90),
|
||
Size = new Size(80, 20),
|
||
Font = new Font("微软雅黑", 9)
|
||
};
|
||
|
||
ListBox pointListBox = new ListBox
|
||
{
|
||
Location = new Point(20, 110),
|
||
Size = new Size(280, 64), // 4行高度,每行约16px
|
||
Font = new Font("微软雅黑", 8),
|
||
ScrollAlwaysVisible = true, // 按需显示滚动条
|
||
};
|
||
|
||
// 路径点详情显示区域
|
||
Label detailLabel = new Label
|
||
{
|
||
Text = "路径点详情:",
|
||
Location = new Point(20, 165), // 调整位置适应列表高度变化
|
||
Size = new Size(80, 15),
|
||
Font = new Font("微软雅黑", 9)
|
||
};
|
||
|
||
Label pointDetailLabel = new Label
|
||
{
|
||
Text = "请选择一个路径点查看详情",
|
||
Location = new Point(20, 185),
|
||
Size = new Size(280, 50), // 增加高度到50px以容纳3行文本
|
||
Font = new Font("微软雅黑", 8),
|
||
ForeColor = System.Drawing.Color.DarkBlue,
|
||
BorderStyle = BorderStyle.FixedSingle,
|
||
BackColor = System.Drawing.Color.LightCyan
|
||
};
|
||
|
||
// 路径点操作按钮(调整位置到详情下方)
|
||
Button deletePointButton = new Button
|
||
{
|
||
Text = "删除选中点",
|
||
Location = new Point(110, 235), // 调整位置以适应减少的GroupBox高度
|
||
Size = new Size(90, 25),
|
||
Font = new Font("微软雅黑", 8),
|
||
Enabled = false
|
||
};
|
||
|
||
Button clearAllPointsButton = new Button
|
||
{
|
||
Text = "清除所有点",
|
||
Location = new Point(210, 235), // 调整位置以适应减少的GroupBox高度
|
||
Size = new Size(90, 25),
|
||
Font = new Font("微软雅黑", 8),
|
||
Enabled = false
|
||
};
|
||
|
||
// 操作说明标签
|
||
Label instructionLabel = new Label
|
||
{
|
||
Text = "说明: 第一个点自动设为起点,退出编辑时最后一个点自动设为终点",
|
||
Location = new Point(20, 265), // 调整位置以适应减少的GroupBox高度
|
||
Size = new Size(280, 15),
|
||
Font = new Font("微软雅黑", 8),
|
||
ForeColor = System.Drawing.Color.Gray
|
||
};
|
||
|
||
// 事件处理
|
||
enterEditModeButton.Click += (sender, e) =>
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
// 获取当前选中的模型项
|
||
ModelItemCollection selectedItems = NavisApplication.ActiveDocument.CurrentSelection.SelectedItems;
|
||
|
||
if (selectedItems.Count == 0)
|
||
{
|
||
MessageBox.Show("请先选择要作为通道的模型项", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
// 添加测试日志
|
||
LogManager.Info("[测试] 用户点击了进入路径编辑按钮");
|
||
|
||
// 获取或创建路径规划管理器(确保使用同一个实例)
|
||
PathPlanningManager pathManager = PathPlanningManager.GetActivePathManager();
|
||
if (pathManager == null)
|
||
{
|
||
pathManager = new PathPlanningManager();
|
||
LogManager.Info("[测试] 创建了新的PathPlanningManager实例");
|
||
}
|
||
else
|
||
{
|
||
LogManager.Info("[测试] 使用现有的PathPlanningManager实例");
|
||
}
|
||
|
||
// 设置选中的通道
|
||
var channelList = new List<ModelItem>();
|
||
foreach (ModelItem item in selectedItems)
|
||
{
|
||
channelList.Add(item);
|
||
}
|
||
LogManager.Info($"[测试] 设置通道,选中了 {selectedItems.Count} 个对象");
|
||
pathManager.SelectedChannels.Clear();
|
||
pathManager.SelectedChannels.AddRange(channelList);
|
||
LogManager.Info($"[测试] 通道设置完成,PathManager中有 {pathManager.SelectedChannels.Count} 个通道");
|
||
|
||
// 进入路径编辑模式
|
||
bool success = pathManager.EnterPathEditMode();
|
||
|
||
if (success)
|
||
{
|
||
// 更新按钮状态
|
||
enterEditModeButton.Enabled = false;
|
||
exitEditModeButton.Enabled = true;
|
||
statusLabel.Text = "状态: 已进入编辑模式";
|
||
statusLabel.ForeColor = System.Drawing.Color.Green;
|
||
|
||
// 更新路径点列表
|
||
UpdatePointsList(pointListBox, nextPointTypeLabel, pathManager);
|
||
|
||
// 关闭当前对话框以释放焦点,让用户能在主界面操作
|
||
var parentForm = enterEditModeButton.FindForm();
|
||
|
||
MessageBox.Show("已进入3D路径编辑模式!\n\n请在高亮的通道上点击设置路径点。\n\n完成后重新打开插件面板点击'退出路径编辑'。", "模式切换",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
|
||
// 完全关闭对话框,释放焦点
|
||
if (parentForm != null)
|
||
{
|
||
parentForm.DialogResult = DialogResult.OK;
|
||
parentForm.Close();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
MessageBox.Show("进入3D路径编辑模式失败", "错误",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
}, "进入路径编辑模式");
|
||
};
|
||
|
||
exitEditModeButton.Click += (sender, e) =>
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
var activeManager = PathPlanningManager.GetActivePathManager();
|
||
if (activeManager != null)
|
||
{
|
||
bool success = activeManager.ExitPathEditMode();
|
||
|
||
if (success)
|
||
{
|
||
// 更新按钮状态
|
||
enterEditModeButton.Enabled = true;
|
||
exitEditModeButton.Enabled = false;
|
||
statusLabel.Text = "状态: 未进入编辑模式";
|
||
statusLabel.ForeColor = System.Drawing.Color.Gray;
|
||
nextPointTypeLabel.Text = "下一个点: 起点";
|
||
|
||
// 清空路径点列表
|
||
pointListBox.Items.Clear();
|
||
|
||
MessageBox.Show("已退出3D路径编辑模式", "模式切换",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
else
|
||
{
|
||
MessageBox.Show("退出3D路径编辑模式失败", "错误",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 强制更新UI状态
|
||
enterEditModeButton.Enabled = true;
|
||
exitEditModeButton.Enabled = false;
|
||
statusLabel.Text = "状态: 未进入编辑模式";
|
||
statusLabel.ForeColor = System.Drawing.Color.Gray;
|
||
}
|
||
}, "退出路径编辑模式");
|
||
};
|
||
|
||
deletePointButton.Click += (sender, e) =>
|
||
{
|
||
try
|
||
{
|
||
if (pointListBox.SelectedIndex >= 0)
|
||
{
|
||
var activeManager = PathPlanningManager.GetActivePathManager();
|
||
if (activeManager != null && activeManager.CurrentRoute != null)
|
||
{
|
||
var selectedIndex = pointListBox.SelectedIndex;
|
||
if (selectedIndex < activeManager.CurrentRoute.Points.Count)
|
||
{
|
||
activeManager.CurrentRoute.Points.RemoveAt(selectedIndex);
|
||
UpdatePointsList(pointListBox, nextPointTypeLabel, activeManager);
|
||
MessageBox.Show("已删除选中的路径点", "操作成功",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"删除路径点失败: {ex.Message}", "错误",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
};
|
||
|
||
clearAllPointsButton.Click += (sender, e) =>
|
||
{
|
||
try
|
||
{
|
||
var activeManager = PathPlanningManager.GetActivePathManager();
|
||
if (activeManager != null && activeManager.CurrentRoute != null)
|
||
{
|
||
var result = MessageBox.Show("确定要清除所有路径点吗?", "确认操作",
|
||
MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
||
if (result == DialogResult.Yes)
|
||
{
|
||
activeManager.CurrentRoute.Points.Clear();
|
||
activeManager.Clear3DPathMarkers();
|
||
UpdatePointsList(pointListBox, nextPointTypeLabel, activeManager);
|
||
MessageBox.Show("已清除所有路径点", "操作成功",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"清除路径点失败: {ex.Message}", "错误",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
};
|
||
|
||
// 添加路径点选择事件处理
|
||
pointListBox.SelectedIndexChanged += (sender, e) =>
|
||
{
|
||
try
|
||
{
|
||
if (pointListBox.SelectedIndex >= 0)
|
||
{
|
||
var activeManager = PathPlanningManager.GetActivePathManager();
|
||
if (activeManager?.CurrentRoute?.Points != null &&
|
||
pointListBox.SelectedIndex < activeManager.CurrentRoute.Points.Count)
|
||
{
|
||
var selectedPoint = activeManager.CurrentRoute.Points[pointListBox.SelectedIndex];
|
||
var selectedIndex = pointListBox.SelectedIndex;
|
||
|
||
// 显示路径点详情
|
||
string pointType = selectedPoint.Type == PathPointType.StartPoint ? "🚀 起点" :
|
||
selectedPoint.Type == PathPointType.EndPoint ? "🎯 终点" : "📍 路径点";
|
||
|
||
pointDetailLabel.Text = $"序号: {selectedIndex + 1:D2} / {activeManager.CurrentRoute.Points.Count}\n" +
|
||
$"名称: {selectedPoint.Name} 类型: {pointType}\n" +
|
||
$"3D坐标: X={selectedPoint.Position.X:F2}, Y={selectedPoint.Position.Y:F2}, Z={selectedPoint.Position.Z:F2}";
|
||
|
||
deletePointButton.Enabled = true;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
pointDetailLabel.Text = "请选择一个路径点查看详情";
|
||
deletePointButton.Enabled = false;
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
pointDetailLabel.Text = $"获取路径点详情失败: {ex.Message}";
|
||
}
|
||
};
|
||
|
||
// 添加控件到父容器
|
||
parent.Controls.Add(enterEditModeButton);
|
||
parent.Controls.Add(exitEditModeButton);
|
||
parent.Controls.Add(statusLabel);
|
||
// parent.Controls.Add(nextPointTypeLabel); // 隐藏显示,但保留逻辑
|
||
parent.Controls.Add(pointListLabel);
|
||
parent.Controls.Add(pointListBox);
|
||
parent.Controls.Add(detailLabel);
|
||
parent.Controls.Add(pointDetailLabel);
|
||
parent.Controls.Add(deletePointButton);
|
||
parent.Controls.Add(clearAllPointsButton);
|
||
parent.Controls.Add(instructionLabel);
|
||
|
||
// 如果当前处于编辑模式,更新界面状态和路径点列表
|
||
if (isGlobalEditMode)
|
||
{
|
||
statusLabel.Text = "状态: 3D编辑模式已激活";
|
||
statusLabel.ForeColor = System.Drawing.Color.Green;
|
||
clearAllPointsButton.Enabled = true;
|
||
deletePointButton.Enabled = true;
|
||
|
||
// 获取活动的路径管理器并更新列表
|
||
var activeManager = PathPlanningManager.GetActivePathManager();
|
||
if (activeManager != null)
|
||
{
|
||
UpdatePointsList(pointListBox, nextPointTypeLabel, activeManager);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新路径点列表显示
|
||
/// </summary>
|
||
/// <param name="listBox">列表框控件</param>
|
||
/// <param name="nextPointLabel">下一个点类型标签</param>
|
||
/// <param name="pathManager">路径规划管理器</param>
|
||
private void UpdatePointsList(ListBox listBox, Label nextPointLabel, PathPlanningManager pathManager)
|
||
{
|
||
try
|
||
{
|
||
listBox.Items.Clear();
|
||
|
||
if (pathManager?.CurrentRoute?.Points != null)
|
||
{
|
||
// 使用改进的显示格式
|
||
for (int i = 0; i < pathManager.CurrentRoute.Points.Count; i++)
|
||
{
|
||
var point = pathManager.CurrentRoute.Points[i];
|
||
string pointIcon = point.Type == PathPointType.StartPoint ? "🚀" :
|
||
point.Type == PathPointType.EndPoint ? "🎯" : "📍";
|
||
string pointTypeText = point.Type == PathPointType.StartPoint ? "起点" :
|
||
point.Type == PathPointType.EndPoint ? "终点" : "路径点";
|
||
|
||
listBox.Items.Add($"{i + 1:D2}. {pointIcon} {point.Name} [{pointTypeText}]");
|
||
}
|
||
|
||
// 默认选中第一个点
|
||
if (pathManager.CurrentRoute.Points.Count > 0)
|
||
{
|
||
listBox.SelectedIndex = 0;
|
||
}
|
||
|
||
// 更新下一个点类型提示
|
||
if (pathManager.CurrentRoute.Points.Count == 0)
|
||
{
|
||
nextPointLabel.Text = "下一个点: 起点";
|
||
nextPointLabel.ForeColor = System.Drawing.Color.Green;
|
||
}
|
||
else
|
||
{
|
||
nextPointLabel.Text = "下一个点: 路径点";
|
||
nextPointLabel.ForeColor = System.Drawing.Color.Blue;
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
System.Diagnostics.Debug.WriteLine($"更新路径点列表失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建路径管理控制界面
|
||
/// </summary>
|
||
/// <param name="parent">父容器</param>
|
||
private void CreatePathManagementControls(GroupBox parent)
|
||
{
|
||
// 打开2D地图按钮
|
||
Button open2DMapButton = new Button
|
||
{
|
||
Text = "打开2D地图",
|
||
Size = new Size(100, 30),
|
||
Location = new Point(20, 25),
|
||
Font = new Font("微软雅黑", 9),
|
||
UseVisualStyleBackColor = true
|
||
};
|
||
|
||
// 导入路径按钮
|
||
Button importPathButton = new Button
|
||
{
|
||
Text = "导入路径",
|
||
Size = new Size(90, 30),
|
||
Location = new Point(130, 25),
|
||
Font = new Font("微软雅黑", 9),
|
||
UseVisualStyleBackColor = true
|
||
};
|
||
|
||
// 导出路径按钮
|
||
Button exportPathButton = new Button
|
||
{
|
||
Text = "导出路径",
|
||
Size = new Size(90, 30),
|
||
Location = new Point(230, 25),
|
||
Font = new Font("微软雅黑", 9),
|
||
UseVisualStyleBackColor = true
|
||
};
|
||
|
||
// 事件处理
|
||
open2DMapButton.Click += (sender, e) =>
|
||
{
|
||
try
|
||
{
|
||
var pathPlanningManager = new PathPlanningManager();
|
||
pathPlanningManager.ShowPathPlanningInterface();
|
||
MessageBox.Show("2D导航地图已打开", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"打开2D地图失败: {ex.Message}", "错误",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
};
|
||
|
||
importPathButton.Click += (sender, e) =>
|
||
{
|
||
try
|
||
{
|
||
OpenFileDialog openFileDialog = new OpenFileDialog
|
||
{
|
||
Title = "选择路径文件",
|
||
Filter = "XML文件 (*.xml)|*.xml|JSON文件 (*.json)|*.json|所有文件 (*.*)|*.*",
|
||
FilterIndex = 1
|
||
};
|
||
|
||
if (openFileDialog.ShowDialog() == DialogResult.OK)
|
||
{
|
||
var dataManager = new PathDataManager();
|
||
var routes = new List<PathRoute>();
|
||
|
||
string extension = System.IO.Path.GetExtension(openFileDialog.FileName).ToLower();
|
||
if (extension == ".xml")
|
||
{
|
||
routes = dataManager.ImportFromXml(openFileDialog.FileName);
|
||
}
|
||
else if (extension == ".json")
|
||
{
|
||
routes = dataManager.ImportFromJson(openFileDialog.FileName);
|
||
}
|
||
|
||
if (routes.Count > 0)
|
||
{
|
||
MessageBox.Show($"成功导入 {routes.Count} 条路径", "导入成功",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
else
|
||
{
|
||
MessageBox.Show("文件中未找到有效的路径数据", "导入提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"导入路径失败: {ex.Message}", "错误",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
};
|
||
|
||
exportPathButton.Click += (sender, e) =>
|
||
{
|
||
MessageBox.Show("导出功能正在开发中", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
};
|
||
|
||
// 添加控件到父容器
|
||
parent.Controls.Add(open2DMapButton);
|
||
parent.Controls.Add(importPathButton);
|
||
parent.Controls.Add(exportPathButton);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建类别选择下拉框
|
||
/// </summary>
|
||
/// <param name="parent">父容器</param>
|
||
private void CreateCategoryDropdown(GroupBox parent)
|
||
{
|
||
// 类别标签
|
||
Label categoryLabel = new Label
|
||
{
|
||
Text = "设为类型:",
|
||
Location = new Point(20, 30),
|
||
Size = new Size(80, 20),
|
||
Font = new Font("微软雅黑", 9)
|
||
};
|
||
parent.Controls.Add(categoryLabel);
|
||
|
||
// 类别下拉框
|
||
ComboBox categoryComboBox = new ComboBox
|
||
{
|
||
Location = new Point(100, 28),
|
||
Size = new Size(120, 25),
|
||
Font = new Font("微软雅黑", 9),
|
||
DropDownStyle = ComboBoxStyle.DropDownList
|
||
};
|
||
|
||
// 添加类别选项
|
||
categoryComboBox.Items.Add("门");
|
||
categoryComboBox.Items.Add("电梯");
|
||
categoryComboBox.Items.Add("楼梯");
|
||
categoryComboBox.Items.Add("通道");
|
||
categoryComboBox.Items.Add("障碍物");
|
||
categoryComboBox.Items.Add("装卸区");
|
||
categoryComboBox.Items.Add("停车位");
|
||
categoryComboBox.Items.Add("检查点");
|
||
categoryComboBox.SelectedIndex = 3; // 默认选择"通道"
|
||
|
||
parent.Controls.Add(categoryComboBox);
|
||
|
||
// 应用按钮
|
||
Button applyButton = new Button
|
||
{
|
||
Text = "应用类别",
|
||
Location = new Point(230, 27),
|
||
Size = new Size(80, 27),
|
||
Font = new Font("微软雅黑", 9),
|
||
UseVisualStyleBackColor = true
|
||
};
|
||
|
||
// 应用按钮点击事件
|
||
applyButton.Click += (sender, e) =>
|
||
{
|
||
try
|
||
{
|
||
if (categoryComboBox.SelectedIndex < 0)
|
||
{
|
||
MessageBox.Show("请先选择一个类别", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
// 获取当前选中的模型项
|
||
ModelItemCollection selectedItems = NavisApplication.ActiveDocument.CurrentSelection.SelectedItems;
|
||
|
||
if (selectedItems.Count == 0)
|
||
{
|
||
MessageBox.Show("请先选择要设置属性的模型项", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
// 将下拉框选择转换为枚举类型
|
||
CategoryAttributeManager.LogisticsElementType elementType;
|
||
switch (categoryComboBox.SelectedIndex)
|
||
{
|
||
case 0: elementType = CategoryAttributeManager.LogisticsElementType.门; break;
|
||
case 1: elementType = CategoryAttributeManager.LogisticsElementType.电梯; break;
|
||
case 2: elementType = CategoryAttributeManager.LogisticsElementType.楼梯; break;
|
||
case 3: elementType = CategoryAttributeManager.LogisticsElementType.通道; break;
|
||
case 4: elementType = CategoryAttributeManager.LogisticsElementType.障碍物; break;
|
||
case 5: elementType = CategoryAttributeManager.LogisticsElementType.装卸区; break;
|
||
case 6: elementType = CategoryAttributeManager.LogisticsElementType.停车位; break;
|
||
case 7: elementType = CategoryAttributeManager.LogisticsElementType.检查点; break;
|
||
default: elementType = CategoryAttributeManager.LogisticsElementType.通道; break;
|
||
}
|
||
|
||
// 执行属性添加操作
|
||
int successCount = CategoryAttributeManager.AddLogisticsAttributes(
|
||
selectedItems,
|
||
elementType,
|
||
elementType != CategoryAttributeManager.LogisticsElementType.障碍物, // 障碍物默认不可通行
|
||
5, // 默认优先级
|
||
"标准", // 默认车辆尺寸
|
||
10.0 // 默认速度限制
|
||
);
|
||
|
||
// 显示结果
|
||
if (successCount > 0)
|
||
{
|
||
MessageBox.Show($"成功为 {successCount} 个模型项设置了'{categoryComboBox.SelectedItem}'属性", "操作成功",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
else
|
||
{
|
||
MessageBox.Show("未能为任何模型项设置属性,请检查选择的模型项", "操作失败",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"设置属性时发生错误: {ex.Message}", "错误",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
};
|
||
|
||
parent.Controls.Add(applyButton);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建类别按钮(已弃用,保留以防向后兼容)
|
||
/// </summary>
|
||
/// <param name="parent">父容器</param>
|
||
/// <param name="elementType">元素类型</param>
|
||
/// <param name="index">按钮索引</param>
|
||
private void CreateCategoryButton(GroupBox parent, CategoryAttributeManager.LogisticsElementType elementType, int index)
|
||
{
|
||
Button button = new Button
|
||
{
|
||
Text = $"设为{elementType}",
|
||
Size = new Size(200, 35),
|
||
Location = new Point(45, 30 + index * 35),
|
||
Font = new Font("微软雅黑", 10),
|
||
UseVisualStyleBackColor = true
|
||
};
|
||
|
||
// 添加点击事件
|
||
button.Click += (sender, e) =>
|
||
{
|
||
try
|
||
{
|
||
// 获取当前选中的模型项
|
||
ModelItemCollection selectedItems = NavisApplication.ActiveDocument.CurrentSelection.SelectedItems;
|
||
|
||
if (selectedItems.Count == 0)
|
||
{
|
||
MessageBox.Show("请先选择要设置属性的模型项", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
// 执行属性添加操作
|
||
int successCount = CategoryAttributeManager.AddLogisticsAttributes(
|
||
selectedItems,
|
||
elementType,
|
||
elementType != CategoryAttributeManager.LogisticsElementType.障碍物, // 障碍物默认不可通行
|
||
5, // 默认优先级
|
||
"标准", // 默认车辆尺寸
|
||
10.0 // 默认速度限制
|
||
);
|
||
|
||
// 显示结果
|
||
if (successCount > 0)
|
||
{
|
||
MessageBox.Show($"成功为 {successCount} 个模型项设置了物流属性", "操作成功",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
else
|
||
{
|
||
MessageBox.Show("未能为任何模型项设置属性,请检查选择的模型项", "操作失败",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"设置属性时发生错误: {ex.Message}", "错误",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
};
|
||
|
||
parent.Controls.Add(button);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建可见性控制界面
|
||
/// </summary>
|
||
/// <param name="parent">父容器</param>
|
||
private void CreateVisibilityControls(GroupBox parent)
|
||
{
|
||
// 只显示物流分类项目复选框
|
||
CheckBox logisticsOnlyCheckBox = new CheckBox
|
||
{
|
||
Text = "只显示物流分类项目",
|
||
Size = new Size(200, 20),
|
||
Location = new Point(20, 30),
|
||
Font = new Font("微软雅黑", 9),
|
||
Checked = false,
|
||
UseVisualStyleBackColor = true
|
||
};
|
||
|
||
// 状态标签
|
||
Label statusLabel = new Label
|
||
{
|
||
Text = "状态: 显示所有项目",
|
||
Location = new Point(20, 70),
|
||
Size = new Size(250, 20),
|
||
Font = new Font("微软雅黑", 9),
|
||
ForeColor = System.Drawing.Color.DarkGreen
|
||
};
|
||
|
||
// 复选框事件处理
|
||
logisticsOnlyCheckBox.CheckedChanged += (sender, e) =>
|
||
{
|
||
try
|
||
{
|
||
logisticsOnlyCheckBox.Enabled = false;
|
||
statusLabel.Text = "状态: 正在处理...";
|
||
statusLabel.ForeColor = System.Drawing.Color.Orange;
|
||
|
||
VisibilityOperationResult result;
|
||
|
||
if (logisticsOnlyCheckBox.Checked)
|
||
{
|
||
// 勾选时:隐藏非物流分类项目
|
||
result = VisibilityManager.HideNonLogisticsItems();
|
||
if (result.Success)
|
||
{
|
||
statusLabel.Text = $"状态: 已隐藏 {result.HiddenCount} 个非物流项目";
|
||
statusLabel.ForeColor = System.Drawing.Color.DarkGreen;
|
||
}
|
||
else
|
||
{
|
||
statusLabel.Text = "状态: 隐藏操作失败";
|
||
statusLabel.ForeColor = System.Drawing.Color.Red;
|
||
logisticsOnlyCheckBox.Checked = false; // 回滚状态
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 取消勾选时:显示所有项目
|
||
result = VisibilityManager.ShowAllItems();
|
||
if (result.Success)
|
||
{
|
||
statusLabel.Text = "状态: 显示所有项目";
|
||
statusLabel.ForeColor = System.Drawing.Color.DarkGreen;
|
||
}
|
||
else
|
||
{
|
||
statusLabel.Text = "状态: 显示操作失败";
|
||
statusLabel.ForeColor = System.Drawing.Color.Red;
|
||
logisticsOnlyCheckBox.Checked = true; // 回滚状态
|
||
}
|
||
}
|
||
|
||
// 如果操作失败,显示错误信息
|
||
if (!result.Success)
|
||
{
|
||
MessageBox.Show(result.Message, "操作失败", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
statusLabel.Text = "状态: 发生错误";
|
||
statusLabel.ForeColor = System.Drawing.Color.Red;
|
||
logisticsOnlyCheckBox.Checked = !logisticsOnlyCheckBox.Checked; // 回滚状态
|
||
MessageBox.Show($"操作出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
finally
|
||
{
|
||
logisticsOnlyCheckBox.Enabled = true;
|
||
}
|
||
};
|
||
|
||
// 添加控件到父容器
|
||
parent.Controls.Add(logisticsOnlyCheckBox);
|
||
parent.Controls.Add(statusLabel);
|
||
}
|
||
|
||
|
||
}
|
||
}
|