这里讲解一下用net解析PCB图形绘制实现方法

一.解析PCB图形绘制实现

解析PCB图形,说简单也非常简单,先说一下,PCB Gerber图形由:点,线,弧,铜皮,文字 5类元素组成,通常简写为:P,L,A,S,T五类,这几类元素的难易程度,刚好是按这个顺序排列的(个人实际应用这么认为的)。即然是5类就得建立5种元素的数据结构存储它吧,

PAD结构

    /// <summary>
/// PAD 数据类型
/// </summary>
public struct gP
{
public gPoint p;
public bool negative;//polarity-- positive negative
public int angle;
public bool mirror;
public string symbols;
public string attribut;
public double width;
}

线结构

    /// <summary>
/// Line 数据类型
/// </summary>
public struct gL
{
public gPoint ps;
public gPoint pe;
public bool negative;//polarity-- positive negative
public string symbols;
public string attribut;
public double width;
}

弧结构

    /// <summary>
/// ARC 数据类型
/// </summary>
public struct gA
{
public gPoint ps;
public gPoint pe;
public gPoint pc;
public bool negative;//polarity-- positive negative
public bool ccw; //direction-- cw ccw
public string symbols;
public string attribut;
public double width;
}

铜皮结构

    /// <summary>
/// Surface 坐标泛型集类1
/// </summary>
public struct gSur_Point
{
public gPoint p;
/// <summary>
/// 0为折点 1为顺时针 2为逆时针
/// </summary>
public byte type_point;
}
/// <summary>
/// Surface 坐标泛型集类2
/// </summary>
public class gSur_list
{
public List<gSur_Point> sur_list = new List<gSur_Point>();
/// <summary>
/// 是否为空洞
/// </summary>
public bool is_hole { get; set; }
/// <summary>
/// 是否逆时针
/// </summary>
public bool is_ccw { get; set; }
}
/// <summary>
/// Surface 坐标泛型集类3
/// </summary>
public class gS
{
public List<gSur_list> sur_group = new List<gSur_list>();
/// <summary>
/// 是否为负 polarity-- P N
/// </summary>
public bool negative { get; set; }
public string attribut { get; set; }
}

文字结构

看这个结构比Surface铜皮结构还简单呀,为什么文字结构更复杂了,这里只是实现最普通的字体结构,实际复杂程度远大于Surface,需要解析到所用到的字体库中的的坐标,而且字体存在各式各样的,有二维码,点阵字,有条码,要想保证和Genesis所显示一致,这里需要下点功夫。

    /// <summary>
/// Text 文本数据类型 简易型 更复杂的需要扩展
/// </summary>
public struct gT
{
public gPoint ps;
public string font;
public bool negative;//polarity-- positive negative
public int angle;
public bool mirror;
public double x_size;
public double y_size;
public double width;
public string Text;
public string attribut;
}

那么为什么symbols不算一类呢,因为symbols也是由这5类基础元素组合而成的,绘制时检索symbols中所含元素集合,再将Symbols集合遍历一个一个的元素绘制到画板上来的。

Gerber数据存储到这个结构中后.那用Graphics类,遍历元素集合,依次绘制元素就好了;下面说一下遇到的问题解决方法

二.绘制Gerber图形遇到的几个问题解决方法

1.同一层图形的元素是存在先后顺序的,不能按元素类别分类集合,如List<P>,List<L>,这样是错误的

若元素要按先后顺序保存,那么这里可以选择用ArrayList集合存储数据

2.绘制圆形焊盘时,对于Genesis而言它是一个点坐标,在net中是没有直接绘制点方法.

那么对应net中是用FillEllipse方法绘制就可以了

3.绘制焊盘有很多种symbols,包含标准symbols和非标准symbols(自定义的),如何判断一个symbols是标准symbols还是非标准symbols呢

在解析ODB++或Gerber前,提前将自定义symbols名存储为自定义symbols字典集合中,绘制时优先检测symbols名是否存在自定义字典集合中,如果存在,则解析自定义symbosl绘制,如果不存在,则通过标准symbosl名命名规则匹配,不考虑校率用正则也可以的,如:r200,rect200x300,oval200x300,donut_r300x200等,匹配到标准symbols后通过建立各种标准symbols绘制模版,找到对应的symbols模版再绘制。

