实现ClashDetective结果保存到数据库功能,并在UI中展示碰撞检测历史记录
This commit is contained in:
parent
d473065025
commit
0de096aed0
@ -7,6 +7,7 @@
|
||||
1. [ ] (BUG)虚拟车辆模型每次点击都重建
|
||||
2. [x] (BUG)碰撞结果高亮,应该显示clashdetective检测的结果
|
||||
3. [x] (优化)对clashdetective的检测结果,进行向上合并,找到集合对象。
|
||||
4. [ ] (功能)碰撞检测结果保存数据库,列表展示
|
||||
|
||||
### [2025/12/25]
|
||||
|
||||
|
||||
@ -88,6 +88,11 @@ namespace NavisworksTransport
|
||||
/// </summary>
|
||||
public event EventHandler<CollisionDetectedEventArgs> CollisionDetected;
|
||||
|
||||
/// <summary>
|
||||
/// ClashDetective结果保存到数据库事件
|
||||
/// </summary>
|
||||
public event EventHandler<ClashDetectiveResultSavedEventArgs> ClashDetectiveResultSaved;
|
||||
|
||||
private ClashDetectiveIntegration()
|
||||
{
|
||||
_currentCollisions = new List<ClashResult>();
|
||||
@ -589,6 +594,39 @@ namespace NavisworksTransport
|
||||
// 更新碰撞计数器
|
||||
_clashDetectiveCollisionCount = clashResults.Count;
|
||||
|
||||
// 保存到数据库
|
||||
try
|
||||
{
|
||||
var pathDatabase = PathPlanningManager.Instance?.GetPathDatabase();
|
||||
if (pathDatabase != null)
|
||||
{
|
||||
var record = new ClashDetectiveResultRecord
|
||||
{
|
||||
TestName = _currentTestName,
|
||||
PathName = pathName,
|
||||
RouteId = routeId ?? "",
|
||||
TestTime = DateTime.Now,
|
||||
CollisionCount = clashResults.Count,
|
||||
AnimationCollisionCount = _animationCollisionCount,
|
||||
FrameRate = frameRate,
|
||||
Duration = duration,
|
||||
DetectionGap = detectionGap,
|
||||
AnimatedObjectName = animatedObjectName,
|
||||
CreatedAt = DateTime.Now
|
||||
};
|
||||
pathDatabase.SaveClashDetectiveResult(record);
|
||||
LogManager.Info($"ClashDetective结果已保存到数据库");
|
||||
|
||||
// 触发结果保存事件,通知UI刷新列表
|
||||
ClashDetectiveResultSaved?.Invoke(this, new ClashDetectiveResultSavedEventArgs(pathName, _currentTestName, clashResults.Count));
|
||||
}
|
||||
}
|
||||
catch (Exception dbEx)
|
||||
{
|
||||
LogManager.Error($"保存ClashDetective结果到数据库失败: {dbEx.Message}");
|
||||
// 不影响主流程,继续执行
|
||||
}
|
||||
|
||||
// 第四步:将分组添加到主测试
|
||||
if (collisionGroup.Children.Count > 0)
|
||||
{
|
||||
@ -1666,4 +1704,21 @@ namespace NavisworksTransport
|
||||
CollisionCount = results.Count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ClashDetective结果保存事件参数
|
||||
/// </summary>
|
||||
public class ClashDetectiveResultSavedEventArgs : EventArgs
|
||||
{
|
||||
public string PathName { get; private set; }
|
||||
public string TestName { get; private set; }
|
||||
public int CollisionCount { get; private set; }
|
||||
|
||||
public ClashDetectiveResultSavedEventArgs(string pathName, string testName, int collisionCount)
|
||||
{
|
||||
PathName = pathName;
|
||||
TestName = testName;
|
||||
CollisionCount = collisionCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -43,9 +43,13 @@ namespace NavisworksTransport
|
||||
ExecuteNonQuery("PRAGMA journal_mode=WAL");
|
||||
ExecuteNonQuery("PRAGMA foreign_keys=ON");
|
||||
|
||||
// 无论数据库是否为新数据库,都调用CreateTables()
|
||||
// 因为使用了CREATE TABLE IF NOT EXISTS语法,所以是安全的
|
||||
// 这样可以确保所有表都存在,避免在旧数据库中缺少新表的问题
|
||||
CreateTables();
|
||||
|
||||
if (isNewDatabase)
|
||||
{
|
||||
CreateTables();
|
||||
LogManager.Info($"创建新数据库: {_dbPath}");
|
||||
}
|
||||
else
|
||||
@ -152,10 +156,30 @@ namespace NavisworksTransport
|
||||
)
|
||||
");
|
||||
|
||||
// 6. ClashDetective结果表
|
||||
ExecuteNonQuery(@"
|
||||
CREATE TABLE IF NOT EXISTS ClashDetectiveResults (
|
||||
Id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
TestName TEXT NOT NULL UNIQUE,
|
||||
PathName TEXT NOT NULL,
|
||||
RouteId TEXT NOT NULL,
|
||||
TestTime DATETIME NOT NULL,
|
||||
CollisionCount INTEGER NOT NULL,
|
||||
AnimationCollisionCount INTEGER NOT NULL,
|
||||
FrameRate INTEGER,
|
||||
Duration REAL,
|
||||
DetectionGap REAL,
|
||||
AnimatedObjectName TEXT,
|
||||
CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
");
|
||||
|
||||
// 创建索引
|
||||
ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_reports_route ON CollisionReports(RouteId)");
|
||||
ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_pathpoints_route ON PathPoints(RouteId)");
|
||||
ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_pathedges_route ON PathEdges(RouteId)");
|
||||
ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_clash_path_name ON ClashDetectiveResults(PathName)");
|
||||
ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_clash_test_time ON ClashDetectiveResults(TestTime DESC)");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -342,6 +366,183 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
#region ClashDetective结果管理
|
||||
|
||||
/// <summary>
|
||||
/// 保存ClashDetective碰撞检测结果
|
||||
/// </summary>
|
||||
public void SaveClashDetectiveResult(ClashDetectiveResultRecord record)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 检查TestName是否已存在
|
||||
var checkSql = "SELECT COUNT(*) FROM ClashDetectiveResults WHERE TestName = @testName";
|
||||
using (var checkCmd = new SQLiteCommand(checkSql, _connection))
|
||||
{
|
||||
checkCmd.Parameters.AddWithValue("@testName", record.TestName);
|
||||
var count = Convert.ToInt32(checkCmd.ExecuteScalar());
|
||||
if (count > 0)
|
||||
{
|
||||
throw new InvalidOperationException($"测试名称 '{record.TestName}' 已存在,无法重复保存");
|
||||
}
|
||||
}
|
||||
|
||||
var sql = @"
|
||||
INSERT INTO ClashDetectiveResults
|
||||
(TestName, PathName, RouteId, TestTime, CollisionCount, AnimationCollisionCount,
|
||||
FrameRate, Duration, DetectionGap, AnimatedObjectName, CreatedAt)
|
||||
VALUES (@testName, @pathName, @routeId, @testTime, @collisionCount, @animationCollisionCount,
|
||||
@frameRate, @duration, @detectionGap, @animatedObjectName, @createdAt)
|
||||
";
|
||||
|
||||
using (var cmd = new SQLiteCommand(sql, _connection))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@testName", record.TestName);
|
||||
cmd.Parameters.AddWithValue("@pathName", record.PathName);
|
||||
cmd.Parameters.AddWithValue("@routeId", record.RouteId);
|
||||
cmd.Parameters.AddWithValue("@testTime", record.TestTime);
|
||||
cmd.Parameters.AddWithValue("@collisionCount", record.CollisionCount);
|
||||
cmd.Parameters.AddWithValue("@animationCollisionCount", record.AnimationCollisionCount);
|
||||
cmd.Parameters.AddWithValue("@frameRate", record.FrameRate);
|
||||
cmd.Parameters.AddWithValue("@duration", record.Duration);
|
||||
cmd.Parameters.AddWithValue("@detectionGap", record.DetectionGap);
|
||||
cmd.Parameters.AddWithValue("@animatedObjectName", record.AnimatedObjectName ?? "");
|
||||
cmd.Parameters.AddWithValue("@createdAt", record.CreatedAt);
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
LogManager.Info($"ClashDetective结果已保存: 测试={record.TestName}, 碰撞数={record.CollisionCount}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"保存ClashDetective结果失败: {ex.Message}", ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取路径的所有ClashDetective检测结果
|
||||
/// </summary>
|
||||
public List<ClashDetectiveResultRecord> GetClashDetectiveResultsByPath(string pathName)
|
||||
{
|
||||
var results = new List<ClashDetectiveResultRecord>();
|
||||
|
||||
try
|
||||
{
|
||||
var sql = @"
|
||||
SELECT Id, TestName, PathName, RouteId, TestTime, CollisionCount, AnimationCollisionCount,
|
||||
FrameRate, Duration, DetectionGap, AnimatedObjectName, CreatedAt
|
||||
FROM ClashDetectiveResults
|
||||
WHERE PathName = @pathName
|
||||
ORDER BY TestTime DESC
|
||||
";
|
||||
|
||||
using (var cmd = new SQLiteCommand(sql, _connection))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@pathName", pathName);
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
results.Add(new ClashDetectiveResultRecord
|
||||
{
|
||||
Id = Convert.ToInt32(reader["Id"]),
|
||||
TestName = reader["TestName"].ToString(),
|
||||
PathName = reader["PathName"].ToString(),
|
||||
RouteId = reader["RouteId"]?.ToString(),
|
||||
TestTime = Convert.ToDateTime(reader["TestTime"]),
|
||||
CollisionCount = Convert.ToInt32(reader["CollisionCount"]),
|
||||
AnimationCollisionCount = Convert.ToInt32(reader["AnimationCollisionCount"]),
|
||||
FrameRate = reader["FrameRate"] != DBNull.Value ? Convert.ToInt32(reader["FrameRate"]) : 0,
|
||||
Duration = reader["Duration"] != DBNull.Value ? Convert.ToDouble(reader["Duration"]) : 0.0,
|
||||
DetectionGap = reader["DetectionGap"] != DBNull.Value ? Convert.ToDouble(reader["DetectionGap"]) : 0.0,
|
||||
AnimatedObjectName = reader["AnimatedObjectName"]?.ToString(),
|
||||
CreatedAt = Convert.ToDateTime(reader["CreatedAt"])
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.Debug($"获取到 {results.Count} 条ClashDetective结果记录");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"获取ClashDetective结果失败: {ex.Message}", ex);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取路径最新的ClashDetective检测结果
|
||||
/// </summary>
|
||||
public ClashDetectiveResultRecord GetLatestClashDetectiveResult(string pathName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var sql = @"
|
||||
SELECT Id, TestName, PathName, RouteId, TestTime, CollisionCount, AnimationCollisionCount,
|
||||
FrameRate, Duration, DetectionGap, AnimatedObjectName, CreatedAt
|
||||
FROM ClashDetectiveResults
|
||||
WHERE PathName = @pathName
|
||||
ORDER BY TestTime DESC
|
||||
LIMIT 1
|
||||
";
|
||||
|
||||
using (var cmd = new SQLiteCommand(sql, _connection))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@pathName", pathName);
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
if (reader.Read())
|
||||
{
|
||||
return new ClashDetectiveResultRecord
|
||||
{
|
||||
Id = Convert.ToInt32(reader["Id"]),
|
||||
TestName = reader["TestName"].ToString(),
|
||||
PathName = reader["PathName"].ToString(),
|
||||
RouteId = reader["RouteId"]?.ToString(),
|
||||
TestTime = Convert.ToDateTime(reader["TestTime"]),
|
||||
CollisionCount = Convert.ToInt32(reader["CollisionCount"]),
|
||||
AnimationCollisionCount = Convert.ToInt32(reader["AnimationCollisionCount"]),
|
||||
FrameRate = reader["FrameRate"] != DBNull.Value ? Convert.ToInt32(reader["FrameRate"]) : 0,
|
||||
Duration = reader["Duration"] != DBNull.Value ? Convert.ToDouble(reader["Duration"]) : 0.0,
|
||||
DetectionGap = reader["DetectionGap"] != DBNull.Value ? Convert.ToDouble(reader["DetectionGap"]) : 0.0,
|
||||
AnimatedObjectName = reader["AnimatedObjectName"]?.ToString(),
|
||||
CreatedAt = Convert.ToDateTime(reader["CreatedAt"])
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"获取最新ClashDetective结果失败: {ex.Message}", ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除ClashDetective检测结果
|
||||
/// </summary>
|
||||
public void DeleteClashDetectiveResult(int id)
|
||||
{
|
||||
try
|
||||
{
|
||||
ExecuteNonQuery("DELETE FROM ClashDetectiveResults WHERE Id=@id",
|
||||
new { id = id });
|
||||
LogManager.Info($"已删除ClashDetective结果记录: Id={id}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"删除ClashDetective结果失败: {ex.Message}", ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 保存分析评分结果
|
||||
/// </summary>
|
||||
@ -836,9 +1037,37 @@ namespace NavisworksTransport
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
_connection?.Close();
|
||||
_connection?.Dispose();
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_connection?.Close();
|
||||
_connection?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ClashDetective碰撞检测结果记录
|
||||
/// </summary>
|
||||
public class ClashDetectiveResultRecord
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string TestName { get; set; }
|
||||
public string PathName { get; set; }
|
||||
public string RouteId { get; set; }
|
||||
public DateTime TestTime { get; set; }
|
||||
public int CollisionCount { get; set; }
|
||||
public int AnimationCollisionCount { get; set; }
|
||||
public int FrameRate { get; set; }
|
||||
public double Duration { get; set; }
|
||||
public double DetectionGap { get; set; }
|
||||
public string AnimatedObjectName { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -77,6 +77,56 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
public Guid InstanceGuid { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ClashDetective碰撞检测结果视图模型
|
||||
/// </summary>
|
||||
public class ClashDetectiveResultViewModel
|
||||
{
|
||||
private readonly Action _refreshCallback;
|
||||
|
||||
public ClashDetectiveResultViewModel(ClashDetectiveResultRecord record, Action refreshCallback)
|
||||
{
|
||||
Record = record ?? throw new ArgumentNullException(nameof(record));
|
||||
_refreshCallback = refreshCallback ?? throw new ArgumentNullException(nameof(refreshCallback));
|
||||
ViewCommand = new RelayCommand(() => ExecuteView());
|
||||
ReportCommand = new RelayCommand(() => ExecuteReport());
|
||||
DeleteCommand = new RelayCommand(() => ExecuteDelete());
|
||||
}
|
||||
|
||||
public ClashDetectiveResultRecord Record { get; }
|
||||
public string TestTimeDisplay => Record.TestTime.ToString("HH:mm:ss");
|
||||
public string CollisionCountDisplay => $"{Record.CollisionCount}个";
|
||||
public ICommand ViewCommand { get; }
|
||||
public ICommand ReportCommand { get; }
|
||||
public ICommand DeleteCommand { get; }
|
||||
|
||||
private void ExecuteView()
|
||||
{
|
||||
// 高亮显示该次检测的碰撞对象
|
||||
var clashIntegration = ClashDetectiveIntegration.Instance;
|
||||
clashIntegration?.HighlightClashDetectiveResults(Record.TestName);
|
||||
}
|
||||
|
||||
private void ExecuteReport()
|
||||
{
|
||||
// 打开该次检测的详细报告
|
||||
var command = GenerateCollisionReportCommand.CreateComprehensive(autoHighlight: false);
|
||||
command.ExecuteAsync();
|
||||
}
|
||||
|
||||
private void ExecuteDelete()
|
||||
{
|
||||
// 删除该次检测记录
|
||||
var pathDatabase = PathPlanningManager.Instance?.GetPathDatabase();
|
||||
if (pathDatabase != null)
|
||||
{
|
||||
pathDatabase.DeleteClashDetectiveResult(Record.Id);
|
||||
// 通过回调刷新列表
|
||||
_refreshCallback?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 动画控制视图模型
|
||||
/// 专门处理路径动画播放和碰撞检测功能
|
||||
@ -351,6 +401,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
OnPropertyChanged(nameof(MovementSpeed));
|
||||
OnPropertyChanged(nameof(PathLength));
|
||||
UpdateCanGenerateAnimation();
|
||||
|
||||
// 路径改变时,刷新ClashDetective结果列表
|
||||
RefreshClashDetectiveResultsList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -562,6 +615,16 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
|
||||
#endregion
|
||||
|
||||
#region ClashDetective结果管理
|
||||
|
||||
private ObservableCollection<ClashDetectiveResultViewModel> _clashDetectiveResults = new ObservableCollection<ClashDetectiveResultViewModel>();
|
||||
|
||||
public ObservableCollection<ClashDetectiveResultViewModel> ClashDetectiveResults => _clashDetectiveResults;
|
||||
|
||||
public ICommand RefreshClashDetectiveResultsCommand { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region 媒体控制属性
|
||||
|
||||
/// <summary>
|
||||
@ -706,6 +769,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
|
||||
// 订阅碰撞检测事件
|
||||
_clashIntegration.CollisionDetected += OnCollisionDetected;
|
||||
_clashIntegration.ClashDetectiveResultSaved += OnClashDetectiveResultSaved;
|
||||
|
||||
// 订阅文档状态事件
|
||||
DocumentStateManager.Instance.DocumentInvalidated += OnDocumentInvalidated;
|
||||
@ -786,6 +850,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
ClearCollisionHighlightsCommand = new RelayCommand(ExecuteClearCollisionHighlights, () => HasCollisionResults);
|
||||
HighlightClashDetectiveResultsCommand = new RelayCommand(ExecuteHighlightClashDetectiveResults, () => HasClashDetectiveResults);
|
||||
ClearClashDetectiveHighlightsCommand = new RelayCommand(ExecuteClearClashDetectiveHighlights, () => HasClashDetectiveResults);
|
||||
RefreshClashDetectiveResultsCommand = new RelayCommand(ExecuteRefreshClashDetectiveResults);
|
||||
PlayForwardCommand = new RelayCommand(ExecutePlayForward, CanExecuteMediaCommands);
|
||||
PlayReverseCommand = new RelayCommand(ExecutePlayReverse, CanExecuteMediaCommands);
|
||||
StepForwardCommand = new RelayCommand(ExecuteStepForward, CanExecuteMediaCommands);
|
||||
@ -1408,6 +1473,23 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ClashDetective结果保存事件处理
|
||||
/// </summary>
|
||||
private void OnClashDetectiveResultSaved(object sender, ClashDetectiveResultSavedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 刷新ClashDetective结果列表
|
||||
RefreshClashDetectiveResultsList();
|
||||
LogManager.Info($"ClashDetective结果已保存,列表已刷新: 路径={e.PathName}, 测试={e.TestName}, 碰撞数={e.CollisionCount}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"处理ClashDetective结果保存事件失败: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存碰撞报告到数据库
|
||||
/// </summary>
|
||||
@ -1648,6 +1730,56 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
UpdateMainStatus("已清除ClashDetective高亮");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新ClashDetective结果列表
|
||||
/// </summary>
|
||||
private void RefreshClashDetectiveResultsList()
|
||||
{
|
||||
try
|
||||
{
|
||||
var pathName = CurrentPathRoute?.Name;
|
||||
if (string.IsNullOrEmpty(pathName))
|
||||
{
|
||||
_clashDetectiveResults.Clear();
|
||||
HasClashDetectiveResults = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var pathDatabase = PathPlanningManager.Instance?.GetPathDatabase();
|
||||
if (pathDatabase == null)
|
||||
{
|
||||
_clashDetectiveResults.Clear();
|
||||
HasClashDetectiveResults = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var records = pathDatabase.GetClashDetectiveResultsByPath(pathName);
|
||||
_clashDetectiveResults.Clear();
|
||||
|
||||
foreach (var record in records)
|
||||
{
|
||||
_clashDetectiveResults.Add(new ClashDetectiveResultViewModel(record, RefreshClashDetectiveResultsList));
|
||||
}
|
||||
|
||||
// 更新HasClashDetectiveResults属性
|
||||
HasClashDetectiveResults = _clashDetectiveResults.Count > 0;
|
||||
|
||||
UpdateMainStatus($"已刷新ClashDetective结果列表:{_clashDetectiveResults.Count}条记录");
|
||||
LogManager.Info($"ClashDetective结果列表已刷新:{_clashDetectiveResults.Count}条记录");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"刷新ClashDetective结果列表失败: {ex.Message}");
|
||||
_clashDetectiveResults.Clear();
|
||||
HasClashDetectiveResults = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteRefreshClashDetectiveResults()
|
||||
{
|
||||
RefreshClashDetectiveResultsList();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@ -2598,6 +2730,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
try
|
||||
{
|
||||
_clashIntegration.CollisionDetected -= OnCollisionDetected;
|
||||
_clashIntegration.ClashDetectiveResultSaved -= OnClashDetectiveResultSaved;
|
||||
LogManager.Debug("碰撞检测事件订阅取消完成");
|
||||
}
|
||||
catch (Exception eventEx)
|
||||
|
||||
@ -399,22 +399,105 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管
|
||||
IsEnabled="{Binding HasClashDetectiveResults}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"/>
|
||||
</StackPanel>
|
||||
|
||||
|
||||
|
||||
<!-- 提示信息 -->
|
||||
<TextBlock Text="注:碰撞检测将在动画播放过程中自动进行,结果会在动画完成后显示"
|
||||
Style="{StaticResource StatusTextStyle}"
|
||||
FontStyle="Italic"
|
||||
Opacity="0.7"
|
||||
Margin="0,10,0,0"/>
|
||||
|
||||
<!-- ClashDetective结果列表 -->
|
||||
<StackPanel Margin="0,15,0,0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Grid.Column="0" Content="碰撞检测历史" Style="{StaticResource SectionHeaderStyle}"/>
|
||||
<Button Grid.Column="1"
|
||||
Content="刷新"
|
||||
Command="{Binding RefreshClashDetectiveResultsCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
Height="22"
|
||||
Padding="8,2"
|
||||
Margin="0,0,0,0"/>
|
||||
</Grid>
|
||||
|
||||
<TextBlock Text="当前路径暂无碰撞检测结果"
|
||||
Style="{StaticResource StatusTextStyle}"
|
||||
Foreground="#FF777777"
|
||||
Visibility="{Binding HasClashDetectiveResults, Converter={StaticResource BoolToVisConverter}, ConverterParameter=Inverse}"
|
||||
Margin="0,5,0,0"/>
|
||||
|
||||
<ListView ItemsSource="{Binding ClashDetectiveResults}"
|
||||
Margin="0,5,0,0"
|
||||
Visibility="{Binding HasClashDetectiveResults, Converter={StaticResource BoolToVisConverter}}"
|
||||
MinHeight="120"
|
||||
MaxHeight="200"
|
||||
BorderBrush="#FFE2E8F0"
|
||||
BorderThickness="1">
|
||||
<ListView.View>
|
||||
<GridView>
|
||||
<GridViewColumn Header="测试名称" Width="140">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Record.TestName}"
|
||||
FontWeight="SemiBold"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
ToolTip="{Binding Record.TestName}"/>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="时间" Width="60">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding TestTimeDisplay}"
|
||||
HorizontalAlignment="Center"/>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="碰撞数" Width="60">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding CollisionCountDisplay}"
|
||||
HorizontalAlignment="Center"/>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="操作" Width="200">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="查看"
|
||||
Command="{Binding ViewCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
Height="20"
|
||||
Padding="6,0"
|
||||
Margin="0,0,4,0"/>
|
||||
<Button Content="报告"
|
||||
Command="{Binding ReportCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
Height="20"
|
||||
Padding="6,0"
|
||||
Margin="0,0,4,0"/>
|
||||
<Button Content="删除"
|
||||
Command="{Binding DeleteCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
Height="20"
|
||||
Padding="6,0"
|
||||
Background="#FFFFE6E6"
|
||||
Foreground="#FF8B0000"
|
||||
Margin="0"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</GridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- 区域6: 动画预览和操作指南 -->
|
||||
<!-- 区域6: 当前路径信息 -->
|
||||
<Border BorderBrush="#FFD4E7FF" BorderThickness="1" CornerRadius="0" Margin="0,0,0,0" Padding="12">
|
||||
<StackPanel>
|
||||
<Label Content="动画预览与操作指南" Style="{StaticResource SectionHeaderStyle}"/>
|
||||
<Label Content="当前路径信息" Style="{StaticResource SectionHeaderStyle}"/>
|
||||
|
||||
<!-- 当前路径信息 -->
|
||||
<Grid Margin="0,5,0,10">
|
||||
@ -433,22 +516,6 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管
|
||||
Text="{Binding CurrentPathRoute.Points.Count, StringFormat='路径点数: {0}个', TargetNullValue='路径点数: 0个'}"
|
||||
Style="{StaticResource StatusTextStyle}"/>
|
||||
</Grid>
|
||||
|
||||
<!-- 操作提示 -->
|
||||
<StackPanel Margin="0,5,0,0">
|
||||
<TextBlock Text="• 确保已在路径编辑页签中选择了有效的路径"
|
||||
Style="{StaticResource StatusTextStyle}"
|
||||
Margin="0,2"/>
|
||||
<TextBlock Text="• 动画将沿着当前选中的路径创建"
|
||||
Style="{StaticResource StatusTextStyle}"
|
||||
Margin="0,2"/>
|
||||
<TextBlock Text="• 碰撞检测会在路径上模拟运输过程中的冲突检测"
|
||||
Style="{StaticResource StatusTextStyle}"
|
||||
Margin="0,2"/>
|
||||
<TextBlock Text="• 碰撞检测后可在ClashDetective插件中查看碰撞结果"
|
||||
Style="{StaticResource StatusTextStyle}"
|
||||
Margin="0,2"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user