介紹一種常規的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; }
五.實現效果