update toolblock for get circle center

This commit is contained in:
2025-11-21 14:48:46 +08:00
parent 091ce9b21f
commit cf0dfd1619
14 changed files with 825 additions and 370 deletions

View File

@@ -161,7 +161,6 @@ namespace WaferAlignment
_dev.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE);
_dev.MV_CC_StartGrabbing_NET();
_dev.MV_CC_TriggerSoftwareExecute_NET();
Thread.Sleep(100);
}
public void Stop()
@@ -195,7 +194,7 @@ namespace WaferAlignment
try
{
_startAcqToken.Cancel();
Thread.Sleep(20);
Thread.Sleep(200);
_imageAcquisitionTask.Wait(_stopAcqToken.Token);
_imageAcquisitionTask.Dispose();
}

View File

@@ -16,7 +16,7 @@ namespace ConVX.VXData
/// <summary>
/// 判断线程状态
/// </summary>
private AutoResetEvent _autoReset = null;
//private AutoResetEvent _autoReset = null;
/// <summary>
/// 线程
/// </summary>
@@ -53,7 +53,7 @@ namespace ConVX.VXData
public DataPostbox()
{
_queue = new ConcurrentQueue<CogImage8Grey>();
_autoReset = new AutoResetEvent(false);//线程非终止状态
//_autoReset = new AutoResetEvent(false);//线程非终止状态
}
/// <summary>
/// 启动派发
@@ -72,7 +72,7 @@ namespace ConVX.VXData
try
{
RuningToken.Cancel();
_autoReset.Set();//为了避免线程正在执行或等待状态
//_autoReset.Set();//为了避免线程正在执行或等待状态
await _task;
}
catch (OperationCanceledException ex)
@@ -98,7 +98,7 @@ namespace ConVX.VXData
//}
_queue.Enqueue(envelope);
_autoReset.Set();
//_autoReset.Set();
}
#endregion
@@ -110,7 +110,8 @@ namespace ConVX.VXData
{
if (_queue.IsEmpty)
{
_autoReset.WaitOne();
//_autoReset.WaitOne();
Thread.Sleep(1);
}
else
{

View File

@@ -0,0 +1,101 @@
using Cognex.VisionPro;
using Cognex.VisionPro.PMAlign;
using Cognex.VisionPro.ToolBlock;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Documents;
namespace WaferAdjust
{
public delegate void OnFitCircleResult(double x, double y, double r, double rms);
internal class FitCircleToolBlock
{
private CogToolBlock cogToolBlock;
private bool initialized = false;
public event OnToolReady OnToolReady;
public event OnFitCircleResult OnFitCircleResult;
public CogImage8Grey FitCircleImage;
public void Initialize(string vpp)
{
try
{
if (cogToolBlock != null)
{
cogToolBlock.Ran -= CogToolBlock_Ran;
cogToolBlock.Dispose();
cogToolBlock = null;
}
initialized = false;
cogToolBlock = CogSerializer.LoadObjectFromFile(vpp) as CogToolBlock;
cogToolBlock.Ran += CogToolBlock_Ran;
initialized = true;
OnToolReady?.Invoke(initialized);
LogHelper.LogInfo("FitCircleToolBlock initialized successfully: " + vpp);
}
catch (Exception ex)
{
LogHelper.LogError(ex.Message);
}
}
private void CogToolBlock_Ran(object sender, EventArgs e)
{
try
{
FitCircleImage = cogToolBlock.Outputs["OutputImage"].Value as CogImage8Grey;
OnFitCircleResult?.Invoke(Math.Round((double)cogToolBlock.Outputs["CenterX"].Value, 3),
Math.Round((double)cogToolBlock.Outputs["CenterY"].Value, 3),
Math.Round((double)cogToolBlock.Outputs["Radius"].Value, 3),
Math.Round((double)cogToolBlock.Outputs["RMSError"].Value, 3));
}
catch (Exception ex)
{
LogHelper.LogError(ex.Message + ex.StackTrace);
}
}
public void Run(Bitmap bmp, List<PointInfo> pointInfos)
{
try
{
CogImage8Grey image8Grey = new CogImage8Grey(bmp);
Run(image8Grey, pointInfos);
}
catch (Exception ex)
{
LogHelper.LogError("ScanToolBlock Run Error: " + ex.Message);
}
}
public void Run(CogImage8Grey image8Grey, List<PointInfo> pointInfos)
{
try
{
cogToolBlock.Inputs["OutputImage"].Value = image8Grey;
CogFitCircleTool fitCircleTool = cogToolBlock.Tools["CogFitCircleTool1"] as CogFitCircleTool;
fitCircleTool.RunParams.NumPoints = 0;
foreach (var item in pointInfos)
fitCircleTool.RunParams.AddPoint(item.X, item.Y);
cogToolBlock.Run();
}
catch (Exception ex)
{
LogHelper.LogError("ScanToolBlock Run Error: " + ex.Message);
}
}
public bool Ready()
{
return initialized;
}
public void Stop()
{
if (cogToolBlock != null)
{
cogToolBlock.Ran -= CogToolBlock_Ran;
cogToolBlock.Dispose();
cogToolBlock = null;
}
}
}
}

View File

@@ -68,6 +68,10 @@
this.nud_SizeX = new System.Windows.Forms.NumericUpDown();
this.btn_Action = new System.Windows.Forms.Button();
this.btn_ToZero = new System.Windows.Forms.Button();
this.textBox2 = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.textBox3 = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.Panel2.SuspendLayout();
@@ -93,6 +97,10 @@
//
// splitContainer1.Panel2
//
this.splitContainer1.Panel2.Controls.Add(this.textBox2);
this.splitContainer1.Panel2.Controls.Add(this.label1);
this.splitContainer1.Panel2.Controls.Add(this.textBox3);
this.splitContainer1.Panel2.Controls.Add(this.label2);
this.splitContainer1.Panel2.Controls.Add(this.lbl_Time);
this.splitContainer1.Panel2.Controls.Add(this.txt_Time);
this.splitContainer1.Panel2.Controls.Add(this.lbl_Times);
@@ -167,7 +175,7 @@
// lbl_Times
//
this.lbl_Times.AutoSize = true;
this.lbl_Times.Location = new System.Drawing.Point(234, 15);
this.lbl_Times.Location = new System.Drawing.Point(182, 17);
this.lbl_Times.Name = "lbl_Times";
this.lbl_Times.Size = new System.Drawing.Size(89, 12);
this.lbl_Times.TabIndex = 30;
@@ -175,7 +183,7 @@
//
// txt_Times
//
this.txt_Times.Location = new System.Drawing.Point(326, 12);
this.txt_Times.Location = new System.Drawing.Point(274, 14);
this.txt_Times.Name = "txt_Times";
this.txt_Times.ReadOnly = true;
this.txt_Times.Size = new System.Drawing.Size(129, 21);
@@ -383,9 +391,9 @@
//
// btn_RunTest
//
this.btn_RunTest.Location = new System.Drawing.Point(481, 12);
this.btn_RunTest.Location = new System.Drawing.Point(409, 14);
this.btn_RunTest.Name = "btn_RunTest";
this.btn_RunTest.Size = new System.Drawing.Size(161, 23);
this.btn_RunTest.Size = new System.Drawing.Size(119, 23);
this.btn_RunTest.TabIndex = 9;
this.btn_RunTest.Text = "启动检测";
this.btn_RunTest.UseVisualStyleBackColor = true;
@@ -444,6 +452,7 @@
0,
0,
-2147483648});
this.nud_SizeY.ValueChanged += new System.EventHandler(this.nud_SizeY_ValueChanged);
//
// lbl_X
//
@@ -458,8 +467,13 @@
//
this.nud_SizeX.DecimalPlaces = 2;
this.nud_SizeX.Location = new System.Drawing.Point(80, 137);
this.nud_SizeX.Maximum = new decimal(new int[] {
6,
0,
0,
0});
this.nud_SizeX.Minimum = new decimal(new int[] {
100,
8,
0,
0,
-2147483648});
@@ -471,6 +485,7 @@
0,
0,
0});
this.nud_SizeX.ValueChanged += new System.EventHandler(this.nud_SizeX_ValueChanged);
//
// btn_Action
//
@@ -484,7 +499,7 @@
//
// btn_ToZero
//
this.btn_ToZero.Location = new System.Drawing.Point(17, 99);
this.btn_ToZero.Location = new System.Drawing.Point(17, 95);
this.btn_ToZero.Name = "btn_ToZero";
this.btn_ToZero.Size = new System.Drawing.Size(161, 23);
this.btn_ToZero.TabIndex = 0;
@@ -492,6 +507,42 @@
this.btn_ToZero.UseVisualStyleBackColor = true;
this.btn_ToZero.Click += new System.EventHandler(this.btn_ToZero_Click);
//
// textBox2
//
this.textBox2.Location = new System.Drawing.Point(534, 22);
this.textBox2.Name = "textBox2";
this.textBox2.Size = new System.Drawing.Size(55, 21);
this.textBox2.TabIndex = 33;
this.textBox2.Text = "82";
this.textBox2.TextChanged += new System.EventHandler(this.textBox2_TextChanged);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(532, 7);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(53, 12);
this.label1.TabIndex = 34;
this.label1.Text = "相机计数";
//
// textBox3
//
this.textBox3.Location = new System.Drawing.Point(595, 22);
this.textBox3.Name = "textBox3";
this.textBox3.Size = new System.Drawing.Size(55, 21);
this.textBox3.TabIndex = 35;
this.textBox3.Text = "4096";
this.textBox3.TextChanged += new System.EventHandler(this.textBox3_TextChanged);
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(593, 7);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(41, 12);
this.label2.TabIndex = 36;
this.label2.Text = "总计数";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
@@ -556,7 +607,10 @@
private System.Windows.Forms.DataGridViewTextBoxColumn Column4;
private System.Windows.Forms.Label lbl_Time;
private System.Windows.Forms.TextBox txt_Time;
private System.Windows.Forms.TextBox textBox2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox textBox3;
private System.Windows.Forms.Label label2;
}
}

