数据库保存碰撞节点信息表和相关操作

This commit is contained in:
tian 2026-01-08 17:03:19 +08:00
parent 97bf6dbecd
commit 40fce35bc8
4 changed files with 216 additions and 19 deletions

View File

@ -89,6 +89,7 @@ namespace NavisworksTransport.Core.Animation
private static readonly Dictionary<string, List<AnimationFrame>> _animationFrameCache = new Dictionary<string, List<AnimationFrame>>(); // 动画帧缓存
private static readonly Dictionary<string, List<CollisionResult>> _collisionResultCache = new Dictionary<string, List<CollisionResult>>(); // 碰撞结果缓存
private ModelItem _animatedObject;
private bool _isVirtualVehicle = false; // 是否使用虚拟车辆
private List<Point3D> _pathPoints;
private List<ModelItem> _manualCollisionTargets = new List<ModelItem>();
private bool _manualCollisionOverrideEnabled = false;
@ -1170,7 +1171,8 @@ namespace NavisworksTransport.Core.Animation
_detectionGap,
_pathName,
_currentRouteId,
_animatedObjectName,
_animatedObject,
_isVirtualVehicle,
_animationFrameRate,
_animationDuration
);
@ -2226,16 +2228,12 @@ namespace NavisworksTransport.Core.Animation
/// <param name="durationSeconds">动画持续时间(秒)</param>
/// <param name="pathName">路径名称</param>
/// <param name="routeId">路由ID</param>
public void CreateAnimation(ModelItem animatedObject, List<Point3D> pathPoints, double durationSeconds = 10.0, string pathName = "未知路径", string routeId = null)
public void CreateAnimation(ModelItem animatedObject, List<Point3D> pathPoints, double durationSeconds = 10.0, string pathName = "未知路径", string routeId = null, bool isVirtualVehicle = false)
{
_pathName = pathName;
_currentRouteId = routeId;
_animatedObjectName = animatedObject?.DisplayName ?? "未知对象";
_isVirtualVehicle = isVirtualVehicle; // 设置是否使用虚拟车辆
LogManager.Info($"[PathAnimationManager.CreateAnimation] 接收到参数: pathName='{pathName}', routeId='{routeId}', animatedObjectName='{_animatedObjectName}'");
LogManager.Info($"[PathAnimationManager.CreateAnimation] 存储的值: _pathName='{_pathName}', _currentRouteId='{_currentRouteId}'");
// 注意pathPoints参数已废弃现在使用PathRoute
SetupAnimation(animatedObject, durationSeconds, _route);
SetState(AnimationState.Ready);
}

View File

