public void FixEagleDrillExportIssues(ProgressLog Logger) { List<ParsedGerber> DrillFiles = new List<ParsedGerber>(); List<Tuple<double, ParsedGerber>> DrillFilesToReload = new List<Tuple<double, ParsedGerber>>(); Bounds BB = new Bounds(); foreach (var a in PLSs) { if (a.Layer == BoardLayer.Drill) { DrillFiles.Add(a); } else { BB.AddBox(a.BoundingBox); } } foreach (var a in DrillFiles) { var b = a.BoundingBox; if (b.Width() > BB.Width() * 1.5 || b.Height() > BB.Height() * 1.5) { var MaxRatio = Math.Max(b.Width() / BB.Width(), b.Height() / BB.Height()); if (Logger != null) Logger.AddString(String.Format("Note: Really large drillfile found({0})-fix your export scripts!", a.Name)); Console.WriteLine("Note: Really large drillfile found ({0})- fix your export scripts!", a.Name); DrillFilesToReload.Add(new Tuple<double, ParsedGerber>(MaxRatio, a)); } } foreach (var a in DrillFilesToReload) { PLSs.Remove(a.Item2); var scale = 1.0; if (Double.IsInfinity(a.Item1) || Double.IsNaN(a.Item1)) { Errors.Add("Drill file size reached infinity - ignoring it"); if (Logger != null) Logger.AddString("Drill file size reached infinity - ignoring it"); } else { var R = a.Item1; while (R >= 1.5) { R /= 10; scale /= 10; } AddFileToSet(a.Item2.Name, Logger, scale); } } BoundingBox = new Bounds(); foreach (var a in PLSs) { //Console.WriteLine("Progress: Adding board {6} to box::{0:N2},{1:N2} - {2:N2},{3:N2} -> {4:N2},{5:N2}", a.BoundingBox.TopLeft.X, a.BoundingBox.TopLeft.Y, a.BoundingBox.BottomRight.X, a.BoundingBox.BottomRight.Y, a.BoundingBox.Width(), a.BoundingBox.Height(), Path.GetFileName( a.Name)); //Console.WriteLine("adding box for {0}:{1},{2}", a.Name, a.BoundingBox.Width(), a.BoundingBox.Height()); BoundingBox.AddBox(a.BoundingBox); } }
private static void MultiMerge(string file1, List <string> otherfiles, string output, ProgressLog Log) { int MM = Log.PushActivity("Excellon MultiMerge"); if (File.Exists(file1) == false) { Log.AddString(String.Format("{0} not found! stopping process!", file1)); Log.PopActivity(MM); return; } foreach (var otherfile in otherfiles) { if (File.Exists(otherfile) == false) { Log.AddString(String.Format("{0} not found! stopping process!", otherfile)); Log.PopActivity(MM); return; } } Log.AddString(String.Format("Reading {0}:", file1)); ExcellonFile File1Parsed = new ExcellonFile(); File1Parsed.Load(Log, file1); List <ExcellonFile> OtherFilesParsed = new List <ExcellonFile>(); foreach (var otherfile in otherfiles) { Log.AddString(String.Format("Reading {0}:", otherfile)); ExcellonFile OtherFileParsed = new ExcellonFile(); OtherFileParsed.Load(Log, otherfile); OtherFilesParsed.Add(OtherFileParsed); } int MaxID = 0; foreach (var D in File1Parsed.Tools) { if (D.Value.ID > MaxID) { MaxID = D.Value.ID + 1; } } foreach (var F in OtherFilesParsed) { foreach (var D in F.Tools) { File1Parsed.AddToolWithHoles(D.Value);; // D.Value.ID += MaxID; // File1Parsed.Tools[D.Value.ID] = D.Value; } } File1Parsed.Write(output, 0, 0, 0, 0); Log.PopActivity(MM); }
public static void MergeAll(List <string> Files, string output, ProgressLog Log) { var LogDepth = Log.PushActivity("Excellon MergeAll"); if (Files.Count >= 2) { MultiMerge(Files[0], Files.Skip(1).ToList(), output, Log); Log.PopActivity(LogDepth); return; } if (Files.Count < 2) { if (Files.Count == 1) { Log.AddString("Merging 1 file is copying... doing so..."); if (File.Exists(output)) { File.Delete(output); } File.Copy(Files[0], output); } else { Log.AddString("Need files to do anything??"); } Log.PopActivity(LogDepth); return; } string LastFile = Files[0]; List <string> TempFiles = new List <string>(); for (int i = 1; i < Files.Count - 1; i++) { string NewFile = Path.GetTempFileName(); TempFiles.Add(NewFile); Merge(LastFile, Files[i], NewFile, Log); LastFile = NewFile; } Merge(LastFile, Files.Last(), output, Log); Log.AddString("Removing merge tempfiles"); foreach (string s in TempFiles) { File.Delete(s); } Log.PopActivity(LogDepth); }
public static void Merge(string file1, string file2, string outputfile, ProgressLog Log) { Log.PushActivity("Excellon Merge"); if (File.Exists(file1) == false) { Log.AddString(String.Format("{0} not found! stopping process!", file1)); Log.PopActivity(); return; } if (File.Exists(file2) == false) { Log.AddString(String.Format("{0} not found! stopping process!", file2)); Log.PopActivity(); return; } Log.AddString(String.Format("Reading {0}:", file1)); ExcellonFile File1Parsed = new ExcellonFile(); File1Parsed.Load(Log, file1); Log.AddString(String.Format("Reading {0}:", file2)); ExcellonFile File2Parsed = new ExcellonFile(); File2Parsed.Load(Log, file2); Log.AddString(String.Format("Merging {0} with {1}", file1, file2)); int MaxID = 0; foreach (var D in File1Parsed.Tools) { if (D.Value.ID > MaxID) { MaxID = D.Value.ID + 1; } } foreach (var D in File2Parsed.Tools) { D.Value.ID += MaxID; File1Parsed.Tools[D.Value.ID] = D.Value; } File1Parsed.Write(outputfile, 0, 0, 0, 0); Log.PopActivity(); }
private void RemapPair(ProgressLog log, string from, string to, bool overridevalue) { log.PushActivity("RemapPair"); if (from != to) { var F = FindEntry(from, overridevalue); var T = FindEntry(to, overridevalue); if (F != null) { if (T != null) { foreach (var rd in F.RefDes) { T.RefDes.Add(rd); } F.RefDes.Clear(); RemoveEntry(F); } else { log.AddString(String.Format("From found, but no To: {0}", from)); F.SetCombined(to); } } } log.PopActivity(); }
public static void WriteContainedOnly(string inputfile, PolyLine Boundary, string outputfilename, ProgressLog Log) { Log.PushActivity("Excellon Clipper"); if (File.Exists(inputfile) == false) { Log.AddString(String.Format("{0} not found! stopping process!", Path.GetFileName(inputfile))); Log.PopActivity(); return; } Log.AddString(String.Format("Clipping {0} to {1}", Path.GetFileName(inputfile), Path.GetFileName(outputfilename))); ExcellonFile EF = new ExcellonFile(); EF.Load(Log, inputfile); EF.WriteContained(Boundary, outputfilename, Log); Log.PopActivity(); }
public void AddFileToSet(string aname, ProgressLog Logger, double drillscaler = 1.0) { if (Streams.ContainsKey(aname)) { AddFileToSet(Streams[aname], aname, Logger, drillscaler); } else { Logger.AddString(String.Format("[ERROR] no stream for {0}!!!", aname)); } }
private bool InventOutline(ProgressLog log) { double largest = 0; ParsedGerber Largest = null; PolyLine Outline = null; foreach (var a in PLSs) { var P = a.FindLargestPolygon(); if (P != null) { if (P.Item1 > largest) { largest = P.Item1; Largest = a; Outline = P.Item2; } } } if (largest < BoundingBox.Area() / 3.0) { return(false); } bool zerowidth = true; bool precombine = true; log.AddString(String.Format("Note: Using {0} to extract outline file", Path.GetFileName(Largest.Name))); if (Largest.Layer == BoardLayer.Mill) { Largest.OutlineShapes.Remove(Outline); Largest.Shapes.Remove(Outline); } var b = AddBoardToSet(log, Largest.Name, zerowidth, precombine, 1.0); b.Layer = BoardLayer.Outline; b.Side = BoardSide.Both; b.DisplayShapes.Clear(); b.OutlineShapes.Clear(); b.Shapes.Clear(); Outline.Close(); b.Shapes.Add(Outline); b.OutlineShapes.Add(Outline); //b.DisplayShapes.Add(Outline); //b.BuildBoundary(); b.FixPolygonWindings(); b.CalcPathBounds(); return(true); }
public void CheckRelativeBoundingBoxes(ProgressLog Logger) { List <ParsedGerber> DrillFiles = new List <ParsedGerber>(); List <ParsedGerber> DrillFilesToReload = new List <ParsedGerber>(); Bounds BB = new Bounds(); foreach (var a in PLSs) { if (a.Layer == BoardLayer.Drill) { DrillFiles.Add(a); } else { BB.AddBox(a.BoundingBox); } } foreach (var a in DrillFiles) { if (a.BoundingBox.Intersects(BB) == false) { Errors.Add(String.Format("Drill file {0} does not seem to touch the main bounding box!", Path.GetFileName(a.Name))); if (Logger != null) { Logger.AddString(String.Format("Drill file {0} does not seem to touch the main bounding box!", Path.GetFileName(a.Name))); } PLSs.Remove(a); } } BoundingBox = new Bounds(); foreach (var a in PLSs) { // Console.WriteLine("Progress: Adding board {6} to box::{0:N2},{1:N2} - {2:N2},{3:N2} -> {4:N2},{5:N2}", a.BoundingBox.TopLeft.X, a.BoundingBox.TopLeft.Y, a.BoundingBox.BottomRight.X, a.BoundingBox.BottomRight.Y, a.BoundingBox.Width(), a.BoundingBox.Height(), Path.GetFileName(a.Name)); //Console.WriteLine("adding box for {0}:{1},{2}", a.Name, a.BoundingBox.Width(), a.BoundingBox.Height()); BoundingBox.AddBox(a.BoundingBox); } }
public void Remap(ProgressLog log, string basefolder) { log.PushActivity("Remap"); var D = PartLibrary.CreatePassivesMapping(); File.WriteAllLines(Path.Combine(basefolder, "genmapping.txt"), (from i in D select i.Key + " " + i.Value).ToList()); var map = File.ReadAllLines(Path.Combine(basefolder, "bommapping.txt")); log.AddString("Loaded bommapping!"); foreach (var l in map) { var A = l.Split(' '); if (A.Count() >= 2) { string from = A[0]; string to = A[1]; bool dooverride = false; if (A.Count() > 2) { if (A[2] == "override") { dooverride = true; } ; } RemapPair(log, from, to, dooverride); //Console.WriteLine("remapped {0} to {1}", from, to); } } foreach (var l in D) { RemapPair(log, l.Key, l.Value, false); } log.PopActivity(); }
public void AddBoardsToSet(List <string> FileList, bool fixgroup = true, ProgressLog Logger = null) { foreach (var a in FileList) { BoardSide aSide = BoardSide.Unknown; BoardLayer aLayer = BoardLayer.Unknown; string ext = Path.GetExtension(a); if (ext == ".zip") { using (ZipFile zip1 = ZipFile.Read(a)) { foreach (ZipEntry e in zip1) { MemoryStream MS = new MemoryStream(); if (e.IsDirectory == false) { // e.Extract(MS); // MS.Seek(0, SeekOrigin.Begin); Gerber.DetermineBoardSideAndLayer(e.FileName, out aSide, out aLayer); if (aLayer == BoardLayer.Outline) { HasLoadedOutline = true; } // AddFileStream(MS, e.FileName, drillscaler); } } } } else { Gerber.DetermineBoardSideAndLayer(a, out aSide, out aLayer); } if (aLayer == BoardLayer.Outline) { HasLoadedOutline = true; } } foreach (var a in FileList) { if (Logger != null) { Logger.AddString(String.Format("Loading {0}", Path.GetFileName(a))); } string ext = Path.GetExtension(a); if (ext == ".zip") { using (ZipFile zip1 = ZipFile.Read(a)) { foreach (ZipEntry e in zip1) { MemoryStream MS = new MemoryStream(); if (e.IsDirectory == false) { if (Logger != null) { Logger.AddString(String.Format("Loading inside zip: {0}", Path.GetFileName(e.FileName))); } e.Extract(MS); MS.Seek(0, SeekOrigin.Begin); AddFileToSet(MS, e.FileName, Logger); } } } } else { MemoryStream MS2 = new MemoryStream(); FileStream FS = File.OpenRead(a); FS.CopyTo(MS2); MS2.Seek(0, SeekOrigin.Begin); AddFileToSet(MS2, a, Logger); } } if (fixgroup) { if (Logger != null) { Logger.AddString("Checking for common file format mistakes."); } FixEagleDrillExportIssues(Logger); CheckRelativeBoundingBoxes(Logger); CheckForOutlineFiles(Logger); CheckRelativeBoundingBoxes(Logger); } }
public void CheckForOutlineFiles(ProgressLog Logger) { List <ParsedGerber> Outlines = new List <ParsedGerber>(); List <ParsedGerber> Mills = new List <ParsedGerber>(); List <ParsedGerber> Unknowns = new List <ParsedGerber>(); foreach (var a in PLSs) { if (a.Side == BoardSide.Both && (a.Layer == BoardLayer.Outline)) { Outlines.Add(a); } if (a.Side == BoardSide.Both && (a.Layer == BoardLayer.Mill)) { Mills.Add(a); } if (a.Side == BoardSide.Unknown && a.Layer == BoardLayer.Unknown) { Unknowns.Add(a); Errors.Add(String.Format("Unknown file in set:{0}", Path.GetFileName(a.Name))); if (Logger != null) { Logger.AddString(String.Format("Unknown file in set:{0}", Path.GetFileName(a.Name))); } } } if (Outlines.Count == 0) { if (Unknowns.Count == 0) { Errors.Add(String.Format("No outline file found and all other files accounted for! ")); if (Logger != null) { Logger.AddString(String.Format("No outline file found and all other files accounted for! ")); } // if (Mills.Count == 1) // { // Mills[0].Layer = BoardLayer.Outline; // Errors.Add(String.Format("Elevating mill file to outline!")); // if (Logger != null) Logger.AddString(String.Format("Elevating mill file to outline!")); // } // else // if (!InventOutlineFromMill()) { CreateBoxOutline(); } } else { CreateBoxOutline(); return; //InventOutline(); //return; //foreach (var a in Unknowns) //{ // PLSs.Remove(a); // hasgko = true; // a.Layer = BoardLayer.Outline; // a.Side = BoardSide.Both; // Console.WriteLine("Note: Using {0} as outline file", Path.GetFileName(a.Name)); // if (Logger != null) Logger.AddString(String.Format("Note: Using {0} as outline file", Path.GetFileName(a.Name))); // bool zerowidth = true; // bool precombine = true; // var b = AddBoardToSet(a.Name, zerowidth, precombine, 1.0); // b.Layer = BoardLayer.Outline; // b.Side = BoardSide.Both; //} } } }
public static void MergeFrameIntoGerberSet(string FrameFolder, string OutlineFolder, string OutputFolder, FrameSettings FS, ProgressLog log, string basename) { log.PushActivity("MergeFrame"); 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) { // 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 (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; } 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; } } } } } PNL.UpdateShape(log); Directory.CreateDirectory(OutputFolder); PNL.SaveGerbersToFolder("MergedFrame", OutputFolder, log, true, false, true, basename); 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); }
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, 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); }
/// <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); }
private static Dictionary <string, Tuple <GerberApertureType, List <PointD> > > FillOverlapList(ProgressLog log, Dictionary <string, Tuple <GerberApertureType, List <PointD> > > overlapList, ParsedGerber subtr, string subtractfile) { log.PushActivity("Filling overlap list coords"); List <String> lines = new List <string>(); List <String> outlines = new List <string>(); int CurrentAperture = 10; bool WriteMove = false; int moveswritten = 0; using (StreamReader sr = new StreamReader(subtractfile)) { while (sr.EndOfStream == false) { String line = sr.ReadLine(); if (line.Length > 0) { lines.Add(line); } } } lines = PolyLineSet.SanitizeInputLines(lines); //ParsedGerber Parsed = PolyLineSet.ParseGerber274x(log, lines, true, false, new GerberParserState() { GenerateGeometry = false }); 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 = subtr.State.ApertureMacros[name]; M.Written = true; var gerb = M.BuildGerber(CoordinateFormat, 0, "").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 = subtr.State.Apertures[ATID]; if (Gerber.ShowProgress) { log.AddString(String.Format("found " + Aperture.ToString())); } string gerb = Aperture.BuildGerber(CoordinateFormat, "", 0); if ((Aperture.ShapeType == GerberApertureShape.Compound || Aperture.ShapeType == GerberApertureShape.Macro) && subtr.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; GS.Set("X", X); GS.Set("Y", Y); } if (GS.Get("D") >= 10) { CurrentAperture = (int)GS.Get("D"); // Select Aperture; } string hash = subtr.State.Apertures[CurrentAperture].GetApertureHash(); if (overlapList.ContainsKey(hash)) { overlapList[hash].Item2.Add(new PointD(LastX, LastY)); } if (WriteMove) { GerberSplitter GS2 = new GerberSplitter(); GS2.Set("D", 2); double X0 = 0; double Y0 = 0; if (overlapList.ContainsKey(hash)) { overlapList[hash].Item2.Add(new PointD(0, 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(outputfile, PolyLineSet.SanitizeInputLines(PostProcLines)); } catch (Exception E) { log.AddString(String.Format(E.Message)); } log.PopActivity(); return(overlapList); }
/// <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(); }
public static bool SaveDebugImage(string GerberFilename, string BitmapFilename, float dpi, Color Foreground, Color Background, ProgressLog log) { log.PushActivity("debug image"); 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(log, 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))); log.AddString(String.Format("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); log.PopActivity(); return(true); }
bool ParseExcellon(List <string> lines, double drillscaler, ProgressLog log) { 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; 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; 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; } } 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; } 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++; } log.PopActivity(); return(headerdone); }