修复高级算子的ROI编辑能力
This commit is contained in:
@@ -139,10 +139,8 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
|||||||
control.ResetView();
|
control.ResetView();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 图像切换时清除测量、叠加层和ROI
|
// 图像切换时清除测量和叠加层,但保留 ROI(ROI 是用户标注,应跟随图像持续显示)
|
||||||
control.ClearMeasurements();
|
control.ClearMeasurements();
|
||||||
control.ROIItems?.Clear();
|
|
||||||
control.SelectedROI = null;
|
|
||||||
|
|
||||||
// 图像尺寸变化后刷新十字线
|
// 图像尺寸变化后刷新十字线
|
||||||
if (control.ShowCrosshair)
|
if (control.ShowCrosshair)
|
||||||
|
|||||||
@@ -628,6 +628,10 @@ namespace XplorePlane.ViewModels.Cnc
|
|||||||
if (_currentProgram == null)
|
if (_currentProgram == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
_logger.Debug("[CNC-ROI][HandleNodeModelChanged] 节点={Name}(idx={Idx}),updatedNode类型={Type},调用栈:{Stack}",
|
||||||
|
nodeVm.Name, nodeVm.Index, updatedNode.GetType().Name,
|
||||||
|
new System.Diagnostics.StackTrace(1, false).ToString().Split('\n')[0].Trim());
|
||||||
|
|
||||||
_currentProgram = _cncProgramService.UpdateNode(_currentProgram, nodeVm.Index, updatedNode);
|
_currentProgram = _cncProgramService.UpdateNode(_currentProgram, nodeVm.Index, updatedNode);
|
||||||
IsModified = true;
|
IsModified = true;
|
||||||
ProgramName = _currentProgram.Name;
|
ProgramName = _currentProgram.Name;
|
||||||
@@ -636,6 +640,9 @@ namespace XplorePlane.ViewModels.Cnc
|
|||||||
|
|
||||||
private void RefreshNodes()
|
private void RefreshNodes()
|
||||||
{
|
{
|
||||||
|
_logger.Debug("[CNC-ROI][RefreshNodes] 触发,调用栈:{Stack}",
|
||||||
|
new System.Diagnostics.StackTrace(1, false).ToString().Split('\n')[0].Trim());
|
||||||
|
|
||||||
NormalizeDefaultNodeNamesInCurrentProgram();
|
NormalizeDefaultNodeNamesInCurrentProgram();
|
||||||
|
|
||||||
var selectedId = _preferredSelectedNodeId ?? SelectedNode?.Id;
|
var selectedId = _preferredSelectedNodeId ?? SelectedNode?.Id;
|
||||||
|
|||||||
@@ -93,8 +93,21 @@ namespace XplorePlane.ViewModels.Cnc
|
|||||||
get => _selectedNode;
|
get => _selectedNode;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
var oldKey = _selectedNode?.OperatorKey ?? "(null)";
|
||||||
|
var newKey = value?.OperatorKey ?? "(null)";
|
||||||
|
_logger.Debug("[CNC-ROI][SelectedNode] setter 触发:old={Old}(id={OldId}), new={New}(id={NewId}), caller={Caller}",
|
||||||
|
oldKey, _selectedNode?.GetHashCode(), newKey, value?.GetHashCode(),
|
||||||
|
new System.Diagnostics.StackTrace(1, false).GetFrame(0)?.GetMethod()?.Name ?? "?");
|
||||||
|
|
||||||
if (!SetProperty(ref _selectedNode, value))
|
if (!SetProperty(ref _selectedNode, value))
|
||||||
|
{
|
||||||
|
_logger.Debug("[CNC-ROI][SelectedNode] 值未变化,跳过");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Info("[CNC-ROI][SelectedNode] 已切换:{Old} → {New},调用栈:{Stack}",
|
||||||
|
oldKey, newKey,
|
||||||
|
new System.Diagnostics.StackTrace(1, false).ToString().Split('\n')[0].Trim());
|
||||||
|
|
||||||
// 切换节点时停止当前 ROI 编辑
|
// 切换节点时停止当前 ROI 编辑
|
||||||
CancelRoiEdit();
|
CancelRoiEdit();
|
||||||
@@ -171,9 +184,13 @@ namespace XplorePlane.ViewModels.Cnc
|
|||||||
|
|
||||||
private void RefreshFromSelection()
|
private void RefreshFromSelection()
|
||||||
{
|
{
|
||||||
|
_logger.Info("[CNC-ROI][RefreshFromSelection] 触发,调用栈:{Stack}",
|
||||||
|
new System.Diagnostics.StackTrace(1, false).ToString().Split('\n')[0].Trim());
|
||||||
|
|
||||||
var selected = _editorViewModel.SelectedNode;
|
var selected = _editorViewModel.SelectedNode;
|
||||||
if (selected == null || !selected.IsInspectionModule)
|
if (selected == null || !selected.IsInspectionModule)
|
||||||
{
|
{
|
||||||
|
_logger.Debug("[CNC-ROI][RefreshFromSelection] 无检测模块,清空");
|
||||||
_activeModuleNode = null;
|
_activeModuleNode = null;
|
||||||
PipelineNodes.Clear();
|
PipelineNodes.Clear();
|
||||||
SelectedNode = null;
|
SelectedNode = null;
|
||||||
@@ -184,6 +201,8 @@ namespace XplorePlane.ViewModels.Cnc
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logger.Info("[CNC-ROI][RefreshFromSelection] 加载模块:{Name},Pipeline节点数={Count}",
|
||||||
|
selected.Name, selected.Pipeline?.Nodes?.Count ?? 0);
|
||||||
_activeModuleNode = selected;
|
_activeModuleNode = selected;
|
||||||
_currentFilePath = null;
|
_currentFilePath = null;
|
||||||
LoadPipelineModel(_activeModuleNode.Pipeline ?? new PipelineModel
|
LoadPipelineModel(_activeModuleNode.Pipeline ?? new PipelineModel
|
||||||
@@ -389,6 +408,9 @@ namespace XplorePlane.ViewModels.Cnc
|
|||||||
|
|
||||||
private void LoadPipelineModel(PipelineModel pipeline)
|
private void LoadPipelineModel(PipelineModel pipeline)
|
||||||
{
|
{
|
||||||
|
_logger.Info("[CNC-ROI][LoadPipelineModel] 开始,节点数={Count},调用栈:{Stack}",
|
||||||
|
pipeline?.Nodes?.Count ?? 0,
|
||||||
|
new System.Diagnostics.StackTrace(1, false).ToString().Split('\n')[0].Trim());
|
||||||
_isSynchronizing = true;
|
_isSynchronizing = true;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -440,7 +462,14 @@ namespace XplorePlane.ViewModels.Cnc
|
|||||||
var parameterVm = new ProcessorParameterVM(definition);
|
var parameterVm = new ProcessorParameterVM(definition);
|
||||||
if (savedValues != null && savedValues.TryGetValue(definition.Name, out var savedValue))
|
if (savedValues != null && savedValues.TryGetValue(definition.Name, out var savedValue))
|
||||||
{
|
{
|
||||||
parameterVm.Value = ConvertSavedValue(savedValue, definition.ValueType);
|
var converted = ConvertSavedValue(savedValue, definition.ValueType);
|
||||||
|
parameterVm.Value = converted;
|
||||||
|
// 只记录 ROI 相关参数
|
||||||
|
if (definition.Name is "PolyCount" or "RoiMode")
|
||||||
|
_logger.Debug("[CNC-ROI][LoadNodeParameters] 算子={Key},参数={Param},savedValue={Saved}({SavedType}),converted={Conv}({ConvType})",
|
||||||
|
node.OperatorKey, definition.Name,
|
||||||
|
savedValue, savedValue?.GetType().Name,
|
||||||
|
converted, converted?.GetType().Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
parameterVm.PropertyChanged += (_, e) =>
|
parameterVm.PropertyChanged += (_, e) =>
|
||||||
@@ -457,9 +486,29 @@ namespace XplorePlane.ViewModels.Cnc
|
|||||||
private void PersistActiveModule(string statusMessage)
|
private void PersistActiveModule(string statusMessage)
|
||||||
{
|
{
|
||||||
if (!HasActiveModule || _isSynchronizing)
|
if (!HasActiveModule || _isSynchronizing)
|
||||||
|
{
|
||||||
|
_logger.Debug("[CNC-ROI][PersistActiveModule] 跳过:HasActiveModule={Has},_isSynchronizing={Sync},msg={Msg}",
|
||||||
|
HasActiveModule, _isSynchronizing, statusMessage);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Debug("[CNC-ROI][PersistActiveModule] 执行:{Msg},调用栈:{Stack}",
|
||||||
|
statusMessage,
|
||||||
|
new System.Diagnostics.StackTrace(1, false).ToString().Split('\n')[0].Trim());
|
||||||
|
|
||||||
_activeModuleNode.Pipeline = BuildPipelineModel();
|
_activeModuleNode.Pipeline = BuildPipelineModel();
|
||||||
|
|
||||||
|
// 记录写入后 Pipeline 中的 ROI 参数
|
||||||
|
var roiNode = _activeModuleNode.Pipeline?.Nodes?.FirstOrDefault(
|
||||||
|
n => AdvancedModuleOperatorKeys.Contains(n.OperatorKey));
|
||||||
|
if (roiNode != null)
|
||||||
|
{
|
||||||
|
roiNode.Parameters.TryGetValue("PolyCount", out var pc);
|
||||||
|
roiNode.Parameters.TryGetValue("RoiMode", out var rm);
|
||||||
|
_logger.Debug("[CNC-ROI][PersistActiveModule] 写入Pipeline:算子={Key},PolyCount={PC},RoiMode={RM}",
|
||||||
|
roiNode.OperatorKey, pc, rm);
|
||||||
|
}
|
||||||
|
|
||||||
StatusMessage = statusMessage;
|
StatusMessage = statusMessage;
|
||||||
TriggerDebouncedPreview();
|
TriggerDebouncedPreview();
|
||||||
}
|
}
|
||||||
@@ -698,6 +747,11 @@ namespace XplorePlane.ViewModels.Cnc
|
|||||||
StatusMessage = "ROI 编辑中:在图像上点击添加顶点,完成后点击「完成 ROI」";
|
StatusMessage = "ROI 编辑中:在图像上点击添加顶点,完成后点击「完成 ROI」";
|
||||||
|
|
||||||
var existingPoints = ReadRoiPoints(SelectedNode);
|
var existingPoints = ReadRoiPoints(SelectedNode);
|
||||||
|
var polyCountParam = SelectedNode.Parameters.FirstOrDefault(p => p.Name == "PolyCount");
|
||||||
|
var roiModeParam = SelectedNode.Parameters.FirstOrDefault(p => p.Name == "RoiMode");
|
||||||
|
_logger.Info("[CNC-ROI] ExecuteEditRoi:算子={Key},已有顶点数={Count},PolyCount参数值={PC},RoiMode={RM}",
|
||||||
|
SelectedNode.OperatorKey, existingPoints.Count,
|
||||||
|
polyCountParam?.Value, roiModeParam?.Value);
|
||||||
|
|
||||||
_eventAggregator.GetEvent<CncRoiEditRequestedEvent>().Publish(new CncRoiEditRequestedPayload
|
_eventAggregator.GetEvent<CncRoiEditRequestedEvent>().Publish(new CncRoiEditRequestedPayload
|
||||||
{
|
{
|
||||||
@@ -767,10 +821,21 @@ namespace XplorePlane.ViewModels.Cnc
|
|||||||
return Convert.ToInt32(polyCountParam.Value);
|
return Convert.ToInt32(polyCountParam.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IReadOnlyList<System.Windows.Point> ReadRoiPoints(PipelineNodeViewModel node)
|
private IReadOnlyList<System.Windows.Point> ReadRoiPoints(PipelineNodeViewModel node)
|
||||||
{
|
{
|
||||||
|
var roiModeParam = node?.Parameters.FirstOrDefault(p => p.Name == "RoiMode");
|
||||||
|
var polyCountParam = node?.Parameters.FirstOrDefault(p => p.Name == "PolyCount");
|
||||||
|
_logger.Debug("[CNC-ROI][ReadRoiPoints] 算子={Key},nodeId={Id},RoiMode={RM}({RMType}),PolyCount={PC}({PCType})",
|
||||||
|
node?.OperatorKey, node?.GetHashCode(),
|
||||||
|
roiModeParam?.Value, roiModeParam?.Value?.GetType().Name,
|
||||||
|
polyCountParam?.Value, polyCountParam?.Value?.GetType().Name);
|
||||||
|
|
||||||
int count = GetRoiPointCount(node);
|
int count = GetRoiPointCount(node);
|
||||||
if (count < 3) return Array.Empty<System.Windows.Point>();
|
if (count < 3)
|
||||||
|
{
|
||||||
|
_logger.Debug("[CNC-ROI][ReadRoiPoints] count={Count} < 3,返回空列表", count);
|
||||||
|
return Array.Empty<System.Windows.Point>();
|
||||||
|
}
|
||||||
|
|
||||||
var points = new List<System.Windows.Point>(count);
|
var points = new List<System.Windows.Point>(count);
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
@@ -781,24 +846,34 @@ namespace XplorePlane.ViewModels.Cnc
|
|||||||
double y = py != null ? Convert.ToDouble(py.Value) : 0;
|
double y = py != null ? Convert.ToDouble(py.Value) : 0;
|
||||||
points.Add(new System.Windows.Point(x, y));
|
points.Add(new System.Windows.Point(x, y));
|
||||||
}
|
}
|
||||||
|
_logger.Debug("[CNC-ROI][ReadRoiPoints] 读取完成,返回 {Count} 个顶点", points.Count);
|
||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void WriteRoiPoints(PipelineNodeViewModel node, IReadOnlyList<System.Windows.Point> points)
|
private void WriteRoiPoints(PipelineNodeViewModel node, IReadOnlyList<System.Windows.Point> points)
|
||||||
{
|
{
|
||||||
if (node == null) return;
|
if (node == null) return;
|
||||||
|
|
||||||
int count = points?.Count >= 3 ? points.Count : 0;
|
int count = points?.Count >= 3 ? points.Count : 0;
|
||||||
|
_logger.Debug("[CNC-ROI][WriteRoiPoints] 开始写入:算子={Key},nodeId={Id},输入点数={In},将写count={Count}",
|
||||||
|
node.OperatorKey, node.GetHashCode(), points?.Count ?? 0, count);
|
||||||
|
|
||||||
// 更新 RoiMode(BgaVoidRate 专用)
|
// 更新 RoiMode(BgaVoidRate 专用)
|
||||||
var roiModeParam = node.Parameters.FirstOrDefault(p => p.Name == "RoiMode");
|
var roiModeParam = node.Parameters.FirstOrDefault(p => p.Name == "RoiMode");
|
||||||
if (roiModeParam != null)
|
if (roiModeParam != null)
|
||||||
roiModeParam.Value = count >= 3 ? "Polygon" : "None";
|
{
|
||||||
|
var newRoiMode = count >= 3 ? "Polygon" : "None";
|
||||||
|
_logger.Debug("[CNC-ROI][WriteRoiPoints] 设置 RoiMode:{Old} → {New}", roiModeParam.Value, newRoiMode);
|
||||||
|
roiModeParam.Value = newRoiMode;
|
||||||
|
}
|
||||||
|
|
||||||
// 更新 PolyCount
|
// 更新 PolyCount
|
||||||
var polyCountParam = node.Parameters.FirstOrDefault(p => p.Name == "PolyCount");
|
var polyCountParam = node.Parameters.FirstOrDefault(p => p.Name == "PolyCount");
|
||||||
if (polyCountParam != null)
|
if (polyCountParam != null)
|
||||||
|
{
|
||||||
|
_logger.Debug("[CNC-ROI][WriteRoiPoints] 设置 PolyCount:{Old} → {New}", polyCountParam.Value, count);
|
||||||
polyCountParam.Value = count;
|
polyCountParam.Value = count;
|
||||||
|
}
|
||||||
|
|
||||||
// 更新坐标(最多 32 个点)
|
// 更新坐标(最多 32 个点)
|
||||||
for (int i = 0; i < 32; i++)
|
for (int i = 0; i < 32; i++)
|
||||||
@@ -810,6 +885,12 @@ namespace XplorePlane.ViewModels.Cnc
|
|||||||
if (px != null) px.Value = (int)x;
|
if (px != null) px.Value = (int)x;
|
||||||
if (py != null) py.Value = (int)y;
|
if (py != null) py.Value = (int)y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 写入后验证
|
||||||
|
var verifyRoiMode = node.Parameters.FirstOrDefault(p => p.Name == "RoiMode")?.Value;
|
||||||
|
var verifyPolyCount = node.Parameters.FirstOrDefault(p => p.Name == "PolyCount")?.Value;
|
||||||
|
_logger.Debug("[CNC-ROI][WriteRoiPoints] 写入完成验证:RoiMode={RM},PolyCount={PC}",
|
||||||
|
verifyRoiMode, verifyPolyCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using System.Windows.Media;
|
|||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
using Prism.Ioc;
|
using Prism.Ioc;
|
||||||
|
using Serilog;
|
||||||
using XP.ImageProcessing.RoiControl.Controls;
|
using XP.ImageProcessing.RoiControl.Controls;
|
||||||
using XplorePlane.Events;
|
using XplorePlane.Events;
|
||||||
using XplorePlane.Services;
|
using XplorePlane.Services;
|
||||||
@@ -17,6 +18,7 @@ namespace XplorePlane.Views
|
|||||||
{
|
{
|
||||||
public partial class ViewportPanelView : UserControl
|
public partial class ViewportPanelView : UserControl
|
||||||
{
|
{
|
||||||
|
private static readonly ILogger _log = Log.ForContext<ViewportPanelView>();
|
||||||
private MainViewModel _mainVm;
|
private MainViewModel _mainVm;
|
||||||
|
|
||||||
private MainViewModel GetMainVm()
|
private MainViewModel GetMainVm()
|
||||||
@@ -187,43 +189,75 @@ namespace XplorePlane.Views
|
|||||||
|
|
||||||
private void OnCncRoiEditRequested(Events.CncRoiEditRequestedPayload payload)
|
private void OnCncRoiEditRequested(Events.CncRoiEditRequestedPayload payload)
|
||||||
{
|
{
|
||||||
_cncRoiPayload = payload;
|
_log.Information("[CNC-ROI] OnCncRoiEditRequested 触发,ExistingPoints={Count}",
|
||||||
|
payload?.ExistingPoints?.Count ?? -1);
|
||||||
|
|
||||||
// 清理旧的 ROI shape
|
// 先清理旧状态(在保存新 payload 之前)
|
||||||
CleanupCncRoi();
|
CleanupCncRoi();
|
||||||
|
|
||||||
|
_cncRoiPayload = payload;
|
||||||
|
|
||||||
// 确保 ROIItems 集合存在
|
// 确保 ROIItems 集合存在
|
||||||
if (RoiCanvas.ROIItems == null)
|
if (RoiCanvas.ROIItems == null)
|
||||||
|
{
|
||||||
|
_log.Debug("[CNC-ROI] ROIItems 为 null,创建新集合");
|
||||||
RoiCanvas.ROIItems = new System.Collections.ObjectModel.ObservableCollection<XP.ImageProcessing.RoiControl.Models.ROIShape>();
|
RoiCanvas.ROIItems = new System.Collections.ObjectModel.ObservableCollection<XP.ImageProcessing.RoiControl.Models.ROIShape>();
|
||||||
|
}
|
||||||
|
|
||||||
// 创建新的多边形 ROI
|
_log.Debug("[CNC-ROI] 当前 ROIItems.Count={Count}", RoiCanvas.ROIItems.Count);
|
||||||
|
|
||||||
|
// 创建新的多边形 ROI(先加入 canvas,再添加顶点,确保 UI 绑定已建立)
|
||||||
_cncRoiShape = new XP.ImageProcessing.RoiControl.Models.PolygonROI
|
_cncRoiShape = new XP.ImageProcessing.RoiControl.Models.PolygonROI
|
||||||
{
|
{
|
||||||
Color = "Cyan",
|
Color = "Cyan",
|
||||||
IsSelected = true
|
IsSelected = false
|
||||||
};
|
};
|
||||||
|
|
||||||
// 恢复已保存的顶点
|
RoiCanvas.ROIItems.Add(_cncRoiShape);
|
||||||
if (payload.ExistingPoints != null)
|
_log.Debug("[CNC-ROI] PolygonROI 已加入 ROIItems,当前 Count={Count}", RoiCanvas.ROIItems.Count);
|
||||||
|
|
||||||
|
// 恢复已保存的顶点(canvas 已绑定,每次 Add 都会触发 UI 更新)
|
||||||
|
if (payload.ExistingPoints != null && payload.ExistingPoints.Count >= 3)
|
||||||
{
|
{
|
||||||
foreach (var pt in payload.ExistingPoints)
|
foreach (var pt in payload.ExistingPoints)
|
||||||
_cncRoiShape.Points.Add(pt);
|
_cncRoiShape.Points.Add(pt);
|
||||||
|
_log.Information("[CNC-ROI] 已恢复 {Count} 个顶点", _cncRoiShape.Points.Count);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_log.Information("[CNC-ROI] 无已保存顶点,新建空 ROI");
|
||||||
}
|
}
|
||||||
|
|
||||||
RoiCanvas.ROIItems.Add(_cncRoiShape);
|
// 顶点变化时回调(在顶点恢复之后订阅,避免恢复时触发不必要的回调)
|
||||||
RoiCanvas.SelectedROI = _cncRoiShape;
|
_cncRoiShape.Points.CollectionChanged += OnCncRoiPointsCollectionChanged;
|
||||||
|
|
||||||
// 禁用右键菜单,启用画布点击添加顶点
|
// 禁用右键菜单,启用画布点击添加顶点
|
||||||
RoiCanvas.SetValue(System.Windows.Controls.ContextMenuService.IsEnabledProperty, false);
|
RoiCanvas.SetValue(System.Windows.Controls.ContextMenuService.IsEnabledProperty, false);
|
||||||
RoiCanvas.AddHandler(XP.ImageProcessing.RoiControl.Controls.PolygonRoiCanvas.CanvasClickedEvent,
|
RoiCanvas.AddHandler(XP.ImageProcessing.RoiControl.Controls.PolygonRoiCanvas.CanvasClickedEvent,
|
||||||
new RoutedEventHandler(OnCncRoiCanvasClicked));
|
new RoutedEventHandler(OnCncRoiCanvasClicked));
|
||||||
|
|
||||||
// 顶点变化时回调
|
// 延迟设置 SelectedROI,确保 ItemsControl 完成布局后 Adorner 才能正确创建
|
||||||
_cncRoiShape.Points.CollectionChanged += OnCncRoiPointsCollectionChanged;
|
var shapeRef = _cncRoiShape;
|
||||||
|
Dispatcher.BeginInvoke(new Action(() =>
|
||||||
|
{
|
||||||
|
if (shapeRef == _cncRoiShape) // 确保没有被 cleanup 掉
|
||||||
|
{
|
||||||
|
_log.Debug("[CNC-ROI] Dispatcher 延迟:设置 SelectedROI,Points.Count={Count}", shapeRef.Points.Count);
|
||||||
|
RoiCanvas.SelectedROI = null;
|
||||||
|
RoiCanvas.SelectedROI = shapeRef;
|
||||||
|
shapeRef.IsSelected = true;
|
||||||
|
_log.Information("[CNC-ROI] SelectedROI 已设置,ROI 应显示在画布上");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_log.Warning("[CNC-ROI] Dispatcher 延迟:shapeRef 已被 cleanup,跳过 SelectedROI 设置");
|
||||||
|
}
|
||||||
|
}), System.Windows.Threading.DispatcherPriority.Loaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnCncRoiEditCancelled()
|
private void OnCncRoiEditCancelled()
|
||||||
{
|
{
|
||||||
|
_log.Information("[CNC-ROI] OnCncRoiEditCancelled 触发");
|
||||||
CleanupCncRoi();
|
CleanupCncRoi();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,6 +266,8 @@ namespace XplorePlane.Views
|
|||||||
if (_cncRoiShape == null || _cncRoiPayload == null) return;
|
if (_cncRoiShape == null || _cncRoiPayload == null) return;
|
||||||
if (e is XP.ImageProcessing.RoiControl.Controls.CanvasClickedEventArgs args)
|
if (e is XP.ImageProcessing.RoiControl.Controls.CanvasClickedEventArgs args)
|
||||||
{
|
{
|
||||||
|
_log.Debug("[CNC-ROI] 画布点击:Position={X},{Y},当前顶点数={Count}",
|
||||||
|
args.Position.X, args.Position.Y, _cncRoiShape.Points.Count);
|
||||||
InsertPointToPolygon(args.Position, _cncRoiShape.Points);
|
InsertPointToPolygon(args.Position, _cncRoiShape.Points);
|
||||||
_cncRoiShape.IsSelected = true;
|
_cncRoiShape.IsSelected = true;
|
||||||
RoiCanvas.SelectedROI = _cncRoiShape;
|
RoiCanvas.SelectedROI = _cncRoiShape;
|
||||||
@@ -242,11 +278,13 @@ namespace XplorePlane.Views
|
|||||||
System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (_cncRoiPayload?.OnPointsChanged == null || _cncRoiShape == null) return;
|
if (_cncRoiPayload?.OnPointsChanged == null || _cncRoiShape == null) return;
|
||||||
|
_log.Debug("[CNC-ROI] Points 变化,当前顶点数={Count}", _cncRoiShape.Points.Count);
|
||||||
_cncRoiPayload.OnPointsChanged(new List<System.Windows.Point>(_cncRoiShape.Points));
|
_cncRoiPayload.OnPointsChanged(new List<System.Windows.Point>(_cncRoiShape.Points));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CleanupCncRoi()
|
private void CleanupCncRoi()
|
||||||
{
|
{
|
||||||
|
_log.Debug("[CNC-ROI] CleanupCncRoi,_cncRoiShape={HasShape}", _cncRoiShape != null);
|
||||||
if (_cncRoiShape != null)
|
if (_cncRoiShape != null)
|
||||||
{
|
{
|
||||||
_cncRoiShape.Points.CollectionChanged -= OnCncRoiPointsCollectionChanged;
|
_cncRoiShape.Points.CollectionChanged -= OnCncRoiPointsCollectionChanged;
|
||||||
|
|||||||
Reference in New Issue
Block a user