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; }
五.实现效果
作者:pcbren 微信号:yadnfku QQ号: 254566449
博客地址:https://www.cnblogs.com/pcbren/
声明:本博客原创文字只代表本人工作中在某一时间内总结的观点或结论,与本人所在单位没有直接利益关系。非商业,未授权,贴子请以现状保留,转载时必须保留此段声明,且在文章页面明显位置给出原文连接。
如果大家感觉我的博文对大家有帮助,请推荐支持一把。