从数据库中比对历史检测配置是否重复
This commit is contained in:
parent
7fbbcdd448
commit
76d277b6c2
@ -193,7 +193,7 @@ namespace NavisworksTransport
|
||||
FrameRate INTEGER NOT NULL DEFAULT 30,
|
||||
DurationSeconds REAL NOT NULL DEFAULT 10.0,
|
||||
-- 碰撞检测参数
|
||||
DetectionToleranceMeters REAL NOT NULL DEFAULT 0.05,
|
||||
DetectionTolerance REAL NOT NULL DEFAULT 0.05,
|
||||
-- 运动物体参数
|
||||
IsVirtualObject INTEGER NOT NULL DEFAULT 0,
|
||||
AnimatedObjectName TEXT,
|
||||
@ -292,7 +292,7 @@ namespace NavisworksTransport
|
||||
// 12. 设置数据库版本(SQLite内置user_version)
|
||||
// 版本号格式:主版本*10000 + 次版本*100 + 修订号
|
||||
// 例如:2.1.3 = 20103
|
||||
ExecuteNonQuery("PRAGMA user_version = 20102"); // v2.1.2 - 增加时标配置和事件表
|
||||
ExecuteNonQuery("PRAGMA user_version = 20103"); // v2.1.3 - 重命名DetectionToleranceMeters为DetectionTolerance
|
||||
|
||||
// 创建索引
|
||||
ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_reports_route ON CollisionReports(RouteId)");
|
||||
@ -319,7 +319,7 @@ namespace NavisworksTransport
|
||||
ErrorMessage TEXT,
|
||||
FrameRate INTEGER NOT NULL,
|
||||
DurationSeconds REAL NOT NULL,
|
||||
DetectionToleranceMeters REAL NOT NULL,
|
||||
DetectionTolerance REAL NOT NULL,
|
||||
IsVirtualObject INTEGER NOT NULL,
|
||||
VirtualObjectLength REAL,
|
||||
VirtualObjectWidth REAL,
|
||||
@ -1187,7 +1187,175 @@ namespace NavisworksTransport
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取检测记录的排除对象列表
|
||||
/// </summary>
|
||||
public List<CollisionDetectionExcludedObjectRecord> GetDetectionExcludedObjects(int detectionRecordId)
|
||||
{
|
||||
var results = new List<CollisionDetectionExcludedObjectRecord>();
|
||||
|
||||
try
|
||||
{
|
||||
var sql = @"
|
||||
SELECT Id, DetectionRecordId, ModelIndex, PathId, DisplayName, ObjectName, Reason
|
||||
FROM CollisionDetectionExcludedObjects
|
||||
WHERE DetectionRecordId = @detectionRecordId
|
||||
";
|
||||
|
||||
using (var cmd = new SQLiteCommand(sql, _connection))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@detectionRecordId", detectionRecordId);
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
results.Add(new CollisionDetectionExcludedObjectRecord
|
||||
{
|
||||
Id = Convert.ToInt32(reader["Id"]),
|
||||
DetectionRecordId = Convert.ToInt32(reader["DetectionRecordId"]),
|
||||
ModelIndex = reader["ModelIndex"] == DBNull.Value ? 0 : Convert.ToInt32(reader["ModelIndex"]),
|
||||
PathId = reader["PathId"] == DBNull.Value ? null : reader["PathId"].ToString(),
|
||||
DisplayName = reader["DisplayName"]?.ToString(),
|
||||
ObjectName = reader["ObjectName"]?.ToString(),
|
||||
Reason = reader["Reason"]?.ToString()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"获取排除对象列表失败: {ex.Message}", ex);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取检测记录的手工碰撞目标列表
|
||||
/// </summary>
|
||||
public List<CollisionDetectionManualTargetRecord> GetDetectionManualTargets(int detectionRecordId)
|
||||
{
|
||||
var results = new List<CollisionDetectionManualTargetRecord>();
|
||||
|
||||
try
|
||||
{
|
||||
var sql = @"
|
||||
SELECT Id, DetectionRecordId, ModelIndex, PathId, DisplayName, ObjectName
|
||||
FROM CollisionDetectionManualTargets
|
||||
WHERE DetectionRecordId = @detectionRecordId
|
||||
";
|
||||
|
||||
using (var cmd = new SQLiteCommand(sql, _connection))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@detectionRecordId", detectionRecordId);
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
results.Add(new CollisionDetectionManualTargetRecord
|
||||
{
|
||||
Id = Convert.ToInt32(reader["Id"]),
|
||||
DetectionRecordId = Convert.ToInt32(reader["DetectionRecordId"]),
|
||||
ModelIndex = reader["ModelIndex"] == DBNull.Value ? 0 : Convert.ToInt32(reader["ModelIndex"]),
|
||||
PathId = reader["PathId"] == DBNull.Value ? null : reader["PathId"].ToString(),
|
||||
DisplayName = reader["DisplayName"]?.ToString(),
|
||||
ObjectName = reader["ObjectName"]?.ToString()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"获取手工目标列表失败: {ex.Message}", ex);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 通过基础参数查询匹配的检测记录(用于检查配置是否重复)
|
||||
/// 注意:数值参数使用容差匹配,返回的记录还需要进一步比较排除列表和手工目标
|
||||
/// </summary>
|
||||
public List<CollisionDetectionRecord> FindDetectionRecordsByBaseParams(
|
||||
string routeId,
|
||||
int frameRate,
|
||||
double durationSeconds,
|
||||
double detectionTolerance,
|
||||
bool isVirtualObject,
|
||||
double? virtualObjectLength,
|
||||
double? virtualObjectWidth,
|
||||
double? virtualObjectHeight,
|
||||
double objectRotationCorrection,
|
||||
bool isManualMode)
|
||||
{
|
||||
var results = new List<CollisionDetectionRecord>();
|
||||
|
||||
try
|
||||
{
|
||||
// 使用容差匹配浮动数值参数
|
||||
var sql = @"
|
||||
SELECT cdr.*, pr.Name AS PathName
|
||||
FROM CollisionDetectionRecords cdr
|
||||
INNER JOIN PathRoutes pr ON cdr.RouteId = pr.Id
|
||||
WHERE cdr.RouteId = @routeId
|
||||
AND cdr.FrameRate = @frameRate
|
||||
AND ABS(cdr.DurationSeconds - @duration) < 0.01
|
||||
AND ABS(cdr.DetectionTolerance - @tolerance) < 0.001
|
||||
AND cdr.IsVirtualObject = @isVirtual
|
||||
AND ABS(cdr.ObjectRotationCorrection - @rotation) < 0.01
|
||||
AND cdr.DetectAllObjects = @detectAll
|
||||
AND cdr.TestName IS NOT NULL
|
||||
";
|
||||
|
||||
using (var cmd = new SQLiteCommand(sql, _connection))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@routeId", routeId);
|
||||
cmd.Parameters.AddWithValue("@frameRate", frameRate);
|
||||
cmd.Parameters.AddWithValue("@duration", durationSeconds);
|
||||
cmd.Parameters.AddWithValue("@tolerance", detectionTolerance);
|
||||
cmd.Parameters.AddWithValue("@isVirtual", isVirtualObject ? 1 : 0);
|
||||
cmd.Parameters.AddWithValue("@rotation", objectRotationCorrection);
|
||||
cmd.Parameters.AddWithValue("@detectAll", isManualMode ? 0 : 1);
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
var record = ReadCollisionDetectionRecordFromReader(reader);
|
||||
|
||||
// 虚拟物体尺寸比较(如果是虚拟物体)
|
||||
if (isVirtualObject && virtualObjectLength.HasValue)
|
||||
{
|
||||
if (!record.VirtualObjectLength.HasValue ||
|
||||
Math.Abs(record.VirtualObjectLength.Value - virtualObjectLength.Value) > 0.01)
|
||||
continue;
|
||||
if (!record.VirtualObjectWidth.HasValue ||
|
||||
Math.Abs(record.VirtualObjectWidth.Value - virtualObjectWidth.Value) > 0.01)
|
||||
continue;
|
||||
if (!record.VirtualObjectHeight.HasValue ||
|
||||
Math.Abs(record.VirtualObjectHeight.Value - virtualObjectHeight.Value) > 0.01)
|
||||
continue;
|
||||
}
|
||||
|
||||
results.Add(record);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.Debug($"[FindByBaseParams] 找到 {results.Count} 条基础参数匹配的记录");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"通过基础参数查询检测记录失败: {ex.Message}", ex);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存分析评分结果
|
||||
/// </summary>
|
||||
@ -2086,14 +2254,14 @@ namespace NavisworksTransport
|
||||
{
|
||||
var sql = @"
|
||||
INSERT INTO CollisionDetectionRecords (
|
||||
RouteId, CreatedTime, FrameRate, DurationSeconds, DetectionToleranceMeters,
|
||||
RouteId, CreatedTime, FrameRate, DurationSeconds, DetectionTolerance,
|
||||
IsVirtualObject, AnimatedObjectName, ObjectModelIndex, ObjectPathId,
|
||||
VirtualObjectLength, VirtualObjectWidth, VirtualObjectHeight,
|
||||
DetectAllObjects, ObjectRotationCorrection, Description,
|
||||
TestName, TestTime, CollisionCount, AnimationCollisionCount
|
||||
)
|
||||
VALUES (
|
||||
@RouteId, @CreatedTime, @FrameRate, @DurationSeconds, @DetectionToleranceMeters,
|
||||
@RouteId, @CreatedTime, @FrameRate, @DurationSeconds, @DetectionTolerance,
|
||||
@IsVirtualObject, @AnimatedObjectName, @ObjectModelIndex, @ObjectPathId,
|
||||
@VirtualObjectLength, @VirtualObjectWidth, @VirtualObjectHeight,
|
||||
@DetectAllObjects, @ObjectRotationCorrection, @Description,
|
||||
@ -2109,7 +2277,7 @@ namespace NavisworksTransport
|
||||
cmd.Parameters.AddWithValue("@FrameRate", record.FrameRate);
|
||||
cmd.Parameters.AddWithValue("@DurationSeconds", record.DurationSeconds);
|
||||
// 内部使用模型单位,写入数据库时转换为米单位
|
||||
cmd.Parameters.AddWithValue("@DetectionToleranceMeters", record.DetectionTolerance * UnitsConverter.GetUnitsToMetersConversionFactor());
|
||||
cmd.Parameters.AddWithValue("@DetectionTolerance", record.DetectionTolerance); // 模型单位,不转换
|
||||
cmd.Parameters.AddWithValue("@IsVirtualObject", record.IsVirtualObject ? 1 : 0);
|
||||
cmd.Parameters.AddWithValue("@AnimatedObjectName", record.AnimatedObjectName ?? "");
|
||||
cmd.Parameters.AddWithValue("@ObjectModelIndex", record.ObjectModelIndex ?? (object)DBNull.Value);
|
||||
@ -2417,7 +2585,7 @@ namespace NavisworksTransport
|
||||
FrameRate = Convert.ToInt32(reader["FrameRate"]),
|
||||
DurationSeconds = Convert.ToDouble(reader["DurationSeconds"]),
|
||||
// 数据库中存储米单位,读取时转换为模型单位
|
||||
DetectionTolerance = Convert.ToDouble(reader["DetectionToleranceMeters"]) * UnitsConverter.GetMetersToUnitsConversionFactor(),
|
||||
DetectionTolerance = Convert.ToDouble(reader["DetectionTolerance"]), // 模型单位,不转换
|
||||
IsVirtualObject = Convert.ToInt32(reader["IsVirtualObject"]) == 1,
|
||||
AnimatedObjectName = reader["AnimatedObjectName"]?.ToString(),
|
||||
ObjectModelIndex = reader["ObjectModelIndex"] != DBNull.Value ? Convert.ToInt32(reader["ObjectModelIndex"]) : (int?)null,
|
||||
@ -2581,7 +2749,7 @@ namespace NavisworksTransport
|
||||
cmd.CommandText = @"
|
||||
INSERT INTO BatchQueueItems (
|
||||
RouteId, Status, CreatedTime, StartTime, EndTime, ErrorMessage,
|
||||
FrameRate, DurationSeconds, DetectionToleranceMeters,
|
||||
FrameRate, DurationSeconds, DetectionTolerance,
|
||||
IsVirtualObject, VirtualObjectLength, VirtualObjectWidth, VirtualObjectHeight,
|
||||
DetectAllObjects,
|
||||
ClashDetectiveTestName, CollisionCount, ObjectRotationCorrection,
|
||||
@ -2589,7 +2757,7 @@ namespace NavisworksTransport
|
||||
)
|
||||
VALUES (
|
||||
@RouteId, @Status, @CreatedTime, @StartTime, @EndTime, @ErrorMessage,
|
||||
@FrameRate, @DurationSeconds, @DetectionToleranceMeters,
|
||||
@FrameRate, @DurationSeconds, @DetectionTolerance,
|
||||
@IsVirtualObject, @VirtualObjectLength, @VirtualObjectWidth, @VirtualObjectHeight,
|
||||
@DetectAllObjects,
|
||||
@ClashDetectiveTestName, @CollisionCount, @ObjectRotationCorrection,
|
||||
@ -2606,7 +2774,7 @@ namespace NavisworksTransport
|
||||
cmd.Parameters.AddWithValue("@FrameRate", item.FrameRate);
|
||||
cmd.Parameters.AddWithValue("@DurationSeconds", item.DurationSeconds);
|
||||
// 内部使用模型单位,写入数据库时转换为米单位
|
||||
cmd.Parameters.AddWithValue("@DetectionToleranceMeters", item.DetectionTolerance * UnitsConverter.GetUnitsToMetersConversionFactor());
|
||||
cmd.Parameters.AddWithValue("@DetectionTolerance", item.DetectionTolerance); // 模型单位,不转换
|
||||
cmd.Parameters.AddWithValue("@IsVirtualObject", item.IsVirtualObject ? 1 : 0);
|
||||
cmd.Parameters.AddWithValue("@VirtualObjectLength", item.VirtualObjectLength);
|
||||
cmd.Parameters.AddWithValue("@VirtualObjectWidth", item.VirtualObjectWidth);
|
||||
@ -2651,7 +2819,7 @@ namespace NavisworksTransport
|
||||
FrameRate = Convert.ToInt32(reader["FrameRate"]),
|
||||
DurationSeconds = Convert.ToDouble(reader["DurationSeconds"]),
|
||||
// 数据库中存储米单位,读取时转换为模型单位
|
||||
DetectionTolerance = Convert.ToDouble(reader["DetectionToleranceMeters"]) * UnitsConverter.GetMetersToUnitsConversionFactor(),
|
||||
DetectionTolerance = Convert.ToDouble(reader["DetectionTolerance"]), // 模型单位,不转换
|
||||
IsVirtualObject = isVirtualObject,
|
||||
VirtualObjectLength = Convert.ToDouble(reader["VirtualObjectLength"]),
|
||||
VirtualObjectWidth = Convert.ToDouble(reader["VirtualObjectWidth"]),
|
||||
@ -2690,7 +2858,7 @@ namespace NavisworksTransport
|
||||
{
|
||||
var sql = @"
|
||||
SELECT bqi.Id, bqi.RouteId, pr.Name AS PathRouteName, pr.PathType, bqi.Status, bqi.CreatedTime, bqi.StartTime, bqi.EndTime, bqi.ErrorMessage,
|
||||
bqi.FrameRate, bqi.DurationSeconds, bqi.DetectionToleranceMeters,
|
||||
bqi.FrameRate, bqi.DurationSeconds, bqi.DetectionTolerance,
|
||||
bqi.IsVirtualObject, bqi.VirtualObjectLength, bqi.VirtualObjectWidth, bqi.VirtualObjectHeight,
|
||||
bqi.DetectAllObjects,
|
||||
bqi.ClashDetectiveTestName, bqi.CollisionCount, bqi.ObjectRotationCorrection,
|
||||
@ -2750,7 +2918,7 @@ namespace NavisworksTransport
|
||||
{
|
||||
cmd.CommandText = @"
|
||||
SELECT bqi.Id, bqi.RouteId, pr.Name AS PathRouteName, pr.PathType, bqi.Status, bqi.CreatedTime, bqi.StartTime, bqi.EndTime, bqi.ErrorMessage,
|
||||
bqi.FrameRate, bqi.DurationSeconds, bqi.DetectionToleranceMeters,
|
||||
bqi.FrameRate, bqi.DurationSeconds, bqi.DetectionTolerance,
|
||||
bqi.IsVirtualObject, bqi.VirtualObjectLength, bqi.VirtualObjectWidth, bqi.VirtualObjectHeight,
|
||||
bqi.DetectAllObjects,
|
||||
bqi.ClashDetectiveTestName, bqi.CollisionCount, bqi.ObjectRotationCorrection,
|
||||
|
||||
@ -3255,73 +3255,87 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否已有相同配置的检测记录
|
||||
/// 通过动画配置哈希匹配已完成的检测记录
|
||||
/// 策略:1.先检查内存缓存 2.SQL过滤基础参数 3.比较排除列表和手工目标
|
||||
/// </summary>
|
||||
/// <returns>(记录ID, 用户选择),不存在或用户取消则返回null</returns>
|
||||
private (int id, UserChoice userChoice)? CheckExistingDetectionRecord()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 计算当前动画配置的哈希
|
||||
var animatedObject = UseVirtualObject ? VirtualObjectManager.Instance.CurrentVirtualObject : SelectedAnimatedObject;
|
||||
var route = CurrentPathRoute?.Route;
|
||||
|
||||
if (animatedObject == null || route == null)
|
||||
var routeId = CurrentPathRoute?.Id;
|
||||
if (string.IsNullOrEmpty(routeId))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var currentHash = _pathAnimationManager.ComputeAnimationConfigHashFromRoute(animatedObject, route);
|
||||
|
||||
// 查询PathAnimationManager中是否有相同配置的记录
|
||||
var existingRecordId = _pathAnimationManager.GetDetectionRecordIdByHash(currentHash);
|
||||
|
||||
if (existingRecordId.HasValue)
|
||||
var pathDatabase = _pathPlanningManager?.GetPathDatabase();
|
||||
if (pathDatabase == null)
|
||||
{
|
||||
// 验证数据库中该记录是否仍然存在
|
||||
var pathDatabase = _pathPlanningManager?.GetPathDatabase();
|
||||
var record = pathDatabase?.GetDetectionResultById(existingRecordId.Value);
|
||||
|
||||
if (record != null)
|
||||
return null;
|
||||
}
|
||||
|
||||
var animatedObject = UseVirtualObject ? VirtualObjectManager.Instance.CurrentVirtualObject : SelectedAnimatedObject;
|
||||
if (animatedObject == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// 1. 先检查内存缓存(程序运行期间已处理过的)
|
||||
var currentHash = _pathAnimationManager.ComputeAnimationConfigHashFromRoute(animatedObject, CurrentPathRoute.Route);
|
||||
var cachedRecordId = _pathAnimationManager.GetDetectionRecordIdByHash(currentHash);
|
||||
if (cachedRecordId.HasValue)
|
||||
{
|
||||
var cachedRecord = pathDatabase.GetDetectionResultById(cachedRecordId.Value);
|
||||
if (cachedRecord != null)
|
||||
{
|
||||
LogManager.Info($"[CheckExistingDetectionRecord] 找到相同配置的检测记录: Hash={currentHash.Substring(0, 8)}..., RecordId={existingRecordId}");
|
||||
|
||||
// 弹出提示框询问用户
|
||||
var message = $"检测配置已存在!\n\n" +
|
||||
$"找到一条相同配置的历史检测记录:\n" +
|
||||
$"• 测试名称:{record.TestName ?? "未命名"}\n" +
|
||||
$"• 检测时间:{record.TestTime:yyyy-MM-dd HH:mm:ss}\n" +
|
||||
$"• 碰撞数量:{record.CollisionCount} 个\n\n" +
|
||||
$"您可以:\n" +
|
||||
$"• 【是】直接使用历史记录(跳过重复检测)\n" +
|
||||
$"• 【否】重新生成新记录";
|
||||
|
||||
var result = System.Windows.MessageBox.Show(
|
||||
message,
|
||||
"检测配置已存在",
|
||||
System.Windows.MessageBoxButton.YesNo,
|
||||
System.Windows.MessageBoxImage.Question);
|
||||
|
||||
if (result == System.Windows.MessageBoxResult.Yes)
|
||||
{
|
||||
// 用户选择使用历史记录
|
||||
_lastReusedRecordId = existingRecordId.Value;
|
||||
return (existingRecordId.Value, UserChoice.UseExisting);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 用户选择重新生成
|
||||
_lastReusedRecordId = null;
|
||||
return (existingRecordId.Value, UserChoice.CreateNew);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 记录已被删除,清除缓存
|
||||
_pathAnimationManager.RemoveDetectionRecordHash(currentHash);
|
||||
LogManager.Info($"[CheckExistingDetectionRecord] 内存缓存命中: RecordId={cachedRecordId}");
|
||||
return ShowDuplicateConfigDialog(cachedRecord);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 2. SQL过滤基础参数匹配的记录
|
||||
// 注意:数据库存储的是模型单位(不带Meters后缀),查询时传模型单位
|
||||
var factor = UnitsConverter.GetMetersToUnitsConversionFactor();
|
||||
var matchingRecords = pathDatabase.FindDetectionRecordsByBaseParams(
|
||||
routeId,
|
||||
_animationFrameRate,
|
||||
AnimationDuration,
|
||||
_detectionTolerance * factor, // 米 → 模型单位
|
||||
UseVirtualObject,
|
||||
UseVirtualObject ? VirtualObjectLengthInMeters * factor : (double?)null, // 米 → 模型单位
|
||||
UseVirtualObject ? VirtualObjectWidthInMeters * factor : (double?)null,
|
||||
UseVirtualObject ? VirtualObjectHeightInMeters * factor : (double?)null,
|
||||
_objectRotationCorrection,
|
||||
IsManualCollisionTargetEnabled
|
||||
);
|
||||
|
||||
if (matchingRecords == null || matchingRecords.Count == 0)
|
||||
{
|
||||
LogManager.Info("[CheckExistingDetectionRecord] SQL基础参数过滤无匹配");
|
||||
return null;
|
||||
}
|
||||
|
||||
LogManager.Info($"[CheckExistingDetectionRecord] SQL找到 {matchingRecords.Count} 条记录,开始比较排除列表");
|
||||
|
||||
// 3. 逐个比较排除列表和手工目标
|
||||
var currentExcluded = GetCurrentExcludedObjects();
|
||||
var currentTargets = GetCurrentManualTargets();
|
||||
|
||||
foreach (var record in matchingRecords)
|
||||
{
|
||||
if (IsExcludedListMatch(record.Id, currentExcluded, pathDatabase) &&
|
||||
IsManualTargetListMatch(record.Id, currentTargets, pathDatabase))
|
||||
{
|
||||
LogManager.Info($"[CheckExistingDetectionRecord] 找到完全匹配: RecordId={record.Id}");
|
||||
|
||||
// 注册到内存缓存
|
||||
_pathAnimationManager.RegisterAnimationHashToRecordId(currentHash, record.Id);
|
||||
|
||||
return ShowDuplicateConfigDialog(record);
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.Info("[CheckExistingDetectionRecord] 未找到完全匹配的记录");
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -3331,6 +3345,115 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示重复配置对话框
|
||||
/// </summary>
|
||||
private (int id, UserChoice userChoice)? ShowDuplicateConfigDialog(CollisionDetectionRecord record)
|
||||
{
|
||||
var message = $"检测配置已存在!\n\n" +
|
||||
$"找到一条相同配置的历史检测记录:\n" +
|
||||
$"• 测试名称:{record.TestName ?? "未命名"}\n" +
|
||||
$"• 检测时间:{record.TestTime:yyyy-MM-dd HH:mm:ss}\n" +
|
||||
$"• 碰撞数量:{record.CollisionCount} 个\n\n" +
|
||||
$"您可以:\n" +
|
||||
$"• 【是】直接使用历史记录(跳过重复检测)\n" +
|
||||
$"• 【否】重新生成新记录";
|
||||
|
||||
var result = System.Windows.MessageBox.Show(
|
||||
message,
|
||||
"检测配置已存在",
|
||||
System.Windows.MessageBoxButton.YesNo,
|
||||
System.Windows.MessageBoxImage.Question);
|
||||
|
||||
if (result == System.Windows.MessageBoxResult.Yes)
|
||||
{
|
||||
_lastReusedRecordId = record.Id;
|
||||
return (record.Id, UserChoice.UseExisting);
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastReusedRecordId = null;
|
||||
return (record.Id, UserChoice.CreateNew);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前排除对象列表(ModelIndex + PathId)
|
||||
/// </summary>
|
||||
private List<(int ModelIndex, string PathId)> GetCurrentExcludedObjects()
|
||||
{
|
||||
var result = new List<(int, string)>();
|
||||
var excludedObjects = _pathAnimationManager?.GetExcludedObjects();
|
||||
|
||||
if (excludedObjects != null)
|
||||
{
|
||||
foreach (var obj in excludedObjects)
|
||||
{
|
||||
if (obj == null) continue;
|
||||
try
|
||||
{
|
||||
var pathId = Autodesk.Navisworks.Api.Application.ActiveDocument.Models.CreatePathId(obj);
|
||||
result.Add((pathId.ModelIndex, pathId.PathId));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
return result.OrderBy(x => x.Item1).ThenBy(x => x.Item2).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前手工碰撞目标列表(ModelIndex + PathId)
|
||||
/// </summary>
|
||||
private List<(int ModelIndex, string PathId)> GetCurrentManualTargets()
|
||||
{
|
||||
var result = new List<(int, string)>();
|
||||
|
||||
if (IsManualCollisionTargetEnabled && _manualCollisionTargets != null)
|
||||
{
|
||||
foreach (var target in _manualCollisionTargets)
|
||||
{
|
||||
if (target?.ModelItem == null) continue;
|
||||
try
|
||||
{
|
||||
var pathId = Autodesk.Navisworks.Api.Application.ActiveDocument.Models.CreatePathId(target.ModelItem);
|
||||
result.Add((pathId.ModelIndex, pathId.PathId));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
return result.OrderBy(x => x.Item1).ThenBy(x => x.Item2).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 比较排除列表是否匹配
|
||||
/// </summary>
|
||||
private bool IsExcludedListMatch(int recordId, List<(int ModelIndex, string PathId)> currentList, PathDatabase db)
|
||||
{
|
||||
var dbList = db.GetDetectionExcludedObjects(recordId)
|
||||
.Select(e => (e.ModelIndex, e.PathId))
|
||||
.OrderBy(x => x.ModelIndex)
|
||||
.ThenBy(x => x.PathId)
|
||||
.ToList();
|
||||
|
||||
return dbList.SequenceEqual(currentList);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 比较手工目标列表是否匹配
|
||||
/// </summary>
|
||||
private bool IsManualTargetListMatch(int recordId, List<(int ModelIndex, string PathId)> currentList, PathDatabase db)
|
||||
{
|
||||
var dbList = db.GetDetectionManualTargets(recordId)
|
||||
.Select(t => (t.ModelIndex, t.PathId))
|
||||
.OrderBy(x => x.ModelIndex)
|
||||
.ThenBy(x => x.PathId)
|
||||
.ToList();
|
||||
|
||||
return dbList.SequenceEqual(currentList);
|
||||
}
|
||||
|
||||
private void ExecuteToggleWireframeMode()
|
||||
{
|
||||
try
|
||||
|
||||
Loading…
Reference in New Issue
Block a user