实现路径坐标点手动编辑功能

This commit is contained in:
tian 2025-12-30 09:55:36 +08:00
parent 0c1de9b45d
commit f3a07eb482
8 changed files with 484 additions and 227 deletions

View File

@ -226,6 +226,9 @@
<Compile Include="src\UI\WPF\Views\MediaControlBar.xaml.cs">
<DependentUpon>MediaControlBar.xaml</DependentUpon>
</Compile>
<Compile Include="src\UI\WPF\Views\EditCoordinatesWindow.xaml.cs">
<DependentUpon>EditCoordinatesWindow.xaml</DependentUpon>
</Compile>
<!-- UI - WPF ViewModels -->
<Compile Include="src\UI\WPF\ViewModels\ViewModelBase.cs" />
<Compile Include="src\UI\WPF\ViewModels\LogisticsControlViewModel.cs" />
@ -278,6 +281,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="src\UI\WPF\Views\EditCoordinatesWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="src\UI\WPF\Views\ModelSettingsView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

View File

@ -4,14 +4,15 @@
### [2025/12/25]
1. [ ] (功能)对路径上的各点进行坐标编辑
1. [x] (功能)对路径上的各点进行坐标编辑
2. [ ] (功能)记录并查看路径文件操作的历史记录
3. [ ] (功能)自动隐藏或淡化非关键层,以便专注于物流路径相关的层级。
4. [ ] (优化)优化路径时间标签功能
5. [ ] 测试路径规划文件能导入DELMIA
6. [ ] (优化)优化路径规划分析和分析报告
7. [ ] (功能)增加物流属性自定义
8. [x] (BUG) 动画时物流车在起点时应该朝向路径方向,切换虚拟车辆和指定物体时,原有的要归位
8. [x] BUG 动画时物流车在起点时应该朝向路径方向,切换虚拟车辆和指定物体时,原有的要归位
9. [ ] (功能)物流车在路径点转弯时,要对转弯的动作进行仿真,要设置角速率、转弯半径,并进行碰撞检测,意味着路径要变成曲线
### [2025/12/18]

View File

@ -263,7 +263,7 @@ namespace NavisworksTransport
{
var previousRoute = _currentRoute;
_currentRoute = value;
// 只有真正的业务操作才触发事件UI同步不触发事件
RaiseCurrentRouteChanged(previousRoute, value, triggerEvent: true);
}
@ -1101,7 +1101,7 @@ namespace NavisworksTransport
{
SetCurrentRouteInternal(route, triggerEvent: false);
}
/// <summary>
/// 内部设置当前路线(可选择是否触发事件)
/// </summary>
@ -2875,6 +2875,15 @@ namespace NavisworksTransport
return _pathDatabase;
}
/// <summary>
/// 更新路径并保存到数据库
/// </summary>
public void UpdateRoute(PathRoute route)
{
if (route == null) return;
SavePathToDatabase(route);
}
#endregion
#region

View File

