增加坐标系管理功能,支持自动检测和手动选择ZUp/YUp坐标系,更新配置文件和UI界面
This commit is contained in:
parent
5fb18b5869
commit
289fb2016b
@ -293,6 +293,12 @@
|
||||
<Compile Include="src\Utils\NavisworksSelectionHelper.cs" />
|
||||
<Compile Include="src\Utils\NavisworksToDMesh3Converter.cs" />
|
||||
<Compile Include="src\Utils\UnitsConverter.cs" />
|
||||
<!-- Coordinate System -->
|
||||
<Compile Include="src\Utils\CoordinateSystem\CoordinateSystemType.cs" />
|
||||
<Compile Include="src\Utils\CoordinateSystem\ICoordinateSystem.cs" />
|
||||
<Compile Include="src\Utils\CoordinateSystem\ZUpCoordinateSystem.cs" />
|
||||
<Compile Include="src\Utils\CoordinateSystem\YUpCoordinateSystem.cs" />
|
||||
<Compile Include="src\Utils\CoordinateSystem\CoordinateSystemManager.cs" />
|
||||
<Compile Include="src\Utils\ViewpointHelper.cs" />
|
||||
<Compile Include="src\Utils\VisibilityHelper.cs" />
|
||||
<Compile Include="src\Utils\ModelItemTransformHelper.cs" />
|
||||
|
||||
@ -58,3 +58,11 @@ speed_limit_meters_per_second = 0.8
|
||||
|
||||
# 宽度限制(默认值:3.0米)
|
||||
width_limit_meters = 3.0
|
||||
|
||||
[coordinate_system]
|
||||
# 坐标系类型
|
||||
# 可选值: "AutoDetect", "ZUp", "YUp"
|
||||
# AutoDetect: 自动检测(推荐)
|
||||
# ZUp: 强制使用 Z-Up 坐标系(Navisworks 默认)
|
||||
# YUp: 强制使用 Y-Up 坐标系(常见于 Revit 导出)
|
||||
type = "AutoDetect"
|
||||
|
||||
@ -218,6 +218,23 @@ namespace NavisworksTransport.Core.Config
|
||||
config.Logistics.SpeedLimitMetersPerSecond = GetRequiredDoubleValue(logistics, "speed_limit_meters_per_second");
|
||||
config.Logistics.WidthLimitMeters = GetRequiredDoubleValue(logistics, "width_limit_meters");
|
||||
|
||||
// 加载坐标系配置(必需)
|
||||
if (!model.ContainsKey("coordinate_system"))
|
||||
{
|
||||
throw new InvalidOperationException("配置文件缺少 [coordinate_system] 部分");
|
||||
}
|
||||
|
||||
var coordSys = model["coordinate_system"] as TomlTable;
|
||||
if (coordSys == null)
|
||||
{
|
||||
throw new InvalidOperationException("[coordinate_system] 部分格式错误");
|
||||
}
|
||||
|
||||
config.CoordinateSystem = new CoordinateSystemConfig
|
||||
{
|
||||
Type = GetRequiredStringValue(coordSys, "type")
|
||||
};
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
@ -233,7 +250,8 @@ namespace NavisworksTransport.Core.Config
|
||||
PathEditing = new PathEditingConfig(),
|
||||
Visualization = new VisualizationConfig(),
|
||||
Animation = new AnimationConfig(),
|
||||
Logistics = new LogisticsConfig()
|
||||
Logistics = new LogisticsConfig(),
|
||||
CoordinateSystem = new CoordinateSystemConfig()
|
||||
};
|
||||
}
|
||||
|
||||
@ -362,6 +380,16 @@ namespace NavisworksTransport.Core.Config
|
||||
logistics["width_limit_meters"] = config.Logistics.WidthLimitMeters;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新坐标系配置
|
||||
if (model.ContainsKey("coordinate_system"))
|
||||
{
|
||||
var coordSys = model["coordinate_system"] as TomlTable;
|
||||
if (coordSys != null && config.CoordinateSystem != null)
|
||||
{
|
||||
coordSys["type"] = config.CoordinateSystem.Type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -436,5 +464,42 @@ namespace NavisworksTransport.Core.Config
|
||||
|
||||
throw new InvalidOperationException($"配置项 '{key}' 的类型错误,应为布尔类型");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取字符串配置值(可选,有默认值)
|
||||
/// </summary>
|
||||
private string GetStringValue(TomlTable table, string key, string defaultValue)
|
||||
{
|
||||
if (!table.ContainsKey(key))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
return table[key]?.ToString() ?? defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取必需的字符串配置值
|
||||
/// </summary>
|
||||
private string GetRequiredStringValue(TomlTable table, string key)
|
||||
{
|
||||
if (!table.ContainsKey(key))
|
||||
{
|
||||
throw new InvalidOperationException($"配置项 '{key}' 不存在");
|
||||
}
|
||||
|
||||
var value = table[key];
|
||||
if (value == null)
|
||||
{
|
||||
throw new InvalidOperationException($"配置项 '{key}' 的值为 null");
|
||||
}
|
||||
|
||||
var strValue = value.ToString();
|
||||
if (string.IsNullOrWhiteSpace(strValue))
|
||||
{
|
||||
throw new InvalidOperationException($"配置项 '{key}' 不能为空");
|
||||
}
|
||||
|
||||
return strValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,6 +35,11 @@ namespace NavisworksTransport.Core.Config
|
||||
/// 物流属性配置
|
||||
/// </summary>
|
||||
public LogisticsConfig Logistics { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 坐标系配置
|
||||
/// </summary>
|
||||
public CoordinateSystemConfig CoordinateSystem { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -235,4 +240,19 @@ namespace NavisworksTransport.Core.Config
|
||||
/// </summary>
|
||||
public double WidthLimit => WidthLimitMeters * Utils.UnitsConverter.GetMetersToUnitsConversionFactor();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 坐标系配置
|
||||
/// </summary>
|
||||
public class CoordinateSystemConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 坐标系类型
|
||||
/// 可选值: "AutoDetect", "ZUp", "YUp"
|
||||
/// AutoDetect: 基于 Document.UpVector 自动检测
|
||||
/// ZUp: 强制使用 Z-Up 坐标系
|
||||
/// YUp: 强制使用 Y-Up 坐标系
|
||||
/// </summary>
|
||||
public string Type { get; set; } = "AutoDetect";
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ using NavisworksTransport.UI.WPF.Collections;
|
||||
using NavisworksTransport.Core;
|
||||
using NavisworksTransport.Core.Config;
|
||||
using NavisworksTransport.Utils;
|
||||
using NavisworksTransport.Utils.CoordinateSystem;
|
||||
using NavisworksTransport.Commands;
|
||||
|
||||
namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
@ -119,6 +120,29 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
public ICommand ReadTransformTestCommand { get; private set; }
|
||||
public ICommand CoordinateSystemExplorerCommand { get; private set; }
|
||||
|
||||
// 坐标系设置
|
||||
public ObservableCollection<string> CoordinateSystemOptions { get; private set; }
|
||||
|
||||
private string _selectedCoordinateSystem = "AutoDetect";
|
||||
public string SelectedCoordinateSystem
|
||||
{
|
||||
get => _selectedCoordinateSystem;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedCoordinateSystem, value))
|
||||
{
|
||||
OnCoordinateSystemChanged(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string _currentCoordinateSystemInfo = "当前坐标系: 未初始化";
|
||||
public string CurrentCoordinateSystemInfo
|
||||
{
|
||||
get => _currentCoordinateSystemInfo;
|
||||
set => SetProperty(ref _currentCoordinateSystemInfo, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 构造函数
|
||||
@ -145,6 +169,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
|
||||
// 初始化系统管理设置
|
||||
_ = InitializeSystemManagementSettingsAsync();
|
||||
|
||||
// 订阅文档切换事件,以便重新检测坐标系
|
||||
SubscribeToDocumentEvents();
|
||||
|
||||
LogManager.Info("SystemManagementViewModel构造函数执行完成");
|
||||
}
|
||||
@ -224,6 +251,27 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
ReadTransformTestCommand = new RelayCommand(() => ExecuteReadTransformTest());
|
||||
CoordinateSystemExplorerCommand = new RelayCommand(() => ExecuteCoordinateSystemExplorer());
|
||||
|
||||
// 初始化坐标系选项
|
||||
CoordinateSystemOptions = new ObservableCollection<string> { "AutoDetect", "ZUp", "YUp" };
|
||||
|
||||
// 从配置加载当前坐标系设置
|
||||
var configType = ConfigManager.Instance.Current.CoordinateSystem?.Type ?? "AutoDetect";
|
||||
_selectedCoordinateSystem = configType;
|
||||
|
||||
// 订阅文档事件(用于自动检测坐标系)
|
||||
SubscribeToDocumentEvents();
|
||||
|
||||
// 检查当前是否已有活动文档,如果有立即检测
|
||||
if (Autodesk.Navisworks.Api.Application.ActiveDocument != null)
|
||||
{
|
||||
InitializeCoordinateSystem();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 没有活动文档,显示等待状态
|
||||
CurrentCoordinateSystemInfo = "当前坐标系: 等待文档加载...";
|
||||
}
|
||||
|
||||
LogManager.Info("系统管理命令初始化完成");
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -261,6 +309,205 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化坐标系
|
||||
/// </summary>
|
||||
private void InitializeCoordinateSystem()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 解析配置类型
|
||||
if (!Enum.TryParse<CoordinateSystemType>(_selectedCoordinateSystem, out var configType))
|
||||
{
|
||||
configType = CoordinateSystemType.AutoDetect;
|
||||
}
|
||||
|
||||
// 初始化坐标系管理器
|
||||
CoordinateSystemManager.Instance.Initialize(configType);
|
||||
|
||||
// 更新显示信息
|
||||
UpdateCoordinateSystemInfo();
|
||||
|
||||
LogManager.Info($"坐标系初始化完成: {configType}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"坐标系初始化失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 坐标系选择改变时调用
|
||||
/// </summary>
|
||||
private void OnCoordinateSystemChanged(string newValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Enum.TryParse<CoordinateSystemType>(newValue, out var type))
|
||||
{
|
||||
type = CoordinateSystemType.AutoDetect;
|
||||
}
|
||||
|
||||
// 设置新坐标系
|
||||
CoordinateSystemManager.Instance.SetCoordinateSystem(type);
|
||||
|
||||
// 更新显示信息
|
||||
UpdateCoordinateSystemInfo();
|
||||
|
||||
// 更新配置
|
||||
ConfigManager.Instance.Current.CoordinateSystem.Type = newValue;
|
||||
|
||||
UpdateMainStatus($"坐标系已切换为: {newValue}");
|
||||
LogManager.Info($"坐标系已手动切换为: {newValue}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"切换坐标系失败: {ex.Message}");
|
||||
UpdateMainStatus($"切换坐标系失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新坐标系显示信息
|
||||
/// </summary>
|
||||
private void UpdateCoordinateSystemInfo()
|
||||
{
|
||||
var info = CoordinateSystemManager.Instance.GetCurrentInfo();
|
||||
CurrentCoordinateSystemInfo = $"当前坐标系: {info}";
|
||||
}
|
||||
|
||||
#region 文档事件处理
|
||||
|
||||
/// <summary>
|
||||
/// 订阅文档切换事件
|
||||
/// </summary>
|
||||
private void SubscribeToDocumentEvents()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 订阅文档切换后事件(文档已完全加载)
|
||||
Autodesk.Navisworks.Api.Application.ActiveDocumentChanged += OnActiveDocumentChanged;
|
||||
|
||||
// 同时订阅模型集合变化事件(SDI架构下的真正文档变化)
|
||||
if (Autodesk.Navisworks.Api.Application.ActiveDocument != null)
|
||||
{
|
||||
Autodesk.Navisworks.Api.Application.ActiveDocument.Models.CollectionChanged += OnModelsCollectionChanged;
|
||||
}
|
||||
|
||||
LogManager.Info("[系统管理] 已订阅文档相关事件");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[系统管理] 订阅文档事件失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取消订阅文档事件
|
||||
/// </summary>
|
||||
private void UnsubscribeFromDocumentEvents()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 取消订阅文档切换事件
|
||||
Autodesk.Navisworks.Api.Application.ActiveDocumentChanged -= OnActiveDocumentChanged;
|
||||
|
||||
// 取消订阅模型集合变化事件
|
||||
if (Autodesk.Navisworks.Api.Application.ActiveDocument != null)
|
||||
{
|
||||
Autodesk.Navisworks.Api.Application.ActiveDocument.Models.CollectionChanged -= OnModelsCollectionChanged;
|
||||
}
|
||||
|
||||
LogManager.Info("[系统管理] 已取消订阅文档相关事件");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($"[系统管理] 取消订阅文档事件时出现警告: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文档切换事件处理
|
||||
/// </summary>
|
||||
private void OnActiveDocumentChanged(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info("[系统管理] 检测到文档切换");
|
||||
|
||||
// 订阅新文档的 Models.CollectionChanged
|
||||
if (Autodesk.Navisworks.Api.Application.ActiveDocument != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Autodesk.Navisworks.Api.Application.ActiveDocument.Models.CollectionChanged += OnModelsCollectionChanged;
|
||||
LogManager.Info("[系统管理] 已订阅新文档的模型集合变化事件");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($"[系统管理] 订阅模型集合变化事件失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// 执行坐标系检测
|
||||
HandleDocumentChange();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[系统管理] 文档切换处理失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 模型集合变化事件处理(SDI架构下的真正文档变化)
|
||||
/// </summary>
|
||||
private void OnModelsCollectionChanged(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info("[系统管理] 检测到模型集合变化");
|
||||
HandleDocumentChange();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[系统管理] 模型集合变化处理失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理文档变化,重新检测坐标系
|
||||
/// </summary>
|
||||
private void HandleDocumentChange()
|
||||
{
|
||||
// 检查文档是否已完全加载
|
||||
var doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
|
||||
if (doc == null || string.IsNullOrEmpty(doc.FileName))
|
||||
{
|
||||
LogManager.Debug("[系统管理] 文档尚未完全加载,跳过坐标系检测");
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果配置为自动检测,重新检测坐标系
|
||||
if (_selectedCoordinateSystem == "AutoDetect")
|
||||
{
|
||||
// 在 UI 线程执行
|
||||
_ = _uiStateManager.ExecuteUIUpdateAsync(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
InitializeCoordinateSystem();
|
||||
UpdateMainStatus("坐标系已根据新文档重新检测");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[系统管理] 坐标系检测失败: {ex.Message}");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 初始化系统管理设置
|
||||
/// </summary>
|
||||
@ -1235,6 +1482,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
{
|
||||
LogManager.Info("开始清理SystemManagementViewModel资源");
|
||||
|
||||
// 取消订阅文档相关事件
|
||||
UnsubscribeFromDocumentEvents();
|
||||
|
||||
// 停止性能监控Idle任务,替代DispatcherTimer清理
|
||||
try
|
||||
{
|
||||
|
||||
@ -86,6 +86,43 @@ NavisworksTransport 系统管理页签视图 - 采用与其他页签一致的Nav
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- 区域2.5: 坐标系设置 -->
|
||||
<Border BorderBrush="#FFD4E7FF" BorderThickness="1" CornerRadius="0" Margin="0,0,0,15" Padding="12">
|
||||
<StackPanel>
|
||||
<Label Content="坐标系设置" Style="{StaticResource SectionHeaderStyle}"/>
|
||||
|
||||
<TextBlock Text="配置模型坐标系(用于适配Y-up坐标系模型)"
|
||||
FontSize="10"
|
||||
Foreground="{StaticResource NavisworksDarkBrush}"
|
||||
Margin="0,5,0,10"
|
||||
TextWrapping="Wrap"/>
|
||||
|
||||
<!-- 坐标系选择 -->
|
||||
<Grid Margin="0,5,0,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Grid.Column="0" Content="坐标系类型:" Style="{StaticResource ParameterLabelStyle}" Width="100"/>
|
||||
<ComboBox Grid.Column="1"
|
||||
ItemsSource="{Binding CoordinateSystemOptions}"
|
||||
SelectedItem="{Binding SelectedCoordinateSystem}"
|
||||
Width="120"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="5,0,0,0"
|
||||
ToolTip="AutoDetect: 自动检测, ZUp: Z轴向上, YUp: Y轴向上"/>
|
||||
</Grid>
|
||||
|
||||
<!-- 当前坐标系信息 -->
|
||||
<TextBlock Text="{Binding CurrentCoordinateSystemInfo}"
|
||||
FontSize="10"
|
||||
Foreground="{StaticResource NavisworksPrimaryBrush}"
|
||||
Margin="0,5,0,5"
|
||||
TextWrapping="Wrap"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- 区域3: 系统信息 -->
|
||||
<Border BorderBrush="#FFD4E7FF" BorderThickness="1" CornerRadius="0" Margin="0,0,0,15" Padding="12">
|
||||
|
||||
198
src/Utils/CoordinateSystem/CoordinateSystemManager.cs
Normal file
198
src/Utils/CoordinateSystem/CoordinateSystemManager.cs
Normal file
@ -0,0 +1,198 @@
|
||||
using System;
|
||||
using Autodesk.Navisworks.Api;
|
||||
|
||||
namespace NavisworksTransport.Utils.CoordinateSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// 坐标系管理器 - 全局访问点和自动检测
|
||||
/// 简化版:基于 Document.UpVector 自动检测
|
||||
/// </summary>
|
||||
public class CoordinateSystemManager
|
||||
{
|
||||
#region 单例模式
|
||||
|
||||
private static readonly Lazy<CoordinateSystemManager> _instance =
|
||||
new Lazy<CoordinateSystemManager>(() => new CoordinateSystemManager());
|
||||
|
||||
public static CoordinateSystemManager Instance => _instance.Value;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 私有字段
|
||||
|
||||
private ICoordinateSystem _current;
|
||||
private CoordinateSystemType _configuredType = CoordinateSystemType.AutoDetect;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 公共属性
|
||||
|
||||
/// <summary>
|
||||
/// 当前活动的坐标系
|
||||
/// </summary>
|
||||
public ICoordinateSystem Current => _current ?? (_current = new ZUpCoordinateSystem());
|
||||
|
||||
/// <summary>
|
||||
/// 当前配置的坐标系类型
|
||||
/// </summary>
|
||||
public CoordinateSystemType ConfiguredType => _configuredType;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 构造函数
|
||||
|
||||
private CoordinateSystemManager()
|
||||
{
|
||||
// 默认使用 Z-Up
|
||||
_current = new ZUpCoordinateSystem();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 公共方法
|
||||
|
||||
/// <summary>
|
||||
/// 初始化坐标系
|
||||
/// 根据配置自动检测或强制指定
|
||||
/// </summary>
|
||||
/// <param name="configType">配置的类型</param>
|
||||
public void Initialize(CoordinateSystemType configType)
|
||||
{
|
||||
_configuredType = configType;
|
||||
|
||||
switch (configType)
|
||||
{
|
||||
case CoordinateSystemType.AutoDetect:
|
||||
_current = AutoDetectFromDocument();
|
||||
break;
|
||||
case CoordinateSystemType.ZUp:
|
||||
_current = new ZUpCoordinateSystem();
|
||||
LogManager.Info("[坐标系] 强制使用 Z-Up 坐标系");
|
||||
break;
|
||||
case CoordinateSystemType.YUp:
|
||||
_current = new YUpCoordinateSystem();
|
||||
LogManager.Info("[坐标系] 强制使用 Y-Up 坐标系");
|
||||
break;
|
||||
default:
|
||||
_current = new ZUpCoordinateSystem();
|
||||
LogManager.Warning($"[坐标系] 未知配置类型 {configType},使用默认 Z-Up");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重新检测坐标系(用于文档切换后)
|
||||
/// </summary>
|
||||
public void ReDetect()
|
||||
{
|
||||
if (_configuredType == CoordinateSystemType.AutoDetect)
|
||||
{
|
||||
_current = AutoDetectFromDocument();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 手动设置坐标系(用于系统管理界面)
|
||||
/// </summary>
|
||||
/// <param name="type">坐标系类型</param>
|
||||
public void SetCoordinateSystem(CoordinateSystemType type)
|
||||
{
|
||||
_configuredType = type;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case CoordinateSystemType.AutoDetect:
|
||||
_current = AutoDetectFromDocument();
|
||||
break;
|
||||
case CoordinateSystemType.ZUp:
|
||||
_current = new ZUpCoordinateSystem();
|
||||
LogManager.Info("[坐标系] 手动切换为 Z-Up 坐标系");
|
||||
break;
|
||||
case CoordinateSystemType.YUp:
|
||||
_current = new YUpCoordinateSystem();
|
||||
LogManager.Info("[坐标系] 手动切换为 Y-Up 坐标系");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前坐标系的描述信息
|
||||
/// </summary>
|
||||
public string GetCurrentInfo()
|
||||
{
|
||||
return $"类型: {_current.Type}, 向上向量: ({_current.UpVector.X:F2}, {_current.UpVector.Y:F2}, {_current.UpVector.Z:F2})";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 私有方法
|
||||
|
||||
/// <summary>
|
||||
/// 基于 Document.UpVector 自动检测坐标系
|
||||
/// </summary>
|
||||
private ICoordinateSystem AutoDetectFromDocument()
|
||||
{
|
||||
try
|
||||
{
|
||||
var doc = Application.ActiveDocument;
|
||||
if (doc == null)
|
||||
{
|
||||
LogManager.Debug("[坐标系检测] 无活动文档,使用默认 Z-Up");
|
||||
return new ZUpCoordinateSystem();
|
||||
}
|
||||
|
||||
// 检查文档是否已完全加载(通过检查文件名)
|
||||
if (string.IsNullOrEmpty(doc.FileName))
|
||||
{
|
||||
LogManager.Debug("[坐标系检测] 文档尚未完全加载,使用默认 Z-Up");
|
||||
return new ZUpCoordinateSystem();
|
||||
}
|
||||
|
||||
// 安全获取 UpVector
|
||||
Vector3D upVector;
|
||||
try
|
||||
{
|
||||
upVector = doc.UpVector;
|
||||
}
|
||||
catch
|
||||
{
|
||||
LogManager.Debug("[坐标系检测] 无法获取 Document.UpVector,使用默认 Z-Up");
|
||||
return new ZUpCoordinateSystem();
|
||||
}
|
||||
|
||||
// 如果 UpVector 未定义(Zero),使用默认 Z-Up
|
||||
if (upVector.IsZero)
|
||||
{
|
||||
LogManager.Warning("[坐标系检测] Document.UpVector 未定义,使用默认 Z-Up");
|
||||
LogManager.Warning("[坐标系检测] 如需使用 Y-Up,请在系统管理中手动设置");
|
||||
return new ZUpCoordinateSystem();
|
||||
}
|
||||
|
||||
// 检测 Y-Up: UpVector 主要在 Y 方向
|
||||
if (Math.Abs(upVector.Y) > 0.9)
|
||||
{
|
||||
LogManager.Info($"[坐标系检测] Document.UpVector=({upVector.X:F2}, {upVector.Y:F2}, {upVector.Z:F2}) 表明 Y-Up 坐标系");
|
||||
return new YUpCoordinateSystem();
|
||||
}
|
||||
|
||||
// 检测 Z-Up: UpVector 主要在 Z 方向
|
||||
if (Math.Abs(upVector.Z) > 0.9)
|
||||
{
|
||||
LogManager.Info($"[坐标系检测] Document.UpVector=({upVector.X:F2}, {upVector.Y:F2}, {upVector.Z:F2}) 表明 Z-Up 坐标系");
|
||||
return new ZUpCoordinateSystem();
|
||||
}
|
||||
|
||||
// 未知情况
|
||||
LogManager.Warning($"[坐标系检测] Document.UpVector=({upVector.X:F2}, {upVector.Y:F2}, {upVector.Z:F2}) 非标准向量,使用默认 Z-Up");
|
||||
return new ZUpCoordinateSystem();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[坐标系检测] 自动检测失败: {ex.Message}");
|
||||
return new ZUpCoordinateSystem();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
23
src/Utils/CoordinateSystem/CoordinateSystemType.cs
Normal file
23
src/Utils/CoordinateSystem/CoordinateSystemType.cs
Normal file
@ -0,0 +1,23 @@
|
||||
namespace NavisworksTransport.Utils.CoordinateSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// 支持的坐标系类型
|
||||
/// </summary>
|
||||
public enum CoordinateSystemType
|
||||
{
|
||||
/// <summary>
|
||||
/// 自动检测(基于 Document.UpVector)
|
||||
/// </summary>
|
||||
AutoDetect,
|
||||
|
||||
/// <summary>
|
||||
/// Z轴向上(Navisworks 默认)
|
||||
/// </summary>
|
||||
ZUp,
|
||||
|
||||
/// <summary>
|
||||
/// Y轴向上(常见于 Revit 等软件导出)
|
||||
/// </summary>
|
||||
YUp
|
||||
}
|
||||
}
|
||||
55
src/Utils/CoordinateSystem/ICoordinateSystem.cs
Normal file
55
src/Utils/CoordinateSystem/ICoordinateSystem.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using Autodesk.Navisworks.Api;
|
||||
|
||||
namespace NavisworksTransport.Utils.CoordinateSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// 坐标系接口 - 抽象不同坐标系的差异
|
||||
/// </summary>
|
||||
public interface ICoordinateSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// 坐标系类型
|
||||
/// </summary>
|
||||
CoordinateSystemType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取向上向量
|
||||
/// </summary>
|
||||
Vector3D UpVector { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取垂直扫描方向(用于障碍物检测,通常是 -UpVector)
|
||||
/// </summary>
|
||||
Vector3D VerticalScanDirection { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取点的高度值(统一抽象)
|
||||
/// </summary>
|
||||
double GetElevation(Point3D point);
|
||||
|
||||
/// <summary>
|
||||
/// 设置点的高度值,返回新点
|
||||
/// </summary>
|
||||
Point3D SetElevation(Point3D point, double elevation);
|
||||
|
||||
/// <summary>
|
||||
/// 获取水平面坐标(返回X和另一个水平轴)
|
||||
/// </summary>
|
||||
(double h1, double h2) GetHorizontalCoords(Point3D point);
|
||||
|
||||
/// <summary>
|
||||
/// 从水平面坐标和高度构建3D点
|
||||
/// </summary>
|
||||
Point3D CreatePoint(double h1, double h2, double elevation);
|
||||
|
||||
/// <summary>
|
||||
/// 获取包围盒的高度范围
|
||||
/// </summary>
|
||||
(double min, double max) GetHeightRange(BoundingBox3D bounds);
|
||||
|
||||
/// <summary>
|
||||
/// 获取包围盒的水平范围
|
||||
/// </summary>
|
||||
(double min1, double max1, double min2, double max2) GetHorizontalRange(BoundingBox3D bounds);
|
||||
}
|
||||
}
|
||||
52
src/Utils/CoordinateSystem/YUpCoordinateSystem.cs
Normal file
52
src/Utils/CoordinateSystem/YUpCoordinateSystem.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using Autodesk.Navisworks.Api;
|
||||
|
||||
namespace NavisworksTransport.Utils.CoordinateSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Y轴向上坐标系实现(常见于 Revit 等软件导出)
|
||||
/// X = Right, Y = Up, Z = Front
|
||||
/// </summary>
|
||||
public class YUpCoordinateSystem : ICoordinateSystem
|
||||
{
|
||||
public CoordinateSystemType Type => CoordinateSystemType.YUp;
|
||||
|
||||
public Vector3D UpVector => new Vector3D(0, 1, 0);
|
||||
|
||||
public Vector3D VerticalScanDirection => new Vector3D(0, -1, 0);
|
||||
|
||||
public double GetElevation(Point3D point)
|
||||
{
|
||||
return point.Y;
|
||||
}
|
||||
|
||||
public Point3D SetElevation(Point3D point, double elevation)
|
||||
{
|
||||
return new Point3D(point.X, elevation, point.Z);
|
||||
}
|
||||
|
||||
public (double h1, double h2) GetHorizontalCoords(Point3D point)
|
||||
{
|
||||
return (point.X, point.Z);
|
||||
}
|
||||
|
||||
public Point3D CreatePoint(double h1, double h2, double elevation)
|
||||
{
|
||||
return new Point3D(h1, elevation, h2);
|
||||
}
|
||||
|
||||
public (double min, double max) GetHeightRange(BoundingBox3D bounds)
|
||||
{
|
||||
return (bounds.Min.Y, bounds.Max.Y);
|
||||
}
|
||||
|
||||
public (double min1, double max1, double min2, double max2) GetHorizontalRange(BoundingBox3D bounds)
|
||||
{
|
||||
return (bounds.Min.X, bounds.Max.X, bounds.Min.Z, bounds.Max.Z);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "Y-Up 坐标系 (Y轴向上)";
|
||||
}
|
||||
}
|
||||
}
|
||||
52
src/Utils/CoordinateSystem/ZUpCoordinateSystem.cs
Normal file
52
src/Utils/CoordinateSystem/ZUpCoordinateSystem.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using Autodesk.Navisworks.Api;
|
||||
|
||||
namespace NavisworksTransport.Utils.CoordinateSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Z轴向上坐标系实现(Navisworks 默认)
|
||||
/// X = Right, Y = Back, Z = Up
|
||||
/// </summary>
|
||||
public class ZUpCoordinateSystem : ICoordinateSystem
|
||||
{
|
||||
public CoordinateSystemType Type => CoordinateSystemType.ZUp;
|
||||
|
||||
public Vector3D UpVector => new Vector3D(0, 0, 1);
|
||||
|
||||
public Vector3D VerticalScanDirection => new Vector3D(0, 0, -1);
|
||||
|
||||
public double GetElevation(Point3D point)
|
||||
{
|
||||
return point.Z;
|
||||
}
|
||||
|
||||
public Point3D SetElevation(Point3D point, double elevation)
|
||||
{
|
||||
return new Point3D(point.X, point.Y, elevation);
|
||||
}
|
||||
|
||||
public (double h1, double h2) GetHorizontalCoords(Point3D point)
|
||||
{
|
||||
return (point.X, point.Y);
|
||||
}
|
||||
|
||||
public Point3D CreatePoint(double h1, double h2, double elevation)
|
||||
{
|
||||
return new Point3D(h1, h2, elevation);
|
||||
}
|
||||
|
||||
public (double min, double max) GetHeightRange(BoundingBox3D bounds)
|
||||
{
|
||||
return (bounds.Min.Z, bounds.Max.Z);
|
||||
}
|
||||
|
||||
public (double min1, double max1, double min2, double max2) GetHorizontalRange(BoundingBox3D bounds)
|
||||
{
|
||||
return (bounds.Min.X, bounds.Max.X, bounds.Min.Y, bounds.Max.Y);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "Z-Up 坐标系 (Z轴向上)";
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user