#初步的cnc编辑功能,实现插入参考点的流程
This commit is contained in:
@@ -46,7 +46,8 @@ namespace XplorePlane.Models
|
||||
/// <summary>参考点节点 | Reference point node</summary>
|
||||
public record ReferencePointNode(
|
||||
Guid Id, int Index, string Name,
|
||||
double XM, double YM, double ZT, double ZD, double TiltD, double Dist
|
||||
double XM, double YM, double ZT, double ZD, double TiltD, double Dist,
|
||||
bool IsRayOn, double Voltage, double Current
|
||||
) : CncNode(Id, Index, CncNodeType.ReferencePoint, Name);
|
||||
|
||||
/// <summary>保存节点(含图像)| Save node with image</summary>
|
||||
@@ -113,4 +114,4 @@ namespace XplorePlane.Models
|
||||
DateTime UpdatedAt,
|
||||
IReadOnlyList<CncNode> Nodes
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using XP.Common.Logging.Interfaces;
|
||||
using XP.Hardware.RaySource.Services;
|
||||
using XplorePlane.Models;
|
||||
using XplorePlane.Services.AppState;
|
||||
|
||||
@@ -20,6 +21,7 @@ namespace XplorePlane.Services.Cnc
|
||||
public class CncProgramService : ICncProgramService
|
||||
{
|
||||
private readonly IAppStateService _appStateService;
|
||||
private readonly IRaySourceService _raySourceService;
|
||||
private readonly ILoggerService _logger;
|
||||
|
||||
// ── 序列化配置 | Serialization options ──
|
||||
@@ -32,12 +34,15 @@ namespace XplorePlane.Services.Cnc
|
||||
|
||||
public CncProgramService(
|
||||
IAppStateService appStateService,
|
||||
IRaySourceService raySourceService,
|
||||
ILoggerService logger)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(appStateService);
|
||||
ArgumentNullException.ThrowIfNull(raySourceService);
|
||||
ArgumentNullException.ThrowIfNull(logger);
|
||||
|
||||
_appStateService = appStateService;
|
||||
_raySourceService = raySourceService;
|
||||
_logger = logger.ForModule<CncProgramService>();
|
||||
|
||||
_logger.Info("CncProgramService 已初始化 | CncProgramService initialized");
|
||||
@@ -344,6 +349,7 @@ namespace XplorePlane.Services.Cnc
|
||||
private ReferencePointNode CreateReferencePointNode(Guid id, int index)
|
||||
{
|
||||
var motion = _appStateService.MotionState;
|
||||
var raySource = _appStateService.RaySourceState;
|
||||
return new ReferencePointNode(
|
||||
id, index, $"参考点_{index}",
|
||||
XM: motion.XM,
|
||||
@@ -351,7 +357,10 @@ namespace XplorePlane.Services.Cnc
|
||||
ZT: motion.ZT,
|
||||
ZD: motion.ZD,
|
||||
TiltD: motion.TiltD,
|
||||
Dist: motion.Dist);
|
||||
Dist: motion.Dist,
|
||||
IsRayOn: raySource.IsOn,
|
||||
Voltage: raySource.Voltage,
|
||||
Current: TryReadCurrent());
|
||||
}
|
||||
|
||||
/// <summary>创建保存节点(含图像)| Create save node with image</summary>
|
||||
@@ -382,5 +391,24 @@ namespace XplorePlane.Services.Cnc
|
||||
id, index, $"保存位置_{index}",
|
||||
MotionState: _appStateService.MotionState);
|
||||
}
|
||||
private double TryReadCurrent()
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = _raySourceService.ReadCurrent();
|
||||
if (result?.Success == true)
|
||||
{
|
||||
return result.GetFloat();
|
||||
}
|
||||
|
||||
_logger.Warn("Failed to read ray source current, ReferencePoint node will use 0");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Warn("Failed to read ray source current: {Message}", ex.Message);
|
||||
}
|
||||
|
||||
return 0d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ namespace XplorePlane.ViewModels.Cnc
|
||||
if (_currentProgram == null)
|
||||
{
|
||||
_logger.Warn("无法插入节点:当前无程序 | Cannot insert node: no current program");
|
||||
return;
|
||||
ExecuteNewProgram();
|
||||
}
|
||||
|
||||
try
|
||||
@@ -365,7 +365,7 @@ namespace XplorePlane.ViewModels.Cnc
|
||||
|
||||
var sb = new StringBuilder();
|
||||
// CSV 表头 | CSV header
|
||||
sb.AppendLine("Index,NodeType,Name,XM,YM,ZT,ZD,TiltD,Dist,Voltage_kV,Power_W,RayOn,DetectorConnected,FrameRate,Resolution,ImageFile,MarkerType,MarkerX,MarkerY,DialogTitle,DialogMessage,DelayMs,Pipeline");
|
||||
sb.AppendLine("Index,NodeType,Name,XM,YM,ZT,ZD,TiltD,Dist,Voltage_kV,Current_uA,Power_W,RayOn,DetectorConnected,FrameRate,Resolution,ImageFile,MarkerType,MarkerX,MarkerY,DialogTitle,DialogMessage,DelayMs,Pipeline");
|
||||
|
||||
var inv = CultureInfo.InvariantCulture;
|
||||
|
||||
@@ -373,11 +373,11 @@ namespace XplorePlane.ViewModels.Cnc
|
||||
{
|
||||
var row = node switch
|
||||
{
|
||||
ReferencePointNode rp => $"{rp.Index},{rp.NodeType},{Esc(rp.Name)},{rp.XM.ToString(inv)},{rp.YM.ToString(inv)},{rp.ZT.ToString(inv)},{rp.ZD.ToString(inv)},{rp.TiltD.ToString(inv)},{rp.Dist.ToString(inv)},,,,,,,,,,,,,,",
|
||||
ReferencePointNode rp => $"{rp.Index},{rp.NodeType},{Esc(rp.Name)},{rp.XM.ToString(inv)},{rp.YM.ToString(inv)},{rp.ZT.ToString(inv)},{rp.ZD.ToString(inv)},{rp.TiltD.ToString(inv)},{rp.Dist.ToString(inv)},{rp.Voltage.ToString(inv)},{rp.Current.ToString(inv)},,{rp.IsRayOn},,,,,,,,,,",
|
||||
|
||||
SaveNodeWithImageNode sni => $"{sni.Index},{sni.NodeType},{Esc(sni.Name)},{sni.MotionState.XM.ToString(inv)},{sni.MotionState.YM.ToString(inv)},{sni.MotionState.ZT.ToString(inv)},{sni.MotionState.ZD.ToString(inv)},{sni.MotionState.TiltD.ToString(inv)},{sni.MotionState.Dist.ToString(inv)},{sni.RaySourceState.Voltage.ToString(inv)},{sni.RaySourceState.Power.ToString(inv)},{sni.RaySourceState.IsOn},{sni.DetectorState.IsConnected},{sni.DetectorState.FrameRate.ToString(inv)},{Esc(sni.DetectorState.Resolution)},{Esc(sni.ImageFileName)},,,,,,",
|
||||
SaveNodeWithImageNode sni => $"{sni.Index},{sni.NodeType},{Esc(sni.Name)},{sni.MotionState.XM.ToString(inv)},{sni.MotionState.YM.ToString(inv)},{sni.MotionState.ZT.ToString(inv)},{sni.MotionState.ZD.ToString(inv)},{sni.MotionState.TiltD.ToString(inv)},{sni.MotionState.Dist.ToString(inv)},{sni.RaySourceState.Voltage.ToString(inv)},,{sni.RaySourceState.Power.ToString(inv)},{sni.RaySourceState.IsOn},{sni.DetectorState.IsConnected},{sni.DetectorState.FrameRate.ToString(inv)},{Esc(sni.DetectorState.Resolution)},{Esc(sni.ImageFileName)},,,,,,",
|
||||
|
||||
SaveNodeNode sn => $"{sn.Index},{sn.NodeType},{Esc(sn.Name)},{sn.MotionState.XM.ToString(inv)},{sn.MotionState.YM.ToString(inv)},{sn.MotionState.ZT.ToString(inv)},{sn.MotionState.ZD.ToString(inv)},{sn.MotionState.TiltD.ToString(inv)},{sn.MotionState.Dist.ToString(inv)},{sn.RaySourceState.Voltage.ToString(inv)},{sn.RaySourceState.Power.ToString(inv)},{sn.RaySourceState.IsOn},{sn.DetectorState.IsConnected},{sn.DetectorState.FrameRate.ToString(inv)},{Esc(sn.DetectorState.Resolution)},,,,,,,",
|
||||
SaveNodeNode sn => $"{sn.Index},{sn.NodeType},{Esc(sn.Name)},{sn.MotionState.XM.ToString(inv)},{sn.MotionState.YM.ToString(inv)},{sn.MotionState.ZT.ToString(inv)},{sn.MotionState.ZD.ToString(inv)},{sn.MotionState.TiltD.ToString(inv)},{sn.MotionState.Dist.ToString(inv)},{sn.RaySourceState.Voltage.ToString(inv)},,{sn.RaySourceState.Power.ToString(inv)},{sn.RaySourceState.IsOn},{sn.DetectorState.IsConnected},{sn.DetectorState.FrameRate.ToString(inv)},{Esc(sn.DetectorState.Resolution)},,,,,,,",
|
||||
|
||||
SavePositionNode sp => $"{sp.Index},{sp.NodeType},{Esc(sp.Name)},{sp.MotionState.XM.ToString(inv)},{sp.MotionState.YM.ToString(inv)},{sp.MotionState.ZT.ToString(inv)},{sp.MotionState.ZD.ToString(inv)},{sp.MotionState.TiltD.ToString(inv)},{sp.MotionState.Dist.ToString(inv)},,,,,,,,,,,,,,",
|
||||
|
||||
@@ -466,4 +466,4 @@ namespace XplorePlane.ViewModels.Cnc
|
||||
.Publish(new CncProgramChangedPayload(ProgramName ?? string.Empty, IsModified));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Imaging;
|
||||
using XplorePlane.Events;
|
||||
using XplorePlane.ViewModels.Cnc;
|
||||
using XplorePlane.Views;
|
||||
using XplorePlane.Views.Cnc;
|
||||
using XP.Common.Logging.Interfaces;
|
||||
@@ -23,6 +24,8 @@ namespace XplorePlane.ViewModels
|
||||
private readonly ILoggerService _logger;
|
||||
private readonly IContainerProvider _containerProvider;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly CncEditorViewModel _cncEditorViewModel;
|
||||
private readonly CncPageView _cncPageView;
|
||||
private string _licenseInfo = "当前时间";
|
||||
|
||||
public string LicenseInfo
|
||||
@@ -51,6 +54,17 @@ namespace XplorePlane.ViewModels
|
||||
public DelegateCommand OpenLibraryVersionsCommand { get; }
|
||||
public DelegateCommand OpenUserManualCommand { get; }
|
||||
public DelegateCommand OpenCameraSettingsCommand { get; }
|
||||
public DelegateCommand NewCncProgramCommand { get; }
|
||||
public DelegateCommand SaveCncProgramCommand { get; }
|
||||
public DelegateCommand LoadCncProgramCommand { get; }
|
||||
public DelegateCommand InsertReferencePointCommand { get; }
|
||||
public DelegateCommand InsertSavePositionCommand { get; }
|
||||
public DelegateCommand InsertCompleteProgramCommand { get; }
|
||||
public DelegateCommand InsertInspectionMarkerCommand { get; }
|
||||
public DelegateCommand InsertInspectionModuleCommand { get; }
|
||||
public DelegateCommand InsertSaveNodeCommand { get; }
|
||||
public DelegateCommand InsertPauseDialogCommand { get; }
|
||||
public DelegateCommand InsertWaitDelayCommand { get; }
|
||||
|
||||
// 硬件命令
|
||||
public DelegateCommand AxisResetCommand { get; }
|
||||
@@ -94,6 +108,8 @@ namespace XplorePlane.ViewModels
|
||||
_logger = logger?.ForModule<MainViewModel>() ?? throw new ArgumentNullException(nameof(logger));
|
||||
_containerProvider = containerProvider ?? throw new ArgumentNullException(nameof(containerProvider));
|
||||
_eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator));
|
||||
_cncEditorViewModel = _containerProvider.Resolve<CncEditorViewModel>();
|
||||
_cncPageView = new CncPageView { DataContext = _cncEditorViewModel };
|
||||
|
||||
NavigationTree = new ObservableCollection<object>();
|
||||
|
||||
@@ -115,6 +131,17 @@ namespace XplorePlane.ViewModels
|
||||
OpenLibraryVersionsCommand = new DelegateCommand(() => ShowWindow(new Views.LibraryVersionsWindow(), "关于"));
|
||||
OpenUserManualCommand = new DelegateCommand(ExecuteOpenUserManual);
|
||||
OpenCameraSettingsCommand = new DelegateCommand(ExecuteOpenCameraSettings);
|
||||
NewCncProgramCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.NewProgramCommand.Execute()));
|
||||
SaveCncProgramCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.SaveProgramCommand.Execute()));
|
||||
LoadCncProgramCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.LoadProgramCommand.Execute()));
|
||||
InsertReferencePointCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertReferencePointCommand.Execute()));
|
||||
InsertSavePositionCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertSavePositionCommand.Execute()));
|
||||
InsertCompleteProgramCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertCompleteProgramCommand.Execute()));
|
||||
InsertInspectionMarkerCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertInspectionMarkerCommand.Execute()));
|
||||
InsertInspectionModuleCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertInspectionModuleCommand.Execute()));
|
||||
InsertSaveNodeCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertSaveNodeCommand.Execute()));
|
||||
InsertPauseDialogCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertPauseDialogCommand.Execute()));
|
||||
InsertWaitDelayCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertWaitDelayCommand.Execute()));
|
||||
|
||||
// 硬件命令
|
||||
AxisResetCommand = new DelegateCommand(ExecuteAxisReset);
|
||||
@@ -186,7 +213,20 @@ namespace XplorePlane.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
ImagePanelContent = new CncPageView();
|
||||
ShowCncEditor();
|
||||
}
|
||||
|
||||
private void ExecuteCncEditorAction(Action<CncEditorViewModel> action)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(action);
|
||||
|
||||
ShowCncEditor();
|
||||
action(_cncEditorViewModel);
|
||||
}
|
||||
|
||||
private void ShowCncEditor()
|
||||
{
|
||||
ImagePanelContent = _cncPageView;
|
||||
ImagePanelWidth = new GridLength(430);
|
||||
_isCncEditorMode = true;
|
||||
_logger.Info("CNC 编辑器已切换到主界面图像区域");
|
||||
|
||||
@@ -53,7 +53,8 @@
|
||||
<ColumnDefinition Width="*" MinWidth="260" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<ListBox
|
||||
<!--树行节点显示-->
|
||||
<ListBox
|
||||
x:Name="CncNodeListBox"
|
||||
Grid.Column="0"
|
||||
Background="Transparent"
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
<StackPanel>
|
||||
<telerik:RadRibbonButton
|
||||
telerik:ScreenTip.Title="新建CNC"
|
||||
Command="{Binding Path=SetStyle.Command}"
|
||||
Command="{Binding NewCncProgramCommand}"
|
||||
Size="Medium"
|
||||
SmallImage="/Assets/Icons/new-doc.png"
|
||||
Text="新建CNC" />
|
||||
@@ -82,11 +82,12 @@
|
||||
telerik:ScreenTip.Description="保存当前X射线实时图像"
|
||||
telerik:ScreenTip.Title="保存图像"
|
||||
Size="Medium"
|
||||
Command="{Binding SaveCncProgramCommand}"
|
||||
SmallImage="/Assets/Icons/save.png"
|
||||
Text="保存" />
|
||||
<telerik:RadRibbonButton
|
||||
telerik:ScreenTip.Title="另存为"
|
||||
Command="{Binding OpenFileCommand}"
|
||||
Command="{Binding SaveCncProgramCommand}"
|
||||
Size="Medium"
|
||||
SmallImage="/Assets/Icons/saveas.png"
|
||||
Text="另存为" />
|
||||
@@ -94,7 +95,7 @@
|
||||
<StackPanel>
|
||||
<telerik:RadRibbonButton
|
||||
telerik:ScreenTip.Title="加载CNC"
|
||||
Command="{Binding OpenFileCommand}"
|
||||
Command="{Binding LoadCncProgramCommand}"
|
||||
Size="Large"
|
||||
SmallImage="/Assets/Icons/open.png"
|
||||
Text="加载CNC" />
|
||||
@@ -293,16 +294,19 @@
|
||||
<telerik:RadRibbonButton
|
||||
telerik:ScreenTip.Title="参考点"
|
||||
Size="Medium"
|
||||
Command="{Binding InsertReferencePointCommand}"
|
||||
SmallImage="/Assets/Icons/reference.png"
|
||||
Text="参考点" />
|
||||
<telerik:RadRibbonButton
|
||||
telerik:ScreenTip.Title="添加位置"
|
||||
Size="Medium"
|
||||
Command="{Binding InsertSavePositionCommand}"
|
||||
SmallImage="/Assets/Icons/add-pos.png"
|
||||
Text="添加位置" />
|
||||
<telerik:RadRibbonButton
|
||||
telerik:ScreenTip.Title="完成"
|
||||
Size="Medium"
|
||||
Command="{Binding InsertCompleteProgramCommand}"
|
||||
SmallImage="/Assets/Icons/finish.png"
|
||||
Text="完成" />
|
||||
</StackPanel>
|
||||
@@ -310,16 +314,19 @@
|
||||
<telerik:RadRibbonButton
|
||||
telerik:ScreenTip.Title="标记"
|
||||
Size="Medium"
|
||||
Command="{Binding InsertInspectionMarkerCommand}"
|
||||
SmallImage="/Assets/Icons/mark.png"
|
||||
Text="标记" />
|
||||
<telerik:RadRibbonButton
|
||||
telerik:ScreenTip.Title="模块"
|
||||
Size="Medium"
|
||||
Command="{Binding InsertInspectionModuleCommand}"
|
||||
SmallImage="/Assets/Icons/Module.png"
|
||||
Text="检测模块" />
|
||||
<telerik:RadRibbonButton
|
||||
telerik:ScreenTip.Title="全部保存"
|
||||
Size="Medium"
|
||||
Command="{Binding SaveCncProgramCommand}"
|
||||
SmallImage="/Assets/Icons/saveall.png"
|
||||
Text="全部保存" />
|
||||
</StackPanel>
|
||||
@@ -327,11 +334,13 @@
|
||||
<telerik:RadRibbonButton
|
||||
telerik:ScreenTip.Title="消息"
|
||||
Size="Medium"
|
||||
Command="{Binding InsertPauseDialogCommand}"
|
||||
SmallImage="/Assets/Icons/message.png"
|
||||
Text="消息弹窗" />
|
||||
<telerik:RadRibbonButton
|
||||
telerik:ScreenTip.Title="等待"
|
||||
Size="Medium"
|
||||
Command="{Binding InsertWaitDelayCommand}"
|
||||
SmallImage="/Assets/Icons/wait.png"
|
||||
Text="插入等待" />
|
||||
</StackPanel>
|
||||
|
||||
Reference in New Issue
Block a user