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


這里講解一下用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在圖形上只能玩點小玩意了,注定玩不了大了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM