增加角度修正功能,增加批处理列表内容

This commit is contained in:
tian 2026-01-26 17:14:36 +08:00
parent d0ade35042
commit 82c523a3db
9 changed files with 143 additions and 69 deletions

View File

@ -283,6 +283,7 @@
<Compile Include="src\UI\WPF\Converters\PathTypeConverter.cs" />
<Compile Include="src\UI\WPF\Converters\BatchQueueStatusConverter.cs" />
<Compile Include="src\UI\WPF\Converters\BatchQueueStatusHelper.cs" />
<Compile Include="src\UI\WPF\Converters\NullToDashConverter.cs" />
<Compile Include="src\UI\WPF\Models\LogisticsModel.cs" />
<Compile Include="src\UI\WPF\Models\PathRouteViewModel.cs" />
<Compile Include="src\UI\WPF\Models\SplitPreviewItem.cs" />

View File

@ -261,7 +261,8 @@ namespace NavisworksTransport.Core
config.FrameRate,
config.DurationSeconds,
config.DetectionToleranceMeters,
null
null,
item.ObjectRotationCorrection
);
// 检查预计算是否成功

View File

@ -35,17 +35,19 @@ namespace NavisworksTransport.Core.Collision
int frameRate,
double duration,
double detectionGap,
List<ModelItem> manualDetectionTargets = null)
List<ModelItem> manualDetectionTargets = null,
double objectRotationCorrection = 0.0)
{
try
{
LogManager.Info($"[批处理] 开始预计算动画帧 - 路径: {route.Name}, 帧率: {frameRate}, 时长: {duration}秒");
LogManager.Info($"[批处理] 开始预计算动画帧 - 路径: {route.Name}, 帧率: {frameRate}, 时长: {duration}秒, 角度修正: {objectRotationCorrection:F1}°");
// 设置动画管理器参数但不触发UI操作
_animationManager.SetRoute(route);
_animationManager.SetAnimatedObject(animatedObject);
_animationManager.SetVirtualVehicleParameters(isVirtualVehicle, virtualVehicleLength, virtualVehicleWidth, virtualVehicleHeight);
_animationManager.SetAnimationParameters(frameRate, duration, detectionGap);
_animationManager.SetObjectRotationCorrectionDirect(objectRotationCorrection);
if (manualDetectionTargets != null && manualDetectionTargets.Count > 0)
{

View File

@ -36,7 +36,8 @@ namespace NavisworksTransport.Core.Collision
int frameRate,
double duration,
double detectionGap,
List<ModelItem> manualDetectionTargets = null);
List<ModelItem> manualDetectionTargets = null,
double objectRotationCorrection = 0.0);
/// <summary>
/// 创建并运行ClashDetective测试纯计算无UI操作

View File

@ -36,6 +36,9 @@ namespace NavisworksTransport.Core.Models
public List<string> DetectionItems { get; set; } = new List<string>();
public bool DetectAllObjects { get; set; } = true;
// 角度修正配置
public double ObjectRotationCorrection { get; set; }
// 结果
public string ClashDetectiveTestName { get; set; }
public int? CollisionCount { get; set; }

View File

@ -236,7 +236,8 @@ namespace NavisworksTransport
DetectionItems TEXT,
DetectAllObjects INTEGER NOT NULL DEFAULT 1,
ClashDetectiveTestName TEXT,
CollisionCount INTEGER
CollisionCount INTEGER,
ObjectRotationCorrection REAL
)
");
@ -1652,14 +1653,14 @@ namespace NavisworksTransport
FrameRate, DurationSeconds, DetectionToleranceMeters,
IsVirtualVehicle, VirtualVehicleLength, VirtualVehicleWidth, VirtualVehicleHeight,
VehicleObjectId, VehicleObjectName, DetectionItems, DetectAllObjects,
ClashDetectiveTestName, CollisionCount
ClashDetectiveTestName, CollisionCount, ObjectRotationCorrection
)
VALUES (
@PathRouteId, @PathRouteName, @Status, @CreatedTime, @StartTime, @EndTime, @ErrorMessage,
@FrameRate, @DurationSeconds, @DetectionToleranceMeters,
@IsVirtualVehicle, @VirtualVehicleLength, @VirtualVehicleWidth, @VirtualVehicleHeight,
@VehicleObjectId, @VehicleObjectName, @DetectionItems, @DetectAllObjects,
@ClashDetectiveTestName, @CollisionCount
@ClashDetectiveTestName, @CollisionCount, @ObjectRotationCorrection
);
SELECT last_insert_rowid();";
@ -1683,67 +1684,13 @@ namespace NavisworksTransport
cmd.Parameters.AddWithValue("@DetectAllObjects", item.DetectAllObjects ? 1 : 0);
cmd.Parameters.AddWithValue("@ClashDetectiveTestName", item.ClashDetectiveTestName ?? "");
cmd.Parameters.AddWithValue("@CollisionCount", item.CollisionCount ?? (object)DBNull.Value);
cmd.Parameters.AddWithValue("@ObjectRotationCorrection", item.ObjectRotationCorrection);
return Convert.ToInt32(cmd.ExecuteScalar());
}
});
}
/// <summary>
/// 获取批处理队列项
/// </summary>
public async Task<BatchQueueItem> GetBatchQueueItemAsync(int itemId)
{
return await Task.Run(() =>
{
using (var cmd = new SQLiteCommand(_connection))
{
cmd.CommandText = @"
SELECT Id, PathRouteId, PathRouteName, Status, CreatedTime, StartTime, EndTime, ErrorMessage,
FrameRate, DurationSeconds, DetectionToleranceMeters,
IsVirtualVehicle, VirtualVehicleLength, VirtualVehicleWidth, VirtualVehicleHeight,
VehicleObjectId, VehicleObjectName, DetectionItems, DetectAllObjects,
ClashDetectiveTestName, CollisionCount
FROM BatchQueueItems
WHERE Id = @Id";
cmd.Parameters.AddWithValue("@Id", itemId);
using (var reader = cmd.ExecuteReader())
{
if (reader.Read())
{
return new BatchQueueItem
{
Id = Convert.ToInt32(reader["Id"]),
PathRouteId = reader["PathRouteId"].ToString(),
PathRouteName = reader["PathRouteName"].ToString(),
Status = (BatchQueueStatus)Enum.Parse(typeof(BatchQueueStatus), reader["Status"].ToString()),
CreatedTime = DateTime.Parse(reader["CreatedTime"].ToString()),
StartTime = reader["StartTime"].ToString() != "" ? (DateTime?)DateTime.Parse(reader["StartTime"].ToString()) : null,
EndTime = reader["EndTime"].ToString() != "" ? (DateTime?)DateTime.Parse(reader["EndTime"].ToString()) : null,
ErrorMessage = reader["ErrorMessage"].ToString(),
FrameRate = Convert.ToInt32(reader["FrameRate"]),
DurationSeconds = Convert.ToDouble(reader["DurationSeconds"]),
DetectionToleranceMeters = Convert.ToDouble(reader["DetectionToleranceMeters"]),
IsVirtualVehicle = Convert.ToBoolean(reader["IsVirtualVehicle"]),
VirtualVehicleLength = Convert.ToDouble(reader["VirtualVehicleLength"]),
VirtualVehicleWidth = Convert.ToDouble(reader["VirtualVehicleWidth"]),
VirtualVehicleHeight = Convert.ToDouble(reader["VirtualVehicleHeight"]),
VehicleObjectId = reader["VehicleObjectId"].ToString(),
VehicleObjectName = reader["VehicleObjectName"].ToString(),
DetectionItems = reader["DetectionItems"].ToString() != "" ? reader["DetectionItems"].ToString().Split(',').ToList() : new List<string>(),
DetectAllObjects = Convert.ToBoolean(reader["DetectAllObjects"]),
ClashDetectiveTestName = reader["ClashDetectiveTestName"].ToString(),
CollisionCount = !Convert.IsDBNull(reader["CollisionCount"]) ? (int?)Convert.ToInt32(reader["CollisionCount"]) : null
};
}
return null;
}
}
});
}
/// <summary>
/// 获取批处理队列项列表
/// </summary>
@ -1759,7 +1706,7 @@ namespace NavisworksTransport
FrameRate, DurationSeconds, DetectionToleranceMeters,
IsVirtualVehicle, VirtualVehicleLength, VirtualVehicleWidth, VirtualVehicleHeight,
VehicleObjectId, VehicleObjectName, DetectionItems, DetectAllObjects,
ClashDetectiveTestName, CollisionCount
ClashDetectiveTestName, CollisionCount, ObjectRotationCorrection
FROM BatchQueueItems";
var conditions = new List<string>();
@ -1817,7 +1764,8 @@ namespace NavisworksTransport
DetectionItems = reader["DetectionItems"].ToString() != "" ? reader["DetectionItems"].ToString().Split(',').ToList() : new List<string>(),
DetectAllObjects = Convert.ToBoolean(reader["DetectAllObjects"]),
ClashDetectiveTestName = reader["ClashDetectiveTestName"].ToString(),
CollisionCount = !Convert.IsDBNull(reader["CollisionCount"]) ? (int?)Convert.ToInt32(reader["CollisionCount"]) : null
CollisionCount = !Convert.IsDBNull(reader["CollisionCount"]) ? (int?)Convert.ToInt32(reader["CollisionCount"]) : null,
ObjectRotationCorrection = Convert.ToDouble(reader["ObjectRotationCorrection"])
});
}
}
@ -1826,6 +1774,62 @@ namespace NavisworksTransport
});
}
/// <summary>
/// 获取批处理队列项
/// </summary>
public async Task<BatchQueueItem> GetBatchQueueItemAsync(int itemId)
{
return await Task.Run(() =>
{
using (var cmd = new SQLiteCommand(_connection))
{
cmd.CommandText = @"
SELECT Id, PathRouteId, PathRouteName, Status, CreatedTime, StartTime, EndTime, ErrorMessage,
FrameRate, DurationSeconds, DetectionToleranceMeters,
IsVirtualVehicle, VirtualVehicleLength, VirtualVehicleWidth, VirtualVehicleHeight,
VehicleObjectId, VehicleObjectName, DetectionItems, DetectAllObjects,
ClashDetectiveTestName, CollisionCount, ObjectRotationCorrection
FROM BatchQueueItems
WHERE Id = @Id";
cmd.Parameters.AddWithValue("@Id", itemId);
using (var reader = cmd.ExecuteReader())
{
if (reader.Read())
{
return new BatchQueueItem
{
Id = Convert.ToInt32(reader["Id"]),
PathRouteId = reader["PathRouteId"].ToString(),
PathRouteName = reader["PathRouteName"].ToString(),
Status = (BatchQueueStatus)Enum.Parse(typeof(BatchQueueStatus), reader["Status"].ToString()),
CreatedTime = DateTime.Parse(reader["CreatedTime"].ToString()),
StartTime = reader["StartTime"].ToString() != "" ? (DateTime?)DateTime.Parse(reader["StartTime"].ToString()) : null,
EndTime = reader["EndTime"].ToString() != "" ? (DateTime?)DateTime.Parse(reader["EndTime"].ToString()) : null,
ErrorMessage = reader["ErrorMessage"].ToString(),
FrameRate = Convert.ToInt32(reader["FrameRate"]),
DurationSeconds = Convert.ToDouble(reader["DurationSeconds"]),
DetectionToleranceMeters = Convert.ToDouble(reader["DetectionToleranceMeters"]),
IsVirtualVehicle = Convert.ToBoolean(reader["IsVirtualVehicle"]),
VirtualVehicleLength = Convert.ToDouble(reader["VirtualVehicleLength"]),
VirtualVehicleWidth = Convert.ToDouble(reader["VirtualVehicleWidth"]),
VirtualVehicleHeight = Convert.ToDouble(reader["VirtualVehicleHeight"]),
VehicleObjectId = reader["VehicleObjectId"].ToString(),
VehicleObjectName = reader["VehicleObjectName"].ToString(),
DetectionItems = reader["DetectionItems"].ToString() != "" ? reader["DetectionItems"].ToString().Split(',').ToList() : new List<string>(),
DetectAllObjects = Convert.ToBoolean(reader["DetectAllObjects"]),
ClashDetectiveTestName = reader["ClashDetectiveTestName"].ToString(),
CollisionCount = !Convert.IsDBNull(reader["CollisionCount"]) ? (int?)Convert.ToInt32(reader["CollisionCount"]) : null,
ObjectRotationCorrection = Convert.ToDouble(reader["ObjectRotationCorrection"])
};
}
}
}
return null;
});
}
/// <summary>
/// 更新批处理队列项
/// </summary>

View File

@ -0,0 +1,53 @@
using System;
using System.Globalization;
using System.Windows.Data;
namespace NavisworksTransport.UI.WPF.Converters
{
/// <summary>
/// 空值转短横线转换器
/// </summary>
public class NullToDashConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// 如果值为null或空字符串返回"-"
if (value == null || string.IsNullOrEmpty(value.ToString()))
{
return "-";
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
/// <summary>
/// 布尔值转"*"/""转换器
/// </summary>
public class BooleanToYesNoConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool boolValue)
{
// DetectAllObjects = true 表示检测所有物体(自动),不显示*
// DetectAllObjects = false 表示手工指定了检测对象,显示*
return !boolValue ? "*" : "";
}
return "";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string strValue)
{
return strValue != "*";
}
return true;
}
}
}

View File

@ -3492,7 +3492,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
DetectAllObjects = !IsManualCollisionTargetEnabled,
DetectionItems = IsManualCollisionTargetEnabled
? GetValidManualCollisionTargets(pruneInvalidEntries: true).Select(t => t.ToString()).ToList()
: new List<string>()
: new List<string>(),
// 角度修正配置
ObjectRotationCorrection = _objectRotationCorrection
};
// 调用批处理管理器添加到队列
@ -3507,10 +3510,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
var itemId = await batchQueueManager.AddQueueItemAsync(queueItem);
LogManager.Info($"[批处理] 已创建队列项: {queueItem.PathRouteName}, " +
$"虚拟车辆: {queueItem.IsVirtualVehicle}, " +
$"帧率: {queueItem.FrameRate}, " +
$"时长: {queueItem.DurationSeconds:F2}秒, " +
$"ID: {itemId}");
$"虚拟车辆: {queueItem.IsVirtualVehicle}, " +
$"帧率: {queueItem.FrameRate}, " +
$"时长: {queueItem.DurationSeconds:F2}秒, " +
$"角度修正: {queueItem.ObjectRotationCorrection:F1}°, " +
$"ID: {itemId}");
UpdateMainStatus($"已添加到批处理队列: {queueItem.PathRouteName}");
}

