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); }
private static void GetTransformedCoord(double DX, double DY, double DXp, double DYp, double Angle, double CA, double SA, GerberNumberFormat CoordinateFormat, bool translate, ref double X, ref double Y) { if (translate) { X = (X * CoordinateFormat.Multiplier + DXp) / CoordinateFormat.Multiplier; Y = (Y * CoordinateFormat.Multiplier + DYp) / CoordinateFormat.Multiplier; } if (Angle != 0) { double nX = X * CA - Y * SA; double nY = X * SA + Y * CA; X = nX; Y = nY; } if (translate) { X = (X * CoordinateFormat.Multiplier + DX) / CoordinateFormat.Multiplier; Y = (Y * CoordinateFormat.Multiplier + DY) / CoordinateFormat.Multiplier; } }
/// <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(string sourcefile, string destfile, double DX, double DY, double DXp, double DYp, double AngleInDeg = 0) { 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(lines, true); if (Gerber.ShowProgress) { Console.WriteLine("found apertures: "); foreach (var a in Parsed.State.Apertures) { Console.WriteLine(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) { Console.WriteLine("Skipping bad aperture definition: {0}", lines[i]); } else { int ATID = (int)GCC.numbercommands[0]; var Aperture = Parsed.State.Apertures[ATID]; if (Gerber.ShowProgress) { Console.WriteLine("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) { Console.WriteLine("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.0f; break; case 70: CoordinateFormat.Multiplier = 25.4f; break; } } if (DumpToOutput) { outlines.Add(lines[i]); if (lines[i].Contains("LNData")) { Console.WriteLine(" 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++; Console.WriteLine(" 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("G") && Angle != 0) { int g = (int)GS.Get("G"); if (g == 2 || g == 3) { double I = 0; double J = 0; if (GS.Has("I")) { I = GS.Get("I"); } if (GS.Has("J")) { J = GS.Get("J"); } 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) { Console.WriteLine("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) { Console.WriteLine(E.Message); } }
bool ParseExcellon(List <string> lines, double drillscaler) { Tools.Clear(); bool headerdone = false; int currentline = 0; ExcellonTool CurrentTool = null; GerberNumberFormat GNF = new GerberNumberFormat(); GNF.DigitsBefore = 3; GNF.DigitsAfter = 3; GNF.OmitLeading = true; double Scaler = 1.0f; bool FormatSpecified = false; bool NumberSpecHad = false; double LastX = 0; double LastY = 0; while (currentline < lines.Count) { switch (lines[currentline]) { // case "M70": GNF.Multiplier = 25.4; break; // inch mode case "INCH": if (Gerber.ExtremelyVerbose) { Console.WriteLine("Out of header INCH found!"); } GNF.SetImperialMode(); break; // inch mode case "METRIC": if (Gerber.ExtremelyVerbose) { Console.WriteLine("Out of header METRIC found!"); } GNF.SetMetricMode(); break; case "M72": if (Gerber.ExtremelyVerbose) { Console.WriteLine("Out of header M72 found!"); } GNF.SetImperialMode(); break; // inch mode case "M71": if (Gerber.ExtremelyVerbose) { Console.WriteLine("Out of header M71 found!"); } GNF.SetMetricMode(); break; // metric mode } if (lines[currentline] == "M48") { //Console.WriteLine("Excellon header starts at line {0}", currentline); currentline++; while ((lines[currentline] != "%" && lines[currentline] != "M95")) { headerdone = true; //double InchMult = 1;// 0.010; switch (lines[currentline]) { // case "M70": GNF.Multiplier = 25.4; break; // inch mode case "INCH": GNF.SetImperialMode(); //Scaler = 0.01; break; // inch mode case "METRIC": GNF.SetMetricMode(); break; case "M72": //GNF.Multiplier = 25.4 * InchMult; GNF.SetImperialMode(); // Scaler = 0.01; break; // inch mode case "M71": //GNF.Multiplier = 1.0; GNF.SetMetricMode(); break; // metric mode default: { var S = lines[currentline].Split(','); if (S[0].IndexOf("INCH") == 0 || S[0].IndexOf("METRIC") == 0) { if (S[0].IndexOf("INCH") == 0) { GNF.SetImperialMode(); } else { GNF.SetMetricMode(); } if (S.Count() > 1) { for (int i = 1; i < S.Count(); i++) { if (S[i][0] == '0') { Console.WriteLine("Number spec reading!: {0}", S[i]); var A = S[i].Split('.'); if (A.Length == 2) { GNF.DigitsBefore = A[0].Length; GNF.DigitsAfter = A[1].Length; NumberSpecHad = true; } } if (S[i] == "LZ") { GNF.OmitLeading = false; } if (S[i] == "TZ") { GNF.OmitLeading = true; } } } } else { if (lines[currentline][0] == ';') { if (Gerber.ShowProgress) { Console.WriteLine(lines[currentline]); } if (lines[currentline].Contains(";FILE_FORMAT=")) { var N = lines[currentline].Substring(13).Split(':'); GNF.DigitsBefore = int.Parse(N[0]); GNF.DigitsAfter = int.Parse(N[1]); FormatSpecified = true; } } else { GCodeCommand GCC = new GCodeCommand(); GCC.Decode(lines[currentline], GNF); if (GCC.charcommands.Count > 0) { switch (GCC.charcommands[0]) { case 'T': { ExcellonTool ET = new ExcellonTool(); ET.ID = (int)GCC.numbercommands[0]; ET.Radius = GNF.ScaleFileToMM(GCC.GetNumber('C')) / 2.0f; Tools[ET.ID] = ET; } break; } } } } } break; } currentline++; } // Console.WriteLine("Excellon header stops at line {0}", currentline); if (FormatSpecified == false && NumberSpecHad == false) { if (GNF.CurrentNumberScale == GerberNumberFormat.NumberScale.Imperial) { // GNF.OmitLeading = true; GNF.DigitsBefore = 2; GNF.DigitsAfter = 4; } else { GNF.DigitsAfter = 3; GNF.DigitsBefore = 3; } } } else { if (headerdone) { GCodeCommand GCC = new GCodeCommand(); GCC.Decode(lines[currentline], GNF); if (GCC.charcommands.Count > 0) { switch (GCC.charcommands[0]) { case 'T': if ((int)GCC.numbercommands[0] > 0) { CurrentTool = Tools[(int)GCC.numbercommands[0]]; } else { CurrentTool = null; } break; default: { GerberSplitter GS = new GerberSplitter(); GS.Split(GCC.originalline, GNF, true); if (GS.Has("G") && GS.Get("G") == 85 && (GS.Has("X") || GS.Has("Y"))) { GerberListSplitter GLS = new GerberListSplitter(); GLS.Split(GCC.originalline, GNF, true); double x1 = LastX; double y1 = LastY; if (GLS.HasBefore("G", "X")) { x1 = GNF.ScaleFileToMM(GLS.GetBefore("G", "X") * Scaler); LastX = x1; } if (GLS.HasBefore("G", "Y")) { y1 = GNF.ScaleFileToMM(GLS.GetBefore("G", "Y") * Scaler); LastY = y1; } double x2 = LastX; double y2 = LastY; if (GLS.HasAfter("G", "X")) { x2 = GNF.ScaleFileToMM(GLS.GetAfter("G", "X") * Scaler); LastX = x2; } if (GLS.HasAfter("G", "Y")) { y2 = GNF.ScaleFileToMM(GLS.GetAfter("G", "Y") * Scaler); LastY = y2; } CurrentTool.Slots.Add(new ExcellonTool.SlotInfo() { Start = new PointD(x1 * drillscaler, y1 * drillscaler), End = new PointD(x2 * drillscaler, y2 * drillscaler) }); LastX = x2; LastY = y2; } else { if (GS.Has("X") || GS.Has("Y")) { double X = LastX; if (GS.Has("X")) { X = GNF.ScaleFileToMM(GS.Get("X") * Scaler); } double Y = LastY; if (GS.Has("Y")) { Y = GNF.ScaleFileToMM(GS.Get("Y") * Scaler); } CurrentTool.Drills.Add(new PointD(X * drillscaler, Y * drillscaler)); LastX = X; LastY = Y; } } } break; } } } } currentline++; } return(headerdone); }
public static string MoveTo(PointD t, GerberNumberFormat GNF) { return(String.Format("X{0}Y{1}D02*", GNF.Format(GNF._ScaleMMToFile(t.X)), GNF.Format(GNF._ScaleMMToFile(t.Y)))); }
public void Split(string p, GerberNumberFormat form, bool finddecimalpoint = false) { // StandardConsoleLog L = new StandardConsoleLog(); // L.PushActivity("Split"); if (p.Length < 2) { return; } try { if (p.Substring(0, 3) == "G04") { GNP.Command = "G"; GNP.Number = 4; Pairs[GNP.Command] = GNP; CommandsInOrder.Add(GNP.Command); // line is a comment! // Console.WriteLine("comment: {0}", p.Substring(3)); // L.PopActivity(); return; } bool wasnumber = false; bool isnumber = false; // bool hasdecimalpoint = false; string running = ""; for (int i = 0; i < p.Length; i++) { char current = p[i]; // L.AddString(p[i].ToString()); if (char.IsNumber(current) || current == '+' || current == '-' || current == '.') { isnumber = true; // L.AddString(p[i].ToString() +" is a number" ); } else { isnumber = false; // L.AddString(p[i].ToString() + " is not a number"); } if (isnumber != wasnumber) { // L.AddString("number state change!"); if (isnumber) { // L.AddString("Setting up running command: " + running); GNP.Command = running; GNP.Orig = running; } else { // L.AddString("trying to parse" + running); GNP.Orig += running; GNP.Parse(running, form, finddecimalpoint); Pairs[GNP.Command] = GNP; CommandsInOrder.Add(GNP.Command); GNP = new GerberNumberPair(); } wasnumber = isnumber; running = ""; } if (current != '+') { running += current; } } if (GNP.Command.Length > 0) { GNP.Parse(running, form, finddecimalpoint); Pairs[GNP.Command] = GNP; CommandsInOrder.Add(GNP.Command); } } catch (Exception) { Console.WriteLine("this line does not seem to contain gerber: {0}", p); } // L.PopActivity(); }
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); }
internal void Split(string p, GerberNumberFormat form, bool hasdecimalpoint = false) { try { bool wasnumber = false; bool isnumber = false; string running = ""; for (int i = 0; i < p.Length; i++) { char current = p[i]; if (char.IsNumber(current) || current == '+' || current == '-' || (hasdecimalpoint && current == '.')) { isnumber = true; } else { isnumber = false; } if (isnumber != wasnumber) { if (isnumber) { GNP.Command = running; GNP.Orig = running; } else { GNP.Orig += running; GNP.Parse(running, form, hasdecimalpoint); if (Pairs.ContainsKey(GNP.Command) == false) { GerberNumberPairList GNPL = new GerberNumberPairList(); GNPL.Command = GNP.Command; GNPL.Orig = GNP.Orig; Pairs[GNP.Command] = GNPL; } Pairs[GNP.Command].Numbers.Add(GNP); CommandsInOrder.Add(GNP.Command); GNP = new GerberNumberPair(); } wasnumber = isnumber; running = ""; } if (current != '+') { running += current; } } if (GNP.Command.Length > 0) { GNP.Parse(running, form, hasdecimalpoint); if (Pairs.ContainsKey(GNP.Command) == false) { GerberNumberPairList GNPL = new GerberNumberPairList(); GNPL.Command = GNP.Command; GNPL.Orig = GNP.Orig; Pairs[GNP.Command] = GNPL; } Pairs[GNP.Command].Numbers.Add(GNP); CommandsInOrder.Add(GNP.Command); } } catch (Exception) { Console.WriteLine("this line does not seem to contain gerber: {0}", p); } }
public string Rebuild(GerberNumberFormat form) { string Res = ""; if ((Has("X") || Has("Y")) && Has("D")) { CommandsInOrder.Remove("X"); CommandsInOrder.Remove("Y"); CommandsInOrder.Remove("I"); CommandsInOrder.Remove("J"); CommandsInOrder.Remove("D"); if (Has("X")) { CommandsInOrder.Add("X"); } if (Has("Y")) { CommandsInOrder.Add("Y"); } if (Has("I")) { CommandsInOrder.Add("I"); } if (Has("J")) { CommandsInOrder.Add("J"); } CommandsInOrder.Add("D"); } else { if (Has("D") && Get("D") < 10) { CommandsInOrder.Remove("D"); CommandsInOrder.Add("D"); } } foreach (var a in CommandsInOrder) { if (a == "D" || a == "G" || a == "M") { Res += a; Res += ((int)Get(a)).ToString("D2"); } else { bool Write = true; if (a == "J" || a == "I") { string R = form.Format(Get(a)); int zerocount = 0; for (int i = 0; i < R.Count(); i++) { if (R[i] == '0') { zerocount++; } } if (zerocount == R.Count()) { Write = false; } } if (Write) { Res += a; Res += form.Format(Get(a)); } } } return(Res + "*"); }
static void Main(string[] args) { // Gerber.ShowProgress = true; GerberNumberFormat GNF = new GerberNumberFormat(); GNF.DigitsAfter = 3; GNF.DigitsBefore = 3; GNF.SetMetricMode(); // GerberSplitter GS = new GerberSplitter(); // GS.Split("X-1.15Y-1.9", GNF, true); //foreach(var a in GS.Pairs)// // { // Console.WriteLine("{0}:{1} {2}", a.Key, a.Value.Command, a.Value.Number); // } // Console.ReadKey(); if (args.Count() == 0) { Console.WriteLine("Usage:"); Console.WriteLine("GerberAnalyse <inputfile>");// <-forcezerowidth> <-dim>"); return; } /* * ParsedGerber PLS; * bool forcezerowidth = false; * bool compact = false; * * for (int i = 1; i < args.Count(); i++) * { * if (args[i] == "-forcezerowidth") forcezerowidth = true; * if (args[i] == "-dim") compact = true; * } * * if (Gerber.FindFileType(args[0].ToLower()) == BoardFileType.Drill) * { * PLS = PolyLineSet.LoadExcellonDrillFile(args[0]); * // ExcellonFile EF = new ExcellonFile(); * // EF.Load(a); * } * else * { * // PLS.PreCombinePolygons = false; * // forcezerowidth = true; * PLS = PolyLineSet.LoadGerberFile(args[0], forcezerowidth, false, new GerberParserState() { PreCombinePolygons = false}); * } * * PLS.CalcPathBounds(); * * if (compact) { * * CultureInfo CI = CultureInfo.InvariantCulture; * * Console.WriteLine("{0}x{1}(mm)", (PLS.BoundingBox.BottomRight.X - PLS.BoundingBox.TopLeft.X).ToString("N3", CI), (PLS.BoundingBox.BottomRight.Y - PLS.BoundingBox.TopLeft.Y).ToString("N3", CI)); * Console.WriteLine("{0}x{1}(imp)", ((PLS.BoundingBox.BottomRight.X - PLS.BoundingBox.TopLeft.X) / 25.4).ToString("N3", CI), ((PLS.BoundingBox.BottomRight.Y - PLS.BoundingBox.TopLeft.Y) / 25.4).ToString("N3", CI)); * } * else * { * Console.WriteLine("Report for {0}:", args[0]); * Console.WriteLine("Suspected file side: {0}, layertype: {1}", PLS.Side.ToString(), PLS.Layer.ToString()); * Console.WriteLine("DisplayShape #: {0}", PLS.DisplayShapes.Count); * foreach (var o in PLS.DisplayShapes) * { * Console.WriteLine("\tOutline {0} vertices thin:{1}", o.Vertices.Count, o.Thin); * foreach (var v in o.Vertices) * { * Console.WriteLine("\t\t{0}", v); * } * * } * * Console.WriteLine("OutlineShape #: {0}", PLS.OutlineShapes.Count); * foreach (var o in PLS.OutlineShapes) * { * Console.WriteLine("\tOutline {0} vertices thin:{1}", o.Vertices.Count, o.Thin); * foreach (var v in o.Vertices) * { * Console.WriteLine("\t\t{0}", v); * } * } * Console.WriteLine("Aperture #: {0}", PLS.State.Apertures.Count); * foreach (var apt in PLS.State.Apertures) * { * Console.Write("\tAperture D{0} ", apt.Key.ToString("D2")); * Console.Write("type: {0} ", apt.Value.ShapeType.ToString()); * switch (apt.Value.ShapeType) * { * case GerberApertureShape.Circle: * * Console.Write("diameter {0} ", apt.Value.CircleRadius * 2); break; * } * Console.WriteLine(); * } * Console.WriteLine("Corners: "); * Console.WriteLine(PLS.BoundingBox.TopLeft); * Console.WriteLine(PLS.BoundingBox.BottomRight); * Console.WriteLine("Size: {0}x{1} mm", PLS.BoundingBox.BottomRight.X - PLS.BoundingBox.TopLeft.X, PLS.BoundingBox.BottomRight.Y - PLS.BoundingBox.TopLeft.Y); * } */ Stats TheStats = new Stats(); if (Directory.Exists(args[0])) { GerberLibrary.GerberImageCreator GIC = new GerberLibrary.GerberImageCreator(); foreach (var L in Directory.GetFiles(args[0]).ToList()) { TheStats.AddFile(L); } } else if (File.Exists(args[0])) { if (Path.GetExtension(args[0]).ToLower() == ".zip") { using (ZipFile zip1 = ZipFile.Read(args[0])) { foreach (ZipEntry e in zip1) { MemoryStream MS = new MemoryStream(); if (e.IsDirectory == false) { e.Extract(MS); MS.Seek(0, SeekOrigin.Begin); TheStats.AddFile(MS, e.FileName); } } } } else { TheStats.AddFile(args[0]); } } TheStats.Complete(); Console.WriteLine("Corners: "); Console.WriteLine(TheStats.Box.TopLeft); Console.WriteLine(TheStats.Box.BottomRight); Console.WriteLine("Size: {0}x{1} mm", TheStats.Width, TheStats.Height); //var json = new JavaScriptSerializer().Serialize(TheStats); //Console.WriteLine(json); // Console.WriteLine("Press any key to continue"); // Console.ReadKey(); }
/// <summary> /// /// </summary> /// <param name="lines"></param> /// <param name="drillscaler"></param> /// <param name="log"></param> /// <param name="radiusAdjust">半径修正系数,用于实现电镀孔厚度,单位mm</param> /// <returns></returns> bool ParseExcellon(List <string> lines, double drillscaler, ProgressLog log, double radiusScaler = 1.0f) { var LogID = log.PushActivity("Parse Excellon"); Tools.Clear(); bool headerdone = false; int currentline = 0; ExcellonTool CurrentTool = null; GerberNumberFormat GNF = new GerberNumberFormat(); GNF.DigitsBefore = 3; GNF.DigitsAfter = 3; GNF.OmitLeading = true; double Scaler = 1.0f; bool FormatSpecified = false; bool NumberSpecHad = false; double LastX = 0; double LastY = 0; CutterCompensation Compensation = CutterCompensation.None; List <PointD> PathCompensation = new List <PointD>(); bool WarnIntersections = true; while (currentline < lines.Count) { switch (lines[currentline]) { // case "M70": GNF.Multiplier = 25.4; break; // inch mode case "INCH": if (Gerber.ExtremelyVerbose) { log.AddString("Out of header INCH found!"); } GNF.SetImperialMode(); break; // inch mode case "METRIC": if (Gerber.ExtremelyVerbose) { log.AddString("Out of header METRIC found!"); } GNF.SetMetricMode(); break; case "M72": if (Gerber.ExtremelyVerbose) { log.AddString("Out of header M72 found!"); } GNF.SetImperialMode(); break; // inch mode case "M71": if (Gerber.ExtremelyVerbose) { log.AddString("Out of header M71 found!"); } GNF.SetMetricMode(); break; // metric mode } if (lines[currentline] == "M48") { //Console.WriteLine("Excellon header starts at line {0}", currentline); currentline++; while ((lines[currentline] != "%" && lines[currentline] != "M95")) { headerdone = true; //double InchMult = 1;// 0.010; switch (lines[currentline]) { // case "M70": GNF.Multiplier = 25.4; break; // inch mode case "INCH": GNF.SetImperialMode(); //Scaler = 0.01; break; // inch mode case "METRIC": GNF.SetMetricMode(); break; case "M72": //GNF.Multiplier = 25.4 * InchMult; GNF.SetImperialMode(); // Scaler = 0.01; break; // inch mode case "M71": //GNF.Multiplier = 1.0; GNF.SetMetricMode(); break; // metric mode default: { var S = lines[currentline].Split(','); if (S[0].IndexOf("INCH") == 0 || S[0].IndexOf("METRIC") == 0) { if (S[0].IndexOf("INCH") == 0) { GNF.SetImperialMode(); } else { GNF.SetMetricMode(); } if (S.Count() > 1) { for (int i = 1; i < S.Count(); i++) { if (S[i][0] == '0') { log.AddString(String.Format("Number spec reading!: {0}", S[i])); var A = S[i].Split('.'); if (A.Length == 2) { GNF.DigitsBefore = A[0].Length; GNF.DigitsAfter = A[1].Length; NumberSpecHad = true; } } if (S[i] == "LZ") { GNF.OmitLeading = false; } if (S[i] == "TZ") { GNF.OmitLeading = true; } } } } else { if (lines[currentline][0] == ';') { if (Gerber.ShowProgress) { log.AddString(lines[currentline]); } if (lines[currentline].Contains(";FILE_FORMAT=")) { var N = lines[currentline].Substring(13).Split(':'); GNF.DigitsBefore = int.Parse(N[0]); GNF.DigitsAfter = int.Parse(N[1]); FormatSpecified = true; } } else { GCodeCommand GCC = new GCodeCommand(); GCC.Decode(lines[currentline], GNF); if (GCC.charcommands.Count > 0) { switch (GCC.charcommands[0]) { case 'T': { ExcellonTool ET = new ExcellonTool(); ET.ID = (int)GCC.numbercommands[0]; ET.Radius = GNF.ScaleFileToMM(GCC.GetNumber('C')) / 2.0f * radiusScaler; Tools[ET.ID] = ET; } break; } } } } } break; } currentline++; } // Console.WriteLine("Excellon header stops at line {0}", currentline); if (FormatSpecified == false && NumberSpecHad == false) { if (GNF.CurrentNumberScale == GerberNumberFormat.NumberScale.Imperial) { // GNF.OmitLeading = true; GNF.DigitsBefore = 2; GNF.DigitsAfter = 4; } else { GNF.DigitsAfter = 3; GNF.DigitsBefore = 3; } } } else { if (headerdone) { GCodeCommand GCC = new GCodeCommand(); GCC.Decode(lines[currentline], GNF); if (GCC.charcommands.Count > 0) { switch (GCC.charcommands[0]) { case 'T': if ((int)GCC.numbercommands[0] > 0) { CurrentTool = Tools[(int)GCC.numbercommands[0]]; } else { CurrentTool = null; } break; case 'M': default: { GerberSplitter GS = new GerberSplitter(); GS.Split(GCC.originalline, GNF, true); if (GS.Has("G") && GS.Get("G") == 85 && (GS.Has("X") || GS.Has("Y"))) { GerberListSplitter GLS = new GerberListSplitter(); GLS.Split(GCC.originalline, GNF, true); double x1 = LastX; double y1 = LastY; if (GLS.HasBefore("G", "X")) { x1 = GNF.ScaleFileToMM(GLS.GetBefore("G", "X") * Scaler); LastX = x1; } if (GLS.HasBefore("G", "Y")) { y1 = GNF.ScaleFileToMM(GLS.GetBefore("G", "Y") * Scaler); LastY = y1; } double x2 = LastX; double y2 = LastY; if (GLS.HasAfter("G", "X")) { x2 = GNF.ScaleFileToMM(GLS.GetAfter("G", "X") * Scaler); LastX = x2; } if (GLS.HasAfter("G", "Y")) { y2 = GNF.ScaleFileToMM(GLS.GetAfter("G", "Y") * Scaler); LastY = y2; } CurrentTool.Slots.Add(new ExcellonTool.SlotInfo() { Start = new PointD(x1 * drillscaler, y1 * drillscaler), End = new PointD(x2 * drillscaler, y2 * drillscaler) }); LastX = x2; LastY = y2; } else if (GS.Has("G") && GS.Get("G") == 00 && (GS.Has("X") || GS.Has("Y"))) { GerberListSplitter GLS = new GerberListSplitter(); GLS.Split(GCC.originalline, GNF, true); double x1 = LastX; double y1 = LastY; if (GLS.HasAfter("G", "X")) { x1 = GNF.ScaleFileToMM(GLS.GetAfter("G", "X") * Scaler); LastX = x1; } if (GLS.HasAfter("G", "Y")) { y1 = GNF.ScaleFileToMM(GLS.GetAfter("G", "Y") * Scaler); LastY = y1; } /* cancel cutter compensation */ Compensation = CutterCompensation.None; PathCompensation.Clear(); } else if (GS.Has("G") && GS.Get("G") == 01 && (GS.Has("X") || GS.Has("Y"))) { GerberListSplitter GLS = new GerberListSplitter(); GLS.Split(GCC.originalline, GNF, true); double x1 = LastX; double y1 = LastY; double x2 = LastX; double y2 = LastY; if (GLS.HasAfter("G", "X")) { x2 = GNF.ScaleFileToMM(GLS.GetAfter("G", "X") * Scaler); LastX = x2; } if (GLS.HasAfter("G", "Y")) { y2 = GNF.ScaleFileToMM(GLS.GetAfter("G", "Y") * Scaler); LastY = y2; } if (Compensation == CutterCompensation.None) { CurrentTool.Slots.Add(new ExcellonTool.SlotInfo() { Start = new PointD(x1 * drillscaler, y1 * drillscaler), End = new PointD(x2 * drillscaler, y2 * drillscaler) }); } else { PathCompensation.Add(new PointD(x2 * drillscaler, y2 * drillscaler)); } LastX = x2; LastY = y2; } else if (GS.Has("G") && GS.Get("G") == 40) /* cutter compensation off */ { var comp = CutCompensation(PathCompensation, Compensation, CurrentTool.Radius * drillscaler); if (WarnIntersections) { /* warn about path intersections */ for (int i = 0; i < comp.Count - 1; i++) { for (int j = i + 2; j < comp.Count - 1; j++) { var intersection = Helpers.SegmentSegmentIntersect(comp[i], comp[i + 1], comp[j], comp[j + 1]); if (intersection != null) { log.AddString("Path with intersections found on cut compensation! Inspect output for accuracy!"); WarnIntersections = false; break; } } if (!WarnIntersections) { break; } } } /* create line segments from set of points */ var array = comp.Zip(comp.Skip(1), Tuple.Create); CurrentTool.Slots.AddRange(array.Select(i => new ExcellonTool.SlotInfo() { Start = i.Item1, End = i.Item2 })); Compensation = CutterCompensation.None; PathCompensation.Clear(); } else if (GS.Has("G") && GS.Get("G") == 41) /* cutter compensation left: offset of the cutter radius is to the LEFT of contouring direction */ { if (Compensation != CutterCompensation.None) { log.AddString("Unterminated cutter compensation block found! Inspect output for accuracy!"); } Compensation = CutterCompensation.Left; PathCompensation.Clear(); PathCompensation.Add(new PointD(LastX * drillscaler, LastY * drillscaler)); } else if (GS.Has("G") && GS.Get("G") == 42) /* cutter compensation right: offset of the cutter radius is to the RIGHT of contouring direction */ { if (Compensation != CutterCompensation.None) { log.AddString("Unterminated cutter compensation block found! Inspect output for accuracy!"); } Compensation = CutterCompensation.Right; PathCompensation.Clear(); PathCompensation.Add(new PointD(LastX * drillscaler, LastY * drillscaler)); } else { //Deal with the repeat code if (GS.Has("R") && (GS.Has("X") || GS.Has("Y"))) { double repeatX = 0; double repeatY = 0; if (GS.Has("X")) { repeatX = GNF.ScaleFileToMM(GS.Get("X") * Scaler); } if (GS.Has("Y")) { repeatY = GNF.ScaleFileToMM(GS.Get("Y") * Scaler); } for (int repeatIndex = 1; repeatIndex <= GS.Get("R"); repeatIndex++) { double X = LastX; if (GS.Has("X")) { X += repeatX; } double Y = LastY; if (GS.Has("Y")) { Y += repeatY; } CurrentTool.Drills.Add(new PointD(X * drillscaler, Y * drillscaler)); LastX = X; LastY = Y; } } else if (GS.Has("X") || GS.Has("Y")) { double X = LastX; if (GS.Has("X")) { X = GNF.ScaleFileToMM(GS.Get("X") * Scaler); } double Y = LastY; if (GS.Has("Y")) { Y = GNF.ScaleFileToMM(GS.Get("Y") * Scaler); } if (Compensation == CutterCompensation.None) { CurrentTool.Drills.Add(new PointD(X * drillscaler, Y * drillscaler)); } else { PathCompensation.Add(new PointD(X * drillscaler, Y * drillscaler)); } LastX = X; LastY = Y; } } } break; } } } } currentline++; } log.PopActivity(LogID); return(headerdone); }
public void Split(string p, GerberNumberFormat form, bool finddecimalpoint = false) { if (p.Length < 2) { return; } try { if (p.Substring(0, 3) == "G04") { GNP.Command = "G"; GNP.Number = 4; Pairs[GNP.Command] = GNP; CommandsInOrder.Add(GNP.Command); // line is a comment! // Console.WriteLine("comment: {0}", p.Substring(3)); return; } bool wasnumber = false; bool isnumber = false; // bool hasdecimalpoint = false; string running = ""; for (int i = 0; i < p.Length; i++) { char current = p[i]; if (char.IsNumber(current) || current == '+' || current == '-' || current == '.') { isnumber = true; } else { isnumber = false; } if (isnumber != wasnumber) { if (isnumber) { GNP.Command = running; GNP.Orig = running; } else { GNP.Orig += running; GNP.Parse(running, form, finddecimalpoint); Pairs[GNP.Command] = GNP; CommandsInOrder.Add(GNP.Command); GNP = new GerberNumberPair(); } wasnumber = isnumber; running = ""; } if (current != '+') { running += current; } } if (GNP.Command.Length > 0) { GNP.Parse(running, form, finddecimalpoint); Pairs[GNP.Command] = GNP; CommandsInOrder.Add(GNP.Command); } } catch (Exception) { Console.WriteLine("this line does not seem to contain gerber: {0}", p); } }