Example #1
0
        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);
            }
        }
Example #4
0
        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);
        }
Example #5
0
 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))));
 }
Example #6
0
        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();
        }
Example #7
0
        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);
        }
Example #8
0
        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);
            }
        }
Example #9
0
        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 + "*");
        }
Example #10
0
        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();
        }
Example #11
0
        /// <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);
        }
Example #12
0
        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);
            }
        }