View File

@ -28,6 +28,8 @@ NavisworksTransport 批处理队列管理页签视图 - 采用与其他页签一
<!-- 转换器资源 -->
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
<converters:BatchQueueStatusConverter x:Key="BatchQueueStatusConverter"/>
<converters:NullToDashConverter x:Key="NullToDashConverter"/>
<converters:BooleanToYesNoConverter x:Key="BooleanToYesNoConverter"/>
<!-- 批处理队列管理页面特有的样式 -->
<Style x:Key="InfoTextStyle" TargetType="Label">
@ -121,6 +123,9 @@ NavisworksTransport 批处理队列管理页签视图 - 采用与其他页签一
Height="300">
<DataGrid.Columns>
<DataGridTextColumn Header="路径名称" Binding="{Binding PathRouteName}" Width="*"/>
<DataGridTextColumn Header="物流对象" Binding="{Binding VehicleObjectName, Converter={StaticResource NullToDashConverter}}" Width="120"/>
<DataGridTextColumn Header="调整角度" Binding="{Binding ObjectRotationCorrection, StringFormat={}{0:F1}°}" Width="80"/>
<DataGridTextColumn Header="手工指定" Binding="{Binding DetectAllObjects, Converter={StaticResource BooleanToYesNoConverter}}" Width="80"/>
<DataGridTextColumn Header="状态" Binding="{Binding Status, Converter={StaticResource BatchQueueStatusConverter}}" Width="80"/>
<DataGridTextColumn Header="碰撞数" Binding="{Binding CollisionCount, StringFormat=\{0\}}" Width="60"/>
<DataGridTextColumn Header="创建时间" Binding="{Binding CreatedTime, StringFormat=yyyy-MM-dd HH:mm}" Width="120"/>