NavisworksTransport/src/Commands/CoordinateSystemExplorerCommand.cs

202 lines
10 KiB
C#

using System;
using System.Linq;
using System.Text;
using System.Windows;
using Autodesk.Navisworks.Api;
using Autodesk.Navisworks.Api.Plugins;
using ComApi = Autodesk.Navisworks.Api.Interop.ComApi;
using ComApiBridge = Autodesk.Navisworks.Api.ComApi.ComApiBridge;
using NavisworksTransport.Utils;
namespace NavisworksTransport.Commands
{
/// <summary>
/// 坐标系检测命令 - 用于探索 Navisworks API 中的坐标系相关信息
/// </summary>
[Plugin("CoordinateSystemExplorer", "NavisworksTransport", DisplayName = "坐标系检测")]
[AddInPlugin(AddInLocation.AddIn)]
public class CoordinateSystemExplorerCommand : AddInPlugin
{
public override int Execute(params string[] parameters)
{
try
{
var doc = Application.ActiveDocument;
if (doc == null || doc.IsClear)
{
MessageBox.Show("没有活动的文档!", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
return 1;
}
var sb = new StringBuilder();
sb.AppendLine("=== Navisworks 坐标系检测 ===\n");
// 1. Document 级别信息
sb.AppendLine("【1. Document 级别信息】");
sb.AppendLine($"文档名称: {doc.FileName}");
sb.AppendLine($"文档标题: {doc.Title}");
sb.AppendLine($"模型数量: {doc.Models.Count}");
sb.AppendLine();
// 2. Model 级别信息
sb.AppendLine("【2. Model 级别信息】");
int modelIndex = 0;
foreach (Model model in doc.Models)
{
sb.AppendLine($"模型 [{modelIndex}]: {model.Title}");
sb.AppendLine($" - 源文件名: {model.SourceFileName}");
sb.AppendLine($" - 源格式: {model.SourceFileFormat}");
var rootItem = model.RootItem;
if (rootItem != null)
{
sb.AppendLine($" - RootItem.DisplayName: {rootItem.DisplayName}");
sb.AppendLine($" - RootItem.Transform: {rootItem.Transform}");
var components = rootItem.Transform.Factor();
sb.AppendLine($" - Transform.Translation: ({components.Translation.X:F4}, {components.Translation.Y:F4}, {components.Translation.Z:F4})");
sb.AppendLine($" - Transform.Rotation.Axis: ({components.Rotation.Axis.X:F4}, {components.Rotation.Axis.Y:F4}, {components.Rotation.Axis.Z:F4})");
sb.AppendLine($" - Transform.Rotation.Angle: {components.Rotation.Angle:F6} rad ({components.Rotation.Angle * 180 / Math.PI:F2}°)");
sb.AppendLine($" - Transform.Scale: ({components.Scale.X:F4}, {components.Scale.Y:F4}, {components.Scale.Z:F4})");
var bbox = rootItem.BoundingBox();
sb.AppendLine($" - 包围盒 Min: ({bbox.Min.X:F4}, {bbox.Min.Y:F4}, {bbox.Min.Z:F4})");
sb.AppendLine($" - 包围盒 Max: ({bbox.Max.X:F4}, {bbox.Max.Y:F4}, {bbox.Max.Z:F4})");
double xSpan = bbox.Max.X - bbox.Min.X;
double ySpan = bbox.Max.Y - bbox.Min.Y;
double zSpan = bbox.Max.Z - bbox.Min.Z;
sb.AppendLine($" - 跨度: X={xSpan:F2}, Y={ySpan:F2}, Z={zSpan:F2}");
sb.AppendLine($" - 坐标系推测: {(ySpan > zSpan * 2 ? " Y-Up" : " Z-Up")}");
}
sb.AppendLine();
modelIndex++;
}
// 3. 当前选择项的 Transform 详情
sb.AppendLine("【3. 当前选择项信息】");
var selection = doc.CurrentSelection.SelectedItems;
if (selection.Count > 0)
{
var item = selection.First();
sb.AppendLine($"选中项: {item.DisplayName}");
sb.AppendLine($" - ClassName: {item.ClassName}");
sb.AppendLine($" - ClassDisplayName: {item.ClassDisplayName}");
sb.AppendLine($" - HasGeometry: {item.HasGeometry}");
var transform = item.Transform;
var comp = transform.Factor();
sb.AppendLine($" - Transform.Translation: ({comp.Translation.X:F4}, {comp.Translation.Y:F4}, {comp.Translation.Z:F4})");
sb.AppendLine($" - Transform.Rotation.Axis: ({comp.Rotation.Axis.X:F4}, {comp.Rotation.Axis.Y:F4}, {comp.Rotation.Axis.Z:F4})");
sb.AppendLine($" - Transform.Rotation.Angle: {comp.Rotation.Angle:F6} rad");
var itemBbox = item.BoundingBox();
sb.AppendLine($" - 包围盒 Center: ({itemBbox.Center.X:F4}, {itemBbox.Center.Y:F4}, {itemBbox.Center.Z:F4})");
}
else
{
sb.AppendLine("当前没有选择项");
}
sb.AppendLine();
// 4. Viewpoint 信息
sb.AppendLine("【4. Viewpoint 信息】");
var vp = doc.CurrentViewpoint.Value;
sb.AppendLine($"WorldUpVector: ({vp.WorldUpVector.X:F4}, {vp.WorldUpVector.Y:F4}, {vp.WorldUpVector.Z:F4})");
sb.AppendLine($"Position: ({vp.Position.X:F4}, {vp.Position.Y:F4}, {vp.Position.Z:F4})");
sb.AppendLine($"Rotation.Axis: ({vp.Rotation.Axis.X:F4}, {vp.Rotation.Axis.Y:F4}, {vp.Rotation.Axis.Z:F4})");
sb.AppendLine($"Rotation.Angle: {vp.Rotation.Angle:F6} rad");
sb.AppendLine();
// 5. COM API 探索
sb.AppendLine("【5. COM API 探索】");
try
{
var comState = ComApiBridge.ToInwOpState(doc);
sb.AppendLine($"COM State 类型: {comState.GetType().FullName}");
// 尝试获取模型的 COM 表示
if (doc.Models.Count > 0)
{
var firstModel = doc.Models[0];
// 注意:这里可能需要不同的方法来获取 COM 模型对象
sb.AppendLine($"尝试访问 COM 模型对象...");
// 通过选择获取 COM 对象
var modelCollection = new ModelItemCollection { firstModel.RootItem };
var comSelection = ComApiBridge.ToInwOpSelection(modelCollection);
sb.AppendLine($"COM Selection 路径数: {comSelection.Paths().Count}");
// 释放 COM 对象
System.Runtime.InteropServices.Marshal.ReleaseComObject(comSelection);
}
sb.AppendLine("COM API 访问成功");
}
catch (Exception ex)
{
sb.AppendLine($"COM API 访问失败: {ex.Message}");
sb.AppendLine($"堆栈: {ex.StackTrace}");
}
sb.AppendLine();
// 6. 坐标系推测总结
sb.AppendLine("【6. 坐标系推测总结】");
if (doc.Models.Count > 0)
{
var rootBounds = doc.Models[0].RootItem.BoundingBox();
double xSpan = rootBounds.Max.X - rootBounds.Min.X;
double ySpan = rootBounds.Max.Y - rootBounds.Min.Y;
double zSpan = rootBounds.Max.Z - rootBounds.Min.Z;
sb.AppendLine($"模型跨度分析:");
sb.AppendLine($" - X (左右): {xSpan:F2} 单位");
sb.AppendLine($" - Y (前后/上下): {ySpan:F2} 单位");
sb.AppendLine($" - Z (上下/前后): {zSpan:F2} 单位");
sb.AppendLine();
sb.AppendLine($"启发式判断:");
if (ySpan > zSpan * 3)
{
sb.AppendLine($" - Y 跨度显著大于 Z 跨度 ({ySpan/zSpan:F1}x)");
sb.AppendLine($" - 推测: Y-Up 坐标系 (Y轴向上)");
}
else if (zSpan > ySpan * 3)
{
sb.AppendLine($" - Z 跨度显著大于 Y 跨度 ({zSpan/ySpan:F1}x)");
sb.AppendLine($" - 推测: Z-Up 坐标系 (Z轴向上)");
}
else
{
sb.AppendLine($" - Y 和 Z 跨度相近");
sb.AppendLine($" - 无法确定坐标系,可能是特殊模型或 Z-Up");
}
}
// 显示结果
string result = sb.ToString();
// 保存到日志
LogManager.Info(result);
// 显示对话框(如果内容太长,可能需要截断)
const int maxLength = 4000;
string displayText = result.Length > maxLength
? result.Substring(0, maxLength) + "\n\n... (内容已截断,请查看完整日志)"
: result;
MessageBox.Show(displayText, "坐标系检测结果", MessageBoxButton.OK, MessageBoxImage.Information);
return 0;
}
catch (Exception ex)
{
string errorMsg = $"坐标系检测失败: {ex.Message}\n{ex.StackTrace}";
LogManager.Error(errorMsg);
MessageBox.Show(errorMsg, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
return 1;
}
}
}
}