PCB genesis识别邮票孔开通窗实现方法

       介绍一种常规的genesis识别邮票孔开通窗实现方法

 一.需求:识别邮票孔并开通窗

 二.常见的几种邮票孔类型

 

 三.邮票孔有哪些特征

     1.  邮票孔属性是NPTH无铜孔(non_plated)

     2. 邮票孔与邮票孔间距常规<=0.5mm

     3.邮票孔与外形间距<=0.5mm

     4.邮票孔个数 通常>=3个 (也存在1个或2个邮票孔的情况)

 

     5.邮票孔与邮票孔间距步长公差不超过0.2mm

     6.邮票孔与邮票孔角度步长公差不超过0.2度

     7.邮票孔3点最大角>150度(此规则是对第6条特征补充,当邮票孔刚好只有3个孔的时候,可以用角度来判断是否邮票孔)

 

 

 

 四.代码实现(跟据定义的邮票孔特征来代码实现)
        /// <summary>
        /// 从钻孔层中获取邮孔并创建新层
        /// </summary>
        /// <param name="DrillLayer">钻孔层名</param>
        /// <param name="RoutLayer">外形层名</param>
        /// <param name="StampHoleLayer">邮票孔创建层名</param>
        /// <param name="StampHoleUpVal">邮票最大间距</param>
        /// <param name="Ang_Tol">允许角度公差</param>
        /// <param name="Di_Tol">允许距离公差</param>
        /// <param name="AngDiff_Standard">角度差值</param>
        /// <returns>【-1】 未检测到NPTH孔  【0】检测到邮票孔 >【0】检测到邮票孔组数</returns>
        public static int CreateStampHoleLayer(string DrillLayer = "drl", string RoutLayer = "rout", string stamp_holeLayerName = "stamp_hole", double StampHoleUpVal = 500, double Ang_Tol = 0.2, double Di_Tol = 0.2, double AngDiff_Standard = 30)
        {
            StampHoleUpVal *= 2;
            var SurfaceFeatCount = 0;
            g.SetWorkLayer("");
            g.COM(g._change_units_mm);
            g.SetAffectedLayer(DrillLayer);
            g.FilterAtrSet(".drill", "non_plated");
            g.FilterSelect();
            g.FilterReset();
            if (g.getSelectCount() == 0)
                return -1;
            //判断是否存在邮票孔
            string npth_hole = "npth_hole";
            string npth_hole_surface = "npth_hole_surface";
            g.Sel_CopyLayer(npth_hole);
            g.CopyLayer(npth_hole, npth_hole_surface);
            g.SetAffectedLayer(npth_hole_surface);
            g.Sel_Resize(StampHoleUpVal);
            g.Sel_Contourize();
            if (g.Check_Layer_Exist(RoutLayer))
            {
                g.Sel_Ref_feat(Ref_feat_mode.touch, RoutLayer);
                g.getSelectCountReverseIsDelete();
            }
            g.SetAffectedLayer(npth_hole);
            g.Sel_Resize(StampHoleUpVal + 100);
            g.Sel_Ref_feat(Ref_feat_mode.include, npth_hole_surface);
            g.getSelectCountIsDelete();
            g.Sel_Ref_feat(Ref_feat_mode.touch, npth_hole_surface);
            g.getSelectCountReverseIsDelete();
            g.Sel_Resize(-(StampHoleUpVal + 100));
            var HoleFeatCount = g.getLayerFeatCount();
            g.SetAffectedLayer(npth_hole_surface);
            g.Sel_Ref_feat(Ref_feat_mode.disjoint, npth_hole);
            g.getSelectCountIsDelete();
            SurfaceFeatCount = g.getLayerFeatCount();
            g.DelLayer(stamp_holeLayerName);
            g.CopyLayer(npth_hole_surface, stamp_holeLayerName);
            g.CopyLayer(npth_hole, stamp_holeLayerName);
            g.DelLayer(npth_hole_surface);
            g.DelLayer(npth_hole);

            //选择并获取邮票孔
            g.SetAffectedLayer(stamp_holeLayerName);
            gLayer StampHoleLayer = new gLayer();
            d2 calc2 = new d2();
            add addCOM = new add();
            for (int i = 1; i <= SurfaceFeatCount; i++)
            {
                g.COM(g._sel_clear_feat);
                g.Sel_Layer_feat(i, stamp_holeLayerName);
                g.Sel_Ref_feat(Ref_feat_mode.touch);
                if (g.getSelectCount() >= 3)
                {
                    bool isOK = true;
                    bool isArc = false;
                    var StampHoleList = g.getFEATURES(stamp_holeLayerName).Plist;
                    var StampHoleSymbolCount = StampHoleList.GroupBy(tt => tt.symbols).Select(tt => tt.Key).Count();
                    if (StampHoleSymbolCount > 1) continue;
                    var StampHoleRect = calc2.p_RectP(StampHoleList);
                    if (StampHoleRect.size.x > StampHoleRect.size.y)
                        StampHoleList = StampHoleList.OrderBy(tt => tt.p.x).ToList();
                    else
                        StampHoleList = StampHoleList.OrderBy(tt => tt.p.y).ToList();
                    var AngPre = calc2.p_ang(StampHoleList[0].p, StampHoleList[1].p);
                    var AngDiffPre = 0.0;
                    var DiPre = calc2.p2p_di(StampHoleList[0].p, StampHoleList[1].p);
                    for (int j = 2; j < StampHoleList.Count(); j++)
                    {
                        var Ang = calc2.p_ang(StampHoleList[j - 1].p, StampHoleList[j].p);
                        var AngDiff = Math.Abs(Ang - AngPre);
                        isArc = AngDiff > 0.01;
                        var Di = calc2.p2p_di(StampHoleList[j - 1].p, StampHoleList[j].p);
                        if (!(AngDiff <= AngDiff_Standard)) { isOK = false; break; }
                        if (!(Math.Abs(DiPre - Di) <= Di_Tol)) { isOK = false; break; }
                        if (j >= 3 && !(Math.Abs(AngDiffPre - AngDiff) <= Ang_Tol)) { isOK = false; break; }
                        AngPre = Ang;
                        AngDiffPre = AngDiff;
                        DiPre = Di;
                    }
                    if (isOK)
                    {
                        var Width = d2.getSymbolsVal(StampHoleList[0].symbols);
                        if (isArc)
                        {
                            var Pcenter = calc2.a_3Point2Acenter(StampHoleList[0].p, StampHoleList[StampHoleList.Count >> 1].p, StampHoleList[StampHoleList.Count - 1].p);
                            gA arc = new gA(StampHoleList[0].p, Pcenter, StampHoleList[StampHoleList.Count - 1].p, Width);
                            if (calc2.a_Angle(arc) >= 180) arc.ccw = true;
                            addCOM.arc(arc);
                            StampHoleLayer.Alist.Add(arc);
                        }
                        else
                        {
                            gL line = new gL(StampHoleList[0].p, StampHoleList[StampHoleList.Count - 1].p, Width);
                            StampHoleLayer.Llist.Add(line);
                        }
                    }
                }
            }
            g.COM(g._sel_clear_feat);
            g.COM(g._sel_delete);
            int FeatCount = (StampHoleLayer.Llist.Count() + StampHoleLayer.Alist.Count());
            if (FeatCount > 0)
                addCOM.any(StampHoleLayer);
            else
                g.DelLayer(stamp_holeLayerName);
            g.SetAffectedLayer();
            return FeatCount;
        }
 五.实现效果

posted @ 2019-12-07 00:20  pcbren  阅读(1886)  评论(0编辑  收藏  举报