2026-01-26 14:51:28 +09:00

652 lines
29 KiB
C#

using Aurora;
using Aurora.Api;
using Aurora.Api.Devices;
using Aurora.Api.Manager;
using Aurora.View;
using AuroraLaser;
using AuroraLaserScanner;
using CoreUnit.Scanner.UserControl.ScannerCanvas;
using Microsoft.Win32;
using MilUI;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reactive.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Threading;
using VisionCommon;
using WeldingCommon.Sequences;
using WeldingCommon.Settings;
using WeldingCommon.Utils;
namespace WeldingCommon.Views
{
public class UCScannerCalibrationViewModel : NotifyPropertyChangedBase
{
private readonly Logger Log = new Logger("UCScannerCalibrationViewModel");
public ICommand CMD_VisibleChanged { get; }
public ICommand CMD_ApplyGridItems { get; }
public ICommand CMD_SaveDataFile { get; }
public ICommand CMD_RunCorreXionPro { get; }
public ICommand CMD_RunMarkGrid { get; }
public ICommand CMD_StopMarkGrid { get; }
public ICommand CMD_RunScannerCalibration { get; }
public ICommand CMD_StopScannerCalibration { get; }
public ICommand CMD_FindPattern { get; }
public ICommand CMD_CalculateDistance { get; }
//public ICommand CMD_ChangedCaltype { get; }
//public ICommand CMD_SeqStop { get; }
private readonly IAuroraEnvironment _Aurora;
private SystemParameter _SystemParameter;
private readonly Scanner _Scanner;
private readonly ILaserDevice _Laser;
private readonly ScannerConfig _ScannerConfig;
private ISequence _SeqMarkGrid;
private bool _IsSequenceRunning_MarkGrid;
public bool IsSequenceRunning_MarkGrid { get => _IsSequenceRunning_MarkGrid; set => SetProperty(ref _IsSequenceRunning_MarkGrid, value); }
private ISequence _SeqScannerCalibration;
private bool _IsSequenceRunning_ScannerCalibration;
public bool IsSequenceRunning_ScannerCalibration { get => _IsSequenceRunning_ScannerCalibration; set => SetProperty(ref _IsSequenceRunning_ScannerCalibration, value); }
// Support VisionCorrectionList Selection.
private ObservableCollection<CorrectionUnit> _SelectedVisionCorrectionList;
public ObservableCollection<CorrectionUnit> SelectedVisionCorrectionList { get => _SelectedVisionCorrectionList; set => SetProperty(ref _SelectedVisionCorrectionList, value); }
private ObservableCollection<CorrectionUnit> _VisionCorrectionList;
public ObservableCollection<CorrectionUnit> VisionCorrectionList { get => _VisionCorrectionList; set => SetProperty(ref _VisionCorrectionList, value); }
private ObservableCollection<PatternCorrectionUnit> _PatternCorrectionList;
public ObservableCollection<PatternCorrectionUnit> PatternCorrectionList { get => _PatternCorrectionList; set => SetProperty(ref _PatternCorrectionList, value); }
// Correction Param
private int _GridRowCount;
public int GridRowCount { get => _GridRowCount; set => SetProperty(ref _GridRowCount, value); }
private int _GridColumnCount;
public int GridColumnCount { get => _GridColumnCount; set => SetProperty(ref _GridColumnCount, value); }
private float _UnitLength;
public float UnitLength { get => _UnitLength; set => SetProperty(ref _UnitLength, value); }
private float _TiltingDegree;
public float TiltingDegree { get => _TiltingDegree; set => SetProperty(ref _TiltingDegree, value); }
private double _CurrentX;
public double CurrentX { get => _CurrentX; set => SetProperty(ref _CurrentX, value); }
private double _CurrentY;
public double CurrentY { get => _CurrentY; set => SetProperty(ref _CurrentY, value); }
private bool _Is1StepCalibration;
public bool Is1StepCalibration { get => _Is1StepCalibration; set => SetProperty(ref _Is1StepCalibration, value); }
private int _RetryNum;
public int RetryNum { get => _RetryNum; set => SetProperty(ref _RetryNum, value); }
private int _SelectedRowIndex;
public int SelectedRowIndex { get => _SelectedRowIndex; set => SetProperty(ref _SelectedRowIndex, value); }
// Vision Param
private double _MPosOffsetX;
public double MPosOffsetX { get => _MPosOffsetX; set => SetProperty(ref _MPosOffsetX, value); }
private double _MPosOffsetY;
public double MPosOffsetY { get => _MPosOffsetY; set => SetProperty(ref _MPosOffsetY, value); }
private double _OffsetThreshold;
public double OffsetThreshold { get => _OffsetThreshold; set => SetProperty(ref _OffsetThreshold, value); }
// Vision Param - Calibration Type
private bool _IsVisionCalibration;
public bool IsVisionCalibration { get => _IsVisionCalibration; set => SetProperty(ref _IsVisionCalibration, value); }
// Laser Param
private double _MarkPower;
public double MarkPower { get => _MarkPower; set => SetProperty(ref _MarkPower, value); }
private double _MarkSpeed;
public double MarkSpeed { get => _MarkSpeed; set => SetProperty(ref _MarkSpeed, value); }
private double _MarkLength;
public double MarkLength { get => _MarkLength; set => SetProperty(ref _MarkLength, value); }
private bool _LaserStatus;
public bool LaserStatus { get => _LaserStatus; set => SetProperty(ref _LaserStatus, value); }
private bool _IsModulation;
public bool IsModulation { get => _IsModulation; set => SetProperty(ref _IsModulation, value); }
private uint _Frequency;
public uint Frequency { get => _Frequency; set => SetProperty(ref _Frequency, value); }
private uint _PulseDuration;
public uint PulseDuration { get => _PulseDuration; set => SetProperty(ref _PulseDuration, value); }
//Pixel Resolution
private bool _IsGrabLiveLimage;
public bool IsGrabLiveLimage { get => _IsGrabLiveLimage; set => SetProperty(ref _IsGrabLiveLimage, value); }
private double _ReferenceDistance;
public double ReferenceDistance { get => _ReferenceDistance; set => SetProperty(ref _ReferenceDistance, value); }
private double _PixelDistanceMin;
public double PixelDistanceMin { get => _PixelDistanceMin; set => SetProperty(ref _PixelDistanceMin, value); }
private double _PixelDistanceMax;
public double PixelDistanceMax { get => _PixelDistanceMax; set => SetProperty(ref _PixelDistanceMax, value); }
private double _DistanceAverage;
public double DistanceAverage { get => _DistanceAverage; set => SetProperty(ref _DistanceAverage, value); }
private double _LensMagnification;
public double LensMagnification { get => _LensMagnification; set => SetProperty(ref _LensMagnification, value); }
private FovInfo _FovInfo;
private CameraAgentBase _CameraAgent;
private PatternAgentBase _PatternAgent;
private object _GrabImage;
private PatternResult _PatternResult;
private readonly DispatcherTimer _MonitorTimer;
//private string _CalibrationType;
public UCScannerCalibrationViewModel(IAuroraEnvironment aurora)
{
_Aurora = aurora;
_SystemParameter = aurora.SettingEntry[CommonSettingIds.SystemParameter] as SystemParameter;
_Scanner = _Aurora.DeviceManager[CommonDeviceIds.Scanner] as Scanner;
_Laser = _Aurora.DeviceManager[CommonDeviceIds.Laser] as ILaserDevice;
_ScannerConfig = _Aurora.DeviceManager.GetDeviceConfig(_Scanner.DeviceId) as ScannerConfig;
_SeqMarkGrid = _Aurora.SequenceEntry[CommonSequenceIds.SeqMarkGrid] as ISequence;
_SeqScannerCalibration = _Aurora.SequenceEntry[CommonSequenceIds.SeqScannerCalibration] as ISequence;
_FovInfo = VisionRecipeManager.GetFovInfos().FirstOrDefault();
_CameraAgent = CameraAgentManager.GetCameraAgent(_FovInfo);
//FovInfo는 UI 생성자를 통해 전달된 Params의 FovInfo를 사용한다.
_PatternAgent = PatternAgentManager.GetAgent(_FovInfo);
//GrabImageBuffer를 Update할 필요가 있으면 아래 코드 사용
//IpAdapter.Instance.IpEnvironment.FreeImage(_GrabImage);
_GrabImage = _CameraAgent.CloneImageBuffer();
VisionCorrectionList = new ObservableCollection<CorrectionUnit>();
SelectedVisionCorrectionList = new ObservableCollection<CorrectionUnit>();
PatternCorrectionList = new ObservableCollection<PatternCorrectionUnit>();
InitVariable();
CMD_VisibleChanged = new DelegateCommand(VisibleChanged);
CMD_ApplyGridItems = new DelegateCommand(PerformCmdApplyGridItems);
CMD_SaveDataFile = new DelegateCommand(PerformCmdSaveDataFile);
CMD_RunCorreXionPro = new DelegateCommand(PerformCmdRunCorreXionPro);
CMD_RunMarkGrid = new DelegateCommand(PerformCmdRunMarkGrid);
CMD_StopMarkGrid = new DelegateCommand(PerformCmdStopMarkGrid);
CMD_RunScannerCalibration = new DelegateCommand(PerformCmdRunScannerCalibration);
CMD_StopScannerCalibration = new DelegateCommand(PerformCmdStopScannerCalibration);
CMD_FindPattern = new DelegateCommand(PerformCmdFindPattern);
CMD_CalculateDistance = new DelegateCommand(PerformCmdCalculateDistance);
_MonitorTimer = new DispatcherTimer();
_MonitorTimer.Tick += OnMonitoring;
_MonitorTimer.Interval = TimeSpan.FromMilliseconds(100);
// ian0513, 아래 Sequence 에서 보내 주는 걸로만 event 처리 하지 말고, event 등록 해서 처리 되도록 하는 것이 명확함.
_Aurora.EventObservable.AsObservable(CommonSequenceIds.SeqScannerCalibration)
.ObserveOnDispatcher().Subscribe(x => OnUpdateCorrectionTable(x));
}
private void InitVariable()
{
GridRowCount = 13;
GridColumnCount = 13;
UnitLength = 10;
TiltingDegree = 0;
MPosOffsetX = 0;
MPosOffsetY = 0;
OffsetThreshold = 0.01;
IsVisionCalibration = true;
MarkPower = 10;
MarkSpeed = 100;
MarkLength = 10;
LaserStatus = false;
Frequency = 10000;
PulseDuration = 10000;
//InitializeDataGridViewItem(GridColumnCount, GridRowCount, UnitLength, TiltingDegree);
}
private void VisibleChanged(object obj)
{
bool visible = (bool)obj;
if (visible) {
_MonitorTimer.Start();
} else {
_MonitorTimer.Stop();
}
}
private void OnMonitoring(object sender, EventArgs e)
{
double xPos, yPos;
if (_Scanner != null) {
_Scanner.GetXYPos(out xPos, out yPos);
CurrentX = xPos;
CurrentY = yPos;
}
if (_Laser.GetLaserReady()) {
LaserStatus = true;
} else {
LaserStatus = false;
}
}
private void OnUpdateCorrectionTable(EventMessage obj)
{
var updateDataGridItem = obj.Param as UpdateDataGridItem;
if (updateDataGridItem != null) {
VisionCorrectionList[updateDataGridItem.Upositionindex].VisionX = updateDataGridItem.UVisionX;
VisionCorrectionList[updateDataGridItem.Upositionindex].VisionY = updateDataGridItem.UVisionY;
}
}
private void PerformCmdApplyGridItems(object obj)
{
// 1. 원래 있던 data table 을 전부 초기화한다
// 2. 새로 적용된 row count 와 column count 로 새로 data table 을 만든다
// 3. VisionX 와 VisionY 는 0값을 넣어둔다. Calibration에서 패턴매칭 값을 이벤트로 받아와서 업데이트한다.
try {
InitializeDataGridViewItem(GridColumnCount, GridRowCount, UnitLength, TiltingDegree);
} catch (Exception ex) {
MessageUtil.ShowErrorToast(ex.Message);
}
}
private void PerformCmdSaveDataFile(object obj)
{
// 저장양식이 정해지면 업데이트하자
// 이전 버전은 database 에 저장하게 되어있음
try {
SaveFileDialog dlg = new SaveFileDialog();
dlg.InitialDirectory = @"D:\LASA.eqpdata\Scanner\Correction";
dlg.DefaultExt = "dat";
dlg.Filter = "data 파일 (*.dat)|*.dat";
dlg.Title = "data 파일 저장";
if (dlg.ShowDialog() == true) {
using (StreamWriter sw = new StreamWriter(dlg.FileName, false, Encoding.Default)) {
string oldCorrectionFile = IsVisionCalibration ?
_Scanner.Config.CorrectionFile : _Scanner.Config.LaserCorrectionFile;
FileInfo oldCorrectionFileInfo = new FileInfo(oldCorrectionFile);
sw.WriteLine(string.Format("OLDCTFILE\t= {0}", oldCorrectionFileInfo.Name));
sw.WriteLine(string.Format("NEWCTFILE\t= NewCorrectionTable.ct5"));
sw.WriteLine(string.Format("\r\nTOLERANCE\t= 1.0"));
uint newCal = (uint)Math.Round(_Scanner.Config.ScaleXYFactor);
sw.WriteLine(string.Format("\r\nNEWCAL\t= {0}", newCal));
//sw.WriteLine(string.Format("LIMITS"));
sw.WriteLine(string.Format("\r\n// RTC-X [Bit] RTC-Y[Bit] REAL-X[mm] REAL-Y[mm]\r\n"));
double visionX = 0;
double visionY = 0;
double realX = 0;
double realY = 0;
double tempX = 0;
double tempY = 0;
for (int i = 0; i < GridRowCount * GridColumnCount; i++) {
visionX = Convert.ToDouble(VisionCorrectionList[i].VisionX);
visionY = Convert.ToDouble(VisionCorrectionList[i].VisionY);
realX = Convert.ToDouble(VisionCorrectionList[i].MasterX);
realY = Convert.ToDouble(VisionCorrectionList[i].MasterY);
sw.WriteLine(string.Format("{0}\t{1}\t{2}\t{3}", visionX, visionY, realX, realY));
//string finalX;
//string finalY;
//if (tempX == 0)
//{
// finalX = "0,0";
//}
//else
//{
// string sX;
// string upperX;
// string lowerX;
// if ((Math.Round(tempX, 3) - Math.Truncate(tempX)) == 0)
// {
// sX = Convert.ToString(Math.Truncate(tempX));
// upperX = sX;
// lowerX = "0";
// }
// else
// {
// //sX = Convert.ToString(Math.Round(tempX, 3));
// sX = Math.Round(tempX, 3).ToString("f3");
// upperX = sX.Substring(0, sX.IndexOf("."));
// lowerX = sX.Substring(sX.IndexOf(".") + 1);
// }
// finalX = upperX + "," + lowerX;
//}
//if (tempY == 0)
//{
// finalY = "0,0";
//}
//else
//{
// string sY;
// string upperY;
// string lowerY;
// if ((Math.Round(tempY, 3) - Math.Truncate(tempY)) == 0)
// {
// sY = Convert.ToString(Math.Truncate(tempY));
// upperY = sY;
// lowerY = "0";
// }
// else
// {
// //sY = Convert.ToString(Math.Round(tempY, 3));
// sY = Math.Round(tempY, 3).ToString("f3");
// upperY = sY.Substring(0, sY.IndexOf("."));
// lowerY = sY.Substring(sY.IndexOf(".") + 1);
// }
// finalY = upperY + "," + lowerY;
//}
}
}
}
} catch (Exception ex) {
Log.E(string.Format(ex.Message));
}
}
private void PerformCmdRunCorreXionPro(object obj)
{
var filePath = ConfigurationManager.AppSettings.Get("DATA_PATH");
var fullPath = Path.Combine(filePath, "_device", "_scanner", "correXionPro.exe");
if (File.Exists(fullPath)) {
Process.Start(fullPath);
} else {
Log.I("correXionPro is not exist");
}
}
private void PerformCmdRunMarkGrid(object obj)
{
if (_ScannerConfig.UseMarkingOnTheFly == true) {
MessageUtil.ShowWarningToast(string.Format("Please Check Marking on the Fly(MOTF)"));
return;
}
if (VisionCorrectionList.Count <= 0 || LaserStatus == false) {
MessageUtil.ShowWarningToast(string.Format("Please Check DataCorrection or LaserStatus or LaserCalType"));
return;
}
var result = MessageUtil.ShowYesNoMessageDialog("Laser Calibration", "Start Laser Calibration Sequence?");
if (result == false) {
return;
}
if (_SeqMarkGrid.RunState == SequenceRunState.Running) {
MessageUtil.ShowWarningToast(string.Format("이미 시퀀스가 Start 상태입니다.", "_SeqMarkGrid"));
return;
}
var param = new SeqMarkGrid_InitParam() {
ColumnCount = GridColumnCount,
RowCount = GridRowCount,
UnitLength = UnitLength,
MarkPower = MarkPower,
MarkSpeed = MarkSpeed,
MarkLength = MarkLength,
IsModulation = IsModulation,
Frequnecy = Frequency,
PulseDulation = PulseDuration
};
IsSequenceRunning_MarkGrid = true;
_SeqMarkGrid.Start(param, OnCompleteMarkGrid);
}
private void OnCompleteMarkGrid(SequenceActionResult res)
{
if (res != null) {
if (res.Param is SeqMarkGrid_OutParam result && result.Success == true) {
IsSequenceRunning_MarkGrid = false;
MessageUtil.ShowSuccessToast(string.Format("Success SeqMarkGrid"));
return;
}
}
IsSequenceRunning_MarkGrid = false;
MessageUtil.ShowWarningToast(string.Format("Fail SeqMarkGrid"));
}
private void PerformCmdStopMarkGrid(object obj)
{
if (_SeqMarkGrid.RunState == SequenceRunState.Idle) {
return;
}
IsSequenceRunning_MarkGrid = false;
_SeqMarkGrid.Stop();
}
private void PerformCmdRunScannerCalibration(object obj)
{
if (_ScannerConfig.UseMarkingOnTheFly == true) {
MessageUtil.ShowWarningToast(string.Format("Please Check Marking on the Fly(MOTF)"));
return;
}
if (VisionCorrectionList.Count <= 0) {
MessageUtil.ShowWarningToast(string.Format("\"Please Check Data Correction apply"));
return;
}
var result = MessageUtil.ShowYesNoMessageDialog("Scanner Calibration", "Start Scanner Calibration Sequence?\nCheck Calibration Type\nTo calibrate after MarkGrid, CalType set to Laser");
if (result == false) {
return;
}
if (_SeqScannerCalibration.RunState == SequenceRunState.Running) {
MessageUtil.ShowWarningToast(string.Format("이미 시퀀스가 Start 상태입니다.", "_SeqScannerCalibration"));
return;
}
var param = new SeqScannerCalibration_InitParam() {
FovInfo = _FovInfo,
IsVisionCalibration = IsVisionCalibration,
ColumnCount = GridColumnCount,
RowCount = GridRowCount,
UnitLength = UnitLength,
TiltingDegree = TiltingDegree,
CheckOffset = OffsetThreshold,
MasterPosOffsetX = MPosOffsetX, // ian0513, 원본에는 MPosOffsetY 로 되어 있던데... 확인 필요.
MasterPosOffsetY = MPosOffsetY,
//1step Calibration Param
Is1StepCalibration = Is1StepCalibration,
RetryNum = RetryNum,
SelectedRowIndex = SelectedRowIndex
};
IsSequenceRunning_ScannerCalibration = true;
_SeqScannerCalibration.Start(param, OnCompleteScannerCalibration);
}
private void OnCompleteScannerCalibration(SequenceActionResult res)
{
if (res != null) {
if (res.Param is SeqScannerCalibration_OutParam result && result.Success == true) {
IsSequenceRunning_ScannerCalibration = false;
MessageUtil.ShowSuccessToast(string.Format("Success SeqScannerCalibration"));
return;
}
}
IsSequenceRunning_ScannerCalibration = false;
MessageUtil.ShowWarningToast(string.Format("Fail SeqScannerCalibration"));
}
private void PerformCmdStopScannerCalibration(object obj)
{
if (_SeqScannerCalibration.RunState == SequenceRunState.Idle) {
return;
}
IsSequenceRunning_ScannerCalibration = false;
_SeqScannerCalibration.Stop();
}
public void MoveScanner()
{
double scannerPosX = VisionCorrectionList[_SelectedRowIndex].MasterX;
double scannerPosY = VisionCorrectionList[SelectedRowIndex].MasterY;
var res = MessageUtil.ShowYesNoMessageDialog("Scanner", $"Move Scanner to Postion(X : {scannerPosX}, Y: {scannerPosY}) of Selected Cell?");
if (res) {
_Scanner.JumpAbs(scannerPosX, scannerPosY, eFunctionType.COMMAND);
}
}
private void InitializeDataGridViewItem(int columnCount, int rowCount, float unitLength, float tiltingDegree)
{
try {
VisionCorrectionList.Clear();
for (int column = 0; column < columnCount; column++) {
for (int row = 0; row < rowCount; row++) {
CorrectionUnit dtItem = new CorrectionUnit();
dtItem.Column = column + 1;
dtItem.Row = row + 1;
float tempX = unitLength * ((column % columnCount) - (columnCount - 1) / 2f);
float tempY = unitLength * ((row % rowCount) - (rowCount - 1) / 2f);
float masterX = tempX * (float)Math.Cos(tiltingDegree * Math.PI / 180) - tempY * (float)Math.Sin(tiltingDegree * Math.PI / 180);
float masterY = tempX * (float)Math.Sin(tiltingDegree * Math.PI / 180) + tempY * (float)Math.Cos(tiltingDegree * Math.PI / 180);
dtItem.MasterX = masterX;
dtItem.MasterY = masterY;
dtItem.VisionX = 0;
dtItem.VisionY = 0;
VisionCorrectionList.Add(dtItem);
}
}
} catch (Exception) {
MessageUtil.CreateAndShowMessageDialog("Correction", "Init Table Fail.");
}
}
private void PerformCmdFindPattern(object obj)
{
var cameraDisplay = CameraDisplayManager.GetDisplay(_FovInfo, eDisplayType.Pattern) as CameraDisplay;
var procPatternInfo = VisionRecipeManager.GetProcPatternInfo(_FovInfo, "Align1", eProcPatternId.ProcPattern1);
var patternInfo = _PatternAgent.GetPatternInfo(_FovInfo, procPatternInfo.PatternId);
// Live GrabImage 또는 LoadImage 둘다 사용할 수 있도록 한다.
if (IsGrabLiveLimage) {
_CameraAgent.GrabSync(cameraDisplay, ref _GrabImage);
} else {
_GrabImage = cameraDisplay.GetImage();
}
if (_GrabImage != null) {
_PatternResult = _PatternAgent.Find(patternInfo, _GrabImage, cameraDisplay);
} else {
Log.W("GrabImage is Null");
}
if(_PatternResult.Status == eFoundStatus.FoundOK) {
var resultsList = _PatternResult.Results.ToList();
PatternCorrectionList.Clear();
for (int i = 0; i < resultsList.Count; i++) {
PatternCorrectionUnit patternCorrectionUnit = new PatternCorrectionUnit();
patternCorrectionUnit.Index = i;
patternCorrectionUnit.PosX = Math.Round(resultsList[i].ImagePosition.X, 3);
patternCorrectionUnit.PosY = Math.Round(resultsList[i].ImagePosition.Y, 3);
PatternCorrectionList.Add(patternCorrectionUnit);
}
_PatternAgent.Draw(patternInfo, _PatternResult, cameraDisplay);
} else {
Log.W("Pattern is not found.");
}
}
private void PerformCmdCalculateDistance(object obj)
{
try {
List<double> lsDistances = new List<double>();
foreach (var item1 in PatternCorrectionList) {
double dDistanceMin = double.MaxValue;
foreach (var item2 in PatternCorrectionList) {
if (item1 == item2) continue;
double dDistance = Math.Sqrt(Math.Pow(item2.PosX - item1.PosX, 2) + Math.Pow(item2.PosY - item1.PosY, 2));
if (dDistance > PixelDistanceMin && dDistance < PixelDistanceMax)
lsDistances.Add(dDistance);
if (dDistance < dDistanceMin) {
dDistanceMin = dDistance;
}
}
if (lsDistances.Count > 0) {
item1.Distance = lsDistances.Average();
} else {
item1.Distance = dDistanceMin;
}
}
if (PatternCorrectionList.Count > 0) {
DistanceAverage = Math.Round(PatternCorrectionList.Average(x => x.Distance), 3);
} else {
DistanceAverage = 0;
}
LensMagnification = (DistanceAverage * _SystemParameter.CameraPixelSize) / (ReferenceDistance * 1000.0);
} catch (Exception e) {
Log.W($"{e.Message}");
}
}
}
public class CorrectionUnit : NotifyPropertyChangedBase
{
private int _Column;
public int Column { get => _Column; set => SetProperty(ref _Column, value); }
private int _Row;
public int Row { get => _Row; set => SetProperty(ref _Row, value); }
private float _MasterX;
public float MasterX { get => _MasterX; set => SetProperty(ref _MasterX, value); }
private float _MasterY;
public float MasterY { get => _MasterY; set => SetProperty(ref _MasterY, value); }
private int _VisionX;
public int VisionX { get => _VisionX; set => SetProperty(ref _VisionX, value); }
private int _VisionY;
public int VisionY { get => _VisionY; set => SetProperty(ref _VisionY, value); }
}
public class PatternCorrectionUnit : NotifyPropertyChangedBase
{
public int Index { get; set; }
private double _PosX;
public double PosX { get => _PosX; set => SetProperty(ref _PosX, value); }
private double _PosY;
public double PosY { get => _PosY; set => SetProperty(ref _PosY, value); }
// Distance : 가장 가까운 cross line 과의 거리
private double _Distance;
public double Distance { get => _Distance; set => SetProperty(ref _Distance, value); }
}
}