PCB钻Slot槽一般都采用G85命令钻槽孔,而采用G85命令工程CAM无法准确的知道Slot槽钻多少个孔,并不能决定钻槽孔的顺序,因为采用G85命令钻孔密度与钻槽顺序由钻机本身决定的.在这里介绍一种如果不用G85命令,如何将Slot槽生成多个钻孔。

一.我们先了解一下G85命令钻槽

钻孔顺序

孔密度

连一篇文章有关于Slot槽孔数计算方式: https://www.cnblogs.com/pcbren/p/9379178.html

二.求解思路

1.通过孔密度,求出孔与孔中心距离

2.再以Slot槽的一端做为起点,增量值(孔中心距),方位角(Slot槽的方位角),逐个求出下一个钻孔位置.直到到达Slot槽终点节止。

三.C#简易代码实现:

1.Slot槽转钻孔代码(这里段代码实现将Slot槽转为钻孔,钻孔顺序是一个SLOT槽依次逐个从头钻到头尾,和G85命令钻槽顺序不一样)

            string drilllayer = "drl";
gLayer layer = g.getFEATURES($"{drilllayer}", g.STEP, g.JOB, "mm", true);
List<gPP> pList = new List<gPP>();
foreach (var line in layer.Llist)
{
var HoleCenterDi = calc2.p_Convex(line.width * 0.0005);
pList.AddRange(calc2.l_2Plist(line, HoleCenterDi, true));
}
foreach (var arc in layer.Alist)
{
var HoleCenterDi = calc2.p_Convex(arc.width * 0.0005);
pList.AddRange(calc2.a_2Plist(arc, HoleCenterDi,, true));
}
addCOM.pad(pList);

2.计算函数

        /// <summary>
