示例#1
0
            public override string ToString()
            {
                // for some reason the arc in version 5.99 needs start middle end
                // rather than start end angle like for fp_arc ... go figure
                // X1, Y1 = centre
                double Xs, Ys, Xm, Ym, Xe, Ye;

                Xs = Math.Round(X1 + Radius * Math.Cos(Radians(StartAngle)), Precision);
                Ys = Math.Round(Y1 + Radius * Math.Sin(Radians(StartAngle)), Precision);
                Xm = Math.Round(X1 + Radius * Math.Cos(Radians(StartAngle + (EndAngle - StartAngle) / 2)), Precision);
                Ym = Math.Round(Y1 + Radius * Math.Sin(Radians(StartAngle + (EndAngle - StartAngle) / 2)), Precision);
                Xe = Math.Round(X1 + Radius * Math.Cos(Radians(EndAngle)), Precision);
                Ye = Math.Round(Y1 + Radius * Math.Sin(Radians(EndAngle)), Precision);

                string netstr = (net == -1) ? "" : $"(net {net})";

                if (Brd.IsCopperLayer(Layer))
                {
                    return($"  (arc (start {Xs} {-Ys}) (mid {Xm} {-Ym}) (end {Xe} {-Ye}) (layer {Brd.GetLayer(Layer)}) {netstr} (width {Width}))\n");
                }
                else
                {
                    return($"  (gr_arc (start {Math.Round(X1, Precision)} {Math.Round(-Y1, Precision)}) (end {Math.Round(Xs, Precision)} {Math.Round(-Ys, Precision)}) (angle {Math.Round(-(EndAngle - StartAngle), Precision)}) (layer {Brd.GetLayer(Layer)}) (width {Width}))\n");
                }
            }
示例#2
0
            public override bool ProcessLine(byte[] line)
            {
                double StartAngle, EndAngle, Radius, Width;
                Layers Layer;
                double X1, Y1;
                Int16  Component;
                Int16  net;

                base.ProcessLine();
                ArcStruct a = ByteArrayToStructure <ArcStruct>(line);

                Layer = (Layers)a.Layer;
                net   = a.net;
                net++;
                Component  = a.Component;
                X1         = Math.Round((double)a.X1 * 25.4 / 10000000 - originX, Precision);
                Y1         = Math.Round((double)a.Y1 * 25.4 / 10000000 - originY, Precision);
                Radius     = Math.Round((double)a.Radius * 25.4 / 10000000, Precision);
                StartAngle = a.StartAngle;
                EndAngle   = a.EndAngle;
                Width      = (double)a.Width * 25.4 / 10000000;

                bool   InComponent = Component != -1;
                double Angle;

                if (EndAngle < StartAngle)
                {
                    EndAngle += 360;
                }

                Angle = (EndAngle - StartAngle);
                double X     = X1 + Radius * Math.Cos(StartAngle * Math.PI / 180);
                double Y     = Y1 + Radius * Math.Sin(StartAngle * Math.PI / 180);
                string layer = Brd.GetLayer(Layer);

                if (!InComponent)
                {
                    if (net > 0 && Brd.IsCopperLayer(Layer))
                    {
                        if (!Globals.PcbnewVersion)
                        {
                            // arcs with nets on copper layers allowed in 5.99
                            Arc Arc = new Arc(X1, Y1, StartAngle, EndAngle, Radius, Layer, Width, net);
                            ArcsL.Add(Arc);
                        }
                        else
                        {
                            //arcs.Append($"  (arc (start {Math.Round(X1, Precision)} {Math.Round(-Y1, Precision)}) (end {Math.Round(X, Precision)} {Math.Round(-Y, Precision)}) (angle {Math.Round(Angle, Precision)}) (layer {L}) (net {Net}) (width {Width}))\n");

                            // we have an arc/track on a copper layer and it has a net
                            // these aren't supported by KiCad yet so generate a curve out of track segments
                            // first normalise it so that the centre is at 0,0
                            // save the centre point
                            double XC = X1;
                            double YC = Y1;

                            X = X - XC;
                            Y = Y - YC;

                            double radius = Math.Sqrt(X * X + Y * Y);
                            // start angle in radians
                            double start_angle = Arc.Radians(StartAngle);
                            double end_angle   = Arc.Radians(EndAngle);
                            double X2          = Radius * Math.Cos(end_angle);
                            double Y2          = Radius * Math.Sin(end_angle);
                            X = Radius * Math.Cos(start_angle);
                            Y = Radius * Math.Sin(start_angle);

                            // generate arc segments at 5° increments
                            for (double angle = start_angle; angle < end_angle; angle += 2 * Math.PI / 72)
                            {
                                X1 = Radius * Math.Cos(angle);
                                Y1 = Radius * Math.Sin(angle);
                                Line Line = new Line(XC + X, YC + Y, XC + X1, YC + Y1, layer, Width, net);
                                LinesL.Add(Line);
                                X = X1;
                                Y = Y1;
                            }
                            // do last segment
                            if (X != X2 || Y != Y2)
                            {
                                Line Line = new Line(X + XC, Y + YC, X2 + XC, Y2 + YC, layer, Width, net);
                                LinesL.Add(Line);
                            }
                        }
                    }
                    else
                    {
                        // only add if not part of board outline
                        if ((layer != "Edge.Cuts") || !Brd.CheckExistingArc(X1, Y1, X, Y, Angle))
                        {
                            List <string> Layers = Brd.GetLayers(layer);
                            foreach (var L in Layers)
                            {
                                Arc Arc = new Arc(X1, Y1, StartAngle, EndAngle, Radius, Brd.GetAltiumLayer(L), Width);
                                ArcsL.Add(Arc);
                            }
                        }
                    }
                }
                else
                {
                    Arc Arc = new Arc(X1, Y1, StartAngle, EndAngle, Radius, Layer, Width);
                    ModulesL[Component].Arcs.Add(Arc);
                }
                return(true);
            }
