增加了虚拟物流车辆动画生成和碰撞检测功能
This commit is contained in:
parent
e5b8501a63
commit
7446431f9c
@ -121,6 +121,8 @@
|
||||
<Compile Include="src\Core\IdleEventManager.cs" />
|
||||
<!-- Core - Document State Management -->
|
||||
<Compile Include="src\Core\DocumentStateManager.cs" />
|
||||
<!-- Core - Virtual Vehicle Management -->
|
||||
<Compile Include="src\Core\VirtualVehicleManager.cs" />
|
||||
<!-- Core - Configuration Management -->
|
||||
<Compile Include="src\Core\Config\SystemConfig.cs" />
|
||||
<Compile Include="src\Core\Config\ConfigManager.cs" />
|
||||
|
||||
@ -2503,3 +2503,25 @@ await System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
|
||||
|
||||
- ✅ 相同门窗的多实例 → 正确去重
|
||||
- ✅ 地板的多片段 → 正确保留
|
||||
|
||||
### Setting “Units and Transform” values via Navisworks API
|
||||
|
||||
https://blog.autodesk.io/setting-units-and-transform-values-via-navisworks-api/
|
||||
|
||||
DocumentModels models = doc.Models;
|
||||
//Get the required model from DocumentModels
|
||||
Model model;
|
||||
Transform3D oldTransform3d=model.Transform;
|
||||
Transform3DComponents transform3dComponents = oldTransform3d.Factor();
|
||||
//Get Values
|
||||
Vector3D originVector3D = transform3dComponents.Translation;
|
||||
Vector3D scaleVector3D = transform3dComponents.Scale;
|
||||
Rotation3D rotationVector3D = transform3dComponents.Rotation;
|
||||
//Set Values
|
||||
transform3dComponents.Translation = new Vector3D(origin_X, origin_Y, origin_Z); //Eg: new Vector3D(10,10,10);
|
||||
transform3dComponents.Rotation = new Rotation3D(new UnitVector3D(0, 0, 1), 0.872665); //Here 50 degree=0.872665 radian
|
||||
transform3dComponents.Scale = new Vector3D(scale_X, scale_Y, scale_Z); //Eg: new Vector3D(2,2,2);
|
||||
Transform3D newTransform3D = transform3dComponents.Combine();
|
||||
//Change model units value
|
||||
Units units = Units.Meters;
|
||||
models.SetModelUnitsAndTransform(model, units , newTransform3D, true);
|
||||
@ -11,7 +11,7 @@
|
||||
|
||||
1. [ ] (功能)碰撞检测时,增加手工指定被检测构件,用特殊颜色标识
|
||||
2. [ ] (功能)动画时,物流模型朝向随路径变化
|
||||
3. [ ] (功能)动画检测,增加使用模拟物流构件立方体选项
|
||||
3. [x] (功能)动画生成,增加使用模拟物流车辆立方体选项
|
||||
4. [ ] (功能)动画检测时,过滤门和其他可通行构件
|
||||
5. [ ] (BUG)只有手动路径时,导出路径按钮没激活
|
||||
6. [ ] (BUG)重复打开模型,有时程序崩溃,需要先关闭物流插件窗口
|
||||
|
||||
288
doc/working/virtual_vehicle_collision_detection.md
Normal file
288
doc/working/virtual_vehicle_collision_detection.md
Normal file
@ -0,0 +1,288 @@
|
||||
# 虚拟车辆立方体碰撞检测功能设计方案
|
||||
|
||||
## 需求背景
|
||||
|
||||
当前项目中,检测动画用的移动物体是手工选择的。需要增加一种方式,按照路径编辑中车辆的长宽高,动态生成一个立方体,用它来进行碰撞检测。
|
||||
|
||||
**需求来源**:`doc/requirement/todo_features.md` - 2025/12/08 功能点3
|
||||
> (功能)动画检测,增加使用模拟物流构件立方体选项
|
||||
|
||||
## 方案选择
|
||||
|
||||
### 方案A(已弃用):虚拟包围盒
|
||||
- 仅使用虚拟包围盒进行碰撞检测
|
||||
- **问题**:Clash Detective需要两个真实的ModelItem进行精确几何体验证,虚拟包围盒无法满足
|
||||
|
||||
### 方案B(采用):创建真实几何体
|
||||
- 在Navisworks中动态创建一个真实的立方体几何体
|
||||
- 将其作为动画对象,复用现有的全部碰撞检测逻辑
|
||||
- **优势**:完全复用现有代码,支持Clash Detective精确验证
|
||||
|
||||
## 核心思路
|
||||
|
||||
**关键洞察**:虚拟车辆本质上就是一个动态创建的立方体ModelItem,一旦创建完成,后续流程与手动选择物体**完全一致**。
|
||||
|
||||
```
|
||||
用户选择"虚拟车辆模式"
|
||||
↓
|
||||
根据车辆尺寸创建立方体几何体(NWD/NWC文件或内存几何体)
|
||||
↓
|
||||
将创建的立方体作为 _animatedObject
|
||||
↓
|
||||
【完全复用现有流程】
|
||||
- SetupAnimation()
|
||||
- PrecomputeAnimationFrames()
|
||||
- StartAnimation()
|
||||
- CreateClashTestAfterAnimation()
|
||||
```
|
||||
|
||||
## 技术实现
|
||||
|
||||
### 1. 创建立方体几何体的方法
|
||||
|
||||
Navisworks API有以下几种方式创建几何体:
|
||||
|
||||
#### 方法1:使用临时NWD文件(推荐)
|
||||
```csharp
|
||||
// 1. 创建临时NWD文件包含立方体
|
||||
// 2. 追加到当前文档
|
||||
// 3. 获取追加后的ModelItem引用
|
||||
// 4. 动画结束后移除临时模型
|
||||
```
|
||||
|
||||
#### 方法2:使用Presenter API(如果可用)
|
||||
```csharp
|
||||
// 使用 Autodesk.Navisworks.Api.Presenter 命名空间
|
||||
// 创建临时几何体用于可视化
|
||||
```
|
||||
|
||||
#### 方法3:使用外部工具生成
|
||||
```csharp
|
||||
// 预先创建一个单位立方体NWC文件
|
||||
// 运行时追加并缩放到目标尺寸
|
||||
```
|
||||
|
||||
### 2. 实现方案详细设计
|
||||
|
||||
#### 2.1 创建 VirtualVehicleManager 类
|
||||
|
||||
```csharp
|
||||
/// <summary>
|
||||
/// 虚拟车辆管理器 - 负责创建和管理虚拟车辆几何体
|
||||
/// </summary>
|
||||
public class VirtualVehicleManager
|
||||
{
|
||||
private static VirtualVehicleManager _instance;
|
||||
public static VirtualVehicleManager Instance => _instance ?? (_instance = new VirtualVehicleManager());
|
||||
|
||||
private ModelItem _virtualVehicleModelItem;
|
||||
private string _tempFilePath;
|
||||
|
||||
/// <summary>
|
||||
/// 创建虚拟车辆立方体
|
||||
/// </summary>
|
||||
/// <param name="lengthMeters">长度(米)</param>
|
||||
/// <param name="widthMeters">宽度(米)</param>
|
||||
/// <param name="heightMeters">高度(米)</param>
|
||||
/// <param name="position">初始位置</param>
|
||||
/// <returns>创建的ModelItem</returns>
|
||||
public ModelItem CreateVirtualVehicle(double lengthMeters, double widthMeters, double heightMeters, Point3D position)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 1. 清理之前的虚拟车辆
|
||||
RemoveVirtualVehicle();
|
||||
|
||||
// 2. 创建临时NWD文件包含立方体
|
||||
_tempFilePath = CreateCubeNwdFile(lengthMeters, widthMeters, heightMeters);
|
||||
|
||||
// 3. 追加到当前文档
|
||||
var doc = Application.ActiveDocument;
|
||||
doc.AppendFile(_tempFilePath);
|
||||
|
||||
// 4. 获取追加后的ModelItem(最后一个模型的根节点)
|
||||
_virtualVehicleModelItem = GetLastAppendedModel();
|
||||
|
||||
// 5. 移动到指定位置
|
||||
MoveToPosition(_virtualVehicleModelItem, position);
|
||||
|
||||
LogManager.Info($"虚拟车辆创建成功: {lengthMeters:F1}m × {widthMeters:F1}m × {heightMeters:F1}m");
|
||||
return _virtualVehicleModelItem;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"创建虚拟车辆失败: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除虚拟车辆
|
||||
/// </summary>
|
||||
public void RemoveVirtualVehicle()
|
||||
{
|
||||
if (_virtualVehicleModelItem != null)
|
||||
{
|
||||
// 从文档中移除模型
|
||||
// ...
|
||||
_virtualVehicleModelItem = null;
|
||||
}
|
||||
|
||||
// 清理临时文件
|
||||
if (!string.IsNullOrEmpty(_tempFilePath) && File.Exists(_tempFilePath))
|
||||
{
|
||||
File.Delete(_tempFilePath);
|
||||
_tempFilePath = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前虚拟车辆
|
||||
/// </summary>
|
||||
public ModelItem CurrentVirtualVehicle => _virtualVehicleModelItem;
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.2 修改 AnimationControlViewModel
|
||||
|
||||
```csharp
|
||||
private void ExecuteGenerateAnimation()
|
||||
{
|
||||
try
|
||||
{
|
||||
ModelItem animatedObject;
|
||||
|
||||
if (UseVirtualVehicle)
|
||||
{
|
||||
// 创建虚拟车辆几何体
|
||||
var startPosition = CurrentPathRoute.Points.First();
|
||||
animatedObject = VirtualVehicleManager.Instance.CreateVirtualVehicle(
|
||||
VirtualVehicleLength,
|
||||
VirtualVehicleWidth,
|
||||
VirtualVehicleHeight,
|
||||
new Point3D(startPosition.X, startPosition.Y, startPosition.Z)
|
||||
);
|
||||
|
||||
LogManager.Info($"使用虚拟车辆: {VirtualVehicleLength:F1}m × {VirtualVehicleWidth:F1}m × {VirtualVehicleHeight:F1}m");
|
||||
}
|
||||
else
|
||||
{
|
||||
animatedObject = SelectedAnimatedObject;
|
||||
}
|
||||
|
||||
// 【以下完全复用现有逻辑】
|
||||
var pathPoints = CurrentPathRoute.Points.Select(p => new Point3D(p.X, p.Y, p.Z)).ToList();
|
||||
|
||||
_pathAnimationManager.CreateAnimation(
|
||||
animatedObject, // 无论是手动选择的还是虚拟车辆,都是真实的ModelItem
|
||||
pathPoints,
|
||||
AnimationDuration,
|
||||
CurrentPathRoute.Name,
|
||||
CurrentPathRoute.Id
|
||||
);
|
||||
|
||||
// ... 其余现有逻辑不变 ...
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.3 动画结束后清理
|
||||
|
||||
```csharp
|
||||
// 在动画完成后的处理中
|
||||
private void OnAnimationCompleted()
|
||||
{
|
||||
// ... 现有的报告生成和Clash测试创建 ...
|
||||
|
||||
// 如果使用了虚拟车辆,询问用户是否保留
|
||||
if (UseVirtualVehicle && VirtualVehicleManager.Instance.CurrentVirtualVehicle != null)
|
||||
{
|
||||
// 可选:提示用户是否保留虚拟车辆
|
||||
// 或者自动移除
|
||||
// VirtualVehicleManager.Instance.RemoveVirtualVehicle();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 创建立方体NWD文件的技术细节
|
||||
|
||||
由于Navisworks API不直接支持创建几何体,可以采用以下方案:
|
||||
|
||||
#### 方案A:预制单位立方体 + 缩放
|
||||
1. 预先准备一个1m×1m×1m的立方体NWC文件(放在插件资源目录)
|
||||
2. 运行时追加这个文件
|
||||
3. 使用`Transform3D.CreateScale`缩放到目标尺寸
|
||||
|
||||
```csharp
|
||||
private ModelItem CreateScaledCube(double length, double width, double height)
|
||||
{
|
||||
// 追加预制的单位立方体
|
||||
var unitCubePath = Path.Combine(PluginResourcesPath, "unit_cube.nwc");
|
||||
doc.AppendFile(unitCubePath);
|
||||
|
||||
var cubeItem = GetLastAppendedModel();
|
||||
|
||||
// 缩放到目标尺寸
|
||||
var scaleTransform = Transform3D.CreateScale(length, width, height);
|
||||
doc.Models.OverridePermanentTransform(new ModelItemCollection { cubeItem }, scaleTransform, true);
|
||||
|
||||
return cubeItem;
|
||||
}
|
||||
```
|
||||
|
||||
#### 方案B:使用FBX/OBJ中间格式
|
||||
1. 运行时生成OBJ格式的立方体文件
|
||||
2. 使用Navisworks的文件转换功能导入
|
||||
|
||||
### 4. 关于预制立方体文件
|
||||
|
||||
需要准备一个`unit_cube.nwc`文件:
|
||||
- 尺寸:1m × 1m × 1m
|
||||
- 原点:底面中心在原点
|
||||
- 材质:半透明(便于观察碰撞)
|
||||
|
||||
可以使用以下工具创建:
|
||||
1. AutoCAD/Revit 导出
|
||||
2. 3ds Max 导出
|
||||
3. 简单的OBJ文件手动编写后转换
|
||||
|
||||
## 修改文件清单
|
||||
|
||||
| 文件 | 修改类型 | 主要改动 |
|
||||
|------|----------|----------|
|
||||
| `VirtualVehicleManager.cs` | **新增** | 虚拟车辆几何体创建和管理 |
|
||||
| `AnimationControlView.xaml` | 修改 | 添加RadioButton选择组和虚拟车辆尺寸显示 |
|
||||
| `AnimationControlViewModel.cs` | 修改 | 调用VirtualVehicleManager创建虚拟车辆 |
|
||||
| `LogisticsControlPanel.xaml.cs` | 修改 | 添加车辆参数同步逻辑 |
|
||||
| `resources/unit_cube.nwc` | **新增** | 预制的单位立方体模型文件 |
|
||||
|
||||
## 关键优势
|
||||
|
||||
1. **完全复用现有代码**:创建真实ModelItem后,所有现有逻辑(动画、碰撞检测、Clash Detective测试、报告生成)无需任何修改
|
||||
2. **真实的碰撞检测结果**:Clash Detective可以进行精确几何体验证
|
||||
3. **最小改动原则**:只需添加创建几何体的逻辑,其他代码不变
|
||||
|
||||
## 测试要点
|
||||
|
||||
1. **几何体创建**
|
||||
- 虚拟车辆立方体正确创建
|
||||
- 尺寸和位置正确
|
||||
|
||||
2. **碰撞检测**
|
||||
- 与手动选择物体的检测结果一致
|
||||
- Clash Detective测试正常生成
|
||||
|
||||
3. **清理**
|
||||
- 动画结束后正确清理临时文件
|
||||
- 用户可选择是否保留虚拟车辆
|
||||
|
||||
## 实现步骤
|
||||
|
||||
1. 准备预制的单位立方体NWC文件
|
||||
2. 创建VirtualVehicleManager类
|
||||
3. 修改AnimationControlViewModel调用VirtualVehicleManager
|
||||
4. 测试完整流程
|
||||
BIN
resources/unit_cube.nwc
Normal file
BIN
resources/unit_cube.nwc
Normal file
Binary file not shown.
48
resources/unit_cube.obj
Normal file
48
resources/unit_cube.obj
Normal file
@ -0,0 +1,48 @@
|
||||
# Unit Cube 1m x 1m x 1m
|
||||
# Bottom center at origin (0, 0, 0)
|
||||
# For Navisworks Virtual Vehicle
|
||||
|
||||
# Vertices (8 corners)
|
||||
# Bottom face (Z = 0)
|
||||
v -0.5 -0.5 0.0
|
||||
v 0.5 -0.5 0.0
|
||||
v 0.5 0.5 0.0
|
||||
v -0.5 0.5 0.0
|
||||
# Top face (Z = 1)
|
||||
v -0.5 -0.5 1.0
|
||||
v 0.5 -0.5 1.0
|
||||
v 0.5 0.5 1.0
|
||||
v -0.5 0.5 1.0
|
||||
|
||||
# Normals
|
||||
vn 0 0 -1
|
||||
vn 0 0 1
|
||||
vn 0 -1 0
|
||||
vn 0 1 0
|
||||
vn -1 0 0
|
||||
vn 1 0 0
|
||||
|
||||
# Faces (6 faces, 2 triangles each)
|
||||
# Bottom face (Z = 0, normal -Z)
|
||||
f 1//1 3//1 2//1
|
||||
f 1//1 4//1 3//1
|
||||
|
||||
# Top face (Z = 1, normal +Z)
|
||||
f 5//2 6//2 7//2
|
||||
f 5//2 7//2 8//2
|
||||
|
||||
# Front face (Y = -0.5, normal -Y)
|
||||
f 1//3 2//3 6//3
|
||||
f 1//3 6//3 5//3
|
||||
|
||||
# Back face (Y = 0.5, normal +Y)
|
||||
f 3//4 4//4 8//4
|
||||
f 3//4 8//4 7//4
|
||||
|
||||
# Left face (X = -0.5, normal -X)
|
||||
f 1//5 5//5 8//5
|
||||
f 1//5 8//5 4//5
|
||||
|
||||
# Right face (X = 0.5, normal +X)
|
||||
f 2//6 3//6 7//6
|
||||
f 2//6 7//6 6//6
|
||||
@ -1820,7 +1820,6 @@ namespace NavisworksTransport.Core.Animation
|
||||
SetState(AnimationState.Ready);
|
||||
}
|
||||
|
||||
|
||||
#region 动画实现方法
|
||||
|
||||
|
||||
|
||||
306
src/Core/VirtualVehicleManager.cs
Normal file
306
src/Core/VirtualVehicleManager.cs
Normal file
@ -0,0 +1,306 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Autodesk.Navisworks.Api;
|
||||
|
||||
namespace NavisworksTransport.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// 虚拟车辆管理器 - 负责创建和管理虚拟车辆几何体
|
||||
/// 通过追加预制的单位立方体NWC文件并缩放来创建指定尺寸的虚拟车辆
|
||||
/// </summary>
|
||||
public class VirtualVehicleManager
|
||||
{
|
||||
private static VirtualVehicleManager _instance;
|
||||
private static readonly object _lock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// 单例实例
|
||||
/// </summary>
|
||||
public static VirtualVehicleManager Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new VirtualVehicleManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
private ModelItem _virtualVehicleModelItem;
|
||||
private Model _virtualVehicleModel;
|
||||
private bool _isVirtualVehicleActive;
|
||||
|
||||
/// <summary>
|
||||
/// 当前虚拟车辆ModelItem
|
||||
/// </summary>
|
||||
public ModelItem CurrentVirtualVehicle => _virtualVehicleModelItem;
|
||||
|
||||
/// <summary>
|
||||
/// 虚拟车辆是否激活
|
||||
/// </summary>
|
||||
public bool IsVirtualVehicleActive => _isVirtualVehicleActive;
|
||||
|
||||
private VirtualVehicleManager()
|
||||
{
|
||||
_isVirtualVehicleActive = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建虚拟车辆立方体
|
||||
/// </summary>
|
||||
/// <param name="lengthMeters">长度(米)- X方向</param>
|
||||
/// <param name="widthMeters">宽度(米)- Y方向</param>
|
||||
/// <param name="heightMeters">高度(米)- Z方向</param>
|
||||
/// <returns>创建的ModelItem</returns>
|
||||
public ModelItem CreateVirtualVehicle(double lengthMeters, double widthMeters, double heightMeters)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info($"=== 创建虚拟车辆 ===");
|
||||
LogManager.Info($"目标尺寸: {lengthMeters:F2}m × {widthMeters:F2}m × {heightMeters:F2}m");
|
||||
|
||||
// 1. 清理之前的虚拟车辆
|
||||
RemoveVirtualVehicle();
|
||||
|
||||
// 2. 获取单位立方体文件路径
|
||||
var unitCubePath = GetUnitCubeFilePath();
|
||||
if (string.IsNullOrEmpty(unitCubePath) || !File.Exists(unitCubePath))
|
||||
{
|
||||
throw new FileNotFoundException($"找不到单位立方体文件: {unitCubePath}");
|
||||
}
|
||||
|
||||
LogManager.Info($"单位立方体文件: {unitCubePath}");
|
||||
|
||||
// 3. 记录追加前的模型数量
|
||||
var doc = Application.ActiveDocument;
|
||||
int modelCountBefore = doc.Models.Count;
|
||||
LogManager.Info($"追加前模型数量: {modelCountBefore}");
|
||||
|
||||
// 4. 追加单位立方体文件
|
||||
if (!doc.TryAppendFile(unitCubePath))
|
||||
{
|
||||
throw new InvalidOperationException($"无法追加文件: {unitCubePath}");
|
||||
}
|
||||
|
||||
// 5. 获取新追加的模型
|
||||
int modelCountAfter = doc.Models.Count;
|
||||
LogManager.Info($"追加后模型数量: {modelCountAfter}");
|
||||
|
||||
if (modelCountAfter <= modelCountBefore)
|
||||
{
|
||||
throw new InvalidOperationException("追加文件后模型数量未增加");
|
||||
}
|
||||
|
||||
_virtualVehicleModel = doc.Models.Last();
|
||||
_virtualVehicleModelItem = _virtualVehicleModel.RootItem;
|
||||
|
||||
LogManager.Info($"虚拟车辆模型: {_virtualVehicleModel.FileName}");
|
||||
LogManager.Info($"虚拟车辆根项: {_virtualVehicleModelItem.DisplayName}");
|
||||
|
||||
// 6. 获取实际的几何体项(可能在子节点中)
|
||||
var geometryItem = FindFirstGeometryItem(_virtualVehicleModelItem);
|
||||
if (geometryItem != null && !geometryItem.Equals(_virtualVehicleModelItem))
|
||||
{
|
||||
LogManager.Info($"找到几何体项: {geometryItem.DisplayName}");
|
||||
_virtualVehicleModelItem = geometryItem;
|
||||
}
|
||||
|
||||
// 7. 缩放到目标尺寸
|
||||
ScaleVirtualVehicle(lengthMeters, widthMeters, heightMeters);
|
||||
|
||||
_isVirtualVehicleActive = true;
|
||||
|
||||
LogManager.Info($"虚拟车辆创建成功");
|
||||
return _virtualVehicleModelItem;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"创建虚拟车辆失败: {ex.Message}", ex);
|
||||
RemoveVirtualVehicle();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 缩放虚拟车辆到目标尺寸
|
||||
/// 使用DocumentModels.SetModelUnitsAndTransform方法进行模型级缩放
|
||||
/// </summary>
|
||||
private void ScaleVirtualVehicle(double lengthMeters, double widthMeters, double heightMeters)
|
||||
{
|
||||
if (_virtualVehicleModel == null || _virtualVehicleModelItem == null) return;
|
||||
|
||||
var doc = Application.ActiveDocument;
|
||||
|
||||
// 获取当前包围盒(单位立方体应该是1m x 1m x 1m)
|
||||
var boundingBox = _virtualVehicleModelItem.BoundingBox();
|
||||
double currentLength = boundingBox.Max.X - boundingBox.Min.X;
|
||||
double currentWidth = boundingBox.Max.Y - boundingBox.Min.Y;
|
||||
double currentHeight = boundingBox.Max.Z - boundingBox.Min.Z;
|
||||
|
||||
// 获取单位转换因子(米到模型单位)
|
||||
double metersToUnits = Utils.UnitsConverter.GetMetersToUnitsConversionFactor(doc.Units);
|
||||
|
||||
// 当前尺寸(米)
|
||||
double currentLengthMeters = currentLength / metersToUnits;
|
||||
double currentWidthMeters = currentWidth / metersToUnits;
|
||||
double currentHeightMeters = currentHeight / metersToUnits;
|
||||
|
||||
LogManager.Info($"当前尺寸: {currentLengthMeters:F2}m × {currentWidthMeters:F2}m × {currentHeightMeters:F2}m");
|
||||
LogManager.Info($"目标尺寸: {lengthMeters:F2}m × {widthMeters:F2}m × {heightMeters:F2}m");
|
||||
|
||||
// 计算缩放比例
|
||||
double scaleX = currentLengthMeters > 0 ? lengthMeters / currentLengthMeters : lengthMeters;
|
||||
double scaleY = currentWidthMeters > 0 ? widthMeters / currentWidthMeters : widthMeters;
|
||||
double scaleZ = currentHeightMeters > 0 ? heightMeters / currentHeightMeters : heightMeters;
|
||||
|
||||
LogManager.Info($"缩放比例: X={scaleX:F2}, Y={scaleY:F2}, Z={scaleZ:F2}");
|
||||
|
||||
// 使用Transform3DComponents进行缩放
|
||||
// 获取当前模型的变换并分解
|
||||
Transform3D currentTransform = _virtualVehicleModel.Transform;
|
||||
Transform3DComponents transformComponents = currentTransform.Factor();
|
||||
|
||||
// 获取当前值
|
||||
Vector3D currentTranslation = transformComponents.Translation;
|
||||
Rotation3D currentRotation = transformComponents.Rotation;
|
||||
Vector3D currentScale = transformComponents.Scale;
|
||||
|
||||
LogManager.Info($"当前变换 - 平移: ({currentTranslation.X:F2}, {currentTranslation.Y:F2}, {currentTranslation.Z:F2})");
|
||||
LogManager.Info($"当前变换 - 缩放: ({currentScale.X:F2}, {currentScale.Y:F2}, {currentScale.Z:F2})");
|
||||
|
||||
// 设置新的缩放值(在原有缩放基础上乘以新的缩放比例)
|
||||
transformComponents.Scale = new Vector3D(
|
||||
currentScale.X * scaleX,
|
||||
currentScale.Y * scaleY,
|
||||
currentScale.Z * scaleZ
|
||||
);
|
||||
|
||||
// 组合成新的变换
|
||||
Transform3D newTransform = transformComponents.Combine();
|
||||
|
||||
// 获取当前模型单位
|
||||
Units currentUnits = _virtualVehicleModel.Units;
|
||||
|
||||
// 应用新的变换
|
||||
doc.Models.SetModelUnitsAndTransform(_virtualVehicleModel, currentUnits, newTransform, false);
|
||||
|
||||
// 验证缩放结果
|
||||
var newBoundingBox = _virtualVehicleModelItem.BoundingBox();
|
||||
double newLength = newBoundingBox.Max.X - newBoundingBox.Min.X;
|
||||
double newWidth = newBoundingBox.Max.Y - newBoundingBox.Min.Y;
|
||||
double newHeight = newBoundingBox.Max.Z - newBoundingBox.Min.Z;
|
||||
|
||||
double newLengthMeters = newLength / metersToUnits;
|
||||
double newWidthMeters = newWidth / metersToUnits;
|
||||
double newHeightMeters = newHeight / metersToUnits;
|
||||
|
||||
LogManager.Info($"缩放后尺寸: {newLengthMeters:F2}m × {newWidthMeters:F2}m × {newHeightMeters:F2}m");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除虚拟车辆(隐藏模型,因为Navisworks API不支持直接删除追加的模型)
|
||||
/// </summary>
|
||||
public void RemoveVirtualVehicle()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_virtualVehicleModelItem != null)
|
||||
{
|
||||
// Navisworks API不支持直接删除追加的模型
|
||||
// 使用隐藏方式处理
|
||||
var doc = Application.ActiveDocument;
|
||||
var modelItems = new ModelItemCollection { _virtualVehicleModelItem };
|
||||
doc.Models.SetHidden(modelItems, true);
|
||||
|
||||
LogManager.Info($"已隐藏虚拟车辆模型");
|
||||
}
|
||||
|
||||
// 清理引用但不尝试删除模型
|
||||
_virtualVehicleModel = null;
|
||||
_virtualVehicleModelItem = null;
|
||||
_isVirtualVehicleActive = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"隐藏虚拟车辆失败: {ex.Message}");
|
||||
_virtualVehicleModel = null;
|
||||
_virtualVehicleModelItem = null;
|
||||
_isVirtualVehicleActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取单位立方体文件路径
|
||||
/// </summary>
|
||||
private string GetUnitCubeFilePath()
|
||||
{
|
||||
// 方法1:从插件目录获取
|
||||
var assemblyLocation = Assembly.GetExecutingAssembly().Location;
|
||||
var pluginDir = Path.GetDirectoryName(assemblyLocation);
|
||||
|
||||
// 尝试多个可能的位置
|
||||
var possiblePaths = new[]
|
||||
{
|
||||
Path.Combine(pluginDir, "resources", "unit_cube.nwc"),
|
||||
Path.Combine(pluginDir, "unit_cube.nwc"),
|
||||
Path.Combine(pluginDir, "..", "resources", "unit_cube.nwc"),
|
||||
// 开发时的位置
|
||||
@"c:\Users\Tellme\apps\NavisworksTransport\resources\unit_cube.nwc"
|
||||
};
|
||||
|
||||
foreach (var path in possiblePaths)
|
||||
{
|
||||
var fullPath = Path.GetFullPath(path);
|
||||
if (File.Exists(fullPath))
|
||||
{
|
||||
LogManager.Info($"找到单位立方体文件: {fullPath}");
|
||||
return fullPath;
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.Warning($"在以下位置未找到单位立方体文件:");
|
||||
foreach (var path in possiblePaths)
|
||||
{
|
||||
LogManager.Warning($" - {Path.GetFullPath(path)}");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找第一个包含几何体的ModelItem
|
||||
/// </summary>
|
||||
private ModelItem FindFirstGeometryItem(ModelItem root)
|
||||
{
|
||||
if (root.HasGeometry)
|
||||
return root;
|
||||
|
||||
foreach (var child in root.Children)
|
||||
{
|
||||
var result = FindFirstGeometryItem(child);
|
||||
if (result != null)
|
||||
return result;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理资源
|
||||
/// </summary>
|
||||
public void Cleanup()
|
||||
{
|
||||
RemoveVirtualVehicle();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -93,6 +93,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
private bool _hasSelectedAnimatedObject = false;
|
||||
private bool _canGenerateAnimation = false;
|
||||
|
||||
// 虚拟车辆相关字段
|
||||
private bool _useSelectedObject = true; // 默认使用选择物体方式
|
||||
private bool _useVirtualVehicle = false; // 使用虚拟车辆
|
||||
private double _virtualVehicleLength = 1.0; // 虚拟车辆长度(米)
|
||||
private double _virtualVehicleWidth = 1.0; // 虚拟车辆宽度(米)
|
||||
private double _virtualVehicleHeight = 2.0; // 虚拟车辆高度(米)
|
||||
|
||||
#endregion
|
||||
|
||||
@ -356,6 +362,95 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
set => SetProperty(ref _canGenerateAnimation, value);
|
||||
}
|
||||
|
||||
#region 虚拟车辆属性
|
||||
|
||||
/// <summary>
|
||||
/// 是否使用选择的模型物体
|
||||
/// </summary>
|
||||
public bool UseSelectedObject
|
||||
{
|
||||
get => _useSelectedObject;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _useSelectedObject, value))
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
_useVirtualVehicle = false;
|
||||
OnPropertyChanged(nameof(UseVirtualVehicle));
|
||||
}
|
||||
UpdateCanGenerateAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否使用虚拟车辆
|
||||
/// </summary>
|
||||
public bool UseVirtualVehicle
|
||||
{
|
||||
get => _useVirtualVehicle;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _useVirtualVehicle, value))
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
_useSelectedObject = false;
|
||||
OnPropertyChanged(nameof(UseSelectedObject));
|
||||
}
|
||||
UpdateCanGenerateAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 虚拟车辆长度(米)- 只读,从路径编辑同步
|
||||
/// </summary>
|
||||
public double VirtualVehicleLength
|
||||
{
|
||||
get => _virtualVehicleLength;
|
||||
private set => SetProperty(ref _virtualVehicleLength, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 虚拟车辆宽度(米)- 只读,从路径编辑同步
|
||||
/// </summary>
|
||||
public double VirtualVehicleWidth
|
||||
{
|
||||
get => _virtualVehicleWidth;
|
||||
private set => SetProperty(ref _virtualVehicleWidth, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 虚拟车辆高度(米)- 只读,从路径编辑同步
|
||||
/// </summary>
|
||||
public double VirtualVehicleHeight
|
||||
{
|
||||
get => _virtualVehicleHeight;
|
||||
private set => SetProperty(ref _virtualVehicleHeight, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置虚拟车辆参数(由主ViewModel调用)
|
||||
/// </summary>
|
||||
public void SetVirtualVehicleParameters(double length, double width, double height)
|
||||
{
|
||||
VirtualVehicleLength = length;
|
||||
VirtualVehicleWidth = width;
|
||||
VirtualVehicleHeight = height;
|
||||
|
||||
LogManager.Info($"[AnimationControlViewModel] 虚拟车辆参数已更新: {length:F1}m × {width:F1}m × {height:F1}m");
|
||||
|
||||
// 如果当前使用虚拟车辆模式,更新生成动画的可用状态
|
||||
if (UseVirtualVehicle)
|
||||
{
|
||||
UpdateCanGenerateAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 媒体控制属性
|
||||
|
||||
/// <summary>
|
||||
@ -1369,13 +1464,14 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
}
|
||||
|
||||
UpdateMainStatus("正在生成动画...", -1, true);
|
||||
LogManager.Info("开始生成动画");
|
||||
LogManager.Info($"开始生成动画 - 模式: {(UseVirtualVehicle ? "虚拟车辆" : "选择物体")}");
|
||||
|
||||
// 🔥 新增:在生成动画阶段构建碰撞检测缓存
|
||||
var cacheStartTime = DateTime.Now;
|
||||
|
||||
// 构建碰撞检测缓存(两种模式都需要几何对象缓存)
|
||||
UpdateMainStatus("正在构建碰撞检测缓存...", -1, true);
|
||||
LogManager.Info("[动画生成] 开始构建碰撞检测缓存");
|
||||
|
||||
var cacheStartTime = DateTime.Now;
|
||||
try
|
||||
{
|
||||
// 构建全局缓存(与具体移动物体无关)
|
||||
@ -1391,23 +1487,26 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
var cacheElapsed = (DateTime.Now - cacheStartTime).TotalMilliseconds;
|
||||
LogManager.Info($"[动画生成] 碰撞检测缓存构建完成,耗时: {cacheElapsed:F1}ms");
|
||||
|
||||
// 构建特定于动画对象的缓存
|
||||
UpdateMainStatus("正在分析动画对象...", -1, true);
|
||||
var success = _pathAnimationManager.PrecomputeCollisionExclusions(SelectedAnimatedObject);
|
||||
|
||||
if (!success)
|
||||
// 选择物体模式:还需要构建特定于动画对象的缓存
|
||||
if (!UseVirtualVehicle)
|
||||
{
|
||||
var msg = "[动画生成] 动画对象分析失败,无法继续生成动画";
|
||||
LogManager.Error(msg);
|
||||
UpdateMainStatus("生成失败:对象分析错误");
|
||||
return; // 关键修改:直接返回,不再回退到实时模式
|
||||
UpdateMainStatus("正在分析动画对象...", -1, true);
|
||||
var success = _pathAnimationManager.PrecomputeCollisionExclusions(SelectedAnimatedObject);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
var msg = "[动画生成] 动画对象分析失败,无法继续生成动画";
|
||||
LogManager.Error(msg);
|
||||
UpdateMainStatus("生成失败:对象分析错误");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception cacheEx)
|
||||
{
|
||||
LogManager.Error($"[动画生成] 缓存构建失败: {cacheEx.Message}");
|
||||
UpdateMainStatus($"生成失败:{cacheEx.Message}");
|
||||
return; // 关键修改:处理异常并返回
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateMainStatus("正在生成路径动画...", -1, true);
|
||||
@ -1421,19 +1520,55 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
// 将PathRouteViewModel的点转换为Point3D列表
|
||||
var pathPoints = CurrentPathRoute.Points.Select(p => new Point3D(p.X, p.Y, p.Z)).ToList();
|
||||
|
||||
ModelItem animatedObject;
|
||||
|
||||
LogManager.Info($"[ExecuteGenerateAnimation] 准备创建动画: 路径名称='{CurrentPathRoute.Name}', ID='{CurrentPathRoute.Id}', 动画对象='{SelectedAnimatedObject.DisplayName}'");
|
||||
if (UseVirtualVehicle)
|
||||
{
|
||||
// 使用虚拟车辆:创建真实的立方体几何体
|
||||
LogManager.Info($"[ExecuteGenerateAnimation] 准备创建虚拟车辆: " +
|
||||
$"尺寸={VirtualVehicleLength:F1}m × {VirtualVehicleWidth:F1}m × {VirtualVehicleHeight:F1}m");
|
||||
|
||||
// 使用PathAnimationManager创建物体动画
|
||||
_pathAnimationManager.CreateAnimation(SelectedAnimatedObject, pathPoints, AnimationDuration, CurrentPathRoute.Name, CurrentPathRoute.Id);
|
||||
UpdateMainStatus("正在创建虚拟车辆...", -1, true);
|
||||
|
||||
// 创建虚拟车辆几何体
|
||||
animatedObject = Core.VirtualVehicleManager.Instance.CreateVirtualVehicle(
|
||||
VirtualVehicleLength,
|
||||
VirtualVehicleWidth,
|
||||
VirtualVehicleHeight
|
||||
);
|
||||
|
||||
if (animatedObject == null)
|
||||
{
|
||||
LogManager.Error("[动画生成] 虚拟车辆创建失败");
|
||||
UpdateMainStatus("生成失败:无法创建虚拟车辆");
|
||||
return;
|
||||
}
|
||||
|
||||
LogManager.Info($"虚拟车辆创建成功: {animatedObject.DisplayName}");
|
||||
}
|
||||
else
|
||||
{
|
||||
animatedObject = SelectedAnimatedObject;
|
||||
}
|
||||
|
||||
// 【统一使用CreateAnimation,完全复用现有逻辑】
|
||||
LogManager.Info($"[ExecuteGenerateAnimation] 准备创建动画: 路径名称='{CurrentPathRoute.Name}', ID='{CurrentPathRoute.Id}', " +
|
||||
$"动画对象='{animatedObject.DisplayName}'");
|
||||
|
||||
_pathAnimationManager.CreateAnimation(animatedObject, pathPoints, AnimationDuration, CurrentPathRoute.Name, CurrentPathRoute.Id);
|
||||
|
||||
var totalElapsed = (DateTime.Now - cacheStartTime).TotalMilliseconds;
|
||||
LogManager.Info($"[动画生成] 动画生成完成,总耗时: {totalElapsed:F1}ms");
|
||||
LogManager.Info($"动画生成成功: 物体={animatedObject.DisplayName}, 路径={CurrentPathRoute.Name}");
|
||||
|
||||
if (UseVirtualVehicle)
|
||||
{
|
||||
LogManager.Info($"虚拟车辆尺寸: {VirtualVehicleLength:F1}×{VirtualVehicleWidth:F1}×{VirtualVehicleHeight:F1}m");
|
||||
}
|
||||
|
||||
// 更新状态
|
||||
UpdateAnimationButtonStates();
|
||||
UpdateMainStatus("动画生成成功");
|
||||
|
||||
var totalElapsed = (DateTime.Now - cacheStartTime).TotalMilliseconds;
|
||||
LogManager.Info($"[动画生成] 动画生成完成,总耗时: {totalElapsed:F1}ms");
|
||||
LogManager.Info($"动画生成成功: 物体={SelectedAnimatedObject.DisplayName}, 路径={CurrentPathRoute.Name}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -1487,18 +1622,32 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
/// </summary>
|
||||
private void UpdateCanGenerateAnimation()
|
||||
{
|
||||
var hasObject = SelectedAnimatedObject != null;
|
||||
var hasPath = CurrentPathRoute != null && CurrentPathRoute.Points.Count >= 2;
|
||||
|
||||
CanGenerateAnimation = hasObject && hasPath;
|
||||
|
||||
if (!hasObject && !hasPath)
|
||||
bool hasValidObject;
|
||||
if (UseVirtualVehicle)
|
||||
{
|
||||
UpdateMainStatus("请选择移动物体和动画路径");
|
||||
// 使用虚拟车辆时,只需要有效的车辆尺寸
|
||||
hasValidObject = VirtualVehicleLength > 0 &&
|
||||
VirtualVehicleWidth > 0 &&
|
||||
VirtualVehicleHeight > 0;
|
||||
}
|
||||
else if (!hasObject)
|
||||
else
|
||||
{
|
||||
UpdateMainStatus("请选择移动物体");
|
||||
// 使用选择物体时,需要已选择物体
|
||||
hasValidObject = SelectedAnimatedObject != null;
|
||||
}
|
||||
|
||||
CanGenerateAnimation = hasValidObject && hasPath;
|
||||
|
||||
// 更新状态提示
|
||||
if (!hasPath && !hasValidObject)
|
||||
{
|
||||
UpdateMainStatus(UseVirtualVehicle ? "请选择动画路径" : "请选择移动物体和动画路径");
|
||||
}
|
||||
else if (!hasValidObject)
|
||||
{
|
||||
UpdateMainStatus(UseVirtualVehicle ? "虚拟车辆参数无效" : "请选择移动物体");
|
||||
}
|
||||
else if (!hasPath)
|
||||
{
|
||||
|
||||
@ -149,8 +149,22 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管
|
||||
<StackPanel>
|
||||
<Label Content="生成动画" Style="{StaticResource SectionHeaderStyle}"/>
|
||||
|
||||
<!-- 选择移动物体 -->
|
||||
<Grid Margin="0,10,0,10">
|
||||
<!-- 移动物体来源选择 -->
|
||||
<StackPanel Orientation="Horizontal" Margin="0,10,0,10">
|
||||
<RadioButton Content="选择模型物体"
|
||||
IsChecked="{Binding UseSelectedObject}"
|
||||
GroupName="ObjectSource"
|
||||
VerticalAlignment="Center"/>
|
||||
<RadioButton Content="使用虚拟车辆"
|
||||
IsChecked="{Binding UseVirtualVehicle}"
|
||||
GroupName="ObjectSource"
|
||||
VerticalAlignment="Center"
|
||||
Margin="20,0,0,0"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 方式1:选择模型物体 -->
|
||||
<Grid Margin="0,5,0,10"
|
||||
Visibility="{Binding UseSelectedObject, Converter={StaticResource BoolToVisConverter}}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
@ -181,6 +195,39 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- 方式2:虚拟车辆 -->
|
||||
<Grid Margin="0,5,0,10"
|
||||
Visibility="{Binding UseVirtualVehicle, Converter={StaticResource BoolToVisConverter}}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Grid.Column="0" Content="虚拟车辆:" Style="{StaticResource ParameterLabelStyle}" Width="80"/>
|
||||
<TextBlock Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Margin="5,0,10,0"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#FF2B579A"
|
||||
Background="#FFF5F5F5"
|
||||
Padding="5,3">
|
||||
<Run Text="长 "/>
|
||||
<Run Text="{Binding VirtualVehicleLength, StringFormat=F1, Mode=OneWay}"/>
|
||||
<Run Text="m × 宽 "/>
|
||||
<Run Text="{Binding VirtualVehicleWidth, StringFormat=F1, Mode=OneWay}"/>
|
||||
<Run Text="m × 高 "/>
|
||||
<Run Text="{Binding VirtualVehicleHeight, StringFormat=F1, Mode=OneWay}"/>
|
||||
<Run Text="m"/>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
|
||||
<!-- 虚拟车辆提示 -->
|
||||
<TextBlock Text="提示:虚拟车辆尺寸来自路径编辑中的车辆参数设置"
|
||||
Style="{StaticResource StatusTextStyle}"
|
||||
Foreground="#FF666666"
|
||||
Margin="85,0,0,5"
|
||||
Visibility="{Binding UseVirtualVehicle, Converter={StaticResource BoolToVisConverter}}"/>
|
||||
|
||||
<!-- 选择路径 -->
|
||||
<Grid Margin="0,5,0,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
|
||||
@ -156,7 +156,10 @@ namespace NavisworksTransport.UI.WPF
|
||||
// 更新引用
|
||||
AnimationControlView = newAnimationControlView;
|
||||
|
||||
LogManager.Info("AnimationControlView初始化完成 - 支持统一状态栏");
|
||||
// 初始化时同步车辆参数
|
||||
SyncVehicleParametersToAnimationView();
|
||||
|
||||
LogManager.Info("AnimationControlView初始化完成 - 支持统一状态栏和虚拟车辆");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -411,6 +414,13 @@ namespace NavisworksTransport.UI.WPF
|
||||
SyncCurrentPathToAnimationView();
|
||||
LogManager.Info("PathEditingView路径选择已变化,同步到动画控制视图");
|
||||
}
|
||||
// 当车辆参数变化时,同步到AnimationControlView
|
||||
else if (e.PropertyName == nameof(PathEditingViewModel.VehicleLength) ||
|
||||
e.PropertyName == nameof(PathEditingViewModel.VehicleWidth) ||
|
||||
e.PropertyName == nameof(PathEditingViewModel.VehicleHeight))
|
||||
{
|
||||
SyncVehicleParametersToAnimationView();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -418,6 +428,30 @@ namespace NavisworksTransport.UI.WPF
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步车辆参数到动画控制视图
|
||||
/// </summary>
|
||||
private void SyncVehicleParametersToAnimationView()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (AnimationControlView?.ViewModel != null && PathEditingView?.ViewModel != null)
|
||||
{
|
||||
var pathEditingVM = PathEditingView.ViewModel;
|
||||
AnimationControlView.ViewModel.SetVirtualVehicleParameters(
|
||||
pathEditingVM.VehicleLength,
|
||||
pathEditingVM.VehicleWidth,
|
||||
pathEditingVM.VehicleHeight
|
||||
);
|
||||
LogManager.Debug($"车辆参数已同步到动画控制视图: {pathEditingVM.VehicleLength:F1}×{pathEditingVM.VehicleWidth:F1}×{pathEditingVM.VehicleHeight:F1}m");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"同步车辆参数到动画控制视图失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步当前路径到动画控制视图
|
||||
/// </summary>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user