diff --git a/WaferAdjust.sln b/WaferAdjust.sln
new file mode 100644
index 0000000..ec7b861
--- /dev/null
+++ b/WaferAdjust.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.14.36623.8 d17.14
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WaferAdjust", "WaferAdjust\WaferAdjust.csproj", "{941B8ABC-436F-457D-95DA-A79E23C8CA5D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {941B8ABC-436F-457D-95DA-A79E23C8CA5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {941B8ABC-436F-457D-95DA-A79E23C8CA5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {941B8ABC-436F-457D-95DA-A79E23C8CA5D}.Debug|x64.ActiveCfg = Debug|x64
+ {941B8ABC-436F-457D-95DA-A79E23C8CA5D}.Debug|x64.Build.0 = Debug|x64
+ {941B8ABC-436F-457D-95DA-A79E23C8CA5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {941B8ABC-436F-457D-95DA-A79E23C8CA5D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {941B8ABC-436F-457D-95DA-A79E23C8CA5D}.Release|x64.ActiveCfg = Release|x64
+ {941B8ABC-436F-457D-95DA-A79E23C8CA5D}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/WaferAdjust/App.config b/WaferAdjust/App.config
new file mode 100644
index 0000000..4bfa005
--- /dev/null
+++ b/WaferAdjust/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/WaferAdjust/CalibForm.Designer.cs b/WaferAdjust/CalibForm.Designer.cs
new file mode 100644
index 0000000..aa94a2e
--- /dev/null
+++ b/WaferAdjust/CalibForm.Designer.cs
@@ -0,0 +1,39 @@
+namespace WaferAlignment
+{
+ partial class CalibForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(800, 450);
+ this.Text = "CalibForm";
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/WaferAdjust/CalibForm.cs b/WaferAdjust/CalibForm.cs
new file mode 100644
index 0000000..726754e
--- /dev/null
+++ b/WaferAdjust/CalibForm.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace WaferAlignment
+{
+ public partial class CalibForm : Form
+ {
+ public CalibForm()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/WaferAdjust/FitCircle.cs b/WaferAdjust/FitCircle.cs
new file mode 100644
index 0000000..4931634
--- /dev/null
+++ b/WaferAdjust/FitCircle.cs
@@ -0,0 +1,37 @@
+using Cognex.VisionPro;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WaferAdjust
+{
+ public delegate void OnFitCircleResult(double x, double y, double rms);
+ internal class FitCircle
+ {
+ CogFitCircleTool fitCircleTool = new CogFitCircleTool();
+ public event OnFitCircleResult OnFitCircleResult;
+ public void AddPoint(double x, double y)
+ {
+ fitCircleTool.RunParams.AddPoint(x, y);
+ }
+ public void Run(Bitmap bmp)
+ {
+ fitCircleTool.InputImage = new CogImage8Grey(bmp);
+ fitCircleTool.Run();
+ if (fitCircleTool.Result != null)
+ {
+ CogCircle circle = new CogCircle(fitCircleTool.Result.GetCircle());
+ OnFitCircleResult?.Invoke(circle.CenterX, circle.CenterY, fitCircleTool.Result.RMSError);
+ }
+ }
+ public void Init()
+ {
+ fitCircleTool?.Dispose();
+ fitCircleTool = null;
+ fitCircleTool = new CogFitCircleTool();
+ }
+ }
+}
diff --git a/WaferAdjust/FitCircleToolBlock.cs b/WaferAdjust/FitCircleToolBlock.cs
new file mode 100644
index 0000000..8299586
--- /dev/null
+++ b/WaferAdjust/FitCircleToolBlock.cs
@@ -0,0 +1,88 @@
+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;
+
+namespace WaferAdjust
+{
+ public delegate void OnFitCircleResult(double x, double y, 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["RMSError"].Value, 3));
+ }
+ catch (Exception ex)
+ {
+ LogHelper.LogError(ex.Message + ex.StackTrace);
+ }
+ }
+ public void Run(Bitmap bmp, List pointInfos)
+ {
+ try
+ {
+ CogImage8Grey image8Grey = new CogImage8Grey(bmp);
+ 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;
+ }
+ }
+ }
+}
diff --git a/WaferAdjust/Form1.Designer.cs b/WaferAdjust/Form1.Designer.cs
new file mode 100644
index 0000000..5dd5359
--- /dev/null
+++ b/WaferAdjust/Form1.Designer.cs
@@ -0,0 +1,481 @@
+namespace WaferAdjust
+{
+ partial class Form1
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows 窗体设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
+ this.splitContainer1 = new System.Windows.Forms.SplitContainer();
+ this.cogRecordDisplay1 = new Cognex.VisionPro.CogRecordDisplay();
+ this.groupBox2 = new System.Windows.Forms.GroupBox();
+ this.checkBox2 = new System.Windows.Forms.CheckBox();
+ this.checkBox1 = new System.Windows.Forms.CheckBox();
+ this.button7 = new System.Windows.Forms.Button();
+ this.label9 = new System.Windows.Forms.Label();
+ this.textBox10 = new System.Windows.Forms.TextBox();
+ this.label8 = new System.Windows.Forms.Label();
+ this.textBox9 = new System.Windows.Forms.TextBox();
+ this.button6 = new System.Windows.Forms.Button();
+ this.label7 = new System.Windows.Forms.Label();
+ this.textBox8 = new System.Windows.Forms.TextBox();
+ this.label6 = new System.Windows.Forms.Label();
+ this.textBox7 = new System.Windows.Forms.TextBox();
+ this.label5 = new System.Windows.Forms.Label();
+ this.textBox6 = new System.Windows.Forms.TextBox();
+ this.button5 = new System.Windows.Forms.Button();
+ this.textBox2 = new System.Windows.Forms.TextBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.label4 = new System.Windows.Forms.Label();
+ this.textBox3 = new System.Windows.Forms.TextBox();
+ this.textBox5 = new System.Windows.Forms.TextBox();
+ this.label2 = new System.Windows.Forms.Label();
+ this.label3 = new System.Windows.Forms.Label();
+ this.textBox4 = new System.Windows.Forms.TextBox();
+ this.groupBox1 = new System.Windows.Forms.GroupBox();
+ this.button2 = new System.Windows.Forms.Button();
+ this.button4 = new System.Windows.Forms.Button();
+ this.button3 = new System.Windows.Forms.Button();
+ this.textBox1 = new System.Windows.Forms.TextBox();
+ this.button1 = new System.Windows.Forms.Button();
+ this.richTextBox1 = new System.Windows.Forms.RichTextBox();
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
+ this.splitContainer1.Panel1.SuspendLayout();
+ this.splitContainer1.Panel2.SuspendLayout();
+ this.splitContainer1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.cogRecordDisplay1)).BeginInit();
+ this.groupBox2.SuspendLayout();
+ this.groupBox1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // splitContainer1
+ //
+ this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel2;
+ this.splitContainer1.Location = new System.Drawing.Point(0, 0);
+ this.splitContainer1.Name = "splitContainer1";
+ this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
+ //
+ // splitContainer1.Panel1
+ //
+ this.splitContainer1.Panel1.Controls.Add(this.cogRecordDisplay1);
+ //
+ // splitContainer1.Panel2
+ //
+ this.splitContainer1.Panel2.Controls.Add(this.groupBox2);
+ this.splitContainer1.Panel2.Controls.Add(this.groupBox1);
+ this.splitContainer1.Panel2.Controls.Add(this.button3);
+ this.splitContainer1.Panel2.Controls.Add(this.textBox1);
+ this.splitContainer1.Panel2.Controls.Add(this.button1);
+ this.splitContainer1.Panel2.Controls.Add(this.richTextBox1);
+ this.splitContainer1.Size = new System.Drawing.Size(885, 806);
+ this.splitContainer1.SplitterDistance = 558;
+ this.splitContainer1.TabIndex = 1;
+ //
+ // cogRecordDisplay1
+ //
+ this.cogRecordDisplay1.ColorMapLowerClipColor = System.Drawing.Color.Black;
+ this.cogRecordDisplay1.ColorMapLowerRoiLimit = 0D;
+ this.cogRecordDisplay1.ColorMapPredefined = Cognex.VisionPro.Display.CogDisplayColorMapPredefinedConstants.None;
+ this.cogRecordDisplay1.ColorMapUpperClipColor = System.Drawing.Color.Black;
+ this.cogRecordDisplay1.ColorMapUpperRoiLimit = 1D;
+ this.cogRecordDisplay1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.cogRecordDisplay1.DoubleTapZoomCycleLength = 2;
+ this.cogRecordDisplay1.DoubleTapZoomSensitivity = 2.5D;
+ this.cogRecordDisplay1.Location = new System.Drawing.Point(0, 0);
+ this.cogRecordDisplay1.MouseWheelMode = Cognex.VisionPro.Display.CogDisplayMouseWheelModeConstants.Zoom1;
+ this.cogRecordDisplay1.MouseWheelSensitivity = 1D;
+ this.cogRecordDisplay1.Name = "cogRecordDisplay1";
+ this.cogRecordDisplay1.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("cogRecordDisplay1.OcxState")));
+ this.cogRecordDisplay1.Size = new System.Drawing.Size(885, 558);
+ this.cogRecordDisplay1.TabIndex = 0;
+ //
+ // groupBox2
+ //
+ this.groupBox2.Controls.Add(this.checkBox2);
+ this.groupBox2.Controls.Add(this.checkBox1);
+ this.groupBox2.Controls.Add(this.button7);
+ this.groupBox2.Controls.Add(this.label9);
+ this.groupBox2.Controls.Add(this.textBox10);
+ this.groupBox2.Controls.Add(this.label8);
+ this.groupBox2.Controls.Add(this.textBox9);
+ this.groupBox2.Controls.Add(this.button6);
+ this.groupBox2.Controls.Add(this.label7);
+ this.groupBox2.Controls.Add(this.textBox8);
+ this.groupBox2.Controls.Add(this.label6);
+ this.groupBox2.Controls.Add(this.textBox7);
+ this.groupBox2.Controls.Add(this.label5);
+ this.groupBox2.Controls.Add(this.textBox6);
+ this.groupBox2.Controls.Add(this.button5);
+ this.groupBox2.Controls.Add(this.textBox2);
+ this.groupBox2.Controls.Add(this.label1);
+ this.groupBox2.Controls.Add(this.label4);
+ this.groupBox2.Controls.Add(this.textBox3);
+ this.groupBox2.Controls.Add(this.textBox5);
+ this.groupBox2.Controls.Add(this.label2);
+ this.groupBox2.Controls.Add(this.label3);
+ this.groupBox2.Controls.Add(this.textBox4);
+ this.groupBox2.Location = new System.Drawing.Point(358, 133);
+ this.groupBox2.Name = "groupBox2";
+ this.groupBox2.Size = new System.Drawing.Size(515, 99);
+ this.groupBox2.TabIndex = 17;
+ this.groupBox2.TabStop = false;
+ this.groupBox2.Text = "标定后寻边测试";
+ //
+ // checkBox2
+ //
+ this.checkBox2.AutoSize = true;
+ this.checkBox2.Location = new System.Drawing.Point(269, 59);
+ this.checkBox2.Name = "checkBox2";
+ this.checkBox2.Size = new System.Drawing.Size(78, 16);
+ this.checkBox2.TabIndex = 28;
+ this.checkBox2.Text = "y向上为正";
+ this.checkBox2.UseVisualStyleBackColor = true;
+ //
+ // checkBox1
+ //
+ this.checkBox1.AutoSize = true;
+ this.checkBox1.Checked = true;
+ this.checkBox1.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.checkBox1.Location = new System.Drawing.Point(185, 59);
+ this.checkBox1.Name = "checkBox1";
+ this.checkBox1.Size = new System.Drawing.Size(78, 16);
+ this.checkBox1.TabIndex = 27;
+ this.checkBox1.Text = "x向右为正";
+ this.checkBox1.UseVisualStyleBackColor = true;
+ //
+ // button7
+ //
+ this.button7.Location = new System.Drawing.Point(284, 76);
+ this.button7.Name = "button7";
+ this.button7.Size = new System.Drawing.Size(75, 23);
+ this.button7.TabIndex = 26;
+ this.button7.Text = "求原始点";
+ this.button7.UseVisualStyleBackColor = true;
+ this.button7.Click += new System.EventHandler(this.button7_Click);
+ //
+ // label9
+ //
+ this.label9.AutoSize = true;
+ this.label9.Location = new System.Drawing.Point(428, 63);
+ this.label9.Name = "label9";
+ this.label9.Size = new System.Drawing.Size(47, 12);
+ this.label9.TabIndex = 25;
+ this.label9.Text = "旋转点Y";
+ //
+ // textBox10
+ //
+ this.textBox10.Location = new System.Drawing.Point(430, 78);
+ this.textBox10.Name = "textBox10";
+ this.textBox10.Size = new System.Drawing.Size(55, 21);
+ this.textBox10.TabIndex = 24;
+ this.textBox10.Text = "1";
+ //
+ // label8
+ //
+ this.label8.AutoSize = true;
+ this.label8.Location = new System.Drawing.Point(363, 63);
+ this.label8.Name = "label8";
+ this.label8.Size = new System.Drawing.Size(47, 12);
+ this.label8.TabIndex = 23;
+ this.label8.Text = "旋转点X";
+ //
+ // textBox9
+ //
+ this.textBox9.Location = new System.Drawing.Point(365, 78);
+ this.textBox9.Name = "textBox9";
+ this.textBox9.Size = new System.Drawing.Size(55, 21);
+ this.textBox9.TabIndex = 22;
+ this.textBox9.Text = "1";
+ //
+ // button6
+ //
+ this.button6.Location = new System.Drawing.Point(213, 76);
+ this.button6.Name = "button6";
+ this.button6.Size = new System.Drawing.Size(75, 23);
+ this.button6.TabIndex = 21;
+ this.button6.Text = "求旋转点";
+ this.button6.UseVisualStyleBackColor = true;
+ this.button6.Click += new System.EventHandler(this.button6_Click);
+ //
+ // label7
+ //
+ this.label7.AutoSize = true;
+ this.label7.Location = new System.Drawing.Point(150, 63);
+ this.label7.Name = "label7";
+ this.label7.Size = new System.Drawing.Size(29, 12);
+ this.label7.TabIndex = 20;
+ this.label7.Text = "角度";
+ //
+ // textBox8
+ //
+ this.textBox8.Location = new System.Drawing.Point(152, 78);
+ this.textBox8.Name = "textBox8";
+ this.textBox8.Size = new System.Drawing.Size(55, 21);
+ this.textBox8.TabIndex = 19;
+ this.textBox8.Text = "1";
+ //
+ // label6
+ //
+ this.label6.AutoSize = true;
+ this.label6.Location = new System.Drawing.Point(78, 63);
+ this.label6.Name = "label6";
+ this.label6.Size = new System.Drawing.Size(47, 12);
+ this.label6.TabIndex = 18;
+ this.label6.Text = "起始点Y";
+ //
+ // textBox7
+ //
+ this.textBox7.Location = new System.Drawing.Point(80, 78);
+ this.textBox7.Name = "textBox7";
+ this.textBox7.Size = new System.Drawing.Size(55, 21);
+ this.textBox7.TabIndex = 17;
+ this.textBox7.Text = "1";
+ //
+ // label5
+ //
+ this.label5.AutoSize = true;
+ this.label5.Location = new System.Drawing.Point(10, 63);
+ this.label5.Name = "label5";
+ this.label5.Size = new System.Drawing.Size(47, 12);
+ this.label5.TabIndex = 16;
+ this.label5.Text = "起始点X";
+ //
+ // textBox6
+ //
+ this.textBox6.Location = new System.Drawing.Point(12, 78);
+ this.textBox6.Name = "textBox6";
+ this.textBox6.Size = new System.Drawing.Size(55, 21);
+ this.textBox6.TabIndex = 15;
+ this.textBox6.Text = "1";
+ //
+ // button5
+ //
+ this.button5.Location = new System.Drawing.Point(141, 35);
+ this.button5.Name = "button5";
+ this.button5.Size = new System.Drawing.Size(212, 23);
+ this.button5.TabIndex = 6;
+ this.button5.Text = "拟合计算圆中心(机械坐标)";
+ this.button5.UseVisualStyleBackColor = true;
+ this.button5.Click += new System.EventHandler(this.button5_Click);
+ //
+ // textBox2
+ //
+ this.textBox2.Location = new System.Drawing.Point(369, 37);
+ this.textBox2.Name = "textBox2";
+ this.textBox2.Size = new System.Drawing.Size(55, 21);
+ this.textBox2.TabIndex = 7;
+ this.textBox2.Text = "64";
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(367, 22);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(53, 12);
+ this.label1.TabIndex = 8;
+ this.label1.Text = "相机计数";
+ //
+ // label4
+ //
+ this.label4.AutoSize = true;
+ this.label4.Location = new System.Drawing.Point(78, 22);
+ this.label4.Name = "label4";
+ this.label4.Size = new System.Drawing.Size(59, 12);
+ this.label4.TabIndex = 14;
+ this.label4.Text = "旋转中心Y";
+ //
+ // textBox3
+ //
+ this.textBox3.Location = new System.Drawing.Point(430, 37);
+ this.textBox3.Name = "textBox3";
+ this.textBox3.Size = new System.Drawing.Size(55, 21);
+ this.textBox3.TabIndex = 9;
+ this.textBox3.Text = "4096";
+ //
+ // textBox5
+ //
+ this.textBox5.Location = new System.Drawing.Point(80, 37);
+ this.textBox5.Name = "textBox5";
+ this.textBox5.Size = new System.Drawing.Size(55, 21);
+ this.textBox5.TabIndex = 13;
+ this.textBox5.Text = "1";
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(428, 22);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(41, 12);
+ this.label2.TabIndex = 10;
+ this.label2.Text = "总计数";
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Location = new System.Drawing.Point(8, 22);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(59, 12);
+ this.label3.TabIndex = 12;
+ this.label3.Text = "旋转中心X";
+ //
+ // textBox4
+ //
+ this.textBox4.Location = new System.Drawing.Point(10, 37);
+ this.textBox4.Name = "textBox4";
+ this.textBox4.Size = new System.Drawing.Size(55, 21);
+ this.textBox4.TabIndex = 11;
+ this.textBox4.Text = "1";
+ //
+ // groupBox1
+ //
+ this.groupBox1.Controls.Add(this.button2);
+ this.groupBox1.Controls.Add(this.button4);
+ this.groupBox1.Location = new System.Drawing.Point(438, 45);
+ this.groupBox1.Name = "groupBox1";
+ this.groupBox1.Size = new System.Drawing.Size(340, 82);
+ this.groupBox1.TabIndex = 16;
+ this.groupBox1.TabStop = false;
+ this.groupBox1.Text = "九点标定";
+ //
+ // button2
+ //
+ this.button2.Location = new System.Drawing.Point(61, 40);
+ this.button2.Name = "button2";
+ this.button2.Size = new System.Drawing.Size(212, 23);
+ this.button2.TabIndex = 3;
+ this.button2.Text = "拟合圆中心求旋转中心(相机坐标)";
+ this.button2.UseVisualStyleBackColor = true;
+ this.button2.Click += new System.EventHandler(this.button2_Click);
+ //
+ // button4
+ //
+ this.button4.Location = new System.Drawing.Point(61, 11);
+ this.button4.Name = "button4";
+ this.button4.Size = new System.Drawing.Size(212, 23);
+ this.button4.TabIndex = 5;
+ this.button4.Text = "计算各图的圆中心(相机坐标)";
+ this.button4.UseVisualStyleBackColor = true;
+ this.button4.Visible = false;
+ this.button4.Click += new System.EventHandler(this.button4_Click);
+ //
+ // button3
+ //
+ this.button3.Location = new System.Drawing.Point(736, 16);
+ this.button3.Name = "button3";
+ this.button3.Size = new System.Drawing.Size(137, 23);
+ this.button3.TabIndex = 4;
+ this.button3.Text = "清除所有的圆中心";
+ this.button3.UseVisualStyleBackColor = true;
+ this.button3.Click += new System.EventHandler(this.button3_Click);
+ //
+ // textBox1
+ //
+ this.textBox1.Location = new System.Drawing.Point(499, 16);
+ this.textBox1.Name = "textBox1";
+ this.textBox1.Size = new System.Drawing.Size(231, 21);
+ this.textBox1.TabIndex = 2;
+ //
+ // button1
+ //
+ this.button1.Location = new System.Drawing.Point(368, 16);
+ this.button1.Name = "button1";
+ this.button1.Size = new System.Drawing.Size(103, 23);
+ this.button1.TabIndex = 1;
+ this.button1.Text = "选择图像文件夹";
+ this.button1.UseVisualStyleBackColor = true;
+ this.button1.Click += new System.EventHandler(this.button1_Click);
+ //
+ // richTextBox1
+ //
+ this.richTextBox1.Location = new System.Drawing.Point(12, 16);
+ this.richTextBox1.Name = "richTextBox1";
+ this.richTextBox1.Size = new System.Drawing.Size(340, 216);
+ this.richTextBox1.TabIndex = 0;
+ this.richTextBox1.Text = "";
+ //
+ // Form1
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(885, 806);
+ this.Controls.Add(this.splitContainer1);
+ this.Name = "Form1";
+ this.Text = "晶圆校准程序";
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
+ this.Load += new System.EventHandler(this.Form1_Load);
+ this.splitContainer1.Panel1.ResumeLayout(false);
+ this.splitContainer1.Panel2.ResumeLayout(false);
+ this.splitContainer1.Panel2.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
+ this.splitContainer1.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this.cogRecordDisplay1)).EndInit();
+ this.groupBox2.ResumeLayout(false);
+ this.groupBox2.PerformLayout();
+ this.groupBox1.ResumeLayout(false);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.SplitContainer splitContainer1;
+ private Cognex.VisionPro.CogRecordDisplay cogRecordDisplay1;
+ private System.Windows.Forms.TextBox textBox1;
+ private System.Windows.Forms.Button button1;
+ private System.Windows.Forms.RichTextBox richTextBox1;
+ private System.Windows.Forms.Button button2;
+ private System.Windows.Forms.Button button3;
+ private System.Windows.Forms.Button button4;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.TextBox textBox3;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.TextBox textBox2;
+ private System.Windows.Forms.Button button5;
+ private System.Windows.Forms.Label label4;
+ private System.Windows.Forms.TextBox textBox5;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.TextBox textBox4;
+ private System.Windows.Forms.GroupBox groupBox2;
+ private System.Windows.Forms.GroupBox groupBox1;
+ private System.Windows.Forms.Button button7;
+ private System.Windows.Forms.Label label9;
+ private System.Windows.Forms.TextBox textBox10;
+ private System.Windows.Forms.Label label8;
+ private System.Windows.Forms.TextBox textBox9;
+ private System.Windows.Forms.Button button6;
+ private System.Windows.Forms.Label label7;
+ private System.Windows.Forms.TextBox textBox8;
+ private System.Windows.Forms.Label label6;
+ private System.Windows.Forms.TextBox textBox7;
+ private System.Windows.Forms.Label label5;
+ private System.Windows.Forms.TextBox textBox6;
+ private System.Windows.Forms.CheckBox checkBox2;
+ private System.Windows.Forms.CheckBox checkBox1;
+ }
+}
+
diff --git a/WaferAdjust/Form1.cs b/WaferAdjust/Form1.cs
new file mode 100644
index 0000000..e0cef2d
--- /dev/null
+++ b/WaferAdjust/Form1.cs
@@ -0,0 +1,322 @@
+using Cognex.VisionPro;
+using Cognex.VisionPro.Caliper;
+using Cognex.VisionPro.Dimensioning;
+using Cognex.VisionPro.ImageFile;
+using Cognex.VisionPro.ImageProcessing;
+using Cognex.VisionPro.PMAlign;
+using Cognex.VisionPro.ToolBlock;
+using QWhale.Common;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Diagnostics;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.Windows.Interop;
+using System.Xml.Serialization;
+
+
+namespace WaferAdjust
+{
+ public partial class Form1 : Form
+ {
+ GetCircleToolBlock getCircleCameraToolBlock;
+ GetCircleToolBlock getCircleMachineToolBlock;
+ FitCircleToolBlock fitCircleCameraToolBlock;
+ FitCircleToolBlock FitCircleMachineToolBlock;
+ List m_circlePoints;
+ TranslateCirclePoint translateCirclePoint;
+ public Form1()
+ {
+ InitializeComponent();
+ }
+ private void Form1_Load(object sender, EventArgs e)
+ {
+ try
+ {
+ getCircleCameraToolBlock = new GetCircleToolBlock();
+ getCircleCameraToolBlock.OnGetCircleResult += GetCircleCameraToolBlock_OnGetCircleResult;
+ getCircleCameraToolBlock.OnToolReady += GetCircleCameraToolBlock_OnToolReady;
+ getCircleCameraToolBlock.Initialize("vpp\\GetCircleC.vpp");
+
+ fitCircleCameraToolBlock = new FitCircleToolBlock();
+ fitCircleCameraToolBlock.OnFitCircleResult += FitCircleCameraToolBlock_OnFitCircleResult;
+ fitCircleCameraToolBlock.OnToolReady += FitCircleCameraToolBlock_OnToolReady;
+ fitCircleCameraToolBlock.Initialize("vpp\\FitCircleC.vpp");
+
+ getCircleMachineToolBlock = new GetCircleToolBlock();
+ getCircleMachineToolBlock.OnGetCircleResult += GetCircleMachineToolBlock_OnGetCircleResult;
+ getCircleMachineToolBlock.OnToolReady += GetCircleMachineToolBlock_OnToolReady;
+ getCircleMachineToolBlock.Initialize("vpp\\GetCircleM.vpp");
+
+ FitCircleMachineToolBlock = new FitCircleToolBlock();
+ FitCircleMachineToolBlock.OnFitCircleResult += FitCircleMachineToolBlock_OnFitCircleResult;
+ FitCircleMachineToolBlock.OnToolReady += FitCircleMachineToolBlock_OnToolReady;
+ FitCircleMachineToolBlock.Initialize("vpp\\FitCircleM.vpp");
+
+ translateCirclePoint = new TranslateCirclePoint();
+
+ m_graphics2 = new CogGraphicCollection();
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.Message);
+ }
+ }
+
+ private void FitCircleMachineToolBlock_OnToolReady(bool ready)
+ {
+
+ }
+
+ private void FitCircleMachineToolBlock_OnFitCircleResult(double x, double y, double rms)
+ {
+ CogPointMarker marker_1 = new CogPointMarker();
+
+ marker_1.X = x;
+ marker_1.Y = y;
+ marker_1.Color = CogColorConstants.Green;
+ marker_1.Interactive = false;
+ m_graphics2.Add(marker_1);
+
+ CogPointMarker marker_2 = new CogPointMarker();
+
+ marker_2.X = Convert.ToDouble(textBox4.Text);
+ marker_2.Y = Convert.ToDouble(textBox5.Text);
+ marker_2.Color = CogColorConstants.Red;
+ marker_2.Interactive = false;
+ m_graphics2.Add(marker_2);
+
+ ShowMessage($"{Environment.NewLine}X:{x}, Y:{y}, RMS:{rms}{Environment.NewLine}");
+ ShowMessage($"{Environment.NewLine}DiffX:{x - Convert.ToDouble(textBox4.Text)}, DiffY:{y - Convert.ToDouble(textBox5.Text)}, RMS:{rms}{Environment.NewLine}");
+ ImageDisplay(FitCircleMachineToolBlock.FitCircleImage);
+ ImageDisplay(m_graphics);
+ ImageDisplay(m_graphics2);
+ ImageDisplayFit();
+ }
+
+ private void GetCircleMachineToolBlock_OnToolReady(bool ready)
+ {
+
+ }
+
+ private void GetCircleMachineToolBlock_OnGetCircleResult(double x, double y, double r)
+ {
+ translateCirclePoint.AddCircleCenter(x, y, r);
+ translateCirclePoint.AddCirclePoint(getCircleMachineToolBlock.PointInfos);
+ ShowMessage($"X:{x}, Y:{y}, R:{r}{Environment.NewLine}");
+ }
+
+ private void FitCircleCameraToolBlock_OnToolReady(bool ready)
+ {
+
+ }
+
+ private void FitCircleCameraToolBlock_OnFitCircleResult(double x, double y, double rms)
+ {
+ CogPointMarker marker_1 = new CogPointMarker();
+
+ marker_1.X = x;
+ marker_1.Y = y;
+ marker_1.Color = CogColorConstants.Green;
+ marker_1.Interactive = false;
+ m_graphics2.Add(marker_1);
+ ShowMessage($"{Environment.NewLine}X:{x}, Y:{y}, RMS:{rms}{Environment.NewLine}");
+ ImageDisplay(fitCircleCameraToolBlock.FitCircleImage);
+ ImageDisplay(m_graphics);
+ ImageDisplay(m_graphics2);
+ ImageDisplayFit();
+ }
+
+ private void GetCircleCameraToolBlock_OnToolReady(bool ready)
+ {
+
+ }
+
+ private void GetCircleCameraToolBlock_OnGetCircleResult(double x, double y, double r)
+ {
+ ShowMessage($"X:{x}, Y:{y}, R:{r}{Environment.NewLine}");
+ m_circlePoints.Add(new PointInfo(x, y, r));
+ }
+
+ private void Form1_FormClosing(object sender, FormClosingEventArgs e)
+ {
+
+ }
+ Bitmap m_lastBMP = null;
+ private string m_lastPath = "";
+ private void button1_Click(object sender, EventArgs e)
+ {
+ richTextBox1.Clear();
+ using (FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog())
+ {
+ if (m_lastPath != "")
+ folderBrowserDialog.SelectedPath = m_lastPath;
+ if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
+ {
+ m_lastPath = folderBrowserDialog.SelectedPath;
+ textBox1.Text = Path.GetFileName(m_lastPath);
+ }
+ else
+ {
+ m_lastPath = "";
+ textBox1.Text = "";
+ }
+ }
+ }
+ CogGraphicCollection m_graphics;
+ CogGraphicCollection m_graphics2;
+ private void button2_Click(object sender, EventArgs e)
+ {
+ if (!Directory.Exists(m_lastPath))
+ return;
+
+ ShowMessage("计算相机坐标系下各圆弧的圆中心:\n");
+ m_circlePoints = new List();
+ string[] files = Directory.GetFiles(m_lastPath, "*.bmp");
+ foreach (string file in files)
+ {
+ Bitmap bmp = new Bitmap(file);
+ m_lastBMP = bmp;
+ getCircleCameraToolBlock.Run(bmp);
+ }
+
+ if (m_circlePoints == null || m_circlePoints.Count < 4)
+ return;
+ if (m_lastBMP == null)
+ return;
+ ShowMessage("计算相机坐标系下各圆弧的圆中心拟合出的旋转中心:\n");
+ var aa = m_circlePoints;//.OrderBy(x => x.Radius).Skip(2).Take(m_circlePoints.Count - 4).ToList();
+ m_graphics = new CogGraphicCollection();
+ foreach (PointInfo pointInfo in aa)
+ {
+ CogPointMarker marker_1 = new CogPointMarker();//圆
+
+ marker_1.X = pointInfo.X;
+ marker_1.Y = pointInfo.Y;
+ marker_1.Color = CogColorConstants.Green;
+ marker_1.Interactive = false;
+ m_graphics.Add(marker_1);
+ }
+ fitCircleCameraToolBlock.Run(m_lastBMP, aa);
+ }
+ private void ImageDisplay(CogImage8Grey img)
+ {
+ if (InvokeRequired)
+ {
+ BeginInvoke(new Action(() => ImageDisplay(img)));
+ return;
+ }
+ cogRecordDisplay1.Image = img;
+ cogRecordDisplay1.StaticGraphics.Clear();
+ }
+ private void ImageDisplay(CogGraphicCollection graphics)
+ {
+ if (InvokeRequired)
+ {
+ BeginInvoke(new Action(() => ImageDisplay(graphics)));
+ return;
+ }
+ cogRecordDisplay1.StaticGraphics.AddList(graphics, "");
+ }
+ private void ImageDisplayFit()
+ {
+ if (InvokeRequired)
+ {
+ BeginInvoke(new Action(() => ImageDisplayFit()));
+ return;
+ }
+ cogRecordDisplay1.Fit(true);
+ }
+
+ private void button3_Click(object sender, EventArgs e)
+ {
+ m_graphics2?.Clear();
+ }
+ public void ShowMessage(string message)
+ {
+ if (InvokeRequired)
+ {
+ BeginInvoke(new Action(ShowMessage), message);
+ return;
+ }
+ if (richTextBox1.Lines.Length > 2000)
+ richTextBox1.Clear();
+ richTextBox1.AppendText(message);
+ richTextBox1.ScrollToCaret();
+ }
+
+ private void button4_Click(object sender, EventArgs e)
+ {
+ if (!Directory.Exists(m_lastPath))
+ return;
+ ShowMessage("计算相机坐标系下各圆弧的圆中心:\n");
+ m_circlePoints = new List();
+ string[] files = Directory.GetFiles(m_lastPath, "*.bmp");
+ foreach (string file in files)
+ {
+ Bitmap bmp = new Bitmap(file);
+ m_lastBMP = bmp;
+ getCircleCameraToolBlock.Run(bmp);
+ }
+ }
+
+ private void button5_Click(object sender, EventArgs e)
+ {
+ if (!Directory.Exists(m_lastPath))
+ return;
+ ShowMessage("读取机械坐标系下圆弧各点的坐标:\n");
+ translateCirclePoint.SetRotateXY(Convert.ToDouble(textBox4.Text), Convert.ToDouble(textBox5.Text), 360 * Convert.ToDouble(textBox2.Text)/Convert.ToDouble(textBox3.Text));
+ string[] files = Directory.GetFiles(m_lastPath, "*.bmp");
+ foreach (string file in files)
+ {
+ Bitmap bmp = new Bitmap(file);
+ m_lastBMP = bmp;
+ translateCirclePoint.AddCircleIndex();
+ getCircleMachineToolBlock.Run(m_lastBMP);
+ }
+
+ ShowMessage("转换机械坐标系下圆弧各点的原始坐标:\n");
+ var points = translateCirclePoint.DoTranslatePoint();
+
+ ShowMessage("拟合机械坐标系下的圆中心:\n");
+ m_graphics = new CogGraphicCollection();
+ m_graphics2 = new CogGraphicCollection();
+ foreach (PointInfo pointInfo in points)
+ {
+ CogPointMarker marker_1 = new CogPointMarker();//圆
+
+ marker_1.X = pointInfo.X;
+ marker_1.Y = pointInfo.Y;
+ marker_1.Color = CogColorConstants.Green;
+ marker_1.Interactive = false;
+ m_graphics.Add(marker_1);
+ }
+ FitCircleMachineToolBlock.Run(m_lastBMP, points);
+ }
+
+ private void button6_Click(object sender, EventArgs e)
+ {
+ var res = Rotation2D.RotatePointDegrees(Convert.ToDouble(textBox6.Text), Convert.ToDouble(textBox7.Text),
+ Convert.ToDouble(textBox4.Text), Convert.ToDouble(textBox5.Text), Convert.ToDouble(textBox8.Text),
+ checkBox1.Checked, checkBox2.Checked);
+ textBox9.Text = Math.Round(res.x, 3).ToString();
+ textBox10.Text = Math.Round(res.y, 3).ToString();
+ }
+
+ private void button7_Click(object sender, EventArgs e)
+ {
+ var res = Rotation2D.GetOriginalPointDegrees(Convert.ToDouble(textBox9.Text), Convert.ToDouble(textBox10.Text),
+ Convert.ToDouble(textBox4.Text), Convert.ToDouble(textBox5.Text), Convert.ToDouble(textBox8.Text),
+ checkBox1.Checked, checkBox2.Checked);
+ textBox6.Text = Math.Round(res.x, 3).ToString();
+ textBox7.Text = Math.Round(res.y, 3).ToString();
+ }
+ }
+}
diff --git a/WaferAdjust/Form1.resx b/WaferAdjust/Form1.resx
new file mode 100644
index 0000000..e66ae10
--- /dev/null
+++ b/WaferAdjust/Form1.resx
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
+ LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACFTeXN0
+ ZW0uV2luZG93cy5Gb3Jtcy5BeEhvc3QrU3RhdGUBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAtwAAAAIB
+ AAAAAQAAAAAAAAAAAAAAAKIAAAAAAQAAeFsAAKw5AAATAAoKZAALAAAACwAAAAsA//8DAAAAAAADAAEA
+ AAAFAAAAAAAAAAAABQAAAAAAAAAAAAUAAAAAAAAA8D8TAAAAwAALAP//CwD//xMAAIAAAAMAAwAAAAsA
+ //8LAAAAAAAAAAAA4D8AAAAAAADgPwAAAAAAAOA/AAAAAAAA4D8BAAAAAQAAAAsA//8LAAAACwAAAAsA
+ //8L
+
+
+
\ No newline at end of file
diff --git a/WaferAdjust/GetCircleToolBlock.cs b/WaferAdjust/GetCircleToolBlock.cs
new file mode 100644
index 0000000..9de918e
--- /dev/null
+++ b/WaferAdjust/GetCircleToolBlock.cs
@@ -0,0 +1,98 @@
+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);
+ internal class GetCircleToolBlock
+ {
+ private CogToolBlock cogToolBlock;
+ private bool initialized = false;
+ public event OnToolReady OnToolReady;
+ public event OnGetCircleResult OnGetCircleResult;
+ public List PointInfos;
+ public void Initialize(string vpp)
+ {
+ try
+ {
+ if (cogToolBlock != null)
+ {
+ cogToolBlock.Ran -= CogToolBlock_Ran;
+ cogToolBlock.Dispose();
+ cogToolBlock = null;
+ }
+ initialized = false;
+ PointInfos = new List();
+ 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));
+ }
+ catch (Exception ex)
+ {
+ LogHelper.LogError(ex.Message + ex.StackTrace);
+ }
+ }
+ public void Run(Bitmap bmp)
+ {
+ try
+ {
+ CogImage8Grey image8Grey = new CogImage8Grey(bmp);
+ 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;
+ }
+ }
+ }
+}
diff --git a/WaferAdjust/LogHelper.cs b/WaferAdjust/LogHelper.cs
new file mode 100644
index 0000000..da64197
--- /dev/null
+++ b/WaferAdjust/LogHelper.cs
@@ -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);
+ }
+ }
+}
diff --git a/WaferAdjust/Nlog.config b/WaferAdjust/Nlog.config
new file mode 100644
index 0000000..3635098
--- /dev/null
+++ b/WaferAdjust/Nlog.config
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WaferAdjust/PointInfo.cs b/WaferAdjust/PointInfo.cs
new file mode 100644
index 0000000..4e3a830
--- /dev/null
+++ b/WaferAdjust/PointInfo.cs
@@ -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;
+ }
+ }
+}
diff --git a/WaferAdjust/Program.cs b/WaferAdjust/Program.cs
new file mode 100644
index 0000000..3c18c0d
--- /dev/null
+++ b/WaferAdjust/Program.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace WaferAdjust
+{
+ static class Program
+ {
+ ///
+ /// 应用程序的主入口点。
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new Form1());
+ }
+ }
+}
diff --git a/WaferAdjust/Properties/AssemblyInfo.cs b/WaferAdjust/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..3253d90
--- /dev/null
+++ b/WaferAdjust/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的常规信息通过以下
+// 特性集控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("WaferAdjust")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("HP Inc.")]
+[assembly: AssemblyProduct("WaferAdjust")]
+[assembly: AssemblyCopyright("Copyright © HP Inc. 2024")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 使此程序集中的类型
+// 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
+// 则将该类型上的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("1e41d94a-8082-46d2-83cd-92d60d48d97a")]
+
+// 程序集的版本信息由下面四个值组成:
+//
+// 主版本
+// 次版本
+// 生成号
+// 修订号
+//
+// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
+// 方法是按如下所示使用“*”:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/WaferAdjust/Properties/Resources.Designer.cs b/WaferAdjust/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..c84f52d
--- /dev/null
+++ b/WaferAdjust/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本:4.0.30319.42000
+//
+// 对此文件的更改可能会导致不正确的行为,并且如果
+// 重新生成代码,这些更改将会丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace WaferAdjust.Properties {
+ using System;
+
+
+ ///
+ /// 一个强类型的资源类,用于查找本地化的字符串等。
+ ///
+ // 此类是由 StronglyTypedResourceBuilder
+ // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
+ // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
+ // (以 /str 作为命令选项),或重新生成 VS 项目。
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// 返回此类使用的缓存的 ResourceManager 实例。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WaferAdjust.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// 重写当前线程的 CurrentUICulture 属性,对
+ /// 使用此强类型资源类的所有资源查找执行重写。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/WaferAdjust/Properties/Resources.resx b/WaferAdjust/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/WaferAdjust/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/WaferAdjust/Properties/Settings.Designer.cs b/WaferAdjust/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..aed83d9
--- /dev/null
+++ b/WaferAdjust/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本:4.0.30319.42000
+//
+// 对此文件的更改可能会导致不正确的行为,并且如果
+// 重新生成代码,这些更改将会丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace WaferAdjust.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/WaferAdjust/Properties/Settings.settings b/WaferAdjust/Properties/Settings.settings
new file mode 100644
index 0000000..3964565
--- /dev/null
+++ b/WaferAdjust/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/WaferAdjust/Rotation2D.cs b/WaferAdjust/Rotation2D.cs
new file mode 100644
index 0000000..d310406
--- /dev/null
+++ b/WaferAdjust/Rotation2D.cs
@@ -0,0 +1,176 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WaferAdjust
+{
+ ///
+ /// 二维坐标旋转计算器(支持自定义坐标系方向)
+ ///
+ public class Rotation2D
+ {
+ #region 正向旋转:求旋转后的坐标
+
+ ///
+ /// 点A绕点B逆时针旋转指定角度(角度制)
+ ///
+ /// 点A的X坐标
+ /// 点A的Y坐标
+ /// 旋转中心B的X坐标
+ /// 旋转中心B的Y坐标
+ /// 旋转角度(角度制,逆时针)
+ /// X轴正方向是否向右(默认true)
+ /// Y轴正方向是否向上(默认true)
+ /// 旋转后的点A'坐标 (x', y')
+ 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);
+ }
+
+ ///
+ /// 点A绕点B逆时针旋转指定角度(弧度制)
+ ///
+ /// 点A的X坐标
+ /// 点A的Y坐标
+ /// 旋转中心B的X坐标
+ /// 旋转中心B的Y坐标
+ /// 旋转角度(弧度制,逆时针)
+ /// X轴正方向是否向右(默认true)
+ /// Y轴正方向是否向上(默认true)
+ /// 旋转后的点A'坐标 (x', y')
+ 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 反向旋转:求旋转前的原始坐标
+
+ ///
+ /// 已知旋转后的点A',求绕点B逆时针旋转前的原始点A(角度制)
+ ///
+ /// 旋转后的点A'的X坐标
+ /// 旋转后的点A'的Y坐标
+ /// 旋转中心B的X坐标
+ /// 旋转中心B的Y坐标
+ /// 旋转角度(角度制,逆时针)
+ /// X轴正方向是否向右(默认true)
+ /// Y轴正方向是否向上(默认true)
+ /// 原始的未旋转点A坐标 (x, y)
+ 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);
+ }
+
+ ///
+ /// 已知旋转后的点A',求绕点B逆时针旋转前的原始点A(弧度制)
+ ///
+ /// 旋转后的点A'的X坐标
+ /// 旋转后的点A'的Y坐标
+ /// 旋转中心B的X坐标
+ /// 旋转中心B的Y坐标
+ /// 旋转角度(弧度制,逆时针)
+ /// X轴正方向是否向右(默认true)
+ /// Y轴正方向是否向上(默认true)
+ /// 原始的未旋转点A坐标 (x, y)
+ 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 辅助方法
+
+ ///
+ /// 角度转弧度
+ ///
+ private static double DegreesToRadians(double degrees)
+ {
+ return degrees * Math.PI / 180.0;
+ }
+
+ ///
+ /// 弧度转角度(公共方法,供外部使用)
+ ///
+ public static double RadiansToDegrees(double radians)
+ {
+ return radians * 180.0 / Math.PI;
+ }
+
+ #endregion
+ }
+
+}
diff --git a/WaferAdjust/TranslateCirclePoint.cs b/WaferAdjust/TranslateCirclePoint.cs
new file mode 100644
index 0000000..8b3f7e8
--- /dev/null
+++ b/WaferAdjust/TranslateCirclePoint.cs
@@ -0,0 +1,53 @@
+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 totalPoints;
+ List totalCenters;
+ private int circleIndex;
+ private double perAngle;
+ public void SetRotateXY(double x, double y, double angle)
+ {
+ rotateX = x; rotateY = y;
+ totalPoints = new List();
+ totalCenters = new List();
+ circleIndex = 0;
+ perAngle = angle;
+ }
+ public void AddCirclePoint(List pointInfos)
+ {
+ foreach (var item in pointInfos)
+ {
+ totalPoints.Add(new PointInfo(item.X, item.Y, circleIndex * perAngle));
+ }
+ }
+ public void AddCircleIndex()
+ {
+ circleIndex++;
+ }
+ public void AddCircleCenter(double x, double y, double r)
+ {
+ totalCenters.Add(new PointInfo(x, y, r));
+ }
+ public List DoTranslatePoint()
+ {
+ List trans = new List();
+ foreach (var item in totalPoints)
+ {
+ var res = Rotation2D.GetOriginalPointDegrees(item.X, item.Y,
+ rotateX, rotateY, item.Radius, true, false);
+ Console.WriteLine($"{item.X} {item.Y} {item.Radius} ==> {res.x} {res.y}");
+ trans.Add(new PointInfo(res.x, res.y, item.Radius));
+ }
+ return trans;
+ }
+ }
+}
diff --git a/WaferAdjust/WaferAdjust.csproj b/WaferAdjust/WaferAdjust.csproj
new file mode 100644
index 0000000..2c3ca24
--- /dev/null
+++ b/WaferAdjust/WaferAdjust.csproj
@@ -0,0 +1,148 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {941B8ABC-436F-457D-95DA-A79E23C8CA5D}
+ WinExe
+ Properties
+ WaferAdjust
+ WaferAdjust
+ v4.8
+ 512
+ true
+
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE
+ full
+ x64
+ 7.3
+ prompt
+ true
+
+
+ bin\x64\Release\
+ TRACE
+ true
+ pdbonly
+ x64
+ 7.3
+ prompt
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\packages\NLog.6.0.6\lib\net46\NLog.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ Form1.cs
+
+
+
+
+
+
+
+
+
+ Form1.cs
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WaferAdjust/packages.config b/WaferAdjust/packages.config
new file mode 100644
index 0000000..e772309
--- /dev/null
+++ b/WaferAdjust/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file