4.如绘制:donut_r300x200这个symbols时,是绘制300这个实心圆,再绘制黑色背景实现圆环效果呢,

其实这样绘制就是错误的,需采用:GraphicsPath类绘制,再用Region类差集裁减掉不需要多余部份图形。

5.在Gerber图形中一条弧直径只有0.1毫米,转为像素为0,绘制会出错,

要这里需加以判断,0像素时直接跳出不绘

6.在Gerber图形中一条线段,线段间距只有0.1毫米, 转为像素为0时,但线宽为5毫米,转为像不为2像素,

那这是绘呢,还是不绘呢,由于长度像素是0,但线的宽度达到了2个像素,那么就这条线就按一个点来绘制

7.在Gerber中Surface铜皮中存在空洞时,不能用FillPolygon方法绘制,

需采用:GraphicsPath类绘制,再用Region类差集裁减掉不需要多余部份图形

8.在Gerber中Surface铜皮存在弧节点时,不能用FillPolygon方法绘制,这结构它不支持弧节点,

如果一定要要用FillPolygon可以将弧转为多个节点来绘制多边形,当然另一种方法用GraphicsPath类中增Arc结点来完成弧的绘制

9.Gerber中如果字体引用了shx字体如何解析呢

这里就需要熟悉shx的数据结构了才行了,不然一点办法也没有

点击进去:  https://wenku.baidu.com/view/0f7d49c4aa00b52acfc7cab3.html   这是解析方法,解析后再转为坐标数据就可以了

10.如果是:canned_57,standard等字体如何解析呢

这是Genesis自带字体,文件一般存放在:C:\genesis\fw\lib\fonts,这是明文坐标很好解决,直接解析就好了。

三.5类元素基本数据结构

这是基本的不全面,可以扩展并改进的

 /// <summary>