View File

@@ -19,6 +19,7 @@ using System.Windows.Forms;
using System.Xml.Serialization;
using System.Diagnostics;
using Cognex.VisionPro.PMAlign;
using WaferAdjust;
namespace WaferAlignment
@@ -54,20 +55,12 @@ namespace WaferAlignment
/// </summary>
string arAngle = "DB7.DBD76";//设置触发拍照的偏转角度
GetCircleToolBlock getCircleMachineToolBlock;
FitCircleToolBlock FitCircleMachineToolBlock;
TranslateCirclePoint translateCirclePoint;
CogGraphicCollection m_graphics;
CogGraphicCollection m_graphics2;
string vppPath;
CogToolBlock mTB;
CogToolBlock mTB_1;
CogToolBlock mTB_2;
float R = 11.25F;//1024->12
//CogImage8Grey OutputImg;
//旋转中心的坐标应将标定的数据保存后获取
double circleCenterX;
double circleCenterY;
//XML文件读取与写入
ConfigStore _ConfigStore = new ConfigStore();
CenterOfRotation _center = new CenterOfRotation();
@@ -123,7 +116,6 @@ namespace WaferAlignment
_s7.SetValue(arSizeX, (float)0);
_s7.SetValue(arSizeY, (float)0);
_s7.SetValue(arSizeR, (float)0);
_s7.SetValue(arAngle, Convert.ToSingle(R));//角度为10
lbl_CommunState.BackColor = Color.Lime;
lbl_CommunState.Text = "已连接";
}
@@ -150,9 +142,16 @@ namespace WaferAlignment
try
{
// 加载VPP文件
vppPath = Path.Combine(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "vpp", "ToolBlock.vpp");
getCircleMachineToolBlock = new GetCircleToolBlock();
getCircleMachineToolBlock.OnGetCircleResult += GetCircleMachineToolBlock_OnGetCircleResult;
getCircleMachineToolBlock.OnGetNashResult += GetCircleMachineToolBlock_OnGetNashResult;
getCircleMachineToolBlock.OnToolReady += GetCircleMachineToolBlock_OnToolReady;
mTB = CogSerializer.LoadObjectFromFile(vppPath) as CogToolBlock;
FitCircleMachineToolBlock = new FitCircleToolBlock();
FitCircleMachineToolBlock.OnFitCircleResult += FitCircleMachineToolBlock_OnFitCircleResult;
FitCircleMachineToolBlock.OnToolReady += FitCircleMachineToolBlock_OnToolReady;
translateCirclePoint = new TranslateCirclePoint();
m_graphics2 = new CogGraphicCollection();
}
catch (Exception ex)
{
@@ -171,15 +170,117 @@ namespace WaferAlignment
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void FitCircleMachineToolBlock_OnToolReady(bool ready)
{
LogHelper.LogInfo("FitCircleMachineToolBlock_OnToolReady");
}
private void FitCircleMachineToolBlock_OnFitCircleResult(double x, double y, double r, double rms)
{
TCP_X = x.ToString("F4");
TCP_Y = y.ToString("F4");
TCP_RMS = rms.ToString("F4");
TCP_R = r.ToString("F4");
deviationX = Math.Round((x - translateCirclePoint.GetRotateX()), 3);
deviationY = Math.Round((y - translateCirclePoint.GetRotateY()), 3);
AddPointMarker(m_graphics2, x, y);
AddPointMarker(m_graphics2, translateCirclePoint.GetRotateX(), translateCirclePoint.GetRotateY(), CogColorConstants.Red);
PointInfo nPoint = translateCirclePoint.GetNashPoint();
if (nPoint != null)
{
AddPointMarker(m_graphics2, nPoint.X, nPoint.Y, CogColorConstants.Yellow);
AddLineMarker(m_graphics2, x, y, x, y - r);
AddLineMarker(m_graphics2, x, y, nPoint.X, nPoint.Y, CogColorConstants.Yellow);
angle = GetCounterClockwiseAngle360(x, y, x, y - r, nPoint.X, nPoint.Y);
AddLabelMarker(m_graphics2, angle.ToString(), x, y, CogColorConstants.Yellow);
LogHelper.LogInfo($"nash degree:{angle}");
}
// 指定XML文件路径
string filePath = Path.Combine(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "vpp", "CenterOfRotation.xml"); //@"D:\晶圆寻边机\XML文件\CenterOfRotation.xml";
_center = _ConfigStore.ReadConfigFromFile(_center.GetType(), filePath) as CenterOfRotation;
circleCenterX = _center.Center_X;
circleCenterY = _center.Center_Y;
LogHelper.LogInfo($"X:{x}, Y:{y}, RMS:{rms}");
LogHelper.LogInfo($"DiffX:{deviationX}, DiffY:{deviationY}, RMS:{rms}{Environment.NewLine}");
ImageDisplay(FitCircleMachineToolBlock.FitCircleImage);
ImageDisplay(m_graphics);
ImageDisplay(m_graphics2);
ImageDisplayFit();
}
private void AddPointMarker(CogGraphicCollection graphicCollection, double x, double y, CogColorConstants color = CogColorConstants.Green)
{
CogPointMarker marker = new CogPointMarker();
marker.X = x;
marker.Y = y;
marker.Color = color;
marker.Interactive = false;
graphicCollection.Add(marker);
}
private void AddLineMarker(CogGraphicCollection graphicCollection, double x1, double y1, double x2, double y2, CogColorConstants color = CogColorConstants.Green)
{
CogLineSegment line = new CogLineSegment();
line.SetStartEnd((int)x1, (int)y1, (int)x2, (int)y2);
line.Color = color;
line.Interactive = false;
graphicCollection.Add(line);
}
private void AddLabelMarker(CogGraphicCollection graphicCollection, string text, double x, double y, CogColorConstants color = CogColorConstants.Green)
{
CogGraphicLabel label = new CogGraphicLabel();
label.Text = text;
label.X = x;
label.Y = y;
label.Color = color;
graphicCollection.Add(label);
}
/// <summary>
/// 计算从 lineA 到 lineB 的逆时针有向角度0-360度
/// 坐标系:向右为正,向下为正(标准屏幕坐标系)
/// </summary>
public double GetCounterClockwiseAngle360(double x, double y, double x1, double y1, double x2, double y2)
{
// 2. 获取方向向量dy 向下为正)
double dxA = x1 - x;
double dyA = y1 - y;
double dxB = x2 - x;
double dyB = y2 - y;
// 3. 将Y轴翻转转换为标准数学坐标系dy向上为正
// 这样 Math.Atan2 返回的就是标准数学角度(逆时针为正)
double angleA = Math.Atan2(-dyA, dxA); // 注意y取负号
double angleB = Math.Atan2(-dyB, dxB); // 注意y取负号
// 4. 计算逆时针角度差(弧度)
double angleDiff = angleB - angleA;
// 5. 转换为角度并规范化为 [0, 360)
double angleDegrees = angleDiff * 180.0 / Math.PI;
angleDegrees = angleDegrees % 360.0;
if (angleDegrees < 0) angleDegrees += 360.0;
return Math.Round(angleDegrees, 3);
}
private void GetCircleMachineToolBlock_OnToolReady(bool ready)
{
LogHelper.LogInfo("GetCircleMachineToolBlock_OnToolReady");
}
private void GetCircleMachineToolBlock_OnGetNashResult(double x, double y)
{
translateCirclePoint.AddNashPoint(x, y);
LogHelper.LogInfo($"Update Nash X:{x}, Y:{y}");
}
private void GetCircleMachineToolBlock_OnGetCircleResult(double x, double y, double r)
{
translateCirclePoint.AddCircleCenter(x, y, r);
translateCirclePoint.AddCirclePoint(getCircleMachineToolBlock.PointInfos);
LogHelper.LogInfo($"X:{x}, Y:{y}, R:{r}");
}
/// <summary>
/// 接收到TCP数据时根据接收到的数据进行不同操作
/// </summary>
@@ -217,17 +318,11 @@ namespace WaferAlignment
_tcp.SendData(e.ClientIp, "DetectionTime" + TCP_time + " " + "X" + TCP_X + " " + "Y" + TCP_Y + " " + "Angle" + TCP_R + " " + "RMS" + TCP_RMS);
}
}
}
void _cam_OutputImageEvent(Bitmap obj)
{
lstNasR.Add((acqNum + 1) * R);
acqNum++;
//lstNasR.Add((testNum) * R);
//保存图像
//SaveImage(new CogImage8Grey(obj));
ImageData.Mailing(new CogImage8Grey(obj));
Images.Add(new CogImage8Grey(obj));
@@ -235,10 +330,9 @@ namespace WaferAlignment
void ImageData_ErrorEvent(string obj)
{
//throw new NotImplementedException();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
try
@@ -300,7 +394,6 @@ namespace WaferAlignment
this.splitContainer1.Invoke(new Action(() => this.splitContainer1.Panel2.Enabled = true));
});
}
public string ToZero()
{
if (_s7 != null)
@@ -393,15 +486,7 @@ namespace WaferAlignment
}
}
List<double> lstRotation;
List<double> lstX;
List<double> lstY;
List<double> lstRadius;
List<double> lstNasX;
List<double> lstNasY;
List<double> lstNasR;
List<CogImage8Grey> Images;
int acqNum = 0;
int testNum = 0;
double angle = 0;
@@ -411,9 +496,11 @@ namespace WaferAlignment
private void btn_RunTest_Click(object sender, EventArgs e)
{
SavePath = Path.Combine(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "SaveImage", DateTime.Now.ToString("yyyyMMdd_HHmmss"));
m_cameraCount = Convert.ToDouble(textBox2.Text);
m_codeCount = Convert.ToDouble(textBox3.Text);
m_roateX = Convert.ToDouble(nud_SizeX.Value);
m_roateY = Convert.ToDouble(nud_SizeY.Value);
ClearDisplay();
////---------------------------------------
Task.Run(() =>
{
this.splitContainer1.Invoke(new Action(() => this.splitContainer1.Panel2.Enabled = false));
@@ -423,8 +510,6 @@ namespace WaferAlignment
this.splitContainer1.Invoke(new Action(() => this.splitContainer1.Panel2.Enabled = true));
});
//---------------------------------------
}
public string RunTest()
@@ -436,7 +521,6 @@ namespace WaferAlignment
}
else
{
//R轴回0
if (_s7 != null)
{
@@ -480,13 +564,6 @@ namespace WaferAlignment
angle = 0;
acqNum = 0;
testNum = 0;
lstRotation = new List<double>();
lstX = new List<double>();
lstY = new List<double>();
lstRadius = new List<double>();
lstNasX = new List<double>();
lstNasY = new List<double>();
lstNasR = new List<double>();
Images = new List<CogImage8Grey>();
sw_1 = new Stopwatch();//检测时间
@@ -495,6 +572,7 @@ namespace WaferAlignment
deviationY = 0;
times = 0;
//启动拍照
translateCirclePoint.SetRotateXY(m_roateX, m_roateY, 360 * m_cameraCount / m_codeCount);
if (_s7 != null)
{
@@ -529,9 +607,7 @@ namespace WaferAlignment
}
}
//Thread.Sleep(100);
}
}
_cam.SoftwareGrab();
@@ -644,327 +720,62 @@ namespace WaferAlignment
return "NG_RUN";
}
}
private CogImage8Grey m_lastImage;
//所有点
// 调整vpp中CogCaliperTool工具数据需要同时调整Y值与 for (double i = Y; i < 12; i = i + 0.5)中12的值
private void MonitorSpot(CogImage8Grey outputImg)
{
sw_1 = new Stopwatch();//检测时间
sw_1.Start();
//double Y = -17;
//double X = 0;
double X = -15;
double Y = 0;
CogImage8Grey inputImg = new CogImage8Grey();
CogGraphicCollection graphics = new CogGraphicCollection();
CogImage8Grey _OutputImg = new CogImage8Grey();
inputImg = outputImg;
mTB_1 = mTB.Tools["CogToolBlock1"] as CogToolBlock;
mTB_2 = mTB.Tools["CogToolBlock2"] as CogToolBlock;
mTB_1.Inputs["InputImage"].Value = inputImg;
mTB_1.Run();
_OutputImg = mTB_1.Outputs["OutputImage"].Value as CogImage8Grey;
translateCirclePoint.AddCircleIndex();
m_lastImage = outputImg;
getCircleMachineToolBlock.Run(outputImg);
CogCaliperTool mCT = mTB_1.Tools["CogCaliperTool1"] as CogCaliperTool;
//x= cx + (xcx)⋅cos(r)(ycy)⋅sin(r)
//y= cy + (xcx)⋅sin(r) + (ycy)⋅cos(r)
int _count = 0;
for (double i = X; i < 14; i = i + 0.5)
{
mCT.InputImage = _OutputImg;
mCT.Region.CenterX = i;
mCT.Run();
_count = mCT.Results.Count;
if (_count != 0)
{
Y = mCT.Results[0].Edge0.PositionY;
//旋转角度
double r = lstNasR[testNum] / 180 * Math.PI;
//旋转移动到实际位置
lstNasX.Add(i * Math.Cos(r) - Y * Math.Sin(r) + circleCenterX * (1 - Math.Cos(r)) + circleCenterY * Math.Sin(r));
lstNasY.Add(i * Math.Sin(r) + Y * Math.Cos(r) - circleCenterX * Math.Sin(r) + circleCenterY * (1 - Math.Cos(r)));
CogPointMarker marker_1 = new CogPointMarker();//圆
marker_1.X = i;
marker_1.Y = Y;
marker_1.Color = CogColorConstants.Blue;
marker_1.Interactive = false;
graphics.Add(marker_1);
}
else
{
OKorNG = false;
testNum++;
return;
}
if (i == X)
{
double r = lstNasR[testNum] / 180 * Math.PI;
lstX.Add(i * Math.Cos(r) - Y * Math.Sin(r) + circleCenterX * (1 - Math.Cos(r)) + circleCenterY * Math.Sin(r));
lstY.Add(i * Math.Sin(r) + Y * Math.Cos(r) - circleCenterX * Math.Sin(r) + circleCenterY * (1 - Math.Cos(r)));
}
}
sw_1.Stop();
TimeSpan ts = sw_1.Elapsed;
ImageDisplay(_OutputImg, graphics);
DataDisplay(lstNasR[testNum], lstNasX[0], lstNasY[0], ts.TotalMilliseconds);
PointInfo pp = translateCirclePoint.GetFirstPoint();
if (pp != null)
DataDisplay(translateCirclePoint.GetCurrentDegree(), pp.X, pp.Y, ts.TotalMilliseconds);
else
DataDisplay(translateCirclePoint.GetCurrentDegree(), 0, 0, ts.TotalMilliseconds);
testNum++;
times += ts.TotalMilliseconds;
OKorNG = true;
}
//比较半径和点间距,拟合圆
private void FitCircle()
{
if (OKorNG)
{
sw_2 = new Stopwatch();//检测时间
sw_2.Start();
int Image_i = -1;
// 调整vpp中CogCaliperTool工具数据需要同时调整step为x点数*2
int step = 58;
CogPMAlignTool mPM = mTB_2.Tools["CogPMAlignTool2"] as CogPMAlignTool;
LogHelper.LogInfo("转换机械坐标系下圆弧各点的原始坐标:\n");
var points = translateCirclePoint.DoTranslatePoint();
translateCirclePoint.DoTranslateNashPoint();
CogImage8Grey outputImg = mTB_1.Outputs["OutputImage"].Value as CogImage8Grey;
//添加找圆工具的 忽略点数 和 RMS偏差量
CogFitCircleTool fitCircle_1 = new CogFitCircleTool();
CogFitCircleTool fitCircle_2 = new CogFitCircleTool();
CogGraphicCollection graphics = new CogGraphicCollection();
fitCircle_1.InputImage = outputImg;
for (int i = 0; i < lstX.Count; i++)
LogHelper.LogInfo("拟合机械坐标系下的圆中心:\n");
m_graphics = new CogGraphicCollection();
m_graphics2 = new CogGraphicCollection();
foreach (PointInfo pointInfo in points)
{
fitCircle_1.RunParams.AddPoint(lstX[i], lstY[i]);
//CogPointMarker marker_1 = new CogPointMarker();//圆
//marker_1.X = lstNasX[i];
//marker_1.Y = lstNasY[i];
//marker_1.Color = CogColorConstants.White;
//marker_1.Interactive = false;
//graphics.Add(marker_1);
AddPointMarker(m_graphics, pointInfo.X, pointInfo.Y);
}
//fitCircle_1.RunParams.NumToIgnore = 0;
fitCircle_1.Run();
if (fitCircle_1.Result != null)
{
double _RMS = fitCircle_1.Result.RMSError;
CogCircle circle_1 = new CogCircle(fitCircle_1.Result.GetCircle());
circle_1.Color = CogColorConstants.Cyan;
circle_1.Interactive = false;
FitCircleMachineToolBlock.Run(m_lastImage, points);
CogFitLineTool fitLine = new CogFitLineTool();
sw_2.Stop();
TimeSpan ts = sw_2.Elapsed;
//晶圆圆心位置
double _centerX = circle_1.CenterX;
double _centerY = circle_1.CenterY;
double _radius = circle_1.Radius;
times += ts.TotalMilliseconds;
TCP_time = ts.TotalMilliseconds.ToString();
fitCircle_2.InputImage = outputImg;
CogDistancePointPointTool pTp = new CogDistancePointPointTool();
pTp.InputImage = outputImg;
pTp.StartX = _centerX;
pTp.StartY = _centerY;
//double[] _DistanceMin = new double[lstNasX.Count];
//int _distanceMin_i = 0;
for (int i = 0; i < lstNasX.Count; i += step)
{
for (int j = i; j < i + step && j < lstNasX.Count; j++)
{
if (j < (i + step - 15))//忽略重合数据的末尾的15个点
{
pTp.EndX = lstNasX[j];
pTp.EndY = lstNasY[j];
pTp.Run();
double Distance = pTp.Distance;
if (Distance - _radius < 0.1 && Distance - _radius > -0.1)
{
fitCircle_2.RunParams.AddPoint(lstNasX[j], lstNasY[j]);
CogPointMarker marker_1 = new CogPointMarker();//圆
marker_1.X = lstNasX[j];
marker_1.Y = lstNasY[j];
marker_1.Color = CogColorConstants.Green;
marker_1.Interactive = false;
graphics.Add(marker_1);
}
else//忽略的点数
{
if (!(Distance - _radius < 1 && Distance - _radius > -1))
{
if (Image_i == -1)
{
Image_i = (int)(j / step);
}
}
CogPointMarker marker_1 = new CogPointMarker();//圆
marker_1.X = lstNasX[j];
marker_1.Y = lstNasY[j];
marker_1.Color = CogColorConstants.Yellow;
marker_1.Interactive = false;
graphics.Add(marker_1);
}
//_DistanceMin[i] = Distance;
}
else
{
CogPointMarker marker_1 = new CogPointMarker();//圆
marker_1.X = lstNasX[j];
marker_1.Y = lstNasY[j];
marker_1.Color = CogColorConstants.Red;
marker_1.Interactive = false;
//graphics.Add(marker_1);
}
}
}
//忽略的拟合点数
fitCircle_2.RunParams.NumToIgnore = 0;
fitCircle_2.Run();
double RMS = fitCircle_2.Result.RMSError;
CogCircle circle_2 = new CogCircle(fitCircle_2.Result.GetCircle());
circle_2.Color = CogColorConstants.Cyan;
circle_2.Interactive = false;
//晶圆圆心位置
double centerX = circle_2.CenterX;
double centerY = circle_2.CenterY;
double radius = circle_2.Radius;
double PM_X = 0;
double PM_Y = 0;
int _count = 0;
if (Image_i != -1)
{
mTB_2.Inputs["InputImage"].Value = Images[Image_i];
mTB_2.Run();
_count = mPM.Results.Count;
if (_count != 0)
{
double r = lstNasR[Image_i] / 180 * Math.PI;
PM_X = mPM.Results[0].GetPose().TranslationX * Math.Cos(r) - mPM.Results[0].GetPose().TranslationY * Math.Sin(r) + circleCenterX * (1 - Math.Cos(r)) + circleCenterY * Math.Sin(r);
PM_Y = mPM.Results[0].GetPose().TranslationX * Math.Sin(r) + mPM.Results[0].GetPose().TranslationY * Math.Cos(r) - circleCenterX * Math.Sin(r) + circleCenterY * (1 - Math.Cos(r));
}
}
//_distanceMin_i = DistanceMin(_DistanceMin);
////纳什口
//CogLine line_ = new CogLine();
//line_.SetFromStartXYEndXY(centerX, centerY, lstNasX[_distanceMin_i], lstNasY[_distanceMin_i]);
//line_.Color = CogColorConstants.Green;
//line_.Interactive = false;
//graphics.Add(line_);
//纳什口
CogLine line_ = new CogLine();
line_.SetFromStartXYEndXY(centerX, centerY, PM_X, PM_Y);
line_.Color = CogColorConstants.Green;
line_.Interactive = false;
graphics.Add(line_);
//角度值为0
CogLine line_0 = new CogLine();
line_0.SetXYRotation(centerX, centerY, 0);
line_0.Color = CogColorConstants.Blue;
line_0.Interactive = false;
graphics.Add(line_0);
CogAngleLineLineTool llTool = new CogAngleLineLineTool();
llTool.InputImage = outputImg;
llTool.LineA = line_0;
llTool.LineB = line_;
llTool.Run();
angle = CogMisc.RadToDeg(llTool.Angle);
CogPointMarker marker_2 = new CogPointMarker();//圆心
marker_2.X = centerX;
marker_2.Y = centerY;
marker_2.Color = CogColorConstants.Green;
marker_2.Interactive = false;
graphics.Add(marker_2);
CogPointMarker marker_3 = new CogPointMarker();//旋转圆心
marker_3.X = circleCenterX;
marker_3.Y = circleCenterY;
marker_3.Color = CogColorConstants.Orange;
marker_3.Interactive = false;
graphics.Add(marker_3);
graphics.Add(circle_2);
deviationX = centerX - circleCenterX;
deviationY = centerY - circleCenterY;
sw_2.Stop();
TimeSpan ts = sw_2.Elapsed;
times += ts.TotalMilliseconds;
ImageDisplay(outputImg, graphics);
TCP_time = ts.TotalMilliseconds.ToString();
TCP_X = centerX.ToString("F4");
TCP_Y = centerY.ToString("F4");
TCP_RMS = RMS.ToString("F4");
TCP_R = angle.ToString("F4");
ResultDisplay(times, ts.TotalMilliseconds, centerX, centerY, radius, RMS, deviationX, deviationY, angle);
OKorNG = true;
}
else
{
//MessageBox.Show("检测结果为空。");
OKorNG = false;
}
ResultDisplay(times, ts.TotalMilliseconds, TCP_X, TCP_Y, TCP_R, TCP_RMS, deviationX, deviationY, angle);
}
}
//private int DistanceMin(double[] numbers)
//{
// double number = numbers[0];
// int num1 = 0;
// double num2 = ((IEnumerable<double>)numbers).Sum() / (double)((IEnumerable<double>)numbers).Count<double>();
// for (int index = 1; index < numbers.Length; ++index)
// {
// if (numbers[index] < number)
// {
// number = numbers[index];
// num1 = index;
// }
// }
// //return Math.Abs(number - num2) > 0.0 ? num1 : -1;
// return num1;
//}
private void ResultDisplay(double Times,double Time, double X, double Y, double R, double RMS, double dX, double dY, double dR)
private void ResultDisplay(double Times,double Time, string X, string Y, string R, string RMS, double dX, double dY, double dR)
{
if (this.InvokeRequired)
{
@@ -1013,7 +824,6 @@ namespace WaferAlignment
return;
}
this.cogRecordDisplay1.StaticGraphics.AddList(graphics, "");
this.cogRecordDisplay1.Fit(true);
}
private void ImageDisplay(CogImage8Grey img)
{
@@ -1023,9 +833,17 @@ namespace WaferAlignment
return;
}
this.cogRecordDisplay1.Image = img;
this.cogRecordDisplay1.Fit(true);
cogRecordDisplay1.StaticGraphics.Clear();
}
private void ImageDisplayFit()
{
if (InvokeRequired)
{
BeginInvoke(new Action(() => ImageDisplayFit()));
return;
}
cogRecordDisplay1.Fit(true);
}
private void DataDisplay(double Rotation, double X, double Y, double Radius)
{
if (this.InvokeRequired)
@@ -1041,18 +859,6 @@ namespace WaferAlignment
}
string SavePath;
private void SaveImage(ICogImage img)
{
if (!Directory.Exists(SavePath))
{
Directory.CreateDirectory(SavePath);
}
using (CogImageFile imgFile = new CogImageFile())
{
imgFile.Open(Path.Combine(SavePath, DateTime.Now.ToString("yyyyMMdd_HHmmss_fff") + ".bmp"), CogImageFileModeConstants.Write);
imgFile.Append(img);
}
}
private void Save()
{
if (!Directory.Exists(SavePath))
@@ -1068,5 +874,27 @@ namespace WaferAlignment
}
}
}
private double m_cameraCount = 82;
private double m_codeCount = 4096;
private void textBox2_TextChanged(object sender, EventArgs e)
{
m_cameraCount = Convert.ToDouble(textBox2.Text);
}
private void textBox3_TextChanged(object sender, EventArgs e)
{
m_codeCount = Convert.ToDouble(textBox3.Text);
}
private double m_roateX = 1;
private double m_roateY = -1;
private void nud_SizeX_ValueChanged(object sender, EventArgs e)
{
m_roateX = Convert.ToDouble(nud_SizeX.Value);
}
private void nud_SizeY_ValueChanged(object sender, EventArgs e)
{
m_roateY = Convert.ToDouble(nud_SizeY.Value);
}
}
}

