399 lines
15 KiB
C#
399 lines
15 KiB
C#
using JM1.VisionModule;
|
||
using MainShell.AlgorithmCalib.Model;
|
||
using MainShell.AlgorithmCalib.Service;
|
||
using MainShell.AlgorithmCalib.View;
|
||
using MainShell.Common;
|
||
using MainShell.Common.Display.ViewModel;
|
||
using MainShell.Filewritable;
|
||
using MainShell.Hardware;
|
||
using MaxwellFramework.Core.Interfaces;
|
||
using MwFramework.Controls.SystemCalib;
|
||
using MwFramework.ManagerService;
|
||
using Stylet;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Collections.ObjectModel;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using System.Windows;
|
||
using System.Xml;
|
||
using Point = SemiconductorVisionAlgorithm.SemiParams.Point;
|
||
|
||
namespace MainShell.AlgorithmCalib.ViewModel
|
||
{
|
||
public class FusionMenuCalibViewModel : Screen, IPage
|
||
{
|
||
private readonly Dictionary<string, Window> _calibWindows = new Dictionary<string, Window>();
|
||
private List<Point> _calibResultRealPoint = new List<Point>();
|
||
private List<Point> _calibResultAxisPoint = new List<Point>();
|
||
private MotionFusion _motionFusion = new MotionFusion();
|
||
private FusionCalibMotionService _fusionCalibMotionService;
|
||
public string Name { get; set; } = "FusionMenuCalib";
|
||
public string CalibName { get; set; }
|
||
public string FileSaveDir { get; set; }
|
||
private bool _isDataLoaded = false;
|
||
|
||
private CameraAxisViewModel _cameraAxisViewModelSevice = new CameraAxisViewModel();
|
||
public CameraAxisViewModel CameraAxisViewModelSevice
|
||
{
|
||
get { return _cameraAxisViewModelSevice; }
|
||
set
|
||
{
|
||
_cameraAxisViewModelSevice = value;
|
||
OnPropertyChanged(nameof(CameraAxisViewModelSevice));
|
||
}
|
||
}
|
||
private ObservableCollection<FusionCalibParItem> _fusionCalibParItem = new ObservableCollection<FusionCalibParItem>();
|
||
public ObservableCollection<FusionCalibParItem> FusionCalibParItem
|
||
{
|
||
get { return _fusionCalibParItem; }
|
||
set
|
||
{
|
||
_fusionCalibParItem = value;
|
||
OnPropertyChanged(nameof(FusionCalibParItem));
|
||
}
|
||
}
|
||
private FusionCalibParItem _selectedCalibPar;
|
||
public FusionCalibParItem SelectedCalibPar
|
||
{
|
||
get { return _selectedCalibPar; }
|
||
set
|
||
{
|
||
_selectedCalibPar = value;
|
||
OnPropertyChanged(nameof(SelectedCalibPar));
|
||
}
|
||
}
|
||
private FusionCalibParItem _inputParam;
|
||
public FusionCalibParItem InputParam
|
||
{
|
||
get { return _inputParam; }
|
||
set { SetAndNotify(ref _inputParam, value); }
|
||
}
|
||
private FusionCalibParItem _resultParam;
|
||
public FusionCalibParItem ResultParam
|
||
{
|
||
get { return _resultParam; }
|
||
set { SetAndNotify(ref _resultParam, value); }
|
||
}
|
||
private List<HardwareDevice> _hardwareDevice;
|
||
public List<HardwareDevice> HardwareDevice
|
||
{
|
||
get { return _hardwareDevice; }
|
||
set
|
||
{
|
||
_hardwareDevice = value;
|
||
NotifyOfPropertyChange();
|
||
}
|
||
}
|
||
private HardwareManager _hardware;
|
||
public HardwareManager Hardware
|
||
{
|
||
get { return _hardware; }
|
||
set
|
||
{
|
||
_hardware = value;
|
||
NotifyOfPropertyChange();
|
||
}
|
||
}
|
||
private bool _isCalibFinished;
|
||
public bool IsCalibFinished
|
||
{
|
||
get { return _isCalibFinished; }
|
||
set { SetAndNotify(ref _isCalibFinished, value); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 无参构造函数
|
||
/// </summary>
|
||
public FusionMenuCalibViewModel()
|
||
{
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 手动创建时使用的静态工厂方法
|
||
/// </summary>
|
||
/// <param name="cameraName">相机名称,如 "BottomCamera"</param>
|
||
/// <param name="device">对应的硬件设备</param>
|
||
public static FusionMenuCalibViewModel Create(string calibName, string fileSaveName, List<HardwareDevice> device, HardwareManager hardware, FusionCalibMotionService motion)
|
||
{
|
||
var vm = new FusionMenuCalibViewModel();
|
||
vm.Initialize(calibName, fileSaveName, device, hardware, motion);
|
||
return vm;
|
||
}
|
||
|
||
protected override void OnViewLoaded()
|
||
{
|
||
base.OnViewLoaded();
|
||
|
||
if (_hardware != null)
|
||
{
|
||
_cameraAxisViewModelSevice = new CameraAxisViewModel();
|
||
_cameraAxisViewModelSevice.CameraAxisDevices.HardwareDeviceList = HardwareDevice;
|
||
NotifyOfPropertyChange(nameof(CameraAxisViewModel));
|
||
}
|
||
if (!_isDataLoaded)
|
||
{
|
||
ReadCalibData();
|
||
_isDataLoaded = true;
|
||
}
|
||
}
|
||
|
||
private void Initialize(string calibName, string fileSaveName, List<HardwareDevice> device, HardwareManager hardware, FusionCalibMotionService motion)
|
||
{
|
||
CalibName = calibName;
|
||
Hardware = hardware;
|
||
HardwareDevice = device;
|
||
_fusionCalibMotionService = motion;
|
||
FileSaveDir = Path.Combine(Paths.CalibSettingPath, "fusionCalib");
|
||
var paramList = IoC.Get<IParameterManager>() as IParamList;
|
||
}
|
||
|
||
public void btnOpenCalibWindow()
|
||
{
|
||
if (SelectedCalibPar == null)
|
||
{
|
||
MwMessageBox.Show("请先选择一组标定数据。", "提示",
|
||
MessageBoxButton.OK, MessageBoxImage.Information);
|
||
return;
|
||
}
|
||
string cameraId = SelectedCalibPar.Camera_ID;
|
||
|
||
// ── 如果已有缓存窗口,直接激活显示 ──
|
||
if (_calibWindows.TryGetValue(cameraId, out var existingWindow))
|
||
{
|
||
if (existingWindow.WindowState == WindowState.Minimized)
|
||
existingWindow.WindowState = WindowState.Normal;
|
||
existingWindow.Show();
|
||
existingWindow.Activate();
|
||
return;
|
||
}
|
||
|
||
var calibVM = CameraFusionPadCalibViewModel.Create("", CalibName, HardwareDevice, SelectedCalibPar, Hardware, _fusionCalibMotionService);
|
||
calibVM.FileSaveDir = this.FileSaveDir;
|
||
|
||
|
||
|
||
// ② 创建视图
|
||
var calibView = new CameraFusionPadCalibView
|
||
{
|
||
DataContext = calibVM,
|
||
};
|
||
|
||
|
||
|
||
|
||
// 4. 创建 Window 包裹这个 UserControl
|
||
var window = new Window
|
||
{
|
||
Title = $"融合标定-{cameraId}",
|
||
Width = 1100,
|
||
Height = 750,
|
||
WindowStartupLocation = WindowStartupLocation.CenterOwner,
|
||
Owner = Application.Current.MainWindow,
|
||
ResizeMode = ResizeMode.CanResize,
|
||
Content = calibView
|
||
};
|
||
|
||
// ── 拦截关闭:改为隐藏,保留内存状态 ──
|
||
window.Closing += (s, args) =>
|
||
{
|
||
args.Cancel = true; // 取消真正的关闭
|
||
window.Hide(); // 仅隐藏,VM 和 View 状态全部保留
|
||
};
|
||
|
||
// ── 用 Unloaded 代替 Closed 做数据同步 ──
|
||
// 每次隐藏时都把 Service 最新数据写回选中行
|
||
window.IsVisibleChanged += (s, args) =>
|
||
{
|
||
if (!(bool)args.NewValue) // 变为不可见(Hide)
|
||
{
|
||
SyncCalibResultBack(calibVM);
|
||
}
|
||
};
|
||
|
||
// 缓存
|
||
_calibWindows[cameraId] = window;
|
||
window.Show();
|
||
|
||
|
||
window.Closed += (s, args) =>
|
||
{
|
||
var innerData = calibVM.FusionCalibParItem;
|
||
if (innerData != null)
|
||
{
|
||
SelectedCalibPar.Index = innerData.Index;
|
||
SelectedCalibPar.MoveAxisPos = innerData.MoveAxisPos;
|
||
SelectedCalibPar.ApproachXPos = innerData.ApproachXPos;
|
||
SelectedCalibPar.ApproachYPos = innerData.ApproachYPos;
|
||
SelectedCalibPar.StartX = innerData.StartX;
|
||
SelectedCalibPar.StartY = innerData.StartY;
|
||
SelectedCalibPar.Step = innerData.Step;
|
||
SelectedCalibPar.Count = innerData.Count;
|
||
SelectedCalibPar.RulerPoints = innerData.RulerPoints;
|
||
SelectedCalibPar.RealPoints = innerData.RealPoints;
|
||
// 刷新 DataGrid
|
||
OnPropertyChanged(nameof(FusionCalibParItem));
|
||
}
|
||
};
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将内部标定窗口的最新数据同步回外部 DataGrid 选中行
|
||
/// </summary>
|
||
private void SyncCalibResultBack(CameraFusionPadCalibViewModel calibVM)
|
||
{
|
||
var innerData = calibVM.ResultParam;
|
||
if (innerData != null) return;
|
||
var target = FusionCalibParItem.FirstOrDefault(p => p.Camera_ID == calibVM.CameraName);
|
||
if(target == null) return;
|
||
target.Index = innerData.Index;
|
||
target.MoveAxisPos = innerData.MoveAxisPos;
|
||
target.ApproachXPos = innerData.ApproachXPos;
|
||
target.ApproachYPos = innerData.ApproachYPos;
|
||
target.StartX = innerData.StartX;
|
||
target.StartY = innerData.StartY;
|
||
target.Step = innerData.Step;
|
||
target.Count = innerData.Count;
|
||
target.RulerPoints = innerData.RulerPoints;
|
||
target.RealPoints = innerData.RealPoints;
|
||
// 刷新 DataGrid
|
||
OnPropertyChanged(nameof(FusionCalibParItem));
|
||
}
|
||
|
||
public void btnReadCalibData()
|
||
{
|
||
var result = MwMessageBox.Show($"确认读取本地标定数据?", "确认读取", MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||
if (result == MessageBoxResult.Yes)
|
||
{
|
||
if (!ReadCalibData())
|
||
{
|
||
MwMessageBox.Show("读取本地标定数据失败!", "提示", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
}
|
||
}
|
||
public bool ReadCalibData()
|
||
{
|
||
try
|
||
{
|
||
var paramList = IoC.Get<IParameterManager>() as IParamList;
|
||
|
||
//FusionCalibParItem.CalibParList = new ObservableCollection<FusionSysDataItem>();
|
||
|
||
for (int i = 0; i < 4; i++)
|
||
{
|
||
var filePath = Path.Combine(FileSaveDir, $"Fusion_Time{i + 1}.xml");
|
||
var pointsFilePath = Path.Combine(FileSaveDir, $"Fusion_Time{i + 1}.txt");
|
||
|
||
bool hasXml = File.Exists(filePath);
|
||
bool hasTxt = File.Exists(pointsFilePath);
|
||
|
||
double moveAxisPos = 0;
|
||
double approachXPos = 0;
|
||
double approachYPos = 0;
|
||
double startX = 0;
|
||
double startY = 0;
|
||
double step = 0;
|
||
int count = 0;
|
||
List<Point> rulerPoints = new List<Point>();
|
||
List<Point> realPoints = new List<Point>();
|
||
|
||
// ① 有 XML → 读取参数
|
||
if (hasXml)
|
||
{
|
||
//var uiData = UIDataManager.Instance.GetUIData<FusionCalibParItem>(paramList);
|
||
//uiData.Read(filePath);
|
||
//var xmlData=XmlReader(filePath);
|
||
|
||
//if (xmlData.Datas != null && xmlData.Datas.Count > 0)
|
||
//{
|
||
// var item = xmlData.Datas[0]; // 每个文件只有一组数据
|
||
// index=item.Index;
|
||
// moveAxisPos = item.MoveAxisPos;
|
||
// approachXPos = item.ApproachXPos;
|
||
// approachYPos = item.ApproachYPos;
|
||
// startX = item.StartX;
|
||
// startY = item.StartY;
|
||
// step = item.Step;
|
||
// count = item.Count;
|
||
//}
|
||
}
|
||
|
||
// ② 有 TXT → 读取标定点位
|
||
if (hasTxt)
|
||
{
|
||
MotionCalibFileService.ReadCalibPointsFile(
|
||
pointsFilePath, out realPoints, out rulerPoints);
|
||
|
||
rulerPoints = rulerPoints ?? new List<Point>();
|
||
realPoints = realPoints ?? new List<Point>();
|
||
}
|
||
|
||
// ③ 无论什么情况,都加到列表(保证 5 组都在)
|
||
var par = new FusionCalibParItem
|
||
{
|
||
Index = i + 1,
|
||
Camera_ID = "Fusion_Time" + (i + 1),
|
||
MoveAxisPos = moveAxisPos,
|
||
ApproachXPos = approachXPos,
|
||
ApproachYPos = approachYPos,
|
||
StartX = startX,
|
||
StartY = startY,
|
||
Step = step,
|
||
Count = count,
|
||
RulerPoints = rulerPoints,
|
||
RealPoints = realPoints,
|
||
};
|
||
FusionCalibParItem.Add(par);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
catch
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
public void btnApplyCalibData()
|
||
{
|
||
//if (FusionCalibParItem.CalibParList.Count != 5)
|
||
//{
|
||
// MwMessageBox.Show("标定数据不足,请完成全部标定!", "提示", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
// return;
|
||
//}
|
||
//var result = MwMessageBox.Show($"确认应用标定数据?", "确认应用", MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||
//if (result == MessageBoxResult.Yes)
|
||
//{
|
||
// if (true) //
|
||
// {
|
||
|
||
// MwMessageBox.Show("应用标定数据成功!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||
// }
|
||
//}
|
||
}
|
||
|
||
public void ApplayCalibData()
|
||
{
|
||
//List<string> cameraIdList = new List<string>();
|
||
//for (int i = 0; i < 5; i++)
|
||
//{
|
||
// var resultPointsList = FusionCalibParItem.CalibParList[i];
|
||
// _motionFusion.Set(i, resultPointsList.ResultRealPoints, resultPointsList.ResultAxisPoints);
|
||
// cameraIdList.Add(resultPointsList.CameraId);
|
||
//}
|
||
//_motionFusion.AutoSelectPt(cameraIdList[0], cameraIdList[1], cameraIdList[2], cameraIdList[3], out _calibResultRealPoint, out _calibResultAxisPoint);
|
||
|
||
//MwAlgorithmHelper.Instance.RulerToRealMaritex("topCameraPad", _calibResultAxisPoint, _calibResultRealPoint, 1, 1, 1, 1, UIDataManager.CalibDataDir);
|
||
}
|
||
|
||
public void XmlReader(string xmlFilePath)
|
||
{
|
||
|
||
}
|
||
}
|
||
}
|