/// 点 数据类型 (XY)
/// </summary>
public struct gPoint
{
public gPoint(gPoint p_)
{
this.x = p_.x;
this.y = p_.y;
}
public gPoint(double x_val, double y_val)
{
this.x = x_val;
this.y = y_val;
}
public double x;
public double y;
public static gPoint operator +(gPoint p1, gPoint p2)
{
p1.x += p2.x;
p1.y += p2.y;
return p1;
}
public static gPoint operator -(gPoint p1, gPoint p2)
{
p1.x -= p2.x;
p1.y -= p2.y;
return p1;
} } /// <summary>
/// 精简 PAD 数据类型
/// </summary>
public struct gPP
{
public gPP(double x_val, double y_val, double width_)
{
this.p = new gPoint(x_val, y_val);
this.symbols = "r";
this.width = width_;
}
public gPP(gPoint p_, double width_)
{
this.p = p_;
this.symbols = "r";
this.width = width_;
}
public gPP(gPoint p_, string symbols_, double width_)
{
this.p = p_;
this.symbols = symbols_;
this.width = width_;
}
public gPoint p;
public string symbols;
public double width;
public static gPP operator +(gPP p1, gPP p2)
{
p1.p += p2.p;
return p1;
}
public static gPP operator +(gPP p1, gPoint p2)
{
p1.p += p2;
return p1;
}
public static gPP operator -(gPP p1, gPP p2)
{
p1.p -= p2.p;
return p1;
}
public static gPP operator -(gPP p1, gPoint p2)
{
p1.p -= p2;
return p1;
}
}
/// <summary>
/// PAD 数据类型
/// </summary>
public struct gP
{
public gP(double x_val, double y_val, double width_)
{
this.p = new gPoint(x_val, y_val);
this.negative = false;
this.angle = ;
this.mirror = false;
this.symbols = "r";
this.attribut = string.Empty;
this.width = width_;
}
public gP(gPoint p_, double width_)
{
this.p = p_;
this.negative = false;
this.angle = ;
this.mirror = false;
this.symbols = "r";
this.attribut = string.Empty;
this.width = width_;
}
public gP(gPoint p_, string symbols_, double width_)
{
this.p = p_;
this.negative = false;
this.angle = ;
this.mirror = false;
this.symbols = symbols_;
this.attribut = string.Empty;
this.width = width_;
} public gPoint p;
public bool negative;//polarity-- positive negative
public int angle;
public bool mirror;
public string symbols;
public string attribut;
public double width;
public static gP operator +(gP p1, gP p2)
{
p1.p += p2.p;
return p1;
}
public static gP operator +(gP p1, gPP p2)
{
p1.p += p2.p;
return p1;
}
public static gP operator +(gP p1, gPoint p2)
{
p1.p += p2;
return p1;
}
public static gP operator -(gP p1, gP p2)
{
p1.p -= p2.p;
return p1;
}
public static gP operator -(gP p1, gPP p2)
{
p1.p -= p2.p;
return p1;
}
public static gP operator -(gP p1, gPoint p2)
{
p1.p -= p2;
return p1;
}
}
/// <summary>
/// Line 数据类型
/// </summary>
public struct gL
{
public gL(double ps_x, double ps_y, double pe_x, double pe_y, double width_)
{
this.ps = new gPoint(ps_x, ps_y);
this.pe = new gPoint(pe_x, pe_y);
this.negative = false;
this.symbols = "r" + width_.ToString();
this.attribut = string.Empty;
this.width = width_;
}
public gL(gPoint ps_, gPoint pe_, double width_)
{
this.ps = ps_;
this.pe = pe_;
this.negative = false;
this.symbols = "r" + width_.ToString();
this.attribut = string.Empty;
this.width = width_;
}
public gL(gPoint ps_, gPoint pe_, string symbols_, double width_)
{
this.ps = ps_;
this.pe = pe_;
this.negative = false;
this.symbols = symbols_;
this.attribut = string.Empty;
this.width = width_;
}
public gPoint ps;
public gPoint pe;
public bool negative;//polarity-- positive negative
public string symbols;
public string attribut;
public double width;
public static gL operator +(gL l1, gPoint move_p)
{
l1.ps += move_p;
l1.pe += move_p;
return l1;
}
public static gL operator +(gL l1, gPP move_p)
{
l1.ps += move_p.p;
l1.pe += move_p.p;
return l1;
}
public static gL operator +(gL l1, gP move_p)
{
l1.ps += move_p.p;
l1.pe += move_p.p;
return l1;
}
public static gL operator -(gL l1, gPoint move_p)
{
l1.ps -= move_p;
l1.pe -= move_p;
return l1;
}
public static gL operator -(gL l1, gPP move_p)
{
l1.ps -= move_p.p;
l1.pe -= move_p.p;
return l1;
}
public static gL operator -(gL l1, gP move_p)
{
l1.ps -= move_p.p;
l1.pe -= move_p.p;
return l1;
}
}
/// <summary>
/// ARC 数据类型
/// </summary>
public struct gA
{
public gA(double ps_x, double ps_y, double pc_x, double pc_y, double pe_x, double pe_y, double width_, bool ccw_)
{
this.ps = new gPoint(ps_x, ps_y);
this.pc = new gPoint(pc_x, pc_y);
this.pe = new gPoint(pe_x, pe_y);
this.negative = false;
this.ccw = ccw_;
this.symbols = "r" + width_.ToString();
this.attribut = string.Empty;
this.width = width_;
}
public gA(gPoint ps_, gPoint pc_, gPoint pe_, double width_, bool ccw_ = false)
{
this.ps = ps_;
this.pc = pc_;
this.pe = pe_;
this.negative = false;
this.ccw = ccw_;
this.symbols = "r" + width_.ToString();
this.attribut = string.Empty;
this.width = width_;
}
public gPoint ps;
public gPoint pe;
public gPoint pc;
public bool negative;//polarity-- positive negative
public bool ccw; //direction-- cw ccw
public string symbols;
public string attribut;
public double width;
public static gA operator +(gA arc1, gPoint move_p)
{
arc1.ps += move_p;
arc1.pe += move_p;
arc1.pc += move_p;
return arc1;
}
public static gA operator +(gA arc1, gPP move_p)
{
arc1.ps += move_p.p;
arc1.pe += move_p.p;
arc1.pc += move_p.p;
return arc1;
}
public static gA operator +(gA arc1, gP move_p)
{
arc1.ps += move_p.p;
arc1.pe += move_p.p;
arc1.pc += move_p.p;
return arc1;
}
public static gA operator -(gA arc1, gPoint move_p)
{
arc1.ps -= move_p;
arc1.pe -= move_p;
arc1.pc -= move_p;
return arc1;
}
public static gA operator -(gA arc1, gPP move_p)
{
arc1.ps -= move_p.p;
arc1.pe -= move_p.p;
arc1.pc -= move_p.p;
return arc1;
}
public static gA operator -(gA arc1, gP move_p)
{
arc1.ps -= move_p.p;
arc1.pe -= move_p.p;
arc1.pc -= move_p.p;
return arc1;
} }
/// <summary>
/// Text 文本数据类型 简易型 更复杂的需要扩展
/// </summary>
public struct gT
{
public gPoint ps;
public string font;
public bool negative;//polarity-- positive negative
public int angle;
public bool mirror;
public double x_size;
public double y_size;
public double width;
public string Text;
public string attribut;
}
/// <summary>
/// Surface 坐标泛型集类1
/// </summary>
public struct gSur_Point
{
public gSur_Point(double x_val, double y_val, byte type_point_)
{
this.p.x = x_val;
this.p.y = y_val;
this.type_point = type_point_;
}
public gSur_Point(gPoint p, byte type_point_)
{
this.p = p;
this.type_point = type_point_;
}
public gPoint p;
/// <summary>
/// 0为折点 1为顺时针 2为逆时针
/// </summary>
public byte type_point;
}
/// <summary>
/// Surface 坐标泛型集类2
/// </summary>
public class gSur_list
{
public List<gSur_Point> sur_list = new List<gSur_Point>();
/// <summary>
/// 是否为空洞
/// </summary>
public bool is_hole { get; set; }
/// <summary>
/// 是否逆时针
/// </summary>
public bool is_ccw { get; set; }
}
/// <summary>
/// Surface 坐标泛型集类3
/// </summary>
public class gS
{
public List<gSur_list> sur_group = new List<gSur_list>();
/// <summary>
/// 是否为负 polarity-- P N
/// </summary>
public bool negative { get; set; }
public string attribut { get; set; }
}
/// <summary>
/// 整层Layer坐标泛型集类
/// </summary>
public class gLayer //坐标
{
public List<gP> Plist = new List<gP>();
public List<gL> Llist = new List<gL>();
public List<gA> Alist = new List<gA>();
public List<gT> Tlist = new List<gT>();
public List<gS> Slist = new List<gS>();
}

