实现路径坐标点手动编辑功能
This commit is contained in:
parent
0c1de9b45d
commit
f3a07eb482
@ -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>
|
||||
|
||||
@ -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]
|
||||
|
||||
|
||||
@ -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 自动路径规划辅助方法
|
||||
|
||||
@ -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
105
src/UI/WPF/Views/EditCoordinatesWindow.xaml
Normal file
105
src/UI/WPF/Views/EditCoordinatesWindow.xaml
Normal 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>
|
||||
42
src/UI/WPF/Views/EditCoordinatesWindow.xaml.cs
Normal file
42
src/UI/WPF/Views/EditCoordinatesWindow.xaml.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user