• PCB 圆形板切边算法 实现


    在工程CAM处理圆形拼板是个头疼的问题,需人工程师自行设计切边 满足可以拼板并且拼板后锣板板边没有内角,不然会影响装配

    1.原始单 PCS圆形板

        此外形如果不采用邮票孔连接的话,采V-CUT连接须采用切边处理

         

     二.下图为切边处理后的图形 

          这个图形就是接下来算法要生成的图形了

         

     三.下图为拼好的SET

          这样是为了拼SET后没有内角,不影响装配

             

           再来一张大图拼好后的SET

            

    四.求解思路

    五.代码实现:

     private void btnAdd_Click(object sender, EventArgs e)
            {
                g.COM("units,type=mm");
                d2 calc2 = new d2();
                d1 calc1 = new d1();
                string layer = "gko";
                string errinfo = "";
                bool isExist = g.Check_Layer_Exist(layer, g.JOB, g.STEP);
                if (!isExist)
                {
                    errinfo = "gko层不存成";
                    MessageBox.Show(errinfo, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                g.SetWorkLayer(layer);
                double ShaveVal = double.Parse(txtShave.Text);
                double RoutDiVal = double.Parse(txtRoutVal.Text);
                double ConnectWidth = double.Parse(txtConnectWidth.Text);
                double InnerDi = double.Parse(txtInnerDi.Text);
                
                add addCom = new add();
                gLayer layerData = g.getFEATURES(layer, g.STEP, g.JOB);
                List<gA> ACircleList = new List<gA>();
                double CircleRMax = 0;
                if (layerData.Alist.Count > 0)
                {
                    List<gA> Alist = layerData.Alist.OrderByDescending(tt => calc2.p2p_di(tt.pc, tt.ps)).ToList();
                    ACircleList.Add(Alist[0]);
                    CircleRMax = calc2.p2p_di(Alist[0].pc, Alist[0].ps);
                    for (int i = 1; i < Alist.Count; i++)
                    {
                        double p2p_di = calc2.p2p_di(Alist[i - 1].pc, Alist[i].pc);
                        double CircleRCurrent = calc2.p2p_di(Alist[i].pc, Alist[i].ps);
                        if (p2p_di > 0.01 || Math.Abs(CircleRMax - CircleRCurrent) > 0.01)
                            break;
                        ACircleList.Add(Alist[i]);
                    }
                }
                else
                {
                    errinfo = "未检测到弧";
                    MessageBox.Show(errinfo, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                double LineWidth;
                var StrLineWidth = ACircleList[0].symbols.Replace("r", "");
                if (!(double.TryParse(StrLineWidth, out LineWidth)))
                    LineWidth = 151;
                double ShaveDiDirection = CircleRMax - ShaveVal;
                arc_data ShaveArcData = calc1.arc_半径与弓高(CircleRMax, ShaveVal);
                if (ConnectWidth > ShaveArcData.D弦长)
                {
                    errinfo = "连接位长度不能大于弦长";
                    MessageBox.Show(errinfo, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                bool isArc = true; //默认按头尾倒圆角
                double RoutDiDirection = CircleRMax - (ShaveVal + RoutDiVal * 0.5);
                arc_data RoutArcData = calc1.arc_半径与弓高(CircleRMax, (ShaveVal + RoutDiVal * 0.5));
                for (int i = 0; i < 4; i++)  //{ 0, 90, 180, 270 };
                {
                    if (!chkTB.Checked) //1 3
                    {
                        if (i == 1 || i == 3)
                            continue;
                    }
                    if (!chkLR.Checked)//0 2
                    {
                        if (i == 0 || i == 2)
                            continue;
                    }
                    double DirectionAng = g.ang_list[i];
                    double P1Di = CircleRMax;
                    double P1Ang = ShaveArcData.a圆心角 * 0.5;
                    gPoint p1s = calc2.p_val_ang(ACircleList[0].pc, P1Di, DirectionAng - P1Ang);
                    gPoint p1e = calc2.p_val_ang(ACircleList[0].pc, P1Di, DirectionAng + P1Ang);
                    double P2Di = Math.Sqrt(Math.Pow(ShaveDiDirection, 2) + (Math.Pow((ConnectWidth + RoutDiVal) * 0.5, 2)));
                    double P2Ang = calc1.side3_angle(ShaveDiDirection, (ConnectWidth + RoutDiVal) * 0.5, P2Di, 2);
                    gPoint p2s = calc2.p_val_ang(ACircleList[0].pc, P2Di, DirectionAng - P2Ang);
                    gPoint p2e = calc2.p_val_ang(ACircleList[0].pc, P2Di, DirectionAng + P2Ang);
                    double P3Di = Math.Sqrt(Math.Pow(ShaveDiDirection, 2) + (Math.Pow(ConnectWidth * 0.5, 2)));
                    double P3Ang = calc1.side3_angle(ShaveDiDirection, ConnectWidth * 0.5, P3Di, 2);
                    gPoint p3s = calc2.p_val_ang(ACircleList[0].pc, P3Di, DirectionAng - P3Ang);
                    gPoint p3e = calc2.p_val_ang(ACircleList[0].pc, P3Di, DirectionAng + P3Ang);
                    double P4Di = CircleRMax;
                    double P4Ang = RoutArcData.a圆心角 * 0.5;
                    gPoint p4s = calc2.p_val_ang(ACircleList[0].pc, P4Di, DirectionAng - P4Ang);
                    gPoint p4e = calc2.p_val_ang(ACircleList[0].pc, P4Di, DirectionAng + P4Ang);
                    double P5Di = Math.Sqrt(Math.Pow(RoutDiDirection, 2) + (Math.Pow((ConnectWidth + RoutDiVal) * 0.5, 2)));
                    double P5Ang = calc1.side3_angle(RoutDiDirection, (ConnectWidth + RoutDiVal) * 0.5, P5Di, 2);
                    gPoint p5s = calc2.p_val_ang(ACircleList[0].pc, P5Di, DirectionAng - P5Ang);
                    gPoint p5e = calc2.p_val_ang(ACircleList[0].pc, P5Di, DirectionAng + P5Ang);
                    if (calc2.p2p_di(ACircleList[0].pc, p5s) > CircleRMax)
                    {
                        p5s = p4s;
                        p5e = p4e;
                    }
                    List<gSur_Point> polyList = new List<gSur_Point>();
                    if (isArc)
                    {
                        var arc1 = calc2.l2a__Round(new gL(p4s, p5s, LineWidth), ACircleList[0], InnerDi * 0.5, 0.5, 1);
                        polyList.Add(new gSur_Point(arc1.a.pe, 0));
                        polyList.Add(new gSur_Point(arc1.a.pc, 2));
                        polyList.Add(new gSur_Point(arc1.a.ps, 0));
                    }
                    else
                    {
                        polyList.Add(new gSur_Point(p4s, 0));
                    }
                    polyList.Add(new gSur_Point(p5s, 0));
                    polyList.Add(new gSur_Point(p2s, 1));
                    polyList.Add(new gSur_Point(p3s, 0));
                    polyList.Add(new gSur_Point(p3e, 0));
                    polyList.Add(new gSur_Point(p2e, 1));
                    polyList.Add(new gSur_Point(p5e, 0));
                    if (isArc)
                    {
                        var arc2 = calc2.l2a__Round(new gL(p5e, p4e, LineWidth), ACircleList[0], InnerDi*0.5, 0.5, 2);
                        polyList.Add(new gSur_Point(arc2.a.pe, 0));
                        polyList.Add(new gSur_Point(arc2.a.pc, 2));
                        polyList.Add(new gSur_Point(arc2.a.ps, 0));
                    }
                    else
                    {
                        polyList.Add(new gSur_Point(p4e, 0));
                    }
                    addCom.line_poly_AL(polyList, LineWidth);
                }
                g.COM("sel_extend_slots,mode=ext_by,size=500,from=center");
                for (int i = 0; i < 2; i++)  //防止重复线,再次执行
                {
                    if (chkTB.Checked) //1 3
                    {
                        g.COM($"delete_feat, mode = intersect,x={ACircleList[0].pc.x }, y={ACircleList[0].pc.y + CircleRMax}, tol=10", true);
                        g.COM($"delete_feat, mode = intersect,x={ACircleList[0].pc.x }, y={ACircleList[0].pc.y - CircleRMax}, tol=10", true);
                    }
                    if (chkLR.Checked)//0 2
                    {
                        g.COM($"delete_feat, mode = intersect,x={ACircleList[0].pc.x + CircleRMax}, y={ACircleList[0].pc.y}, tol=10", true);
                        g.COM($"delete_feat, mode = intersect,x={ACircleList[0].pc.x - CircleRMax}, y={ACircleList[0].pc.y}, tol=10", true);
                    }
                }
                g.COM("sel_extend_slots,mode=ext_by,size=-500,from=center");
                g.COM("sel_design2rout,det_tol=25.4,con_tol=25.4,rad_tol=2.54");
                MessageBox.Show("执行完成", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                Application.Exit();
            }
    View Code

    六.脚本界面 

    七.切边效果演示

  • 相关阅读:
    AC自动机
    KMP、扩展KMP、MANACHER
    Docker用户身份登录和管理员权限
    Response.Redirect和Server.Transfer比较--(转)
    SQLServer中char、varchar、nchar、nvarchar的区别--(转)
    MsSQL的字段类型--(转)
    读取UEditor编辑框内容到数据库和上传图片的配置
    以做产品的思想分析男女相处之道
    springBoot创建定时任务
    Runnable和Thread的区别
  • 原文地址:https://www.cnblogs.com/pcbren/p/9615138.html
Copyright © 2020-2023  润新知