C#简单晶圆wafermapping显示示范demo

 点击,双击可改变颜色

预设5行8列数据:

 using (fratte.at.WafermapDisplay.Form1 form_show = new fratte.at.WafermapDisplay.Form1()){int[,] data_demo = new int[,]{{ 0,0,0,1,0 },{ 0,5,1,0,0 },{ 1,7,6,2,3 },{ 1,0,1,2,3 },{ 0,2,0,2,3 }, { 1,5,6,2,3 },{ 1,0,6,2,3 }, { 1,0,50,0,1 } };form_show.SetDataSet(data_demo);form_show.SetInteractive(true);form_show.ShowDialog();}

预设颜色对应表:

 private void setupDefaultColors(){// Just some sample colors to get startedcolors = new Color[255];colors[0] = Color.Green;colors[1] = Color.Red;colors[2] = Color.Yellow;colors[3] = Color.Blue;colors[4] = Color.Orange;colors[5] = Color.Magenta;colors[6] = Color.DarkBlue;colors[7] = Color.Pink;colors[50] = Color.Black;}

Wafermap.cs动态库

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;namespace fratte.at.WafermapDisplay
{public partial class Wafermap : UserControl{private String tooSmallString = "TOO SMALL";public String TooSmallString{get { return tooSmallString; }set { tooSmallString = value; }}private String noDataString = "NO DATA";public String NoDataString{get { return noDataString; }set { noDataString = value; }}private int translation_x=0;public int TranslationX{get { return translation_x; }set { translation_x = value; }}private int translation_y=0;public int TranslationY{get { return translation_y; }set { translation_y = value; }}private int rotation;public int Rotation{get { return rotation; }set { if (value % 90 == 0 && value >= 0 && value < 360)rotation = value;elsethrow new ArgumentException("Rotation has to be 0, 90, 180 or 270 degrees (Is "+value+")");}}private float zoom;public float Zoom{get { return zoom; }set { zoom = value; }}private int notchLocation = 0;public int Notchlocation{get { return notchLocation; }set {if (value % 90 == 0 && value >= 0 && value <= 270)notchLocation = value;elsethrow new ArgumentException("NotchLocation has to be 0, 90, 180 or 270 degrees (Is "+value+")");}}private int[,] dataset;public int[,] Dataset{get { return dataset; }set { dataset = value; }}private Color[] colors;public Color[] Colors{get { return colors; }set { colors = value; }}public Wafermap(){zoom=1f;InitializeComponent();SetStyle(ControlStyles.ResizeRedraw, true);DoubleBuffered = true;setupDefaultColors();registerEvents();}private void setupDefaultColors(){// Just some sample colors to get startedcolors = new Color[255];colors[0] = Color.Green;colors[1] = Color.Red;colors[2] = Color.Yellow;colors[3] = Color.Blue;colors[4] = Color.Orange;colors[5] = Color.Magenta;colors[6] = Color.DarkBlue;colors[7] = Color.Pink;colors[50] = Color.Black;}private void Wafermap_Load(object sender, EventArgs e){this.Dock = DockStyle.Fill;}private bool isScaled;public bool IsScaled{get { return isScaled; }}private int scaleFactor;public int ScaleFactor{get { return scaleFactor; }}// We need some globals to be available for calculationsRectangleF boundingBox_;SizeF dieSize_;protected override void OnPaint(PaintEventArgs e){// set rotatione.Graphics.RotateTransform((float)rotation);if(rotation!=0){// When we rotate, we also have to translateswitch (rotation){case 90:e.Graphics.TranslateTransform(0, -boundingBox_.Width);break;case 180:e.Graphics.TranslateTransform(-boundingBox_.Width,-boundingBox_.Height);break;case 270:e.Graphics.TranslateTransform(-boundingBox_.Height, 0);break;}}// set additional translatione.Graphics.TranslateTransform(translation_x, translation_y); // Use antialiase.Graphics.SmoothingMode = SmoothingMode.AntiAlias;// Here comes everything that has to be calculated on each resize/redraw// Just do this calculations once// Let's find the best Size for the outlinefloat w = this.Width*zoom;float h = this.Height*zoom;float size = w < h ? w : h;// Wafersize is size-2 because we're not drawing the first and the last pixelsSizeF wafersize = new SizeF(size - 2, size - 2);PointF starting = new PointF((w - size) / 2f, (h - size) / 2f);RectangleF boundingBox = new RectangleF(starting, wafersize);boundingBox_ = boundingBox;// Create graphics path.GraphicsPath clipPath = new GraphicsPath();clipPath.AddEllipse(boundingBox);// Set clipping region to path.e.Graphics.SetClip(clipPath, CombineMode.Replace);drawCircle(e.Graphics,boundingBox);drawNotch(e.Graphics, boundingBox, notchLocation);// Let's calculate everything needed for drawing the diesif (dataset != null && dataset.Length > 0){int maxX = dataset.GetLength(0);int maxY = dataset.GetLength(1);float sizeX = boundingBox.Width / (float)maxX;float sizeY = boundingBox.Height / (float)maxY;int every = 1;// If dieSizeX or dieSizeY is less then 2 pixels// take only every nth diewhile (sizeX <= 2 || sizeY <= 2){every = every * 2;sizeX = boundingBox.Width / (float)(maxX/every);sizeY = boundingBox.Height / (float)(maxY/every);}SizeF dieSize = new SizeF(sizeX, sizeY);dieSize_ = dieSize;// If every != 1 we recalculate the input data// Otherwise we pass the original dataset// Caveat: We must not overwrite the original dataset ;)if (every > 1){// Create a new dataset// Get the highest bin code in x/y to x/y + every as result for x/y// First set the propertyisScaled = true;scaleFactor = every;drawDies(e.Graphics, boundingBox, fratte.at.WafermapDisplay.WafermapTools.scaleArray(dataset,every), dieSize);// Print "Too small" messageFontFamily myFontFamily = new FontFamily("Arial");Font myFont = new Font(myFontFamily,10,FontStyle.Bold,GraphicsUnit.Pixel);e.Graphics.DrawString(tooSmallString, myFont, new SolidBrush(Color.Red), boundingBox.Location);}else{// PropertiesisScaled = false;scaleFactor = 1;// Simply draw the diedrawDies(e.Graphics, boundingBox, dataset, dieSize);}}else{// Display "No Data" messageFontFamily myFontFamily = new FontFamily("Arial");Font myFont = new Font(myFontFamily,10,FontStyle.Bold,GraphicsUnit.Pixel);e.Graphics.DrawString(noDataString, myFont,new SolidBrush( Color.Red), boundingBox.Location);}}// Try to reuse - only instantiated onceSolidBrush waferFillbrush = new SolidBrush(Color.Silver);Pen blackPen = new Pen(Color.Black);SolidBrush notchFillBrush = new SolidBrush(Color.Black);private void drawCircle(Graphics g, RectangleF boundingBox){ g.FillEllipse(waferFillbrush, boundingBox);g.DrawEllipse(blackPen, boundingBox);}private void drawNotch(Graphics g, RectangleF boundingBox, int location){// Draw the notch (Phyical property on the wafer for alignment. Can be at 0, 90, 180, 270 degrees// starting from 0° at the bottom CCW)// The Shape is  fixed to a cut circlefloat size=boundingBox.Width<boundingBox.Height?boundingBox.Width:boundingBox.Height;size = size * 0.05f;// Calculate the location of the notch// 180°float x=boundingBox.X+(boundingBox.Width/2f)-(size/2f);float y=boundingBox.Y-(size/2f);int start = 0;int end = 180;switch (location){case 0:y = boundingBox.Y +boundingBox.Height-(size / 2f);end = -180;break;case 90:x = boundingBox.X - (size / 2f);y = boundingBox.Y +(boundingBox.Height/2f)- (size / 2f);start = 90;end = -180;break;case 270:x = boundingBox.X +boundingBox.Width- (size / 2f);y = boundingBox.Y + (boundingBox.Height / 2f) - (size / 2f);start = 90;end = 180;break;}g.FillPie(notchFillBrush, x, y, size, size,start,end);}Pen dieOutlinePen = new Pen(Color.Black);private void drawDies(Graphics g, RectangleF boundingBox, int[,] data, SizeF dieSize){for (int x = 0; x < data.GetLength(0); x++){for (int y = 0; y < data.GetLength(1); y++){Color fill = Color.FromArgb(120,colors[data[x, y]]);PointF position = new PointF(boundingBox.X+(float)x * dieSize.Width,boundingBox.Y+(float)y*dieSize.Height);RectangleF die = new RectangleF(position, dieSize);g.FillRectangle(new SolidBrush(fill), die);g.DrawRectangle(dieOutlinePen, die.X,die.Y,die.Width,die.Height);}}}private bool interactive=false;public bool Interactive{get { return interactive; }set { interactive = value;registerEvents();}}private void registerEvents(){// Event to be registeredif (interactive){this.MouseClick += Wafermap_MouseClick;this.MouseMove += Wafermap_MouseMove;this.MouseDoubleClick += Wafermap_MouseDbClick;}}void Wafermap_MouseMove(object sender, MouseEventArgs e){// This one is going to be tricky// We need to calculate the die coordinates from screen coordinates// We have global vars boundingBox_ and dieSize_float x_coord=((float)e.X - boundingBox_.X) / dieSize_.Width;float y_coord = ((float)e.Y - boundingBox_.Y) / dieSize_.Height;int x = (int)Math.Floor(x_coord);int y = (int)Math.Floor(y_coord);try{dieEntered(x, y, dataset[x, y]);}catch (Exception){System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString()+ ":确认在wafer区域移动..");}}public void Wafermap_MouseClick(object sender, MouseEventArgs e){// Basically the same as MouseMove, just a few other infos passedfloat x_coord = ((float)e.X - boundingBox_.X) / dieSize_.Width;float y_coord = ((float)e.Y - boundingBox_.Y) / dieSize_.Height;int x = (int)Math.Floor(x_coord);int y = (int)Math.Floor(y_coord);try{//dieClicked(x, y, dataset[x, y], e.Button);dieClicked(x, y, 0, e.Button);}catch (Exception ex){System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + ":确认单击区域..");throw ex;}}public void Wafermap_MouseDbClick(object sender, MouseEventArgs e){// Basically the same as MouseMove, just a few other infos passedfloat x_coord = ((float)e.X - boundingBox_.X) / dieSize_.Width;float y_coord = ((float)e.Y - boundingBox_.Y) / dieSize_.Height;int x = (int)Math.Floor(x_coord);int y = (int)Math.Floor(y_coord);try{dieClicked(x, y, 2, e.Button);}catch (Exception ex){System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + ":确认双击区域.");throw ex;}}// This method will get called if the mousepointer enters a diepublic virtual void dieEntered(int x, int y, int bincode){// updateDie(x, y, bincode);}// This method should get overridden if you want to reakt on clicks on a diepublic virtual void dieClicked(int x, int y, int bincode,MouseButtons btn){updateDie(x,y, bincode);}// This method should be used to change die coloring of a bin directly// This is needed to avoid redraws when not neccessary// The updated bins are filled with higher alpha to highlight thempublic void updateDie(int x, int y, int bincode){//  Color fill = Color.FromArgb(255, colors[bincode]);Color fill = colors[bincode];PointF position = new PointF(boundingBox_.X + (float)x * dieSize_.Width, boundingBox_.Y + (float)y * dieSize_.Height);RectangleF die = new RectangleF(position, dieSize_);Graphics g = this.CreateGraphics();// update clipping// Create graphics path.GraphicsPath clipPath = new GraphicsPath();clipPath.AddEllipse(boundingBox_);// Set clipping region to path.g.SetClip(clipPath, CombineMode.Replace);// Drawg.FillRectangle(new SolidBrush(fill), die);g.DrawRectangle(dieOutlinePen, die.X, die.Y, die.Width, die.Height);}}
}

构造函数注册点击事件:

 public Wafermap(){zoom=1f;InitializeComponent();SetStyle(ControlStyles.ResizeRedraw, true);DoubleBuffered = true;setupDefaultColors();registerEvents();}

点击双击事件绑定:

 private void registerEvents(){// Event to be registeredif (interactive){this.MouseClick += Wafermap_MouseClick;this.MouseMove += Wafermap_MouseMove;this.MouseDoubleClick += Wafermap_MouseDbClick;}}

SetInteractive(true);

激活事件注册功能

功能代码源码:

待更新。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/166188.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序开发的OA会议之会议,投票,个人中心的页面搭建及模板

目录 一.自定义组件 1.1.创建 1.2.定义 1.3.编写 1.4.使用 二.会议 2.1.数据 2.2.显示 2.3. 样式 三.个人中心 3.1.页面 3.2.样式 四.投票 4.1.引用 4.2.数据 4.3.页面 4.4.样式 好啦今天就到这里了&#xff0c;希望能帮到你哦&#xff01;&#xff01;&…

Unity Animation--动画剪辑(创建动画)

创建一个新的动画编辑 创建新的动画剪辑 &#xff0c;在场景中选择一个GameObject&#xff0c;然后打开“ 动画”窗口&#xff08;顶部菜单&#xff1a;&#xff09;“ 窗口” >“ 动画” >“ 动画”。 如果GameObject 中尚未分配任何动画剪辑&#xff0c;“创建”按钮…

Python 框架学习 Django篇 (四) 数据库增删改查(CURD)

在上一章结尾我们了解到如采用前后端开发分离的架构模式开发&#xff0c;后端几乎不负责任何展现界面的工作&#xff0c;只负责对数据进行管理 &#xff0c;对数据的管理主要体现在&#xff1a; &#xff08;增加、修改、删除、列出 &#xff09;具体的接口参考大佬的文档BYSM…

Spring boot 集成 xxl-job

文章目录 xxl-job 简介引入xxl-job依赖配置xxl-job config添加properties文件配置BEAN模式&#xff08;方法形式&#xff09;步骤一&#xff1a;执行器项目中&#xff0c;开发Job方法&#xff1a;步骤二&#xff1a;调度中心&#xff0c;新建调度任务 xxl-job 简介 官网:https:…

蓝桥杯 (饮料换购,C++)

思路&#xff1a; 1、先加上初始的饮料数n。 2、再加上n可以兑换的饮料数n/3&#xff0c;求多余的瓶盖n%3。循环直至瓶盖数无法兑换新的一瓶饮料。 #include<iostream> using namespace std; int main() {int n,a0,sum0;cin >> n;sum n;while (n){n n a;//加上上…

车载网关通信能力解析——SV900-5G车载网关推荐

随着车联网的发展,各类车载设备对车载网关的需求日益增长。车载网关作为车与车、车与路、车与云之间连接的关键设备,其通信能力直接影响整个系统的性能。本文将详细解析车载网关的通信能力,并推荐性价比高的SV900-5G车载网关。 链接直达&#xff1a;https://www.key-iot.com/i…

【力扣刷题】数组实现栈、后缀表达式(逆波兰表达式)求值、中缀表达式转换为后缀表达式(无括号有括号)

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaEE 操作系统 Redis 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 刷题篇 一、数组实现栈1.1 题目描述1.2 思路…

Filter与Listener(过滤器与监听器)

1.Filter 1.过滤器概述 过滤器——Filter&#xff0c;它是JavaWeb三大组件之一。另外两个是Servlet和Listener 它可以对web应用中的所有资源进行拦截&#xff0c;并且在拦截之后进行一些特殊的操作 在程序中访问服务器资源时&#xff0c;当一个请求到来&#xff0c;服务器首…

接口测试vs功能测试

接口测试和功能测试的区别&#xff1a; 本文主要分为两个部分&#xff1a; 第一部分&#xff1a;主要从问题出发&#xff0c;引入接口测试的相关内容并与前端测试进行简单对比&#xff0c;总结两者之前的区别与联系。但该部分只交代了怎么做和如何做&#xff1f;并没有解释为什…

【diffusion model】扩散模型入门

写在最前&#xff0c;参加DataWhale 10月组队学习。 参考资料&#xff1a; HuggingFace 开源diffusion-models-class 1.扩散模型介绍 2.调用模型生成一张赛博风格的猫咪图片 2.1 安装依赖包 %pip install -qq -U diffusers datasets transformers accelerate ftfy pyarrow9…

软件报错msvcr120.dll丢失怎么办?五个有效修复方法分享

msvcr120.dll是一个动态链接库文件&#xff0c;它是Microsoft Visual C 2012 Redistributable Package的一部分。如果你的电脑在运行一些需要这个文件的程序时出现了“msvcr120.dll丢失”的错误&#xff0c;那么就意味着你的电脑缺少了这个文件&#xff0c;或者这个文件已经损坏…

Jmeter —— 接口之间关联调用(获取上一个接口的返回值作为下一个接口的请求参数)

正则表达式&#xff1a; 具体如何操作&#xff1a; 1. 草稿保存&#xff0c; 此请求的响应数据的id 为发布总结的请求参数draft_id 2. 草稿保存的响应数据 3.在草稿保存的请求中&#xff0c;添加后置处理器- 正则表达式提取器&#xff0c; 提取响应数据的id信息 4. 发布总结请…

[架构之路-239]:目标系统 - 纵向分层 - 中间件middleware

目录 前言&#xff1a; 一、中间件概述 1.1 中间件在软件层次中的位置 1.2 什么是中间件 1.3 为什么需要中间件 1.4 中间件应用场合&#xff08;应用程序不用的底层需求&#xff1a;计算、存储、通信&#xff09; 1.5 中间件分类 - 按内容分 二、嵌入式系统的中间件 2…

TCP/IP(二十二)TCP 实战抓包分析(六)TCP 快速建立连接

一 TCP Fast Open 快速建立连接 说明&#xff1a; 之前讲解TCP 相关知识点遗漏了这个知识点,补充上 ① TFO简介 ② 请求 Fast Open Cookie过程 "原理图" ③ 真正开始 TCP Fast Open 重点&#xff1a; TFO 使 SYN包 可以包含payload 数据 ④ 抓包分析 1、…

怎样才能去除视频中的背景音乐,保留人声?

做视频剪辑&#xff0c;二次创作的朋友&#xff0c;需要去除视频中的背景音乐&#xff0c;保留人声&#xff1b;或者去除人声&#xff0c;保留背景音乐。如果请身边做视频的朋友帮忙&#xff0c;可有时不能沟通到位&#xff0c;完成后的效果并不是很理想&#xff0c;就很尴尬了…

python requests爬取税务总局税案通报、税务新闻和政策解读

文章目录 环境配置页面爬取流程税案通报爬取code税务新闻爬取政策解读爬取 环境配置 python&#xff1a;3.7 requests&#xff1a;发出请求&#xff0c;返回页面 beautifulsoup&#xff1a;解析页面 time&#xff1a;及时 warnings&#xff1a;忽视警告 页面 网址&#xff1…

聊聊设计模式--简单工厂模式

简单工厂模式 ​ 前面也学了很多各种微服务架构的组件&#xff0c;包括后续的服务部署、代码管理、Docker等技术&#xff0c;那么作为后端人员&#xff0c;最重要的任务还是代码编写能力&#xff0c;如何让你的代码写的漂亮、易扩展&#xff0c;让别人一看赏心悦目&#xff0c…

城市正视图(Urban Elevations, ACM/ICPC World Finals 1992, UVa221)rust解法

如图5-4所示&#xff0c;有n&#xff08;n≤100&#xff09;个建筑物。左侧是俯视图&#xff08;左上角为建筑物编号&#xff0c;右下角为高度&#xff09;&#xff0c;右侧是从南向北看的正视图。 输入每个建筑物左下角坐标&#xff08;即x、y坐标的最小值&#xff09;、宽度…

使用Spire.PDF for Python插件从PDF文件提取文字和图片信息

目录 一、Spire.PDF插件的安装 二、从PDF文件提取文字信息 三、从PDF文件提取图片信息 四、提取图片和文字信息的进阶应用 总结 在Python中&#xff0c;提取PDF文件的文字和图片信息是一种常见的需求。为了满足这个需求&#xff0c;许多开发者会选择使用Spire.PDF插件&…

C++特性——inline内联函数

1. 内联函数 1.1 C语言的宏 在C语言中&#xff0c;我们学习了用#define定义的宏函数&#xff0c;例如&#xff1a; #define Add(x, y) ((x) (y)) //两数相加相较于函数&#xff0c;我们知道宏替换具有如下比较明显的优点&#xff1a; 性能优势&#xff1a; 宏在预处理阶段…