四.net实现效果图:

小结:

.NET图形绘制效率真是个一大问题,图形小绘制还感觉不明显,当元素数量大于20W时绘制时间超长,有时内存爆掉,,但同时打开Genesis却不爆,不管是编程语言,数据结构存储,解析算法上都要更高超,不得不佩服Frontline太有实力。看来只能用NET在图形上只能玩点小玩意了,注定玩不了大了。

PCB ODB++(Gerber)图形绘制实现方法的更多相关文章

  1. MFC画图总结-DIB图形绘制

    參考文档: http://blog.csdn.net/hnust_xiehonghao/article/details/37652927 http://blog.sina.com.cn/s/blog_ ...

  2. C#中的GDI+图形绘制方法

    GDI+图形绘制方法 1.首先对于绘制图形,必须的先将命名空间导入:using System.Drawing.Drawing2D; 2.然后在一个事件中写入程序 首先先将Graphics这个对象实例化 ...

  3. cocos2d-x 图形绘制

    转自:http://blog.csdn.net/zhy_cheng/article/details/8480048 图形绘制的话,在cocos2d-x自带的TestCpp里有,包括绘制点,直线,多边形 ...

  4. 一种基于重载的高效c#上图片添加文字图形图片的方法

    在做图片监控显示的时候,需要在图片上添加文字,如果用graphics类绘制图片上的字体,实现图像上添加自定义标记,这种方法经验证是可行的,并且在visual c#2005 编程技巧大全上有提到,但是, ...

  5. 图形绘制 Canvas Paint Path 详解

    图形绘制简介        Android中使用图形处理引擎,2D部分是android SDK内部自己提供,3D部分是用Open GL ES 1.0.大部分2D使用的api都在android.grap ...

  6. VC图形绘制双缓存的代码复用性讨论

    在前文中已经讨论了如何实现界面绘制双缓存的问题,前文网址如下: http://www.2cto.com/kf/201111/112429.html 双缓存的主要思路是:先把图形绘制到内存DC中,然后再 ...

  7. 使用原生JavaScript的Canvas实现拖拽式图形绘制,支持画笔、线条、箭头、三角形、矩形、平行四边形、梯形以及多边形和圆形,不依赖任何库和插件,有演示demo

    前言 需要用到图形绘制,没有找到完整的图形绘制实现,所以自己实现了一个 - - 一.实现的功能 1.基于oop思想构建,支持坐标点.线条(由坐标点组成,包含方向).多边形(由多个坐标点组成).圆形(包 ...

  8. canvas图形绘制

    前面的话 前面分别介绍了canvas的基础用法和进阶用法,本文将使用canvas的各种语法进行图形绘制 绘制线条 [绘制线条] 下面来尝试绘制一段线条 <canvas id="draw ...

  9. (转)GPU图形绘制管线

    摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文名“GPU编程与CG语言之阳春白雪下里巴人”第二章. 图形绘制管线描述GPU渲染流程, ...

随机推荐

  1. kubeadmin 安装k8s集群

    系统设置 CentOS Linux release 7.6.1810 (Core) 修改主机名 vim /etc/hostname k8s-master hostname -F /etc/hostna ...

  2. 向appstore提交app流程

    http://www.cocoachina.com/newbie/tutorial/2013/0508/6155.html http://blog.csdn.net/holydancer/articl ...

  3. webpack之webpack-dev-server 与 webpack-hot-server

    最近在弄框架,用到了webpack打包,当然不可避免的遇到了开发实际问题.在实际开发中,我们不可能改一个文件,就去构建一次,于是想到了实时更新.查看webpack,看到了webpack-dev-ser ...

  4. C/C++野指针

    野指针: 野指针不同于空指针,空指针是指一个指针的值为null,而野指针的值并不为null,野指针会指向一段实际的内存,只是它指向哪里我们并不知情,或者是它所指向的内存空间已经被释放,所以在实际使用的 ...

  5. 关于ISIS协议 CSNP报文的周期更新理解

    为何ISIS协议的CSNP报文在MA网络环境中是以周期更新然而在P2P网络环境中只更新一次? 个人通过视频及资料学习理解: 我们知道ISIS的CSNP报文类似OSPF中的DBD报文,作用就是用来确认彼 ...

  6. ubuntu wsl 子系统使用win10 系统ss代理步骤

    wind10 安装ss客户端 配置server 具体不多说 安装 ubuntu 子系统 3.安装python pip apt install python-pip 4.升级pip pip instal ...

  7. Android jdbc连接mysql报错解决方案 (Communications link failure)

    最近调试安卓连接mysql真是心态爆炸,快两天才搞出来.以下整理一些常见问题. 检查manifest文件里网络权限是否打开 检查数据库IP是否有问题(包括一些沙雕错误,比如是不是在ip首或尾多了个空格 ...

  8. Apache Maven Cookbook(一)maven 使用命令创建、编译java项目

    一.创建 使用命令创建项目分几步: 1.打开命令行窗口,比如cmd,把目录切换至想要创建项目地方. 2.执行如下命令: mvn archetype:generate -DgroupId=com.zua ...

  9. Leetcode 89.格雷编码

    格雷编码 格雷编码是一个二进制数字系统,在该系统中,两个连续的数值仅有一个位数的差异. 给定一个代表编码总位数的非负整数 n,打印其格雷编码序列.格雷编码序列必须以 0 开头. 示例 1: 输入: 2 ...

  10. [luoguP1879] [USACO06NOV]玉米田Corn Fields(DP)

    传送门 说要统计方案,感觉就是个 Σ 而矩阵中只有 01 ,可以用二进制表示 这样,预处理出每一个每一行所有可能的状态 s 然后初始化第一行所有状态的方案数为 1 f[i][j] = Σf[i - 1 ...