public void Write(string filename, double DX, double DY, double DXp, double DYp, double AngleInDeg = 0) { double Angle = AngleInDeg * (Math.PI * 2.0) / 360.0; double CA = Math.Cos(Angle); double SA = Math.Sin(Angle); List <string> lines = new List <string>(); lines.Add("%"); lines.Add("M48"); lines.Add("METRIC,000.000"); //lines.Add("M71"); foreach (var a in Tools) { lines.Add(String.Format("T{0}C{1}", a.Key.ToString("D2"), (a.Value.Radius * 2).ToString("N2").Replace(',', '.'))); } lines.Add("%"); GerberNumberFormat GNF = new GerberNumberFormat(); GNF.SetMetricMode(); GNF.OmitLeading = true; GNF.DigitsAfter = 3; GNF.DigitsBefore = 3; foreach (var a in Tools) { lines.Add(String.Format("T{0}", a.Key.ToString("D2"))); double coordmultiplier = 1; foreach (var d in a.Value.Drills) { double X = (d.X * coordmultiplier + DXp) / coordmultiplier; double Y = (d.Y * coordmultiplier + DYp) / coordmultiplier; if (Angle != 0) { double nX = X * CA - Y * SA; double nY = X * SA + Y * CA; X = nX; Y = nY; } X = (X * coordmultiplier + DX) / coordmultiplier; Y = (Y * coordmultiplier + DY) / coordmultiplier; lines.Add(string.Format("X{0}Y{1}", GNF.Format(X), GNF.Format(Y).Replace(',', '.'))); } foreach (var s in a.Value.Slots) { double XS = (s.Start.X * coordmultiplier + DXp) / coordmultiplier; double YS = (s.Start.Y * coordmultiplier + DYp) / coordmultiplier; double XE = (s.End.X * coordmultiplier + DXp) / coordmultiplier; double YE = (s.End.Y * coordmultiplier + DYp) / coordmultiplier; if (Angle != 0) { double nX = XS * CA - YS * SA; double nY = XS * SA + YS * CA; XS = nX; YS = nY; double neX = XE * CA - YE * SA; double neY = XE * SA + YE * CA; XE = neX; YE = neY; } XS = (XS * coordmultiplier + DX) / coordmultiplier; YS = (YS * coordmultiplier + DY) / coordmultiplier; XE = (XE * coordmultiplier + DX) / coordmultiplier; YE = (YE * coordmultiplier + DY) / coordmultiplier; lines.Add(string.Format("X{0}Y{1}G85X{2}Y{3}", GNF.Format(XS), GNF.Format(YS).Replace(',', '.'), GNF.Format(XE), GNF.Format(YE).Replace(',', '.'))); } } lines.Add("M30"); Gerber.WriteAllLines(filename, lines); }
public static bool SaveDebugImage(string GerberFilename, string BitmapFilename, float dpi, Color Foreground, Color Background) { ParsedGerber PLS; GerberParserState State = new GerberParserState() { PreCombinePolygons = false }; var FileType = Gerber.FindFileType(GerberFilename); Gerber.DetermineBoardSideAndLayer(GerberFilename, out State.Side, out State.Layer); bool forcezero = false; if (State.Layer == BoardLayer.Outline) { // PLS.PreCombinePolygons = true; // forcezero = true; } if (FileType == BoardFileType.Drill) { PLS = PolyLineSet.LoadExcellonDrillFile(GerberFilename); } else { PLS = PolyLineSet.LoadGerberFile(GerberFilename, forcezero, Gerber.WriteSanitized, State); } double WidthInMM = PLS.BoundingBox.BottomRight.X - PLS.BoundingBox.TopLeft.X; double HeightInMM = PLS.BoundingBox.BottomRight.Y - PLS.BoundingBox.TopLeft.Y; int Width = (int)(Math.Ceiling((WidthInMM) * (dpi / 25.4))); int Height = (int)(Math.Ceiling((HeightInMM) * (dpi / 25.4))); Console.WriteLine("Progress: Exporting {0} ({2},{3}mm) to {1} ({4},{5})", GerberFilename, BitmapFilename, WidthInMM, HeightInMM, Width, Height); GerberImageCreator GIC = new GerberImageCreator(); GIC.scale = dpi / 25.4f; // dpi GIC.BoundingBox.AddBox(PLS.BoundingBox); var Tr = GIC.BuildMatrix(Width, Height); Bitmap B2 = GIC.RenderToBitmap(Width, Height, Tr, Foreground, Background, PLS, true); if (B2 == null) { return(false); } var GerberLines = PolyLineSet.SanitizeInputLines(System.IO.File.ReadAllLines(GerberFilename).ToList()); double LastX = 0; double LastY = 0; Graphics G2 = Graphics.FromImage(B2); GerberImageCreator.ApplyAASettings(G2); //G2.Clear(Background); G2.Transform = Tr.Clone(); foreach (var L in GerberLines) { if (L[0] != '%') { GerberSplitter GS = new GerberSplitter(); GS.Split(L, PLS.State.CoordinateFormat); if (GS.Has("G") && (int)GS.Get("G") == 3) { double X = PLS.State.CoordinateFormat.ScaleFileToMM(GS.Get("X")); double Y = PLS.State.CoordinateFormat.ScaleFileToMM(GS.Get("Y")); double I = PLS.State.CoordinateFormat.ScaleFileToMM(GS.Get("I")); double J = PLS.State.CoordinateFormat.ScaleFileToMM(GS.Get("J")); //Console.WriteLine("Counterclockwise Curve {0},{1} -> {2},{3}", LastX, LastY, X, Y); DrawCross(G2, X, Y, Color.Blue); DrawCross(G2, LastX, LastY, Color.Red); DrawCross(G2, LastX + I, LastY - J, Color.Yellow); DrawCross(G2, LastX + I, LastY + J, Color.Purple); DrawCross(G2, LastX - I, LastY - J, Color.Green); DrawCross(G2, LastX - I, LastY + J, Color.Orange); } if (GS.Has("X")) { LastX = PLS.State.CoordinateFormat.ScaleFileToMM(GS.Get("X")); } if (GS.Has("Y")) { LastY = PLS.State.CoordinateFormat.ScaleFileToMM(GS.Get("Y")); } } } B2.Save(BitmapFilename); return(true); }
public static void ZipGerbers(string a, bool frame, int framemm, string framename) { string BaseFolder = Path.GetDirectoryName(a); string Name = Path.GetFileNameWithoutExtension(a); string GerbersFolder = Path.Combine(BaseFolder, "Gerbers"); string BoardGerbersFolder = Path.Combine(GerbersFolder, Name); string BoardGerbersMergedFolder = Path.Combine(GerbersFolder, Name + "_MERGED"); string FactoryFolder = Path.Combine(BaseFolder, "Factory"); if (Directory.Exists(FactoryFolder) == false) { Directory.CreateDirectory(FactoryFolder); } string BoardFactoryFolder = Path.Combine(FactoryFolder, Name); if (Directory.Exists(BoardFactoryFolder) == false) { Directory.CreateDirectory(BoardFactoryFolder); } Gerber.ZipGerberFolderToFactoryFolder(MakeJLCName(Name), BoardGerbersFolder, BoardFactoryFolder); Gerber.ZipGerberFolderToFactoryFolder(MakeJLCName(Name) + "_MERGED", BoardGerbersMergedFolder, BoardFactoryFolder); if (frame) { string FrameFactoryFolder = Path.Combine(FactoryFolder, Name + "_Frame"); if (Directory.Exists(FrameFactoryFolder) == false) { Directory.CreateDirectory(FrameFactoryFolder); } string MergedFrameFactoryFolder = Path.Combine(FactoryFolder, Name + "_Framed"); if (Directory.Exists(MergedFrameFactoryFolder) == false) { Directory.CreateDirectory(MergedFrameFactoryFolder); } string MergedFrameFactoryFolderMerged = Path.Combine(FactoryFolder, Name + "_MERGED_Framed"); if (Directory.Exists(MergedFrameFactoryFolderMerged) == false) { Directory.CreateDirectory(MergedFrameFactoryFolderMerged); } GerberFrameWriter.FrameSettings FS = new GerberFrameWriter.FrameSettings(); FS.FrameTitle = framename; FS.RenderSample = false; FS.margin = 3; FS.roundedOuterCorners = 0; FS.topEdge = FS.leftEdge = framemm; FS.RenderDirectionArrow = true; FS.DirectionArrowSide = GerberLibrary.Core.BoardSide.Both; FS.DefaultFiducials = true; FS.FiducialSide = BoardSide.Both; FS.HorizontalTabs = true; FS.VerticalTabs = true; FS.InsideEdgeMode = GerberFrameWriter.FrameSettings.InsideMode.FormFitting; PolyLine PL = Gerber.FindAndLoadOutlineFile(BoardGerbersFolder); if (PL != null) { FS.PositionAround(PL); GerberFrameWriter.WriteSideEdgeFrame(PL, FS, FrameFactoryFolder + "\\" + Name); GerberFrameWriter.MergeFrameIntoGerberSet(FrameFactoryFolder, BoardGerbersFolder, MergedFrameFactoryFolder, FS, new StandardConsoleLog(), Name); GerberFrameWriter.MergeFrameIntoGerberSet(FrameFactoryFolder, BoardGerbersMergedFolder, MergedFrameFactoryFolderMerged, FS, new StandardConsoleLog(), Name + "Merged"); Gerber.ZipGerberFolderToFactoryFolder(MakeJLCName(Name) + "_FRAMED", MergedFrameFactoryFolder, BoardFactoryFolder); Gerber.ZipGerberFolderToFactoryFolder(MakeJLCName(Name) + "_MERGED_FRAMED", MergedFrameFactoryFolderMerged, BoardFactoryFolder); } } }
public static string WriteMacroPartVertices(List <PointD> Vertices, GerberNumberFormat format) { string res = ""; res += String.Format("4,1,{0}," + Gerber.LineEnding, (Vertices.Count - 2)); for (int i = 0; i < Vertices.Count - 1; i++) { res += String.Format("{0},{1}," + Gerber.LineEnding, Gerber.ToFloatingPointString(format._ScaleMMToFile(Vertices[i].X)).Replace(',', '.'), Gerber.ToFloatingPointString(format._ScaleMMToFile(Vertices[i].Y)).Replace(',', '.')); } res += "0*"; return(res); }
public static string BuildOutlineApertureMacro(string name, List <PointD> Vertices, GerberNumberFormat format) { string res = "%AM" + name + "*" + Gerber.LineEnding; res += String.Format("4,1,{0}," + Gerber.LineEnding, (Vertices.Count - 2)); for (int i = 0; i < Vertices.Count - 1; i++) { res += String.Format("{0},{1}," + Gerber.LineEnding, Gerber.ToFloatingPointString(format._ScaleMMToFile(Vertices[i].X)).Replace(',', '.'), Gerber.ToFloatingPointString(format._ScaleMMToFile(Vertices[i].Y)).Replace(',', '.')); } res += "0*" + Gerber.LineEnding + "%" + Gerber.LineEnding; return(res); }
/// <summary> /// /// </summary> /// <param name="sourcefile"></param> /// <param name="destfile"></param> /// <param name="DX">MM</param> /// <param name="DY">MM</param> /// <param name="Angle">Degrees</param> public static void Transform(ProgressLog log, string sourcefile, string destfile, double DX, double DY, double DXp, double DYp, double AngleInDeg = 0) { log.PushActivity("Gerber Transform"); List <String> lines = new List <string>(); List <String> outlines = new List <string>(); bool WriteMove = false; int moveswritten = 0; double Angle = AngleInDeg * (Math.PI * 2.0) / 360.0; double CA = Math.Cos(Angle); double SA = Math.Sin(Angle); using (StreamReader sr = new StreamReader(sourcefile)) { while (sr.EndOfStream == false) { String line = sr.ReadLine(); if (line.Length > 0) { lines.Add(line); } } } lines = PolyLineSet.SanitizeInputLines(lines); if (Gerber.WriteSanitized) { Gerber.WriteAllLines(sourcefile + ".sanitized.txt", lines); } // PolyLineSet Parsed = new PolyLineSet("parsed gerber"); ParsedGerber Parsed = PolyLineSet.ParseGerber274x(log, lines, true, false, new GerberParserState() { GenerateGeometry = false }); if (Gerber.ShowProgress) { log.AddString("found apertures: "); foreach (var a in Parsed.State.Apertures) { log.AddString(a.Value.ToString()); } } GerberNumberFormat CoordinateFormat = new GerberNumberFormat(); CoordinateFormat.SetImperialMode(); // CoordinateFormat = Parsed.State.CoordinateFormat; int cur = 0; bool formatparsed = false; while (cur < lines.Count && formatparsed == false) { if (lines[cur].Length >= 2 && lines[cur].Substring(0, 2) == "%F") { CoordinateFormat.Parse(lines[cur]); formatparsed = true; } cur++; } // double coordmultiplier = 1.0; double LastX = 0; double LastY = 0; for (int i = 0; i < lines.Count; i++) { GerberSplitter GS = new GerberSplitter(); string FinalLine = lines[i].Replace("%", "").Replace("*", "").Trim(); bool DumpToOutput = false; bool metaopen = false; if (lines[i][0] == '%') { DumpToOutput = true; metaopen = true; } else { GS.Split(lines[i], CoordinateFormat); } switch (FinalLine) { case "G71": CoordinateFormat.SetMetricMode(); break; case "G70": CoordinateFormat.SetImperialMode(); break; case "MOIN": { CoordinateFormat.SetImperialMode(); //CoordinateFormat.Multiplier = 25.4f; } break; case "MOMM": { CoordinateFormat.SetMetricMode(); //CoordinateFormat.Multiplier = 1.0f; } break; } if (lines[i].Length > 3 && lines[i].Substring(0, 3) == "%AM") { string name = lines[i].Substring(3).Split('*')[0]; var M = Parsed.State.ApertureMacros[name]; M.Written = true; var gerb = M.BuildGerber(CoordinateFormat, AngleInDeg).Split('\n'); foreach (var l in gerb) { if (l.Trim().Length > 0) { outlines.Add(l.Trim()); } } // outlines.Add(lines[i]); // if (lines[i][lines[i].Length - 1] != '%') /// { // i++; while (lines[i][lines[i].Length - 1] != '%') { // outlines.Add(lines[i]); i++; } // outlines.Add(lines[i]); // } } else if (lines[i].Length > 3 && lines[i].Substring(0, 3) == "%AD") { GCodeCommand GCC = new GCodeCommand(); GCC.Decode(lines[i], CoordinateFormat); if (GCC.numbercommands.Count < 1) { log.AddString(String.Format("Skipping bad aperture definition: {0}", lines[i])); } else { int ATID = (int)GCC.numbercommands[0]; var Aperture = Parsed.State.Apertures[ATID]; if (Gerber.ShowProgress) { log.AddString(String.Format("found " + Aperture.ToString())); } string gerb = Aperture.BuildGerber(CoordinateFormat, AngleInDeg); if ((Aperture.ShapeType == GerberApertureShape.Compound || Aperture.ShapeType == GerberApertureShape.Macro) && Parsed.State.ApertureMacros[Aperture.MacroName].Written == false) { log.AddString(String.Format("Macro type defined - skipping")); } else { outlines.Add(gerb); } // outlines.Add(lines[i]); if (lines[i][lines[i].Length - 1] != '%') { i++; while (lines[i] != "%") { // outlines.Add(lines[i]); i++; } // outlines.Add(lines[i]); } } } else { bool PureD = false; if (GS.Has("G")) { int GCode = (int)GS.Get("G"); switch (GCode) { case 4: DumpToOutput = true; break; case 90: CoordinateFormat.Relativemode = false; break; case 91: CoordinateFormat.Relativemode = true; break; case 71: CoordinateFormat.Multiplier = 1.0d; break; case 70: CoordinateFormat.Multiplier = 25.4d; break; } } if (DumpToOutput) { outlines.Add(lines[i]); if (lines[i].Contains("LNData")) { log.AddString(String.Format(" heh")); } if (lines[i][0] == '%') { int starti = i; if (lines[i].Length == 1) { i++; } while (lines[i][lines[i].Length - 1] != '%') { if (i > starti) { outlines.Add(lines[i]); } i++; } if (i > starti) { outlines.Add(lines[i]); } } } else { bool translate = true; if (CoordinateFormat.Relativemode) { translate = false; } if (GS.Has("X") == false && GS.Has("Y") == false && (GS.Has("D") && GS.Get("D") < 10)) { PureD = true; int Dcode = (int)GS.Get("D"); if (Dcode == 1 || Dcode == 3) { if (moveswritten == 0) { WriteMove = true; } } moveswritten++; log.AddString(String.Format("Pure D Code: {0}", lines[i])); } else if (GS.Has("X") || GS.Has("Y") || (GS.Has("D") && GS.Get("D") < 10)) { int Dcode = (int)GS.Get("D"); if (Dcode == 1 || Dcode == 3) { if (moveswritten == 0) { WriteMove = true; } } moveswritten++; double X = LastX; if (GS.Has("X")) { X = GS.Get("X"); } double Y = LastY; if (GS.Has("Y")) { Y = GS.Get("Y"); } LastX = X; LastY = Y; GetTransformedCoord(DX, DY, DXp, DYp, Angle, CA, SA, CoordinateFormat, translate, ref X, ref Y); if ((GS.Has("I") || GS.Has("J")) && Angle != 0) { // int g = (int)GS.Get("G"); // if (g == 2 || g == 3) { double I = 0; double J = 0; bool arc = false; if (GS.Has("I")) { I = GS.Get("I"); arc = true; } ; if (GS.Has("J")) { J = GS.Get("J"); arc = true; } ; if (arc) { double nJ = J * CA + I * SA; double nI = -J * SA + I * CA; I = nI; J = nJ; // GS.Set("I", Math.Abs(I)); // GS.Set("J", Math.Abs(J)); GS.Set("I", I); GS.Set("J", J); } } } GS.Set("X", X); GS.Set("Y", Y); } if (WriteMove) { GerberSplitter GS2 = new GerberSplitter(); GS2.Set("D", 2); double X0 = 0; double Y0 = 0; GetTransformedCoord(DX, DY, DXp, DYp, Angle, CA, SA, CoordinateFormat, translate, ref X0, ref Y0); GS2.Set("X", X0); GS2.Set("Y", Y0); WriteMove = false; outlines.Add(GS2.Rebuild(CoordinateFormat)); } outlines.Add(GS.Rebuild(CoordinateFormat)); if (PureD) { log.AddString(String.Format("pureD")); } } } } try { List <String> PostProcLines = new List <string>(); foreach (var a in outlines) { if (a == "%") { PostProcLines[PostProcLines.Count - 1] += "%"; } else { PostProcLines.Add(a); } } Gerber.WriteAllLines(destfile, PolyLineSet.SanitizeInputLines(PostProcLines)); } catch (Exception E) { log.AddString(String.Format(E.Message)); } log.PopActivity(); }
private List <PointD> CutCompensation(List <PointD> path, CutterCompensation compensation, double offset) { if (compensation == CutterCompensation.None) { return(path); } if (path.Count < 2) { return(path); } /* remove contiguous duplicates */ var unique = new List <PointD>(path.Count); PointD prev = null; foreach (var point in path) { if (prev == point) { continue; } prev = point; unique.Add(point); } path = unique; /* create offset segments */ var SegmentsOffset = path.Zip(path.Skip(1), (A, B) => { var angle = A.Angle(B); if (compensation == CutterCompensation.Left) { angle += Math.PI / 2; } else { angle -= Math.PI / 2; } A += new PointD(offset * Math.Cos(angle), offset * Math.Sin(angle)); B += new PointD(offset * Math.Cos(angle), offset * Math.Sin(angle)); return(new { A, B }); }); /* create segment pairs */ var SegmentPairs = SegmentsOffset .Zip(SegmentsOffset.Skip(1), (First, Second) => new { First, Second }) .Zip(path.Skip(1), (pair, Center) => new { pair.First, pair.Second, Center }); var Path = new PolyLine(); Path.Vertices.Add(SegmentsOffset.First().A); foreach (var segment in SegmentPairs) { /* segments are colinear */ if (segment.First.B == segment.Second.A) { continue; } var intersection = Helpers.SegmentSegmentIntersect(segment.First.A, segment.First.B, segment.Second.A, segment.Second.B); /* if segments intersect, */ if (intersection != null) { /* the intersection point is what connects first and second segments */ Path.Vertices.Add(intersection); } else { /* otherwise connect segments with an arc */ var Center = segment.Center - segment.First.B; var arc = Gerber.CreateCurvePoints( segment.First.B.X, segment.First.B.Y, segment.Second.A.X, segment.Second.A.Y, Center.X, Center.Y, compensation == CutterCompensation.Left ? InterpolationMode.ClockWise : InterpolationMode.CounterClockwise, GerberQuadrantMode.Multi); Path.Vertices.AddRange(arc); } } Path.Vertices.Add(SegmentsOffset.Last().B); return(Path.Vertices); }
public static void MergeFrameIntoGerberSet(string FrameFolder, string OutlineFolder, string OutputFolder, FrameSettings FS, ProgressLog log, string basename) { log.PushActivity("MergeFrame"); // log.AddString("....."); if (Directory.Exists(FrameFolder) == false) { log.AddString(String.Format("Framefolder {0} does not exist?", FrameFolder)); } if (Directory.Exists(OutlineFolder) == false) { log.AddString(String.Format("OutlineFolder {0} does not exist?", OutlineFolder)); } if (Directory.Exists(OutputFolder) == false) { log.AddString(String.Format("OutputFolder {0} does not exist?", OutputFolder)); } GerberPanel PNL = new GerberPanel(); PNL.AddGerberFolder(log, FrameFolder); PNL.AddGerberFolder(log, OutlineFolder); PNL.TheSet.ClipToOutlines = false; var FrameInstance = PNL.AddInstance(FrameFolder, new PointD(0, 0)); var OutlineInstance = PNL.AddInstance(OutlineFolder, new PointD(0, 0)); PNL.UpdateShape(log); var BB = OutlineInstance.BoundingBox; foreach (var s in OutlineInstance.TransformedOutlines) { bool ClockWise = s.ClockWise(); if (s.Vertices.Count >= 2) { for (int i = 0; i < s.Vertices.Count; i++) { PointD p1 = s.Vertices[i]; PointD p2 = s.Vertices[(i + 1) % s.Vertices.Count]; var D = p2 - p1; if (Math.Abs(D.X) < 0.5 && Math.Abs(D.Y) >= FS.mmbetweentabs && FS.VerticalTabs) { // perfect vertical! log.AddString(String.Format("vertical found: {0} -> {1}", p1, p2)); double dy = p2.Y - p1.Y; double x = 0; double rad = 0; bool rightside = (dy > 0); if (ClockWise) { rightside = !rightside; } if (FS.InsideEdgeMode == FrameSettings.InsideMode.RegularEdge) { if (rightside) { x = (p1.X + (BB.BottomRight.X + FS.margin)) / 2; rad = Math.Abs((p1.X - (BB.BottomRight.X + FS.margin))) / 2.0 + FS.margin; } else { x = (p1.X + (BB.TopLeft.X - FS.margin)) / 2; rad = Math.Abs((p1.X - (BB.TopLeft.X - FS.margin))) / 2.0 + FS.margin; } } if (FS.InsideEdgeMode == FrameSettings.InsideMode.FormFitting) { if (rightside) { x = p1.X + (FS.margin / 2); rad = FS.margin; } else { x = p1.X - (FS.margin / 2); rad = FS.margin; } } int tabs = (int)Math.Floor(Math.Abs(dy) / FS.mmbetweentabs); for (int j = 0; j < tabs; j++) { double y = p1.Y + (dy / (float)tabs) * (j + 0.5); var BR = PNL.AddTab(new PointD(x, y)); log.AddString(String.Format("tab at {0} - radius {1}", BR.Center, rad)); BR.Radius = (float)rad; } } if (Math.Abs(D.Y) < 0.5 && Math.Abs(D.X) >= FS.mmbetweentabs && FS.HorizontalTabs) { // perfect vertical! log.AddString(String.Format("horizontal found: {0} -> {1}", p1, p2)); double dx = p2.X - p1.X; double y = 0; double rad = 0; bool rightside = (dx < 0); if (ClockWise) { rightside = !rightside; } if (FS.InsideEdgeMode == FrameSettings.InsideMode.RegularEdge) { if (rightside) { y = (p1.Y + (BB.BottomRight.Y + FS.margin)) / 2; rad = Math.Abs((p1.Y - (BB.BottomRight.Y + FS.margin))) / 2.0 + FS.margin; } else { y = (p1.Y + (BB.TopLeft.Y - FS.margin)) / 2; rad = Math.Abs((p1.Y - (BB.TopLeft.Y - FS.margin))) / 2.0 + FS.margin; } } if (FS.InsideEdgeMode == FrameSettings.InsideMode.FormFitting) { if (rightside) { y = p1.Y + (FS.margin / 2); rad = FS.margin; } else { y = p1.Y - (FS.margin / 2); rad = FS.margin; } } int tabs = (int)Math.Floor(Math.Abs(dx) / FS.mmbetweentabs); for (int j = 0; j < tabs; j++) { double x = p1.X + (dx / (float)tabs) * (j + 0.5); var BR = PNL.AddTab(new PointD(x, y)); log.AddString(String.Format("tab at {0} - radius {1}", BR.Center, rad)); BR.Radius = (float)rad; } } } } } PNL.UpdateShape(log); log.AddString("postupdateshape"); try { Directory.CreateDirectory(OutputFolder); var PNLFiles = PNL.SaveGerbersToFolder("MergedFrame", OutputFolder, log, false, true, false, true, basename); } catch (Exception E) { log.AddString("save gerbers to folder Exceptions: " + E.ToString()); } try { if (FS.RenderSample) { GerberImageCreator GIC = new GerberImageCreator(); GIC.AddBoardsToSet(Directory.GetFiles(OutputFolder).ToList(), new SilentLog()); GIC.WriteImageFiles(basename, 200, true, false, true, null); } } catch (Exception E) { log.AddString("GIC Exceptions: " + E.ToString()); } log.PopActivity(); // PNL.SaveOutlineTo(OutputFolder, "mergedframeblended"); return; var FrameFiles = Directory.GetFiles(FrameFolder); var OutlineFiles = Directory.GetFiles(OutlineFolder); List <String> AllFiles = new List <string>(); AllFiles.AddRange(FrameFiles); foreach (var a in OutlineFiles) { BoardLayer layer; BoardSide Side; Gerber.DetermineBoardSideAndLayer(a, out Side, out layer); if (layer != BoardLayer.Outline) { AllFiles.Add(a); } } // AllFiles.AddRange(OutlineFiles); GerberMerger.MergeAllByFileType(AllFiles, OutputFolder, "MergedFrame", log); }