Refine collision analysis dialog and rail assembly markers

This commit is contained in:
tian 2026-03-26 22:49:45 +08:00
parent 9f1924a797
commit a5d1db6416
4 changed files with 178 additions and 115 deletions

View File

@ -3103,50 +3103,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
var dialog = new CollisionAnalysisDialog(hotspots, totalCollisions);
DialogHelper.SetOwnerSafely(dialog);
var result = dialog.ShowDialog();
if (result == null)
{
// 用户取消
UpdateMainStatus("预计算碰撞分析已取消");
return;
}
if (dialog.ExcludedObjects.Count > 0)
{
// 用户选择了排除某些物体并重新生成
LogManager.Info($"[碰撞分析] 用户选择排除 {dialog.ExcludedObjects.Count} 个物体并重新生成");
// 🔥 添加排除对象到UI列表合并自动去重
AddExcludedObjectsToUIList(dialog.ExcludedObjects);
// 🔥 从UI列表获取所有排除对象包括之前手工添加的设置到Manager并重新生成
var allExcludedObjects = _excludedObjects.Select(e => e.ModelItem).Where(m => m != null).ToList();
_pathAnimationManager.SetExcludedObjectsAndClearCache(allExcludedObjects);
// 触发重新生成(使用 Dispatcher 避免阻塞 UI
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
ExecuteGenerateAnimation();
}), DispatcherPriority.Background);
UpdateMainStatus($"已排除 {allExcludedObjects.Count} 个物体,正在重新生成...");
}
else
{
// 用户选择直接继续(无排除对象)
LogManager.Info("[碰撞分析] 用户选择直接继续生成");
UpdateMainStatus($"预计算碰撞分析完成,共 {totalCollisions} 个候选碰撞");
// 🔥 保存检测记录到数据库(保存测试配置)
var recordId = SaveCollisionDetectionRecord();
if (recordId.HasValue && IsReusedHistoryRecord(recordId.Value))
{
// 用户选择使用历史记录,跳过后续流程
LogManager.Info("[碰撞分析] 用户选择使用历史记录,跳过动画生成");
return;
}
}
dialog.Closed += (_, __) => HandleCollisionAnalysisDialogClosed(dialog, totalCollisions);
dialog.Show();
dialog.Activate();
}
catch (Exception ex)
{
@ -3154,6 +3113,57 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
private void HandleCollisionAnalysisDialogClosed(CollisionAnalysisDialog dialog, int totalCollisions)
{
try
{
if (dialog == null)
{
return;
}
switch (dialog.SelectedAction)
{
case CollisionAnalysisDialog.CollisionAnalysisAction.Regenerate:
LogManager.Info($"[碰撞分析] 用户选择排除 {dialog.ExcludedObjects.Count} 个物体并重新生成");
AddExcludedObjectsToUIList(dialog.ExcludedObjects);
var allExcludedObjects = _excludedObjects.Select(e => e.ModelItem).Where(m => m != null).ToList();
_pathAnimationManager.SetExcludedObjectsAndClearCache(allExcludedObjects);
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
ExecuteGenerateAnimation();
}), DispatcherPriority.Background);
UpdateMainStatus($"已排除 {allExcludedObjects.Count} 个物体,正在重新生成...");
break;
case CollisionAnalysisDialog.CollisionAnalysisAction.Continue:
LogManager.Info("[碰撞分析] 用户选择直接继续生成");
UpdateMainStatus($"预计算碰撞分析完成,共 {totalCollisions} 个候选碰撞");
var recordId = SaveCollisionDetectionRecord();
if (recordId.HasValue && IsReusedHistoryRecord(recordId.Value))
{
LogManager.Info("[碰撞分析] 用户选择使用历史记录,跳过动画生成");
}
break;
case CollisionAnalysisDialog.CollisionAnalysisAction.Cancel:
case CollisionAnalysisDialog.CollisionAnalysisAction.None:
default:
UpdateMainStatus("预计算碰撞分析已取消");
break;
}
}
catch (Exception ex)
{
LogManager.Error($"[碰撞分析] 处理分析窗口结果失败: {ex.Message}", ex);
}
}
/// <summary>
/// 保存检测记录到数据库
/// 在生成动画完成后调用,创建检测记录并保存当时的完整配置

