在工程CAM处理圆形拼板是个头疼的问题,需人工程师自行设计切边 满足可以拼板并且拼板后锣板板边没有内角,不然会影响装配
1.原始单 PCS圆形板
此外形如果不采用邮票孔连接的话,采V-CUT连接须采用切边处理
二.下图为切边处理后的图形
这个图形就是接下来算法要生成的图形了
三.下图为拼好的SET
这样是为了拼SET后没有内角,不影响装配
再来一张大图拼好后的SET
四.求解思路
五.代码实现:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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(); }
六.脚本界面
七.切边效果演示