diff --git a/XplorePlane/App.xaml.cs b/XplorePlane/App.xaml.cs index bd10aa4..26cb81b 100644 --- a/XplorePlane/App.xaml.cs +++ b/XplorePlane/App.xaml.cs @@ -265,23 +265,23 @@ namespace XplorePlane // 主窗口加载完成后再连接相机,确保所有模块和原生 DLL 已完成初始化 shell.Loaded += (s, e) => { - TryConnectCamera(); + //TryConnectCamera(); - // 通知 ViewModel 相机状态已确定,启动实时预览或显示错误 - try - { - var cameraVm = Container.Resolve(); - cameraVm.OnCameraReady(); - } - catch (Exception ex) - { - Log.Error(ex, "通知相机 ViewModel 失败"); - } + //// 通知 ViewModel 相机状态已确定,启动实时预览或显示错误 + // try + // { + // var cameraVm = Container.Resolve(); + // cameraVm.OnCameraReady(); + // } + // catch (Exception ex) + // { + // Log.Error(ex, "通知相机 ViewModel 失败"); + // } - if (_cameraError != null) - { - HexMessageBox.Show(_cameraError, MessageBoxButton.OK, MessageBoxImage.Error); - } + // if (_cameraError != null) + // { + // HexMessageBox.Show(_cameraError, MessageBoxButton.OK, MessageBoxImage.Error); + //} }; return shell; diff --git a/XplorePlane/Events/MeasurementToolEvent.cs b/XplorePlane/Events/MeasurementToolEvent.cs new file mode 100644 index 0000000..329af92 --- /dev/null +++ b/XplorePlane/Events/MeasurementToolEvent.cs @@ -0,0 +1,21 @@ +using Prism.Events; + +namespace XplorePlane.Events +{ + /// + /// 测量工具模式 + /// + public enum MeasurementToolMode + { + None, + PointDistance, + PointLineDistance, + Angle, + ThroughHoleFillRate + } + + /// + /// 测量工具激活事件,由 MainViewModel 发布,ViewportPanelViewModel 订阅 + /// + public class MeasurementToolEvent : PubSubEvent { } +} diff --git a/XplorePlane/ViewModels/Main/MainViewModel.cs b/XplorePlane/ViewModels/Main/MainViewModel.cs index 1809723..e28dcbf 100644 --- a/XplorePlane/ViewModels/Main/MainViewModel.cs +++ b/XplorePlane/ViewModels/Main/MainViewModel.cs @@ -75,6 +75,12 @@ namespace XplorePlane.ViewModels public DelegateCommand OpenRaySourceConfigCommand { get; } public DelegateCommand WarmUpCommand { get; } + // 测量命令 + public DelegateCommand PointDistanceMeasureCommand { get; } + public DelegateCommand PointLineDistanceMeasureCommand { get; } + public DelegateCommand AngleMeasureCommand { get; } + public DelegateCommand ThroughHoleFillRateMeasureCommand { get; } + // 设置命令 public DelegateCommand OpenLanguageSwitcherCommand { get; } public DelegateCommand OpenRealTimeLogViewerCommand { get; } @@ -152,6 +158,12 @@ namespace XplorePlane.ViewModels InsertPauseDialogCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertPauseDialogCommand.Execute())); InsertWaitDelayCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertWaitDelayCommand.Execute())); + // 测量命令 + PointDistanceMeasureCommand = new DelegateCommand(ExecutePointDistanceMeasure); + PointLineDistanceMeasureCommand = new DelegateCommand(ExecutePointLineDistanceMeasure); + AngleMeasureCommand = new DelegateCommand(ExecuteAngleMeasure); + ThroughHoleFillRateMeasureCommand = new DelegateCommand(ExecuteThroughHoleFillRateMeasure); + // 硬件命令 AxisResetCommand = new DelegateCommand(ExecuteAxisReset); OpenDetectorConfigCommand = new DelegateCommand(ExecuteOpenDetectorConfig); @@ -419,6 +431,34 @@ namespace XplorePlane.ViewModels #endregion + #region 测量命令实现 + + private void ExecutePointDistanceMeasure() + { + _logger.Info("点点距测量功能已触发"); + _eventAggregator.GetEvent().Publish(MeasurementToolMode.PointDistance); + } + + private void ExecutePointLineDistanceMeasure() + { + _logger.Info("点线距测量功能已触发"); + // TODO: 实现点线距测量逻辑 + } + + private void ExecuteAngleMeasure() + { + _logger.Info("角度测量功能已触发"); + // TODO: 实现角度测量逻辑 + } + + private void ExecuteThroughHoleFillRateMeasure() + { + _logger.Info("通孔填锡率测量功能已触发"); + // TODO: 实现通孔填锡率测量逻辑 + } + + #endregion + #region 设置命令实现 private void ExecuteOpenLanguageSwitcher() diff --git a/XplorePlane/ViewModels/Main/ViewportPanelViewModel.cs b/XplorePlane/ViewModels/Main/ViewportPanelViewModel.cs index 599b638..899db50 100644 --- a/XplorePlane/ViewModels/Main/ViewportPanelViewModel.cs +++ b/XplorePlane/ViewModels/Main/ViewportPanelViewModel.cs @@ -1,3 +1,4 @@ +using Prism.Commands; using Prism.Events; using Prism.Mvvm; using System; @@ -34,16 +35,131 @@ namespace XplorePlane.ViewModels set => SetProperty(ref _imageInfo, value); } + #region 测量工具状态 + + private MeasurementToolMode _currentMeasurementMode = MeasurementToolMode.None; + public MeasurementToolMode CurrentMeasurementMode + { + get => _currentMeasurementMode; + set + { + if (SetProperty(ref _currentMeasurementMode, value)) + { + RaisePropertyChanged(nameof(IsMeasuring)); + RaisePropertyChanged(nameof(MeasurementModeText)); + // 切换模式时重置状态 + ResetMeasurementState(); + } + } + } + + public bool IsMeasuring => CurrentMeasurementMode != MeasurementToolMode.None; + + public string MeasurementModeText => CurrentMeasurementMode switch + { + MeasurementToolMode.PointDistance => "点点距测量 - 请在图像上点击第一个点", + _ => string.Empty + }; + + // 测量点坐标(图像像素坐标) + private Point? _measurePoint1; + public Point? MeasurePoint1 + { + get => _measurePoint1; + set => SetProperty(ref _measurePoint1, value); + } + + private Point? _measurePoint2; + public Point? MeasurePoint2 + { + get => _measurePoint2; + set => SetProperty(ref _measurePoint2, value); + } + + private string _measurementResult; + public string MeasurementResult + { + get => _measurementResult; + set => SetProperty(ref _measurementResult, value); + } + + /// + /// 由 View 层调用:用户在画布上点击了一个点(像素坐标) + /// + public void OnMeasurementPointClicked(Point imagePoint) + { + if (CurrentMeasurementMode == MeasurementToolMode.PointDistance) + { + if (MeasurePoint1 == null) + { + MeasurePoint1 = imagePoint; + ImageInfo = $"点点距测量 - 第一点: ({imagePoint.X:F0}, {imagePoint.Y:F0}),请点击第二个点"; + _logger?.Info("测量第一点: ({X}, {Y})", imagePoint.X, imagePoint.Y); + } + else + { + MeasurePoint2 = imagePoint; + CalculatePointDistance(); + } + } + } + + private void CalculatePointDistance() + { + if (MeasurePoint1 == null || MeasurePoint2 == null) return; + + var p1 = MeasurePoint1.Value; + var p2 = MeasurePoint2.Value; + double dx = p2.X - p1.X; + double dy = p2.Y - p1.Y; + double distance = Math.Sqrt(dx * dx + dy * dy); + double angle = Math.Atan2(dy, dx) * 180.0 / Math.PI; + + MeasurementResult = $"{distance:F2} px"; + ImageInfo = $"点点距: {distance:F2} px | 角度: {angle:F2}° | ({p1.X:F0},{p1.Y:F0}) → ({p2.X:F0},{p2.Y:F0})"; + _logger?.Info("点点距测量完成: {Distance:F2} px, 角度: {Angle:F2}°", distance, angle); + } + + /// + /// 取消/重置当前测量 + /// + public DelegateCommand CancelMeasurementCommand { get; private set; } + + public void ResetMeasurementState() + { + MeasurePoint1 = null; + MeasurePoint2 = null; + MeasurementResult = null; + } + + #endregion + public ViewportPanelViewModel(IEventAggregator eventAggregator, ILoggerService logger) { _logger = logger?.ForModule(); + CancelMeasurementCommand = new DelegateCommand(() => + { + CurrentMeasurementMode = MeasurementToolMode.None; + ImageInfo = "测量已取消"; + }); + eventAggregator.GetEvent() .Subscribe(OnImageCaptured, ThreadOption.BackgroundThread); eventAggregator.GetEvent() .Subscribe(OnManualImageLoaded, ThreadOption.UIThread); eventAggregator.GetEvent() .Subscribe(OnPipelinePreviewUpdated, ThreadOption.UIThread); + + // 订阅测量工具事件 + eventAggregator.GetEvent() + .Subscribe(OnMeasurementToolActivated, ThreadOption.UIThread); + } + + private void OnMeasurementToolActivated(MeasurementToolMode mode) + { + CurrentMeasurementMode = mode; + _logger?.Info("测量工具模式切换: {Mode}", mode); } private void OnImageCaptured(ImageCapturedEventArgs args) diff --git a/XplorePlane/Views/Main/MainWindow.xaml b/XplorePlane/Views/Main/MainWindow.xaml index 33b6ec6..223e1fd 100644 --- a/XplorePlane/Views/Main/MainWindow.xaml +++ b/XplorePlane/Views/Main/MainWindow.xaml @@ -400,6 +400,48 @@ Size="Large" SmallImage="/Assets/Icons/spiral.png" /> + + + + + + + + + + + + + + + + + + - + + + + + +