View File

@ -125,7 +125,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private const double DefaultAssemblyReferenceRodLengthInMeters = 20.0;
private static readonly double DefaultAssemblyReferenceRodDiameterInMeters = CalculateDefaultAssemblyReferenceRodDiameterInMeters();
private const double DefaultAssemblyAnchorVerticalOffsetInMeters = 0.0;
private const double AssemblyVisualizationPointDiameterInMeters = 0.10;
private const double AssemblyVisualizationPointDiameterInMeters = 0.05;
private const double RailNormalOffsetNudgeStepInMeters = 0.1;
private const double DefaultAssemblySphereCenterX = 0.0;
private const double DefaultAssemblySphereCenterY = 0.0;
@ -1749,7 +1749,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private void CreateAssemblyLinearRoute(Point3D startPoint)
{
Point3D endPoint = AssemblyReferencePathManager.Instance.ReferenceLineEnd;
string routeName = $"直线装配_{_pathPlanningManager.Routes.Count + 1}";
string routeName = $"人工_{DateTime.Now:MMdd_HHmmss}";
var route = new PathRoute(routeName)
{
@ -1768,7 +1768,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
_assemblyInstallationPlaneNormal.Z);
}
route.AddPoint(new PathPoint(startPoint, "装配起点", PathPointType.StartPoint));
route.AddPoint(new PathPoint(startPoint, "起点", PathPointType.StartPoint));
route.AddPoint(new PathPoint(endPoint, "装配终点", PathPointType.EndPoint));
if (!_pathPlanningManager.AddRoute(route))

View File

@ -8,7 +8,6 @@
Height="720" Width="720"
WindowStartupLocation="CenterOwner"
ResizeMode="CanResize"
Topmost="True"
Background="White">
<Window.Resources>
@ -97,67 +96,89 @@
<!-- 热点列表 -->
<Border Grid.Row="3" BorderBrush="{StaticResource NavisworksLightBrush}"
BorderThickness="1" CornerRadius="3" Margin="0,0,0,12">
<DataGrid x:Name="HotspotsDataGrid"
AutoGenerateColumns="False"
CanUserAddRows="False"
SelectionMode="Single"
GridLinesVisibility="Horizontal"
BorderThickness="0"
HeadersVisibility="Column"
RowBackground="White"
AlternatingRowBackground="{StaticResource NavisworksBackgroundBrush}"
SelectionChanged="HotspotsDataGrid_SelectionChanged">
<DataGrid.Columns>
<DataGridTextColumn Header="序号" Width="45"
Binding="{Binding Index}" IsReadOnly="True">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="FontSize" Value="11"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridCheckBoxColumn Header="排除" Width="50"
Binding="{Binding IsExcluded, Mode=TwoWay}"/>
<DataGridTextColumn Header="物体名称" Width="*"
Binding="{Binding ObjectName}" IsReadOnly="True">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="11"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="碰撞次数" Width="80"
Binding="{Binding CollisionCount}" IsReadOnly="True">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Foreground" Value="Black"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="占比" Width="60"
Binding="{Binding Percentage, StringFormat={}{0:F1}%}" IsReadOnly="True">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="FontSize" Value="11"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="原因分析" Width="200"
Binding="{Binding Reason}" IsReadOnly="True">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="10"/>
<Setter Property="Foreground" Value="{StaticResource NavisworksTextBrush}"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal" Margin="10,10,10,8">
<TextBlock Text="批量选择:" VerticalAlignment="Center" FontSize="11"
Foreground="{StaticResource NavisworksTextBrush}" Margin="0,0,8,0"/>
<Button Content="全选"
Width="70"
Margin="0,0,6,0"
Click="SelectAllButton_Click"
Style="{StaticResource SecondaryButtonStyle}"/>
<Button Content="全取消"
Width="80"
Click="ClearAllButton_Click"
Style="{StaticResource SecondaryButtonStyle}"/>
</StackPanel>
<DataGrid Grid.Row="1"
x:Name="HotspotsDataGrid"
AutoGenerateColumns="False"
CanUserAddRows="False"
SelectionMode="Single"
GridLinesVisibility="Horizontal"
BorderThickness="0"
HeadersVisibility="Column"
RowBackground="White"
AlternatingRowBackground="{StaticResource NavisworksBackgroundBrush}"
SelectionChanged="HotspotsDataGrid_SelectionChanged">
<DataGrid.Columns>
<DataGridTextColumn Header="序号" Width="45"
Binding="{Binding Index}" IsReadOnly="True">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="FontSize" Value="11"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridCheckBoxColumn Header="排除" Width="50"
Binding="{Binding IsExcluded, Mode=TwoWay}"/>
<DataGridTextColumn Header="物体名称" Width="*"
Binding="{Binding ObjectName}" IsReadOnly="True">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="11"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="碰撞次数" Width="80"
Binding="{Binding CollisionCount}" IsReadOnly="True">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Foreground" Value="Black"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="占比" Width="60"
Binding="{Binding Percentage, StringFormat={}{0:F1}%}" IsReadOnly="True">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="FontSize" Value="11"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="原因分析" Width="200"
Binding="{Binding Reason}" IsReadOnly="True">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="10"/>
<Setter Property="Foreground" Value="{StaticResource NavisworksTextBrush}"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Border>
<!-- 选中物体详情 -->

