/// <summary>
        /// Get layer name
        /// </summary>
        /// <param name="layer">Supported: Drill, Bottom, Top, All, InternalTop, InternalBottom</param>
        /// <returns>Layer name</returns>
        public string this[PcbLayer layer]
        {
            get
            {
                switch (layer)
                {
                case PcbLayer.Drill:
                    return("DRL");

                case PcbLayer.Bottom:
                    return("BOT");

                case PcbLayer.Top:
                    return("TOP");

                case PcbLayer.InternalTop:
                    return("I1");

                case PcbLayer.InternalBottom:
                    return("I2");

                case PcbLayer.All:
                    return("ALL");

                default:
                    throw new ArgumentException("Bad layer.");
                }
            }
        }
 public PcbTrace(PcbLayer layer, double thickness, PcbUnits units, PcbUnits coordinateUnits, List <Point> points)
 {
     XY              = points;
     Layer           = layer;
     Units           = units;
     CoordinateUnits = coordinateUnits;
     Thickness       = thickness;
 }
 public PcbPad(string number, PcbUnits coordinateUnits, double x, double y,
               PcbLayer layer, PcbPadStyle style, string flags = null)
 {
     Number          = number;
     CoordinateUnits = coordinateUnits;
     X     = x;
     Y     = y;
     Layer = layer;
     Style = style;
     Flags = flags;
 }
        /// <summary>
        /// Gets objects that belong to the specified layer.
        /// </summary>
        /// <param name="layer"></param>
        /// <param name="tracesOnly">True = get only traces; False = get everything.</param>
        /// <returns></returns>
        public List <IPcbObject> GetObjectsFromLayer(PcbLayer layer, bool tracesOnly = false)
        {
            List <IPcbObject> res = new List <IPcbObject>(Pads.Count + Traces.Count);

            if (!tracesOnly)
            {
                foreach (var item in Pads)
                {
                    if (item.Layer == layer)
                    {
                        res.Add(item);
                    }
                }
            }
            foreach (var item in Traces)
            {
                if (item.Layer == layer)
                {
                    res.Add(item);
                }
            }
            return(res);
        }
        private static void ProcessDecalPads(PcbDesign res,PcbUnits coordinateUnits,Partdecal decal)
        {
            //Terminals + padstacks = pads
            PadStack defaultStack = decal.PadStacks.FirstOrDefault(x => x.PinDesignator == PadStack.AllTerminalsDesignator);

            res.Pads.Capacity += decal.Terminals.Count;
            foreach (var item in decal.Terminals)
            {
                var padstack = FindSuitablePadstack(decal,item,defaultStack);
                if (padstack == null)
                {
                    WarningListener.Add(new ArgumentException(),"Can't find a suitable padstack for the terminal #" + item.PinDesignator);
                    continue;
                }
                var drillLine = padstack.StackLines.FirstOrDefault(x => x.Arguments[(int)PadStack.StackLine.DependentArguments.DrillSize].Present);
                if (drillLine != null)
                {
                    //Detect drill-only holes
                    double d = (double)drillLine.Arguments[(int)PadStack.StackLine.DependentArguments.DrillSize].Value;
                    if (d >= drillLine.Size)
                    {
                        res.Pads.Add(new PcbPad(item.PinDesignator,coordinateUnits,item.X,item.Y,PcbLayer.Drill,
                                                new PcbPadStyle(PcbPadShape.CircularTH,coordinateUnits,d,0,d)));
                        continue;
                    }
                }
                List <PadStack.StackLine> usefulLines =
                    padstack.StackLines.Where(x => (x.Size != 0 || x.Arguments.Any(y => y.Present))).ToList();
                if (usefulLines.Count == 3)   //Recognize layer "ALL"
                {
                    //PADS requires minimum of 3 layers specified, 0x0 size indicates that the pad is not actually present
                    //If some stacklines have 0 size and no useful arguments (shape does not count), then we effectively have less stacklines
                    if (usefulLines.Select(x => x.Layer).Union(PadStack.AllLayerPattern).Count() == 3)
                    {
                        //Find layer that contains the most arguments (drill for example appears only for component-side layer)
                        int maxArgs = 0;
                        for (int i = 1; i < usefulLines.Count; i++)
                        {
                            if (usefulLines[maxArgs].Arguments.Count(x => x.Present) <
                                usefulLines[i].Arguments.Count(x => x.Present))
                            {
                                maxArgs = i;
                            }
                        }
                        res.Pads.Add(new PcbPad(item.PinDesignator,coordinateUnits,item.X,item.Y,PcbLayer.All,
                                                DeterminePadStyle(usefulLines[maxArgs],coordinateUnits)));
                        continue;
                    }
                }
                //If this is not a special case, parse stacklines one-by-one
                foreach (var line in usefulLines)
                {
                    PcbPadStyle style = DeterminePadStyle(line,coordinateUnits);
                    PcbLayer    layer = DeterminePcbLayer(line);
                    res.Pads.Add(new PcbPad(item.PinDesignator,coordinateUnits,item.X,item.Y,layer,style));
                    //-1 stands for both "Internal layers", but we can return only a single layer, so fix it afterwards
                    if (layer == PcbLayer.InternalBottom)
                    {
                        res.Pads.Add(new PcbPad(item.PinDesignator,coordinateUnits,item.X,item.Y,
                                                PcbLayer.InternalTop,style));
                    }
                }
            }
        }
 public PcbTrace(PcbLayer layer, double thickness, PcbUnits units, PcbUnits coordinateUnits, int capacity = 4)
     : this(layer, thickness, units, coordinateUnits, new List <Point>(capacity))
 {
 }