这里讲解一下用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. Sublime Text 3 快捷键(转载)

    本文转自:https://segmentfault.com/a/1190000002570753 (欢迎阅读原文,侵删) Sublime Text 3 快捷键精华版 Ctrl+Shift+P:打开命令 ...

  2. 【Linux软件安装】

    安装约定 软件安装在/opt目录下,opt目录规范: modules:软件安装的目录 softwares:软件包目录 tools:工具目录 datas:数据目录 如果出现 No XXX package ...

  3. C语言二叉树的创建、(先中后序)遍历以及存在的问题

    #include<stdlib.h> #include<stdio.h> #define True 1 #define False 0 typedef char TElemTy ...

  4. 恶补---bell数

    定义 bell数即一个集合划分的数目 示例 前几项的bell数列为 1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147, 115975 ,... 求值方法 1.bell ...

  5. sublime3注册码

    TwitterInc User License EA7E 1D77F72E 390CDD93 4DCBA022 FAF60790 61AA12C0 A37081C5 D0316412 4584D136 ...

  6. 《编译原理》构造 LL(1) 分析表的步骤 - 例题解析

    <编译原理>构造 LL(1) 分析表的步骤 - 例题解析 易错点及扩展: 1.求每个产生式的 SELECT 集 2.注意区分是对谁 FIRST 集 FOLLOW 集 3.开始符号的 FOL ...

  7. 【Codeforces 992B】Nastya Studies Informatics

    [链接] 我是链接,点我呀:) [题意] 题意 [题解] 因为gcd(a,b)=x 所以设a = nx b = mx 又有ab/gcd(a,b)=lcm(a,b)=y 则nmx = y 即n(m*x) ...

  8. 【Codeforces 356A】Knight Tournament

    [链接] 我是链接,点我呀:) [题意] n个人矩形m场比赛 每场比赛由编号为li~ri且之前没有被淘汰的人进行. 已知第i场的winner是xi winner会把这一场其他所有的人都淘汰. 问你n个 ...

  9. 泛型转换https://www.cnblogs.com/eason-chan/p/3633210.html

    import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;//总结1.st.getClass==Student. ...

  10. 【MangoDB分片】配置mongodb分片群集(sharding cluster)

    配置mongodb分片群集(sharding cluster) Sharding cluster介绍 这是一种可以水平扩展的模式,在数据量很大时特给力,实际大规模应用一般会采用这种架构去构建monod ...