View File

@ -15,8 +15,17 @@ namespace NavisworksTransport.UI.WPF.Views
/// </summary>
public partial class CollisionAnalysisDialog : Window
{
public enum CollisionAnalysisAction
{
None,
Continue,
Regenerate,
Cancel
}
private List<HotspotViewModel> _viewModels;
public List<ModelItem> ExcludedObjects { get; private set; }
public CollisionAnalysisAction SelectedAction { get; private set; } = CollisionAnalysisAction.None;
// 使用项目中定义的预计算碰撞结果高亮类别(紫色 #9C27B0
private const string PrecomputedHighlightCategory = ModelHighlightHelper.PrecomputeCollisionResultsCategory;
@ -122,17 +131,14 @@ namespace NavisworksTransport.UI.WPF.Views
// 清除预计算高亮
ModelHighlightHelper.ClearCategory(PrecomputedHighlightCategory);
// 根据是否有排除对象设置对话框结果
if (ExcludedObjects.Count > 0)
{
// 有排除对象,需要重新生成
DialogResult = true;
SelectedAction = CollisionAnalysisAction.Regenerate;
LogManager.Info($"[碰撞分析] 用户选择排除 {ExcludedObjects.Count} 个物体并重新生成");
}
else
{
// 没有排除对象,直接继续
DialogResult = false;
SelectedAction = CollisionAnalysisAction.Continue;
LogManager.Info("[碰撞分析] 用户选择直接继续生成(无排除对象)");
}
@ -144,10 +150,36 @@ namespace NavisworksTransport.UI.WPF.Views
// 清除预计算高亮
ModelHighlightHelper.ClearCategory(PrecomputedHighlightCategory);
DialogResult = null;
SelectedAction = CollisionAnalysisAction.Cancel;
Close();
}
private void SelectAllButton_Click(object sender, RoutedEventArgs e)
{
if (_viewModels == null)
{
return;
}
foreach (var viewModel in _viewModels)
{
viewModel.IsExcluded = true;
}
}
private void ClearAllButton_Click(object sender, RoutedEventArgs e)
{
if (_viewModels == null)
{
return;
}
foreach (var viewModel in _viewModels)
{
viewModel.IsExcluded = false;
}
}
/// <summary>
/// 视图模型
/// </summary>