介绍一种常规的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;
}
五.实现效果
来源:oschina
链接:https://my.oschina.net/u/4340477/blog/3333783