View File

@@ -140,4 +140,16 @@
<metadata name="Column4.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="Column1.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="Column2.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="Column3.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="Column4.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
</root>

View File

@@ -0,0 +1,117 @@
using Cognex.VisionPro;
using Cognex.VisionPro.Caliper;
using Cognex.VisionPro.ToolBlock;
using QWhale.Common;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WaferAdjust
{
public delegate void OnGetCircleResult(double x, double y, double r);
public delegate void OnToolReady(bool ready);
public delegate void OnGetNashResult(double x, double y);
internal class GetCircleToolBlock
{
private CogToolBlock cogToolBlock;
private bool initialized = false;
public event OnToolReady OnToolReady;
public event OnGetCircleResult OnGetCircleResult;
public event OnGetNashResult OnGetNashResult;
public List<PointInfo> PointInfos;
public void Initialize(string vpp)
{
try
{
if (cogToolBlock != null)
{
cogToolBlock.Ran -= CogToolBlock_Ran;
cogToolBlock.Dispose();
cogToolBlock = null;
}
initialized = false;
PointInfos = new List<PointInfo>();
cogToolBlock = CogSerializer.LoadObjectFromFile(vpp) as CogToolBlock;
cogToolBlock.Ran += CogToolBlock_Ran;
initialized = true;
OnToolReady?.Invoke(initialized);
LogHelper.LogInfo($"{vpp} initialized successfully: " + vpp);
}
catch (Exception ex)
{
LogHelper.LogError(ex.Message);
}
}
private void CogToolBlock_Ran(object sender, EventArgs e)
{
try
{
CogFindCircleTool cogFindCircleTool = cogToolBlock.Tools["CogFindCircleTool1"] as CogFindCircleTool;
PointInfos.Clear();
if (cogFindCircleTool.Results != null)
{
foreach (CogFindCircleResult item in cogFindCircleTool.Results)
{
if (item.Found && item.Used)
PointInfos.Add(new PointInfo(item.X, item.Y, item.DistanceToCircle));
}
}
OnGetCircleResult?.Invoke(Math.Round((double)cogToolBlock.Outputs["CenterX"].Value, 3),
Math.Round((double)cogToolBlock.Outputs["CenterY"].Value, 3),
Math.Round((double)cogToolBlock.Outputs["Radius"].Value, 3));
if ((int)cogToolBlock.Outputs["Results_Count"].Value == 1)
{
OnGetNashResult?.Invoke(Math.Round((double)cogToolBlock.Outputs["TranslationX"].Value, 3),
Math.Round((double)cogToolBlock.Outputs["TranslationY"].Value, 3));
}
}
catch (Exception ex)
{
LogHelper.LogError(ex.Message + ex.StackTrace);
}
}
public void Run(Bitmap bmp)
{
try
{
CogImage8Grey image8Grey = new CogImage8Grey(bmp);
Run(image8Grey);
}
catch (Exception ex)
{
LogHelper.LogError("ScanToolBlock Run Error: " + ex.Message);
}
}
public void Run(CogImage8Grey image8Grey)
{
try
{
cogToolBlock.Inputs["OutputImage"].Value = image8Grey;
cogToolBlock.Run();
}
catch (Exception ex)
{
LogHelper.LogError("ScanToolBlock Run Error: " + ex.Message);
}
}
public bool Ready()
{
return initialized;
}
public void Stop()
{
if (cogToolBlock != null)
{
cogToolBlock.Ran -= CogToolBlock_Ran;
cogToolBlock.Dispose();
cogToolBlock = null;
}
}
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NLog;
namespace WaferAdjust
{
public class LogHelper
{
private static readonly ILogger Logger = LogManager.GetCurrentClassLogger();
public static void LogInfo(string message)
{
Logger.Info(message);
}
public static void LogError(string message)
{
Logger.Error(message);
}
}
}

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
throwConfigExceptions="true">
<variable name="generic" value="${time} | ${level} | ${message} | ${all-event-properties} ${exception:format=tostring}"/>
<targets async="true">
<target xsi:type="File" name="logfile" fileName="${basedir}/logs/${shortdate}.log"
layout="${generic}" encoding="utf-8"/>
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="logfile" />
</rules>
</nlog>

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WaferAdjust
{
internal class PointInfo
{
public double X;
public double Y;
public double Radius;
public PointInfo(double x, double y, double radius)
{
X = x;
Y = y;
Radius = radius;
}
}
}

View File

@@ -0,0 +1,176 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WaferAdjust
{
/// <summary>
/// 二维坐标旋转计算器(支持自定义坐标系方向)
/// </summary>
public class Rotation2D
{
#region
/// <summary>
/// 点A绕点B逆时针旋转指定角度角度制
/// </summary>
/// <param name="ax">点A的X坐标</param>
/// <param name="ay">点A的Y坐标</param>
/// <param name="bx">旋转中心B的X坐标</param>
/// <param name="by">旋转中心B的Y坐标</param>
/// <param name="angleDegrees">旋转角度(角度制,逆时针)</param>
/// <param name="isRight">X轴正方向是否向右默认true</param>
/// <param name="isUp">Y轴正方向是否向上默认true</param>
/// <returns>旋转后的点A'坐标 (x', y')</returns>
public static (double x, double y) RotatePointDegrees(
double ax, double ay,
double bx, double by,
double angleDegrees,
bool isRight = true,
bool isUp = true)
{
return RotatePointRadians(ax, ay, bx, by,
DegreesToRadians(angleDegrees), isRight, isUp);
}
/// <summary>
/// 点A绕点B逆时针旋转指定角度弧度制
/// </summary>
/// <param name="ax">点A的X坐标</param>
/// <param name="ay">点A的Y坐标</param>
/// <param name="bx">旋转中心B的X坐标</param>
/// <param name="by">旋转中心B的Y坐标</param>
/// <param name="angleRadians">旋转角度(弧度制,逆时针)</param>
/// <param name="isRight">X轴正方向是否向右默认true</param>
/// <param name="isUp">Y轴正方向是否向上默认true</param>
/// <returns>旋转后的点A'坐标 (x', y')</returns>
public static (double x, double y) RotatePointRadians(
double ax, double ay,
double bx, double by,
double angleRadians,
bool isRight = true,
bool isUp = true)
{
// 1. 转换为标准数学坐标系(向右为正,向上为正)
double mathAx = isRight ? ax : -ax;
double mathAy = isUp ? ay : -ay;
double mathBx = isRight ? bx : -bx;
double mathBy = isUp ? by : -by;
// 2. 在标准坐标系中执行旋转
double cosR = Math.Cos(angleRadians);
double sinR = Math.Sin(angleRadians);
double dx = mathAx - mathBx;
double dy = mathAy - mathBy;
double rotatedDx = dx * cosR - dy * sinR;
double rotatedDy = dx * sinR + dy * cosR;
double mathNewX = mathBx + rotatedDx;
double mathNewY = mathBy + rotatedDy;
// 3. 转换回用户指定的坐标系
double outputX = isRight ? mathNewX : -mathNewX;
double outputY = isUp ? mathNewY : -mathNewY;
return (outputX, outputY);
}
#endregion
#region
/// <summary>
/// 已知旋转后的点A'求绕点B逆时针旋转前的原始点A角度制
/// </summary>
/// <param name="rotatedX">旋转后的点A'的X坐标</param>
/// <param name="rotatedY">旋转后的点A'的Y坐标</param>
/// <param name="bx">旋转中心B的X坐标</param>
/// <param name="by">旋转中心B的Y坐标</param>
/// <param name="angleDegrees">旋转角度(角度制,逆时针)</param>
/// <param name="isRight">X轴正方向是否向右默认true</param>
/// <param name="isUp">Y轴正方向是否向上默认true</param>
/// <returns>原始的未旋转点A坐标 (x, y)</returns>
public static (double x, double y) GetOriginalPointDegrees(
double rotatedX, double rotatedY,
double bx, double by,
double angleDegrees,
bool isRight = true,
bool isUp = true)
{
return GetOriginalPointRadians(rotatedX, rotatedY, bx, by,
DegreesToRadians(angleDegrees), isRight, isUp);
}
/// <summary>
/// 已知旋转后的点A'求绕点B逆时针旋转前的原始点A弧度制
/// </summary>
/// <param name="rotatedX">旋转后的点A'的X坐标</param>
/// <param name="rotatedY">旋转后的点A'的Y坐标</param>
/// <param name="bx">旋转中心B的X坐标</param>
/// <param name="by">旋转中心B的Y坐标</param>
/// <param name="angleRadians">旋转角度(弧度制,逆时针)</param>
/// <param name="isRight">X轴正方向是否向右默认true</param>
/// <param name="isUp">Y轴正方向是否向上默认true</param>
/// <returns>原始的未旋转点A坐标 (x, y)</returns>
public static (double x, double y) GetOriginalPointRadians(
double rotatedX, double rotatedY,
double bx, double by,
double angleRadians,
bool isRight = true,
bool isUp = true)
{
// 1. 转换为标准数学坐标系
double mathRotatedX = isRight ? rotatedX : -rotatedX;
double mathRotatedY = isUp ? rotatedY : -rotatedY;
double mathBx = isRight ? bx : -bx;
double mathBy = isUp ? by : -by;
// 2. 在标准坐标系中执行反向旋转
double cosR = Math.Cos(angleRadians);
double sinR = Math.Sin(angleRadians);
double dx = mathRotatedX - mathBx;
double dy = mathRotatedY - mathBy;
// 反向旋转(相当于顺时针旋转)
double originalDx = dx * cosR + dy * sinR;
double originalDy = -dx * sinR + dy * cosR;
double mathOriginalX = mathBx + originalDx;
double mathOriginalY = mathBy + originalDy;
// 3. 转换回用户指定的坐标系
double outputX = isRight ? mathOriginalX : -mathOriginalX;
double outputY = isUp ? mathOriginalY : -mathOriginalY;
return (outputX, outputY);
}
#endregion
#region
/// <summary>
/// 角度转弧度
/// </summary>
private static double DegreesToRadians(double degrees)
{
return degrees * Math.PI / 180.0;
}
/// <summary>
/// 弧度转角度(公共方法,供外部使用)
/// </summary>
public static double RadiansToDegrees(double radians)
{
return radians * 180.0 / Math.PI;
}
#endregion
}
}

View File

@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WaferAdjust
{
internal class TranslateCirclePoint
{
private double rotateX;
private double rotateY;
List<PointInfo> totalPoints;
List<PointInfo> totalCenters;
private int circleIndex;
private double perAngle;
PointInfo nashPoint;
PointInfo firstPoint;
public void SetRotateXY(double x, double y, double angle)
{
rotateX = x; rotateY = y;
totalPoints = new List<PointInfo>();
totalCenters = new List<PointInfo>();
circleIndex = 0;
perAngle = angle;
nashPoint = null;
firstPoint = null;
}
public double GetRotateX()
{
return rotateX;
}
public double GetRotateY()
{
return rotateY;
}
public void AddCirclePoint(List<PointInfo> pointInfos)
{
if (pointInfos == null || pointInfos.Count == 0) return;
foreach (var item in pointInfos)
{
totalPoints.Add(new PointInfo(item.X, item.Y, circleIndex * perAngle));
}
firstPoint = pointInfos[0];
}
public PointInfo GetFirstPoint()
{
return firstPoint;
}
public void AddCircleIndex()
{
circleIndex++;
}
public double GetCurrentDegree()
{
return circleIndex * perAngle;
}
public void AddNashPoint(double x, double y)
{
nashPoint = new PointInfo(x, y, circleIndex * perAngle);
}
public void AddCircleCenter(double x, double y, double r)
{
totalCenters.Add(new PointInfo(x, y, r));
}
public List<PointInfo> DoTranslatePoint()
{
List<PointInfo> trans = new List<PointInfo>();
foreach (var item in totalPoints)
{
var res = Rotation2D.GetOriginalPointDegrees(item.X, item.Y,
rotateX, rotateY, item.Radius, true, false);
trans.Add(new PointInfo(res.x, res.y, item.Radius));
}
return trans;
}
public void DoTranslateNashPoint()
{
if (nashPoint == null)
return;
var res = Rotation2D.GetOriginalPointDegrees(nashPoint.X, nashPoint.Y,
rotateX, rotateY, nashPoint.Radius, true, false);
nashPoint = new PointInfo(res.x, res.y, nashPoint.Radius);
}
public PointInfo GetNashPoint()
{
return nashPoint;
}
}
}

View File

@@ -79,6 +79,9 @@
<Reference Include="MvCameraControl.Net">
<HintPath>..\..\..\..\..\..\Program Files (x86)\MVS\Development\DotNet\win64\net40\MvCameraControl.Net.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.6.0.6\lib\net46\NLog.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="QWhale.Common, Version=1.62.4104.36375, Culture=neutral, PublicKeyToken=da632fd1713dff10" />
@@ -86,6 +89,7 @@
<Reference Include="QWhale.Syntax, Version=1.62.4104.36376, Culture=neutral, PublicKeyToken=da632fd1713dff10" />
<Reference Include="QWhale.Syntax.Parsers, Version=1.62.4104.36376, Culture=neutral, PublicKeyToken=da632fd1713dff10" />
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Xaml" />
<Reference Include="System.Xml.Linq" />
@@ -104,15 +108,21 @@
<Compile Include="CenterOfRotation.cs" />
<Compile Include="ConfigStore.cs" />
<Compile Include="DataPostbox.cs" />
<Compile Include="FitCircleToolBlock.cs" />
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
</Compile>
<Compile Include="GetCircleToolBlock.cs" />
<Compile Include="LogHelper.cs" />
<Compile Include="PointInfo.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Rotation2D.cs" />
<Compile Include="TCP.cs" />
<Compile Include="TranslateCirclePoint.cs" />
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
</EmbeddedResource>
@@ -126,6 +136,10 @@
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="Nlog.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NLog" version="6.0.6" targetFramework="net48" />
</packages>