@ -35,7 +35,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels
public double X
{
get => _x;
set => SetProperty(ref _x, value);
set
{
if (SetProperty(ref _x, value))
{
OnPropertyChanged(nameof(CoordinateString));
}
}
}
/// <summary>
@ -44,7 +50,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels
public double Y
{
get => _y;
set => SetProperty(ref _y, value);
set
{
if (SetProperty(ref _y, value))
{
OnPropertyChanged(nameof(CoordinateString));
}
}
}
/// <summary>
@ -53,7 +65,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels
public double Z
{
get => _z;
set => SetProperty(ref _z, value);
set
{
if (SetProperty(ref _z, value))
{
OnPropertyChanged(nameof(CoordinateString));
}
}
}
/// <summary>
@ -64,7 +82,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
get => _name;
set => SetProperty(ref _name, value);
}
/// <summary>
/// 点类型
/// </summary>
@ -80,7 +98,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
}
/// <summary>
/// 点类型的显示字符串
/// </summary>
@ -336,20 +354,20 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
// 获取UI状态管理器实例
_uiStateManager = UIStateManager.Instance;
// 验证关键组件
if (_uiStateManager == null)
{
LogManager.Error("UIStateManager初始化失败");
throw new InvalidOperationException("UIStateManager初始化失败");
}
// 初始化默认值
InitializeDefaults();
// 直接完成初始化,不需要异步
CompleteInitialization();
LogManager.Debug($"PathRouteViewModel构造函数完成{_name}");
}
catch (Exception ex)
@ -397,7 +415,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
_totalLength = 0.0;
_isValidated = false;
_validationStatus = "未验证";
// 初始化点集合
Points = new ObservableCollection<PathPointViewModel>();
}
@ -414,11 +432,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
Points.CollectionChanged += OnPointsCollectionChanged;
}
// 设置初始化完成标志
_isInitialized = true;
OnPropertyChanged(nameof(IsInitialized));
LogManager.Debug($"PathRouteViewModel初始化完成{_name}");
}
catch (Exception ex)
@ -447,14 +465,14 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 通知相关属性变更
OnPropertyChanged(nameof(PointCount));
OnPropertyChanged(nameof(SummaryInfo));
// 重新计算路径长度
_ = CalculateTotalLengthAsync();
// 更新最后修改时间
_lastModifiedTime = DateTime.Now;
OnPropertyChanged(nameof(LastModifiedTime));
// 标记为未验证
if (_isValidated)
{
@ -580,16 +598,16 @@ namespace NavisworksTransport.UI.WPF.ViewModels
try
{
// 先在UI线程上创建快照确保线程安全
var pointsSnapshot = await _uiStateManager.ExecuteUIUpdateAsync(() =>
var pointsSnapshot = await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
return Points?.ToList() ?? new List<PathPointViewModel>();
});
// 然后在后台线程计算
return await Task.Run(() =>
{
double totalLength = 0.0;
if (pointsSnapshot.Count < 2)
{
// 在UI线程上更新总长度
@ -599,24 +617,24 @@ namespace NavisworksTransport.UI.WPF.ViewModels
OnPropertyChanged(nameof(TotalLength));
OnPropertyChanged(nameof(SummaryInfo));
});
return 0.0;
}
for (int i = 0; i < pointsSnapshot.Count - 1; i++)
{
var p1 = pointsSnapshot[i];
var p2 = pointsSnapshot[i + 1];
double distance = Math.Sqrt(
Math.Pow(p2.X - p1.X, 2) +
Math.Pow(p2.Y - p1.Y, 2) +
Math.Pow(p2.Z - p1.Z, 2)
);
totalLength += distance;
}
// 在UI线程上更新总长度
_uiStateManager.QueueUIUpdate(() =>
{
@ -624,7 +642,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
OnPropertyChanged(nameof(TotalLength));
OnPropertyChanged(nameof(SummaryInfo));
});
return totalLength;
});
}
@ -644,45 +662,45 @@ namespace NavisworksTransport.UI.WPF.ViewModels
try
{
// 先在UI线程上创建快照确保线程安全
var pointsSnapshot = await _uiStateManager.ExecuteUIUpdateAsync(() =>
var pointsSnapshot = await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
return Points?.ToList() ?? new List<PathPointViewModel>();
});
var nameSnapshot = await _uiStateManager.ExecuteUIUpdateAsync(() => _name);
// 然后在后台线程验证
return await Task.Run(() =>
{
bool isValid = true;
var validationMessages = new List<string>();
// 检查路径点数量
if (pointsSnapshot.Count < 2)
{
isValid = false;
validationMessages.Add("路径至少需要2个点");
}
// 检查路径名称
if (string.IsNullOrWhiteSpace(nameSnapshot))
{
isValid = false;
validationMessages.Add("路径名称不能为空");
}
// 检查重复点
var duplicatePoints = pointsSnapshot
.GroupBy(p => new { p.X, p.Y, p.Z })
.Where(g => g.Count() > 1)
.ToList();
if (duplicatePoints.Any())
{
isValid = false;
validationMessages.Add($"发现{duplicatePoints.Count}组重复坐标的点");
}
// 在UI线程上更新验证状态
_uiStateManager.QueueUIUpdate(() =>
{
@ -691,7 +709,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
OnPropertyChanged(nameof(IsValidated));
OnPropertyChanged(nameof(ValidationStatus));
});
LogManager.Debug($"路径验证完成:{nameSnapshot},结果:{(isValid ? "" : "")}");
return isValid;
});
@ -788,8 +806,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
/// <returns>是否处于有效状态</returns>
public bool IsValidState()
{
return _uiStateManager != null &&
Points != null &&
return _uiStateManager != null &&
Points != null &&
_isInitialized;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,105 @@
<Window x:Class="NavisworksTransport.UI.WPF.Views.EditCoordinatesWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="编辑路径点坐标" Height="320" Width="400"
WindowStartupLocation="CenterScreen"
ResizeMode="NoResize"
ShowInTaskbar="False"
Background="White">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/NavisworksTransportPlugin;component/src/UI/WPF/Resources/NavisworksStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 标题栏 -->
<Border Grid.Row="0" Background="#FFF8FBFF" BorderBrush="#FFD4E7FF" BorderThickness="0,0,0,1" Padding="20,15">
<StackPanel>
<TextBlock Text="编辑路径点坐标" FontWeight="SemiBold" FontSize="14" Foreground="#FF2B579A"/>
<TextBlock Text="修改路径点的三维坐标位置" FontSize="10" Foreground="#FF666666" Margin="0,3,0,0"/>
</StackPanel>
</Border>
<!-- 输入区域 -->
<Border Grid.Row="1" Padding="20,15">
<StackPanel>
<!-- X坐标 -->
<Grid Margin="0,0,0,12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="X 坐标:" VerticalAlignment="Center" FontSize="11" Foreground="#FF333333"/>
<TextBox Grid.Column="1"
Text="{Binding X, StringFormat=0.000, UpdateSourceTrigger=PropertyChanged}"
Height="28"
VerticalContentAlignment="Center"
Padding="8,0"
FontSize="11"
BorderBrush="#FFCCCCCC"
BorderThickness="1"/>
</Grid>
<!-- Y坐标 -->
<Grid Margin="0,0,0,12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Y 坐标:" VerticalAlignment="Center" FontSize="11" Foreground="#FF333333"/>
<TextBox Grid.Column="1"
Text="{Binding Y, StringFormat=0.000, UpdateSourceTrigger=PropertyChanged}"
Height="28"
VerticalContentAlignment="Center"
Padding="8,0"
FontSize="11"
BorderBrush="#FFCCCCCC"
BorderThickness="1"/>
</Grid>
<!-- Z坐标 -->
<Grid Margin="0,0,0,12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Z 坐标:" VerticalAlignment="Center" FontSize="11" Foreground="#FF333333"/>
<TextBox Grid.Column="1"
Text="{Binding Z, StringFormat=0.000, UpdateSourceTrigger=PropertyChanged}"
Height="28"
VerticalContentAlignment="Center"
Padding="8,0"
FontSize="11"
BorderBrush="#FFCCCCCC"
BorderThickness="1"/>
</Grid>
</StackPanel>
</Border>
<!-- 按钮栏 -->
<Border Grid.Row="2" Background="#FFF8FBFF" BorderBrush="#FFD4E7FF" BorderThickness="0,1,0,0" Padding="20,12">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="保存"
Click="OnSaveClick"
Style="{StaticResource ActionButtonStyle}"
Width="90"
Height="32"
Margin="0,0,10,0"/>
<Button Content="取消"
Click="OnCancelClick"
Style="{StaticResource SecondaryButtonStyle}"
Width="90"
Height="32"/>
</StackPanel>
</Border>
</Grid>
</Window>

View File

@ -0,0 +1,42 @@
using System;
using System.Windows;
namespace NavisworksTransport.UI.WPF.Views
{
public partial class EditCoordinatesWindow : Window
{
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
public EditCoordinatesWindow(double x, double y, double z)
{
try
{
InitializeComponent();
X = x;
Y = y;
Z = z;
DataContext = this;
}
catch (Exception ex)
{
LogManager.Error($"编辑坐标对话框初始化失败: {ex.Message}", ex);
MessageBox.Show($"编辑坐标对话框初始化失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void OnSaveClick(object sender, RoutedEventArgs e)
{
DialogResult = true;
Close();
}
private void OnCancelClick(object sender, RoutedEventArgs e)
{
DialogResult = false;
Close();
}
}
}

View File

@ -321,18 +321,35 @@ NavisworksTransport 路径编辑页签视图 - 采用与动画控制和分层管
<GridViewColumn Header="点名称" DisplayMemberBinding="{Binding Name}" Width="80"/>
<GridViewColumn Header="坐标" DisplayMemberBinding="{Binding CoordinateString}" Width="140"/>
<GridViewColumn Header="类型" DisplayMemberBinding="{Binding TypeDisplayString}" Width="60"/>
<GridViewColumn Header="操作" Width="80">
<GridViewColumn Header="操作" Width="120">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Content="删除"
Command="{Binding DataContext.DeletePointCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
CommandParameter="{Binding}"
Style="{StaticResource SecondaryButtonStyle}"
Background="#FFFFE6E6"
Foreground="#FF8B0000"
FontSize="9"
Padding="2"
Margin="0"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Content="坐标编辑"
ToolTip="编辑坐标..."
Command="{Binding DataContext.EditPointCoordinatesCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
CommandParameter="{Binding}"
Padding="2"
FontSize="10"
Width="52"
Height="20"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="0,0,2,0"/>
<Button Content="删除"
ToolTip="删除路径点"
Command="{Binding DataContext.DeletePointCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
CommandParameter="{Binding}"
Background="#FFFFE6E6"
Foreground="#FF8B0000"
Padding="2"
FontSize="10"
Width="44"
Height="20"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="0"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>