示例#3
0
            public override bool ProcessBinaryFile(byte[] data)
            {
                bool       GenerateTxtFile = true; // set to true to generate text version of the file
                FileStream TextFile        = null;

                StartTimer();
                if (Binary_size == 0)
                {
                    return(false);
                }

                if (GenerateTxtFile)
                {
                    if (ExtractFiles)
                    {
                        TextFile = File.Open("Data.txt", FileMode.OpenOrCreate);
                    }
                }
                try
                {
                    using (MemoryStream ms = new MemoryStream(data))
                    {
                        UInt32 pos  = 0;
                        uint   size = (uint)ms.Length;

                        BinaryReader br = new BinaryReader(ms, System.Text.Encoding.UTF8);
                        ms.Seek(pos, SeekOrigin.Begin);
                        List <UInt32> Starts = new List <UInt32>();
                        // look for record starts
                        {
                            Stopwatch timer = new Stopwatch();
                            timer.Start();
                            // signature is
                            // byte 02
                            // int32 length
                            // byte strlen = length - 1
                            // string strlen ascci chars
                            // bytes 01 00 00 00
                            while (pos < size)
                            {
                                ms.Seek(pos, SeekOrigin.Begin);
                                byte recordtype = br.ReadByte(); // should be 2
                                if (recordtype == 2)
                                {
                                    // possible start
                                    UInt32 nextnamelength = br.ReadUInt32();
                                    if (nextnamelength < 256)
                                    {
                                        uint l = br.ReadByte(); // string length
                                        if (l == nextnamelength - 1)
                                        {
                                            // everything ok so far
                                            // now check bytes in string are ASCII
                                            bool found = true;
                                            for (int i = 0; i < l; i++)
                                            {
                                                byte c = br.ReadByte();
                                                if (c < 0x20 || c > 0x7F)
                                                {
                                                    found = false;
                                                }
                                            }
                                            if (br.ReadByte() != 1)
                                            {
                                                found = false;
                                            }
                                            if (br.ReadByte() != 0)
                                            {
                                                found = false;
                                            }
                                            if (br.ReadByte() != 0)
                                            {
                                                found = false;
                                            }
                                            if (br.ReadByte() != 0)
                                            {
                                                found = false;
                                            }
                                            if (br.ReadByte() != 0)
                                            {
                                                found = false;
                                            }
                                            if (found)
                                            {
                                                // OutputString($"Found header at {pos:x08}");
                                                Starts.Add(pos);
                                            }
                                        }
                                    }
                                }
                                pos = pos + 1;
                            }
                        }
                        pos = 0;
                        int    index = -1;
                        Int16  Component;
                        byte[] r = br.ReadBytes(2);

                        try
                        {
                            UInt32 Longest = 0;
                            UInt32 len;
                            // find the length of the logest pad record
                            foreach (var p in Starts)
                            {
                                index++;
                                if (index < Starts.Count - 1)
                                {
                                    len = Starts[index + 1] - Starts[index];
                                }
                                else
                                {
                                    len = size - Starts[index];
                                }
                                if (len > Longest)
                                {
                                    Longest = len;
                                }
                            }
                            index = -1;
                            if (GenerateTxtFile && ExtractFiles)
                            {
                                AddText(TextFile, $"Altium Version {VersionString}\n");
                                // generate headers for .txt file
                                string Header1 = "Pos                 ";
                                for (int i = 0; i < Longest; i++)
                                {
                                    Header1 += $"{(i / 100),-3:D2}";
                                }
                                string Header2 = "                    ";
                                for (int i = 0; i < Longest; i++)
                                {
                                    Header2 += $"{(i % 100),-3:D2}";
                                }
                                string Header3 = "--------------------";
                                for (int i = 0; i < Longest; i++)
                                {
                                    Header3 += $"---";
                                }
                                if (ExtractFiles)
                                {
                                    AddText(TextFile, Header1 + "\n");
                                    AddText(TextFile, Header2 + "\n");
                                    AddText(TextFile, Header3 + "\n");
                                }
                            }
                            foreach (var p in Starts)
                            {
                                pos = p;
                                //OutputString($"Processing pad record at {pos:x08}");
                                index++;
                                base.ProcessLine();
                                ms.Seek(p, SeekOrigin.Begin);
                                byte   recordtype = br.ReadByte(); // should be 2
                                UInt32 next       = br.ReadUInt32();
                                uint   l          = br.ReadByte(); // string length
                                                                   //pos =  (uint)ms.Position;
                                string name;
                                if (l != 0)
                                {
                                    name = new string(br.ReadChars((int)l));
                                }
                                else
                                {
                                    name = "";
                                }
                                pos = (uint)ms.Position;
                                // find out how many bytes to read
                                if (index < Starts.Count - 1)
                                {
                                    len = Starts[index + 1] - Starts[index];
                                }
                                else
                                {
                                    len = size - Starts[index];
                                }

                                // we are now pointing to the pad record
                                //
                                Layers Layer;
                                byte   shape;
                                bool   plated;
                                double X, Y, XSize, YSize, HoleSize; //, MIDXSize, MIDYSize, BottomXSize, BottomYSize;
                                double Rotation = 0;
                                double RRatio   = 0;
                                Int16  Net;
                                Int16  JumperID;
                                byte[] bytes = br.ReadBytes((int)len - 6); // get record after header stuff

                                if (GenerateTxtFile)
                                {
                                    if (p == 0)
                                    {
                                        r = bytes; // get reference bytes
                                    }
                                    StringBuilder text         = new StringBuilder("");
                                    int           count        = 0;
                                    int           CompareLimit = Math.Min(r.Length, bytes.Length);
                                    foreach (var c in bytes)
                                    {
                                        if (count < CompareLimit && r[count] != bytes[count])
                                        {
                                            text.Append($"|{c:X2}");
                                        }
                                        else
                                        {
                                            text.Append($" {c:X2}");
                                        }
                                        count++;
                                    }
                                    if (ExtractFiles)
                                    {
                                        AddText(TextFile, $"{pos:X8} " + $"{len - name.Length,4} {name,4} {text.ToString()}\n");
                                    }
                                }
                                PadStruct pad = ByteArrayToStructure <PadStruct>(bytes);
                                ms.Seek(pos + pad.Offset, SeekOrigin.Begin);
                                int LayersSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(PadLayers));

                                byte[]    layerbytes = br.ReadBytes(LayersSize); // get layers data
                                PadLayers PadLayers  = ByteArrayToStructure <PadLayers>(layerbytes);
                                Layer = (Layers)pad.Layer;
                                Net   = pad.Net;
                                Net++;
                                string n = NetsL[Net].Name;
                                Component = pad.Component;
                                if (Component != -1 && Component != 0)
                                {
                                    X = 0;
                                }
                                X        = ToMM(pad.X) - originX;
                                Y        = ToMM(pad.Y) - originY;
                                XSize    = ToMM(pad.XSize);
                                YSize    = ToMM(pad.YSize);
                                HoleSize = ToMM(pad.HoleSize);
                                unsafe
                                {
                                    shape = pad.TopShape;
                                    if (len > 160 && shape == 1) // TODO this can't be right
                                    {
                                        shape  = PadLayers.PadShapes[0];
                                        RRatio = (double)PadLayers.RRatios[0] / 200;
                                    }
                                    else
                                    {
                                        RRatio = 0;
                                    }
                                }
                                if (shape > 5)
                                {
                                    shape = 5;
                                }
                                string[] shapes = { "circle", "circle", "rect", "octagonal", "oval", "roundrect" };
                                if (shapes[shape] == "circle" && XSize != YSize)
                                {
                                    shape = 4; // oval pad
                                }
                                Rotation = pad.Rotation;
                                plated   = pad.Plated != 0;
                                JumperID = pad.JumperID;
                                bool InComponent = Component != -1;

                                string type;
                                if (Layer == Layers.Multi_Layer)
                                {
                                    if (plated)
                                    {
                                        type = "thru_hole";
                                    }
                                    else
                                    {
                                        type = "np_thru_hole";
                                        //    name = "\"\"";
                                    }
                                    if (HoleSize < 0.01)
                                    {
                                        OutputError($"Zero size hole through hole pad at {X} {Y}");
                                    }
                                }
                                else
                                {
                                    type = "smd";
                                }
                                string layer = Brd.GetLayer(Layer);
                                if (!Brd.IsCopperLayer(Layer))
                                {
                                    OutputError($"Pad on non copper layer = {Layer} at {X} {-Y}");
                                    // TODO generate circular polygon instead
                                    continue;
                                }
                                if (layer == "Margin") // TODO sort this keepout layer malarky
                                {
                                    layer = "Dwgs.User";
                                }
                                if (type == "smd")
                                {
                                    layer += layer == "F.Cu" ? " F.Mask F.Paste" : (layer == "B.Cu") ? " B.Mask B.Paste" : "";
                                }
                                else
                                {
                                    layer += " *.Mask";
                                }

                                if (XSize < HoleSize | YSize < HoleSize)
                                {
                                    XSize = YSize = HoleSize;
                                }

                                Pad Pad = new Pad(name, type, shapes[shape], X, Y, Rotation, XSize, YSize, HoleSize, layer, Net, RRatio)
                                {
                                    Component = Component
                                };
                                if (pad.UsePasteMaskRules == 1)
                                {
                                    Pad.PasteMaskExpansion = GetRuleValue(Pad, "PasteMaskExpansion", "PasteMaskExpansion");
                                }
                                else
                                {
                                    Pad.PasteMaskExpansion = ToMM(pad.PasteMaskExpansion);
                                }
                                if (pad.UseSolderMaskRules == 1)
                                {
                                    Pad.SolderMaskExpansion = GetRuleValue(Pad, "SolderMaskExpansion", "SolderMaskExpansion");
                                }
                                else
                                {
                                    Pad.SolderMaskExpansion = ToMM(pad.SolderMaskExpansion);
                                }


                                if (!InComponent)
                                {
                                    PadsL.Add(Pad);
                                    // free pads not allowed (at present) in PcbNew so generate a single pad module
                                    Module M = new Module($"FreePad{ModulesL.Count}", X, Y, XSize, YSize, Pad);
                                    ModulesL.Add(M);
                                }
                                else
                                {
                                    try
                                    {
                                        ModulesL[Component].Pads.Add(Pad);
                                    }
                                    catch (Exception Ex)
                                    {
                                        CheckThreadAbort(Ex, $"At position {pos} in Pads file");
                                    }
                                }
                            }
                        }
                        catch (Exception Ex)
                        {
                            CheckThreadAbort(Ex);
                        }
                        if (GenerateTxtFile && TextFile != null)
                        {
                            TextFile.Close();
                        }
                    }
                }
                catch (Exception Ex)
                {
                    CheckThreadAbort(Ex);
                }

                return(true);
            }