高级模块的CNC插入功能
This commit is contained in:
@@ -14,24 +14,35 @@ using Prism.Mvvm;
|
||||
using XP.ImageProcessing.Processors;
|
||||
using XP.ImageProcessing.RoiControl.Controls;
|
||||
using XP.ImageProcessing.RoiControl.Models;
|
||||
using XplorePlane.Models;
|
||||
using XplorePlane.Services.MainViewport;
|
||||
using XplorePlane.ViewModels.Cnc;
|
||||
|
||||
namespace XplorePlane.ViewModels.ImageProcessing
|
||||
{
|
||||
public class BgaDetectionViewModel : BindableBase
|
||||
{
|
||||
private readonly IMainViewportService _viewportService;
|
||||
private CncEditorViewModel _cncEditorViewModel;
|
||||
private BitmapSource _originalImage;
|
||||
private System.Threading.CancellationTokenSource _debounceCts;
|
||||
private const int DebounceMs = 300;
|
||||
private const string BgaVoidRateOperatorKey = "BgaVoidRate";
|
||||
|
||||
public BgaDetectionViewModel(IMainViewportService viewportService)
|
||||
{
|
||||
_viewportService = viewportService;
|
||||
ExecuteCommand = new DelegateCommand(Execute);
|
||||
InsertToCncCommand = new DelegateCommand(ExecuteInsertToCnc);
|
||||
PropertyChanged += OnAnyPropertyChanged;
|
||||
}
|
||||
|
||||
/// <summary>设置 CNC 编辑器 ViewModel 引用,用于插入参数到激活的 CNC 位置节点</summary>
|
||||
public void SetCncEditorViewModel(CncEditorViewModel cncEditorViewModel)
|
||||
{
|
||||
_cncEditorViewModel = cncEditorViewModel;
|
||||
}
|
||||
|
||||
private void OnAnyPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
// 排除结果属性和ROI开关,只监听参数变化
|
||||
@@ -265,6 +276,7 @@ namespace XplorePlane.ViewModels.ImageProcessing
|
||||
public System.Collections.ObjectModel.ObservableCollection<BgaResultItem> Results { get; } = new();
|
||||
|
||||
public DelegateCommand ExecuteCommand { get; }
|
||||
public DelegateCommand InsertToCncCommand { get; }
|
||||
|
||||
private void Execute()
|
||||
{
|
||||
@@ -361,6 +373,119 @@ namespace XplorePlane.ViewModels.ImageProcessing
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将当前 ROI 和算子参数插入到激活的 CNC 位置节点的检测模块中 BGA空洞模块的参数
|
||||
/// </summary>
|
||||
private void ExecuteInsertToCnc()
|
||||
{
|
||||
if (_cncEditorViewModel == null)
|
||||
{
|
||||
MessageBox.Show("CNC 编辑器未就绪,无法插入参数。", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
// 查找当前激活的检测模块节点(SelectedNode 本身是 InspectionModule,或其父节点是 SavePosition)
|
||||
var selectedNode = _cncEditorViewModel.SelectedNode;
|
||||
CncNodeViewModel targetModuleNode = null;
|
||||
|
||||
if (selectedNode == null)
|
||||
{
|
||||
MessageBox.Show("请先在 CNC 编辑器中选择一个位置节点或检测模块。", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectedNode.IsInspectionModule)
|
||||
{
|
||||
// 直接选中的是检测模块
|
||||
targetModuleNode = selectedNode;
|
||||
}
|
||||
else if (selectedNode.IsSavePosition)
|
||||
{
|
||||
// 选中的是位置节点,查找其子节点中的检测模块
|
||||
targetModuleNode = selectedNode.Children.FirstOrDefault(c => c.IsInspectionModule);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 尝试在 Nodes 中找到当前选中节点所属的 SavePosition 的检测模块
|
||||
var allNodes = _cncEditorViewModel.Nodes;
|
||||
// 向前查找最近的 SavePosition
|
||||
CncNodeViewModel ownerPosition = null;
|
||||
foreach (var node in allNodes)
|
||||
{
|
||||
if (node.IsSavePosition)
|
||||
ownerPosition = node;
|
||||
if (node.Id == selectedNode.Id)
|
||||
break;
|
||||
}
|
||||
if (ownerPosition != null)
|
||||
targetModuleNode = ownerPosition.Children.FirstOrDefault(c => c.IsInspectionModule);
|
||||
}
|
||||
|
||||
if (targetModuleNode == null)
|
||||
{
|
||||
MessageBox.Show("未找到激活的检测模块节点。\n请在 CNC 编辑器中选择一个包含检测模块的位置节点。", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取或创建 Pipeline
|
||||
var pipeline = targetModuleNode.Pipeline ?? new PipelineModel { Name = targetModuleNode.Name };
|
||||
|
||||
// 查找已有的 BgaVoidRate 算子节点
|
||||
var bgaNode = pipeline.Nodes.FirstOrDefault(n =>
|
||||
string.Equals(n.OperatorKey, BgaVoidRateOperatorKey, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (bgaNode == null)
|
||||
{
|
||||
// 不存在则新建一个 BgaVoidRate 节点并添加到流水线末尾
|
||||
bgaNode = new PipelineNodeModel
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
OperatorKey = BgaVoidRateOperatorKey,
|
||||
Order = pipeline.Nodes.Count,
|
||||
IsEnabled = true,
|
||||
Parameters = new Dictionary<string, object>()
|
||||
};
|
||||
pipeline.Nodes.Add(bgaNode);
|
||||
}
|
||||
|
||||
// 写入当前参数
|
||||
var parameters = bgaNode.Parameters;
|
||||
parameters["BgaMinArea"] = BgaMinArea;
|
||||
parameters["BgaMaxArea"] = BgaMaxArea;
|
||||
parameters["BgaBlurSize"] = BlurSize;
|
||||
parameters["BgaCircularity"] = Circularity;
|
||||
parameters["MinThreshold"] = MinThreshold;
|
||||
parameters["MaxThreshold"] = MaxThreshold;
|
||||
parameters["MinVoidArea"] = MinVoidArea;
|
||||
parameters["VoidLimit"] = VoidLimit;
|
||||
|
||||
// 写入 ROI 参数
|
||||
if (RoiEnabled && _roiShape != null && _roiShape.Points.Count >= 3)
|
||||
{
|
||||
parameters["RoiMode"] = "Polygon";
|
||||
int count = Math.Min(_roiShape.Points.Count, 32);
|
||||
parameters["PolyCount"] = count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
parameters[$"PolyX{i}"] = (int)_roiShape.Points[i].X;
|
||||
parameters[$"PolyY{i}"] = (int)_roiShape.Points[i].Y;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters["RoiMode"] = "None";
|
||||
parameters["PolyCount"] = 0;
|
||||
}
|
||||
|
||||
// 更新 Pipeline 到节点
|
||||
pipeline.UpdatedAt = DateTime.UtcNow;
|
||||
targetModuleNode.Pipeline = pipeline;
|
||||
|
||||
MessageBox.Show(
|
||||
$"已将 BGA 检测参数插入到检测模块「{targetModuleNode.Name}」。",
|
||||
"插入成功", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
|
||||
private BitmapSource RenderResults(Image<Gray, byte> grayImage, IDictionary<string, object> output)
|
||||
{
|
||||
if (!output.ContainsKey("BgaVoidResult")) return null;
|
||||
|
||||
Reference in New Issue
Block a user