/// 通过孔半径与凸高位求 孔中心距
/// </summary>
/// <param name="Rradius">孔半径</param>
/// <param name="tol_">凸位高度值</param>
/// <returns></returns>
public double p_Convex(double Rradius, double tol_ = 0.0127)
{
return Math.Sqrt(Math.Pow(Rradius, ) - Math.Pow(Rradius - tol_, )) * ;
}
/// <summary>
/// 线Line 转点P组集
/// </summary>
/// <param name="l"></param>
/// <param name="len_">点的间距</param>
/// <returns></returns>
public List<gPP> l_2Plist(gL l, double len_ = 0.1d, bool is_avg = false)
{
List<gPP> list_point = new List<gPP>();//采用优先占用线两端 如果有从线的一端出发增量间距后续再做更改
double line_len = l_Length(l);
gPP tempP;
tempP.p = l.ps;
tempP.symbols = l.symbols;
tempP.width = l.width;
list_point.Add(tempP);
int avg_count = (int)(Math.Ceiling(line_len / len_)) - ;
if (avg_count > )
{
if (is_avg)
len_ = line_len / avg_count;
double angle_ = p_ang(l.ps, l.pe);
for (int i = ; i < avg_count; i++)
{
tempP = p_val_ang(tempP, len_, angle_);
list_point.Add(tempP);
}
}
tempP.p = l.pe;
list_point.Add(tempP);
return list_point;
}
/// <summary>
/// 求方位角
/// </summary>
/// <param name="ps"></param>
/// <param name="pe"></param>
/// <returns></returns>
public double p_ang(gPoint ps, gPoint pe)
{
double a_ang = Math.Atan((pe.y - ps.y) / (pe.x - ps.x)) / Math.PI * ;
//象限角 转方位角 计算所属象限 并求得方位角
if (pe.x >= ps.x && pe.y >= ps.y) //↗ 第一象限
{
return a_ang;
}
else if (!(pe.x >= ps.x) && pe.y >= ps.y) // ↖ 第二象限
{
return a_ang + ;
}
else if (!(pe.x >= ps.x) && !(pe.y >= ps.y)) //↙ 第三象限
{
return a_ang + ;
}
else if (pe.x >= ps.x && !(pe.y >= ps.y)) // ↘ 第四象限
{
return a_ang + ;
}
else
{
return a_ang;
}
}//求方位角
/// <summary>
/// 求增量坐标
/// </summary>
/// <param name="ps">起点</param>
/// <param name="val">增量值</param>
/// <param name="ang_direction">角度</param>
/// <returns></returns>
public gPP p_val_ang(gPP ps, double val, double ang_direction)
{
gPP pe = ps;
pe.p.x = ps.p.x + val * Math.Cos(ang_direction * Math.PI / );
pe.p.y = ps.p.y + val * Math.Sin(ang_direction * Math.PI / );
return pe;
}
/// <summary>
/// 求线Line长度
/// </summary>
/// <param name="l"></param>
/// <param name="is_calc_width"></param>
/// <returns></returns>
public double l_Length(gL l, bool is_calc_width = false)
{
if (is_calc_width)
return Math.Sqrt((l.ps.x - l.pe.x) * (l.ps.x - l.pe.x) + (l.ps.y - l.pe.y) * (l.ps.y - l.pe.y)) + l.width / ;
else
return Math.Sqrt((l.ps.x - l.pe.x) * (l.ps.x - l.pe.x) + (l.ps.y - l.pe.y) * (l.ps.y - l.pe.y));
}
/// <summary>
/// 弧Arc 转点P组集
/// </summary>
/// <param name="a"></param>
/// <param name="val_">此数值表示:分段数值</param>
/// <param name="type_">代表值数值类型 【0】弧长 【1】角度 【2】弦长 </param>
/// <param name="is_avg">是否平均分布 </param>
/// <returns></returns>
public List<gPP> a_2Plist(gA a, double val_ = 0.1d, int type_ = , bool is_avg = false)
{
List<gPP> list_point = new List<gPP>();
gPP tempP;
tempP.p = a.ps;
tempP.symbols = a.symbols;
tempP.width = a.width;
list_point.Add(tempP); double avg_count;
double angle_val = ;
double rad_ = p2p_di(a.pc, a.pe);
double sum_alge = a_Angle(a);
if (type_ == ) // 【1】角度
{
angle_val = val_;
avg_count = (int)(Math.Ceiling(sum_alge / angle_val)) - ; // 总角度/单角度
}
else if (type_ == ) //【2】弦长
{
angle_val = Math.Asin(val_ / (rad_ * )) * / pi;
avg_count = (int)(Math.Ceiling(sum_alge / angle_val)) - ; // 总角度/单角度
}
else // 【0】弧长
{
angle_val = val_ * / (pi * rad_);
avg_count = (int)(Math.Ceiling(sum_alge / angle_val)) - ; // 总角度/单角度
//avg_count = (int)(Math.Ceiling(a_Lenght(a) / val_)) - 1; // 或 总弧长/单弧长
}
if (is_avg)
angle_val = sum_alge / avg_count;
if (avg_count > )
{
gPP centerP = tempP;
centerP.p = a.pc;
double angle_s = p_ang(a.pc, a.ps);
if (a.ccw) { angle_val = - angle_val; }
for (int i = ; i < avg_count; i++)
{
tempP = p_val_ang(centerP, rad_, angle_s - angle_val * i);
list_point.Add(tempP);
}
}
if (!(zero(a.ps.x - a.pe.x) && zero(a.ps.y - a.pe.y)))
{
tempP.p = a.pe;
list_point.Add(tempP);
}
return list_point;
}
/// <summary>
/// 返回两点之间欧氏距离
/// </summary>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <returns></returns>
public double p2p_di(gPoint p1, gPoint p2)
{
return Math.Sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
/// <summary>
/// 求弧Arc圆心角 //后续改进 用叉积 与3P求角度求解 验证哪个效率高
/// </summary>
/// <param name="a"></param>
/// <returns></returns>
public double a_Angle(gA a)
{
double angle_s, angle_e, angle_sum;
if (a.ccw)
{
angle_s = p_ang(a.pc, a.pe);
angle_e = p_ang(a.pc, a.ps);
}
else
{
angle_s = p_ang(a.pc, a.ps);
angle_e = p_ang(a.pc, a.pe);
}
if (angle_s == ) { angle_s = ; }
if (angle_e >= angle_s)
angle_sum = - Math.Abs(angle_s - angle_e);
else
angle_sum = Math.Abs(angle_s - angle_e);
return angle_sum;
}

3.Point,PAD,Line,Arc数据结构

    /// <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>
/// 点 数据类型 (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>
/// 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";
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";
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, 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, 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";
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";
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, 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, gP move_p)
{
arc1.ps -= move_p.p;
arc1.pe -= move_p.p;
arc1.pc -= move_p.p;
return arc1;
}
}

四.实现效果