@ -164,13 +164,38 @@ namespace NavisworksTransport
/// 保存ClashDetective结果到数据库
/// </summary>
private void SaveClashDetectiveResultToDatabase(string pathName, string routeId, List<CollisionResult> clashResults,
int frameRate, double duration, double detectionGap, string animatedObjectName)
int frameRate, double duration, double detectionGap,
ModelItem animatedObject, bool isVirtualVehicle)
{
try
{
var pathDatabase = PathPlanningManager.Instance?.GetPathDatabase();
if (pathDatabase != null)
{
// 获取动画对象名称
string animatedObjectName = "未知对象";
if (!isVirtualVehicle && animatedObject != null)
{
animatedObjectName = ModelItemAnalysisHelper.GetSafeDisplayName(animatedObject);
}
else if (isVirtualVehicle)
{
animatedObjectName = "虚拟车辆";
}
// 设置车辆路径信息
string vehicleModelItemPath = null;
if (!isVirtualVehicle && animatedObject != null)
{
// 只有真实车辆才记录路径
var paths = ModelItemAnalysisHelper.GetModelItemIndexPaths(animatedObject);
if (paths.Count > 0)
{
vehicleModelItemPath = string.Join(";", paths);
}
}
var record = new ClashDetectiveResultRecord
{
TestName = _currentTestName,
@ -183,10 +208,40 @@ namespace NavisworksTransport
Duration = duration,
DetectionGap = detectionGap,
AnimatedObjectName = animatedObjectName,
IsVirtualVehicle = isVirtualVehicle,
VehicleModelItemPath = vehicleModelItemPath,
CreatedAt = DateTime.Now
};
pathDatabase.SaveClashDetectiveResult(record);
LogManager.Info($"ClashDetective结果已保存到数据库");
var resultId = pathDatabase.SaveClashDetectiveResult(record);
LogManager.Info($"ClashDetective结果已保存到数据库Id={resultId}, IsVirtualVehicle={isVirtualVehicle}");
// 保存被撞物体信息只保存Item2不保存车辆Item1
var collisionObjects = new List<ClashDetectiveCollisionObjectRecord>();
foreach (var collision in clashResults)
{
// 只保存被撞到的物体Item2
if (collision.Item2 != null)
{
var paths = ModelItemAnalysisHelper.GetModelItemIndexPaths(collision.Item2);
foreach (var path in paths)
{
collisionObjects.Add(new ClashDetectiveCollisionObjectRecord
{
ResultId = resultId,
ModelItemPath = path,
DisplayName = ModelItemAnalysisHelper.GetSafeDisplayName(collision.Item2),
ObjectName = ModelItemAnalysisHelper.GetSafeDisplayName(collision.Item2)
});
}
}
}
if (collisionObjects.Count > 0)
{
pathDatabase.SaveClashDetectiveCollisionObjects(resultId, collisionObjects);
LogManager.Info($"已保存 {collisionObjects.Count} 个被撞物体到数据库");
}
// 触发结果保存事件通知UI刷新列表
ClashDetectiveResultSaved?.Invoke(this, new ClashDetectiveResultSavedEventArgs(pathName, _currentTestName, clashResults.Count));
@ -352,11 +407,13 @@ namespace NavisworksTransport
/// <param name="detectionGap">检测间隙容差</param>
/// <param name="pathName">路径名称</param>
/// <param name="routeId">路由ID</param>
/// <param name="animatedObjectName">动画对象名称</param>
/// <param name="animatedObject">动画对象(如果是真实车辆)</param>
/// <param name="isVirtualVehicle">是否使用虚拟车辆</param>
/// <param name="frameRate">帧率</param>
/// <param name="duration">动画时长</param>
public void CreateAllAnimationCollisionTests(List<CollisionResult> precomputedCollisions, double detectionGap = 0.05,
string pathName = "未知路径", string routeId = null, string animatedObjectName = null,
string pathName = "未知路径", string routeId = null,
ModelItem animatedObject = null, bool isVirtualVehicle = false,
int frameRate = 30, double duration = 10.0)
{
try
@ -387,7 +444,6 @@ namespace NavisworksTransport
LogManager.Info($"[预计算处理] 原始记录: {precomputedCollisions.Count},有效碰撞: {_animationCollisionCount}");
// 获取动画对象和当前动画终点位置(用于后续恢复)
ModelItem animatedObject = null;
Point3D animationEndPosition = new Point3D(0, 0, 0);
if (collisionResults.Count > 0)
@ -647,7 +703,7 @@ namespace NavisworksTransport
_clashDetectiveCollisionCount = clashResults.Count;
// 保存到数据库
SaveClashDetectiveResultToDatabase(pathName, routeId, clashResults, frameRate, duration, detectionGap, animatedObjectName);
SaveClashDetectiveResultToDatabase(pathName, routeId, clashResults, frameRate, duration, detectionGap, animatedObject, isVirtualVehicle);
// 第四步:将分组添加到主测试
if (collisionGroup.Children.Count > 0)

View File

@ -170,16 +170,32 @@ namespace NavisworksTransport
Duration REAL,
DetectionGap REAL,
AnimatedObjectName TEXT,
IsVirtualVehicle INTEGER,
VehicleModelItemPath TEXT,
CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP
)
");
// 7. ClashDetective碰撞对象表
ExecuteNonQuery(@"
CREATE TABLE IF NOT EXISTS ClashDetectiveCollisionObjects (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
ResultId INTEGER NOT NULL,
ModelItemPath TEXT NOT NULL,
DisplayName TEXT,
ObjectName TEXT,
FOREIGN KEY(ResultId) REFERENCES ClashDetectiveResults(Id) ON DELETE CASCADE
)
");
// 创建索引
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)");
ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_clash_objects_result ON ClashDetectiveCollisionObjects(ResultId)");
ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_clash_objects_path ON ClashDetectiveCollisionObjects(ModelItemPath)");
}
/// <summary>
@ -371,7 +387,7 @@ namespace NavisworksTransport
/// <summary>
/// 保存ClashDetective碰撞检测结果
/// </summary>
public void SaveClashDetectiveResult(ClashDetectiveResultRecord record)
public int SaveClashDetectiveResult(ClashDetectiveResultRecord record)
{
try
{
@ -390,11 +406,12 @@ namespace NavisworksTransport
var sql = @"
INSERT INTO ClashDetectiveResults
(TestName, PathName, RouteId, TestTime, CollisionCount, AnimationCollisionCount,
FrameRate, Duration, DetectionGap, AnimatedObjectName, CreatedAt)
FrameRate, Duration, DetectionGap, AnimatedObjectName, IsVirtualVehicle, VehicleModelItemPath, CreatedAt)
VALUES (@testName, @pathName, @routeId, @testTime, @collisionCount, @animationCollisionCount,
@frameRate, @duration, @detectionGap, @animatedObjectName, @createdAt)
@frameRate, @duration, @detectionGap, @animatedObjectName, @isVirtualVehicle, @vehiclePath, @createdAt)
";
long newId = 0;
using (var cmd = new SQLiteCommand(sql, _connection))
{
cmd.Parameters.AddWithValue("@testName", record.TestName);
@ -407,11 +424,15 @@ namespace NavisworksTransport
cmd.Parameters.AddWithValue("@duration", record.Duration);
cmd.Parameters.AddWithValue("@detectionGap", record.DetectionGap);
cmd.Parameters.AddWithValue("@animatedObjectName", record.AnimatedObjectName ?? "");
cmd.Parameters.AddWithValue("@isVirtualVehicle", record.IsVirtualVehicle);
cmd.Parameters.AddWithValue("@vehiclePath", record.VehicleModelItemPath ?? "");
cmd.Parameters.AddWithValue("@createdAt", record.CreatedAt);
cmd.ExecuteNonQuery();
newId = _connection.LastInsertRowId;
}
LogManager.Info($"ClashDetective结果已保存: 测试={record.TestName}, 碰撞数={record.CollisionCount}");
LogManager.Info($"ClashDetective结果已保存: 测试={record.TestName}, 碰撞数={record.CollisionCount}, Id={newId}");
return (int)newId;
}
catch (Exception ex)
{
@ -541,6 +562,114 @@ namespace NavisworksTransport
}
}
/// <summary>
/// 保存ClashDetective碰撞对象
/// </summary>
public void SaveClashDetectiveCollisionObjects(int resultId, List<ClashDetectiveCollisionObjectRecord> objects)
{
if (objects == null || objects.Count == 0)
return;
try
{
using (var transaction = _connection.BeginTransaction())
{
var sql = @"
INSERT INTO ClashDetectiveCollisionObjects
(ResultId, ModelItemPath, DisplayName, ObjectName)
VALUES (@resultId, @path, @displayName, @objectName)
";
foreach (var obj in objects)
{
using (var cmd = new SQLiteCommand(sql, _connection))
{
cmd.Parameters.AddWithValue("@resultId", resultId);
cmd.Parameters.AddWithValue("@path", obj.ModelItemPath ?? "");
cmd.Parameters.AddWithValue("@displayName", obj.DisplayName ?? "");
cmd.Parameters.AddWithValue("@objectName", obj.ObjectName ?? "");
cmd.ExecuteNonQuery();
}
}
transaction.Commit();
LogManager.Info($"已保存 {objects.Count} 个碰撞对象到数据库ResultId={resultId}");
}
}
catch (Exception ex)
{
LogManager.Error($"保存ClashDetective碰撞对象失败: {ex.Message}", ex);
throw;
}
}
/// <summary>
/// 获取指定ClashDetective结果的所有碰撞对象
/// </summary>
public List<ClashDetectiveCollisionObjectRecord> GetClashDetectiveCollisionObjects(int resultId)
{
var results = new List<ClashDetectiveCollisionObjectRecord>();
try
{
var sql = @"
SELECT Id, ResultId, ModelItemPath, DisplayName, ObjectName
FROM ClashDetectiveCollisionObjects
WHERE ResultId = @resultId
";
using (var cmd = new SQLiteCommand(sql, _connection))
{
cmd.Parameters.AddWithValue("@resultId", resultId);
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
results.Add(new ClashDetectiveCollisionObjectRecord
{
Id = Convert.ToInt32(reader["Id"]),
ResultId = Convert.ToInt32(reader["ResultId"]),
ModelItemPath = reader["ModelItemPath"]?.ToString(),
DisplayName = reader["DisplayName"]?.ToString(),
ObjectName = reader["ObjectName"]?.ToString()
});
}
}
}
LogManager.Debug($"获取到 {results.Count} 个碰撞对象记录");
}
catch (Exception ex)
{
LogManager.Error($"获取ClashDetective碰撞对象失败: {ex.Message}", ex);
}
return results;
}
/// <summary>
/// 根据ModelItemPath查询碰撞次数
/// </summary>
public int GetCollisionCountByModelItemPath(string modelItemPath)
{
try
{
var sql = "SELECT COUNT(*) FROM ClashDetectiveCollisionObjects WHERE ModelItemPath = @path";
using (var cmd = new SQLiteCommand(sql, _connection))
{
cmd.Parameters.AddWithValue("@path", modelItemPath);
var result = cmd.ExecuteScalar();
return Convert.ToInt32(result);
}
}
catch (Exception ex)
{
LogManager.Error($"查询碰撞次数失败: {ex.Message}", ex);
return 0;
}
}
#endregion
/// <summary>
@ -1067,9 +1196,23 @@ namespace NavisworksTransport
public double Duration { get; set; }
public double DetectionGap { get; set; }
public string AnimatedObjectName { get; set; }
public bool IsVirtualVehicle { get; set; }
public string VehicleModelItemPath { get; set; }
public DateTime CreatedAt { get; set; }
}
/// <summary>
/// ClashDetective碰撞对象数据模型
/// </summary>
public class ClashDetectiveCollisionObjectRecord
{
public int Id { get; set; }
public int ResultId { get; set; }
public string ModelItemPath { get; set; }
public string DisplayName { get; set; }
public string ObjectName { get; set; }
}
/// <summary>
/// 路径分析结果数据模型
/// </summary>

View File

@ -2187,7 +2187,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 先设置路径到动画管理器
_pathAnimationManager.SetRoute(pathRoute);
_pathAnimationManager.CreateAnimation(animatedObject, pathPoints, AnimationDuration, CurrentPathRoute.Name, CurrentPathRoute.Id);
_pathAnimationManager.CreateAnimation(animatedObject, pathPoints, AnimationDuration, CurrentPathRoute.Name, CurrentPathRoute.Id, UseVirtualVehicle);
var totalElapsed = (DateTime.Now - cacheStartTime).TotalMilliseconds;
LogManager.Info($"[动画生成] 动画生成完成,总耗时: {totalElapsed:F1}ms");