1. 程式人生 > >PCB ODB++(Gerber)圖形繪制實現方法

PCB ODB++(Gerber)圖形繪制實現方法

lib 如何判斷 fc7 polygon close font plist fonts 多邊形

這裏講解一下用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 = 0;
            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 = 0;
            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 = 0;
            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>();
    }
View Code

四.net實現效果圖:

技術分享圖片

小結:

.NET圖形繪制效率真是個一大問題,圖形小繪制還感覺不明顯,當元素數量大於20W時繪制時間超長,有時內存爆掉,,但同時打開Genesis卻不爆,不管是編程語言,數據結構存儲,解析算法上都要更高超,不得不佩服Frontline太有實力。看來只能用NET在圖形上只能玩點小玩意了,註定玩不了大了。

PCB ODB++(Gerber)圖形繪制實現方法