public string MinimalDXFSave(string outputfile, double offset = 3.0, double holediameter = 3.2) { if (Directory.Exists(outputfile)) { outputfile = Path.Combine(outputfile, "SickOfBeige"); } PolyLine Biggest = null; double BiggestArea = 0; List <PointD> Holes = new List <PointD>(); var holeradius = holediameter / 2.0; double Circumference = 2 * Math.PI * holeradius; foreach (var a in PLSs.Where(x => x.Layer == BoardLayer.Outline)) { foreach (var b in a.OutlineShapes) { var A = b.toPolygon(); double LRatio = (b.OutlineLength() / Circumference); double Lperc = Math.Abs(LRatio - 1); if (Lperc < 0.1) { if (b.Vertices.Count > 5) { var C = b.GetCentroid(); bool round = true; foreach (var v in b.Vertices) { var L = (C - v).Length(); if (Math.Abs(L - holeradius) > 0.2) { // not very round! round = false; } } if (round) { Console.WriteLine("Hole detected in outline:{0} {1} {2} {3} {4} {5}", a.Layer, a.Side, C, LRatio, Lperc, b.Vertices.Count); Holes.Add(C); } } // might be hole! } var Area = Clipper.Area(A); if (Area > BiggestArea) { Biggest = b; BiggestArea = Area; } } } Polygons Offsetted = new Polygons(); List <String> Lines = new List <string>(); Lines.Add("0"); Lines.Add("SECTION"); Lines.Add("2 "); Lines.Add("ENTITIES"); if (Biggest != null) { Polygons clips = new Polygons(); clips.Add(Biggest.toPolygon()); Offsetted = Clipper.OffsetPolygons(clips, offset * 100000.0f, JoinType.jtRound); foreach (var poly in Offsetted) { PolyLine P = new PolyLine(PolyLine.PolyIDs.Temp); P.fromPolygon(poly); for (int i = 0; i < P.Vertices.Count; i++) { var V1 = P.Vertices[i]; var V2 = P.Vertices[(i + 1) % P.Vertices.Count]; Lines.Add("0"); Lines.Add("LINE"); Lines.Add("8"); Lines.Add("Outline"); Lines.Add("10"); Lines.Add(V1.X.ToString().Replace(',', '.')); Lines.Add("20"); Lines.Add(V1.Y.ToString().Replace(',', '.')); Lines.Add("11"); Lines.Add(V2.X.ToString().Replace(',', '.')); Lines.Add("21"); Lines.Add(V2.Y.ToString().Replace(',', '.')); } } } else { Errors.Add("No longest outline found - not generating offset curve"); } foreach (var a in Excellons) { foreach (var t in a.Tools) { var R = t.Value.Radius; if (Math.Abs(R * 2 - holediameter) < 0.05) { foreach (var h in t.Value.Drills) { Holes.Add(h); } } } } foreach (var a in Holes) { for (int i = 0; i < 40; i++) { double P = i * Math.PI * 2.0 / 40.0; double P2 = (i + 1) * Math.PI * 2.0 / 40.0; var C1 = Math.Cos(P) * holeradius; var C2 = Math.Cos(P2) * holeradius; var S1 = Math.Sin(P) * holeradius; var S2 = Math.Sin(P2) * holeradius; double x1 = a.X + C1; double y1 = a.Y + S1; double x2 = a.X + C2; double y2 = a.Y + S2; Lines.Add("0"); Lines.Add("LINE"); Lines.Add("8"); Lines.Add("Holes"); Lines.Add("10"); Lines.Add(x1.ToString().Replace(',', '.')); Lines.Add("20"); Lines.Add(y1.ToString().Replace(',', '.')); Lines.Add("11"); Lines.Add(x2.ToString().Replace(',', '.')); Lines.Add("21"); Lines.Add(y2.ToString().Replace(',', '.')); } } Lines.Add("0"); Lines.Add("ENDSEC"); Lines.Add("0"); Lines.Add("EOF"); File.WriteAllLines(outputfile + ".dxf", Lines); float scalefac = 10; Console.WriteLine("Report: {0} holes created in case ({1} spacers and {1} screws needed!)", Holes.Count, Holes.Count * 2); { var BB = new GerberLibrary.Bounds(); BB.AddPolygons(Offsetted); BB.AddPolyLine(Biggest); Bitmap B = new Bitmap((int)((BB.Width()) * scalefac) + 6, (int)((BB.Height()) * scalefac) + 6); Graphics G = Graphics.FromImage(B); G.Clear(Color.Transparent); G.Clear(Color.White); G.TranslateTransform(3, 3); G.ScaleTransform(scalefac, scalefac); G.TranslateTransform((float)-(BB.TopLeft.X), (float)-(BB.TopLeft.Y)); Pen pen = new Pen(Color.Black, 0.1f); Pen pen2 = new Pen(Color.FromArgb(160, 160, 160), 0.1f); pen2.DashPattern = new float[2] { 2, 2 }; GerberImageCreator.ApplyAASettings(G); RectangleF R = new RectangleF(0, 0, (float)holediameter, (float)holediameter); foreach (var a in Holes) { R.X = (float)a.X - (float)holeradius; R.Y = (float)a.Y - (float)holeradius; G.DrawEllipse(pen, R); } foreach (var poly in Offsetted) { PolyLine Pl = new PolyLine(PolyLine.PolyIDs.Temp); Pl.fromPolygon(poly); var Points = new List <PointF>(Pl.Vertices.Count); for (int i = 0; i < Pl.Vertices.Count; i++) { Points.Add(Pl.Vertices[i].ToF()); } Points.Add(Pl.Vertices[0].ToF()); G.DrawLines(pen, Points.ToArray()); } { PolyLine Pl = Biggest; var Points = new List <PointF>(Pl.Vertices.Count); for (int i = 0; i < Pl.Vertices.Count; i++) { Points.Add(Pl.Vertices[i].ToF()); } Points.Add(Pl.Vertices[0].ToF()); G.DrawLines(pen2, Points.ToArray()); } var ImagePNG = outputfile + ".png"; B.Save(ImagePNG); return(ImagePNG); } }
public static List <string> WriteSideEdgeFrame(PolyLine pl, FrameSettings FS, string basefile, bool insideedge = true) { List <string> Files = new List <string>(); try { int polyid = 0; string fname = System.IO.Path.GetFileName(basefile); string fnamenoext = System.IO.Path.GetFileNameWithoutExtension(basefile); string OutName = Path.Combine(System.IO.Path.GetDirectoryName(basefile), fnamenoext); Console.WriteLine("writing frame files to {0}", OutName); Bounds B = new Bounds(); B.AddPolyLine(pl); // FS.innerHeight = B.Height(); // FS.innerWidth = B.Width(); double W = (double)FS.innerWidth; double H = (double)FS.innerHeight; double TE = (double)FS.topEdge; double LE = (double)FS.leftEdge; double OuterWidth = W + LE * 2.0; double OuterHeight = H + TE * 2.0; double InnerWidth = W; double InnerHeight = H; PCBWriterSet PCB = new PCBWriterSet(); double mountholediameter = (double)FS.holeDiameter; // board outline PolyLine PL = new PolyLine(polyid++); PL.MakeRoundedRect(new PointD(0, 0), new PointD(OuterWidth, OuterHeight), (double)FS.roundedOuterCorners); PCB.AddOutline(PL); if (insideedge) { PolyLine PL2 = new PolyLine(polyid++); PL2.MakeRoundedRect(new PointD(LE, TE), new PointD(InnerWidth + LE, InnerHeight + TE), (double)FS.roundedInnerCorners); PCB.AddOutline(PL2); } #region fiducials List <PointD> Fiducials = new List <PointD>(); foreach (var P in FS.fiducialsListData) { PointD fiducialPoint = P.pos; PCB.Fiducial(fiducialPoint, P.CopperDiameter, P.MaskDiameter, P.Top); } #endregion string FrameTitle = FS.FrameTitle; string FrameTopTitle = FrameTitle + " - Top"; string FrameBottomTitle = FrameTitle + " - Bottom"; double verticaltitleclearance = 0; double horizontaltitleclearance = 0; if (FrameTitle.Length > 0) { FontSet fnt = FontSet.Load("Font.xml"); horizontaltitleclearance = fnt.StringWidth(FrameBottomTitle, TE / 4) + mountholediameter * 2 + FS.topEdge; verticaltitleclearance = fnt.StringWidth(FrameBottomTitle, TE / 4) + mountholediameter * 2 + FS.topEdge; PCB.Label(fnt, new PointD(OuterWidth / 2.0, OuterHeight - TE / 4.0), FrameTopTitle, TE / 4, StringAlign.CenterCenter, 0.1, true, true, 0); PCB.Label(fnt, new PointD(OuterWidth - LE / 4, OuterHeight / 2), FrameTopTitle, TE / 4.0, StringAlign.CenterCenter, 0.1, true, true, -90); PCB.Label(fnt, new PointD(LE / 4, OuterHeight / 2), FrameTopTitle, TE / 4.0, StringAlign.CenterCenter, 0.1, true, true, 90); PCB.Label(fnt, new PointD(OuterWidth / 2.0, TE - TE / 4.0), FrameTopTitle, TE / 4.0, StringAlign.CenterCenter, 0.1, true, true, 0); PCB.Label(fnt, new PointD(OuterWidth / 2.0, OuterHeight - TE / 4.0), FrameBottomTitle, TE / 4, StringAlign.CenterCenter, 0.1, true, true, 0, true, true, true); PCB.Label(fnt, new PointD(OuterWidth - LE / 4, OuterHeight / 2), FrameBottomTitle, TE / 4.0, StringAlign.CenterCenter, 0.1, true, true, -90, true); PCB.Label(fnt, new PointD(LE / 4, OuterHeight / 2), FrameBottomTitle, TE / 4.0, StringAlign.CenterCenter, 0.1, true, true, 90, true); PCB.Label(fnt, new PointD(OuterWidth / 2.0, TE - TE / 4.0), FrameBottomTitle, TE / 4.0, StringAlign.CenterCenter, 0.1, true, true, 0, true); } if (FS.addHoles) { double side = LE / 2.0; double top = TE / 2.0; PCB.Drill(new PointD(side, top), mountholediameter, 1); PCB.Drill(new PointD(OuterWidth - side, top), mountholediameter, 1); PCB.Drill(new PointD(OuterWidth - side, OuterHeight - top), mountholediameter, 1); PCB.Drill(new PointD(side, OuterHeight - top), mountholediameter, 1); double dx = (OuterWidth - side) - side; double dy = (OuterHeight - top) - top; dx -= horizontaltitleclearance; dy -= verticaltitleclearance; dx /= 2; dy /= 2; int horiz = (int)Math.Ceiling((dx / 2) / FS.MaxMountHoleSpacingMM); int vert = (int)Math.Ceiling((dy / 2) / FS.MaxMountHoleSpacingMM); dx /= (float)horiz; dy /= (float)vert; if (dx < FS.MinMountHoleSpacingMM) { horiz = 0; } if (dy < FS.MinMountHoleSpacingMM) { vert = 0; } for (int i = 1; i <= horiz; i++) { PCB.Drill(new PointD(side + (dx) * i, top), mountholediameter, 1); PCB.Drill(new PointD((OuterWidth - side) - (dx) * i, top), mountholediameter, 1); PCB.Drill(new PointD(side + (dx) * i, OuterHeight - top), mountholediameter, 1); PCB.Drill(new PointD((OuterWidth - side) - (dx) * i, OuterHeight - top), mountholediameter, 1); } for (int i = 1; i <= vert; i++) { PCB.Drill(new PointD(side, top + (dy) * i), mountholediameter, 1); PCB.Drill(new PointD(side, (OuterHeight - top) - (dy) * i), mountholediameter, 1); PCB.Drill(new PointD((OuterWidth - side), top + (dy) * i), mountholediameter, 1); PCB.Drill(new PointD((OuterWidth - side), (OuterHeight - top) - (dy) * i), mountholediameter, 1); } } PolyLine Left = new PolyLine(); PolyLine Right = new PolyLine(); PolyLine Top = new PolyLine(); PolyLine Bottom = new PolyLine(); Top.MakePRectangle(OuterWidth + 1, FS.topEdge + 1, -1, -1); Bottom.MakePRectangle(OuterWidth, FS.topEdge, 0, OuterHeight - FS.topEdge); Left.MakePRectangle(FS.leftEdge + 1, OuterHeight + 1, -1, -1); Right.MakePRectangle(FS.leftEdge, OuterHeight, OuterWidth - FS.leftEdge, 0); PCB.ArtInclusions.Add(Left); PCB.ArtInclusions.Add(Right); PCB.ArtInclusions.Add(Top); PCB.ArtInclusions.Add(Bottom); //PCB.CellularArt(); Files.AddRange(PCB.Write(Path.GetDirectoryName(basefile), Path.GetFileNameWithoutExtension(basefile), FS.offset));; if (FS.RenderSample) { GerberImageCreator GIC = new GerberImageCreator(); GIC.AddBoardsToSet(Files, new SilentLog()); GIC.WriteImageFiles(OutName, 200, true, false, true, null); } } catch (Exception e) { Console.Write(" Exception while making frames:{0}", e.Message); } foreach (var s in Files) { Console.WriteLine("Writen edge file {0} succesfully", s); } return(Files); }