PCB genesis Slot槽转钻孔(不用G85命令)实现方法的更多相关文章

  1. PCB genesis 大孔扩孔(不用G84命令)实现方法

    PCB钻孔时,当钻刀>6.3mm时,超出钻孔范围,钻孔工序是没有这么大的钻刀,当这种情况,工程CAM会都采用G84命令用小孔扩孔的方式制作, 在这里介绍一种如果不用G84命令,用程序实现将大孔生 ...

  2. PCB genesis短槽加引导孔实现方法

    一.何为短槽 短槽通常定义:槽长小于2倍槽宽      如:槽长1.8mm,槽宽1.0mm 二.为什么要加短槽加引孔呢 短槽孔在钻孔时孔易偏斜导致槽长偏短, 当槽长宽比越小,则受力越不均匀,在钻第2个 ...

  3. PCB Genesis 无需启动Xmanager图形窗口运行脚本 实现方法

    从事PCB工程行业的都知道,启动Genesis需2个exe程序(Xmanager.exe与get.exe)需一起启动才可以打开我们熟悉的软件, 而Xmanager是图形窗口是给用户UI交互使用的,如果 ...

  4. PCB genesis连孔加除毛刺孔(槽孔与槽孔)实现方法(三)

    一.为什么 连孔加除毛刺孔 原因是 PCB板材中含有玻璃纤维, 毛刺产生位置在于2个孔相交位置,由于此处钻刀受力不均导致纤维切削不断形成毛刺 ,为了解决这个问题:在钻完2个连孔后,在相交处再钻一个孔, ...

  5. PCB genesis连孔加除毛刺孔(圆孔与槽孔)实现方法(二)

    一.为什么 连孔加除毛刺孔 原因是 PCB板材中含有玻璃纤维, 毛刺产生位置在于2个孔相交位置,由于此处钻刀受力不均导致纤维切削不断形成毛刺 ,为了解决这个问题:在钻完2个连孔后,在相交处再钻一个孔, ...

  6. PCB Genesis拼SET画工艺边 实现方法(一)

    在PCB行业中,客户提供的PCB尺寸较小,为方便PCB加工,并生产提高生产效率,通常小于80X80mm需拼板处理的, 拼板要求可能来自按户指定拼板,也有可能是由工厂自行拼板,但对于CAM来说就需将PC ...

  7. PCB genesis自制孔点 Font字体实现方法

    一.先看genesis原有Font字体 在PCB工程CAM加孔点字体要求时,通常我们直接用Geneis软件给我们提供了2种孔点字体canned_57与canned_67,但此字体可能不能满足各个工厂个 ...

  8. PCB genesis方槽加内角槽孔实现方法

    一.为什么方槽孔加内角孔 如下图,客户来的方槽或Slot槽有内角尺寸要求,通常直接钻一个Slot槽孔内角是不能满足客户要求的,这时我们做CAM的需采用小钻刀进行处理.加内角孔或内角槽的方式进行处理了. ...

  9. PCB Genesis SET拼板(圆形板拼板) 实现效果(二)

    越来发现Genesis采用Surface多边形数据结构的重要性了,当撑握了多边形缩放,交集, 差集,并集等算法, 想实现PCB拼板简直轻而易举了;当然借助多边形算法可以开发出更多的PCB实用的工具出来 ...

随机推荐

  1. valgrind检查代码内存泄漏,5种内存泄漏情况

    摘要: valgrind是linux下用于调试程序和查找内存泄露的常用工具.valgrind会报告5种内存泄露,"definitely lost", "indirectl ...

  2. BigDecimal运算

    BigDecimal由任意精度整数未缩放值和32位整数级别组成 . 如果为零或正数,则刻度是小数点右侧的位数. 如果是负数,则数字的非标定值乘以10,以达到等级的否定的幂. 因此,BigDecimal ...

  3. Linux设置history命令显示行数以及时间

    Linux和unix上都提供了history命令,可以查询以前执行的命令历史记录但是,这个记录并不包含时间项目因此只能看到命令,但是不知道什么时间执行的如何让history记录时间呢? 解决方案 注意 ...

  4. Linux基本文件类型

    Linux基本文件类型 基本文件类型 - : 普通文件 d : 文件目录 p : 管道文件 l : 软连接文件 c : 字符设备文件 s : socket文件

  5. Network----轮询

    轮询: 定时每隔多长时间刷新一次,但是,7X24的对服务器的压力会过大,因为在夜间或者是流量低峰期时,他还要持续工作. 客户端发一次请求,服务器就要相应一次. 长轮询: 和轮询的模式不同,长轮询是一次 ...

  6. Grid Convergence Index-- Post Processing in CFD

    t Grid Convergence Index Table of Contents 1. Grid/mesh independence   GCI 1.1. Richardson extrapola ...

  7. Latex Notes

    latex Table of Contents 1. Presentation/Slides with Beamer 2. Drawing in LaTex With TikZ 3. Tracked ...

  8. Boundary Conditions

    test test Table of Contents 1. Boundary conditions 1.1. Neumann boudary condition vs Dirichlet BC 1. ...

  9. Linux 复习四

    第四章 shell程序设计I-入门 一.shell脚本的基本概念 shell脚本(script)是一个可执行的纯文本文件,有多个shell命令组成. 命令的执行时从上而下.从左而右的分析和执行 命令. ...

  10. 【Codeforces 479D】Long Jumps

    [链接] 我是链接,点我呀:) [题意] 如果存在a[j]-a[i]=d 那么认为可以量出来长度d 现在给你量尺上的n个点. 问你最少要加多少个点,才能够量出来长度x和长度y [题解] 设dic1和d ...