Example #1
0
        public GerberNet(GerberImage gerberImage, GerberNet currentNet, GerberLevel level, GerberNetState netState)
        {
            if (level != null)
            {
                Level = level;
            }

            else
            {
                Level = currentNet.Level;
            }

            if (netState != null)
            {
                NetState = netState;
            }

            else
            {
                NetState = currentNet.NetState;
            }

            Label = String.Empty;
            //IsSelected = false;
            gerberImage.GerberNetList.Add(this);
        }
Example #2
0
        }                                                            // Excellon drill statistics for the layer.

        // Constructor
        public GerberImage(string fileTypeName)
        {
            ImageInfo      = new GerberImageInfo();
            ImageInfo.MinX = double.MaxValue;
            ImageInfo.MinY = double.MaxValue;
            ImageInfo.MaxX = double.MinValue;
            ImageInfo.MaxY = double.MinValue;
            if (string.IsNullOrEmpty(fileTypeName))
            {
                ImageInfo.FileTypeName = "Unknown";
            }

            else
            {
                ImageInfo.FileTypeName = fileTypeName;
            }

            // The individual file parsers will have to set this.
            ImageInfo.AttributeList     = null;
            ImageInfo.NumberOfAttribute = 0;
            apertureMacroList           = new Collection <ApertureMacro>();
            ApertureArray = new ApertureDefinition[Gerber.MaximumApertures];
            LevelList     = new List <GerberLevel>();
            NetStateList  = new List <GerberNetState>();
            Format        = new GerberFormat();
            gerberNetList = new Collection <GerberNet>();
            GerberStats   = new GerberFileStats();
            DrillStats    = new DrillFileStats();
            GerberNet gerberNet = new GerberNet();          // Create first gerberNet and fill in some initial values.

            gerberNet.Level    = new GerberLevel(this);     // Create our first level and fill with some default values.
            gerberNet.NetState = new GerberNetState(this);  // Create our first netState.
            gerberNet.Label    = String.Empty;
            GerberNetList.Add(gerberNet);
        }
Example #3
0
        // Test if the net is already selected.

        /*private bool ObjectInSelectionBuffer(GerberNet gerberNet, SelectionInformation selectionInfo)
         * {
         *  foreach (GerberNet net in selectionInfo.SelectedNetList)
         *  {
         *      if (net == gerberNet)
         *          return true;
         *  }
         *
         *  return false;
         * }*/

        private RectangleF BoundingBoxToRectangle(GerberNet net)
        {
            float sx     = (float)net.BoundingBox.Left;
            float sy     = (float)net.BoundingBox.Top;
            float width  = (float)(net.BoundingBox.Right - net.BoundingBox.Left);
            float height = (float)(net.BoundingBox.Top - net.BoundingBox.Bottom);

            rect = new RectangleF(sx, sy, width, height);
            return(rect);
        }
Example #4
0
        // Finds the next renderable object in the net list.
        private static void GetNextRenderObject(Collection <GerberNet> gerberNetList, ref int currentIndex)
        {
            GerberNet currentNet = gerberNetList[currentIndex];

            if (currentNet.Interpolation == GerberInterpolation.PolygonAreaStart)
            {
                // If it's a polygon, step to the next non-polygon net.
                for (; currentIndex < gerberNetList.Count; currentIndex++)
                {
                    currentNet = gerberNetList[currentIndex];
                    if (currentNet.Interpolation == GerberInterpolation.PolygonAreaEnd)
                    {
                        break;
                    }
                }

                currentIndex++;
                return;
            }

            currentIndex++;
        }
Example #5
0
        static GerberNet AddDrillHole(GerberImage image, DrillState drillState, GerberNet currentNet)
        {
            image.DrillStats.IncrementDrillCounter(drillState.CurrentTool);
            GerberNet newDrillNet = new GerberNet(image, currentNet, null, null);

            newDrillNet.BoundingBox = new BoundingBox();
            newDrillNet.StartX      = drillState.CurrentX;
            newDrillNet.StartY      = drillState.CurrentY;
            if (drillState.Unit == GerberUnit.Millimeter)
            {
                newDrillNet.StartX       /= 25.4;
                newDrillNet.StartY       /= 25.4;
                newDrillNet.NetState.Unit = GerberUnit.Inch;
            }

            newDrillNet.StopX         = newDrillNet.StartX - drillState.OriginX;
            newDrillNet.StopY         = newDrillNet.StartY - drillState.OriginY;
            newDrillNet.Aperture      = drillState.CurrentTool;
            newDrillNet.ApertureState = GerberApertureState.Flash;

            // Check if the aperture is set.
            if (image.ApertureArray[drillState.CurrentTool] == null)
            {
                return(newDrillNet);
            }

            newDrillNet.BoundingBox.Left   = newDrillNet.StartX - image.ApertureArray[drillState.CurrentTool].Parameters[0] / 2;
            newDrillNet.BoundingBox.Right  = newDrillNet.StartX + image.ApertureArray[drillState.CurrentTool].Parameters[0] / 2;
            newDrillNet.BoundingBox.Bottom = newDrillNet.StartY - image.ApertureArray[drillState.CurrentTool].Parameters[0] / 2;
            newDrillNet.BoundingBox.Top    = newDrillNet.StartY + image.ApertureArray[drillState.CurrentTool].Parameters[0] / 2;

            image.ImageInfo.MinX = Math.Min(image.ImageInfo.MinX, (newDrillNet.StartX - image.ApertureArray[drillState.CurrentTool].Parameters[0] / 2));
            image.ImageInfo.MinY = Math.Min(image.ImageInfo.MinY, (newDrillNet.StartY - image.ApertureArray[drillState.CurrentTool].Parameters[0] / 2));
            image.ImageInfo.MaxX = Math.Max(image.ImageInfo.MaxX, (newDrillNet.StartX + image.ApertureArray[drillState.CurrentTool].Parameters[0] / 2));
            image.ImageInfo.MaxY = Math.Max(image.ImageInfo.MaxY, (newDrillNet.StartY + image.ApertureArray[drillState.CurrentTool].Parameters[0] / 2));

            return(newDrillNet);
        }
Example #6
0
        static bool ParseDrillSegment(string drillFileName, GerberLineReader lineReader, GerberImage image, DrillState drillState)
        {
            bool           foundEOF   = false;
            DrillFileStats stats      = image.DrillStats;
            GerberNet      currentNet = image.GerberNetList[0];

            currentNet.Level    = image.LevelList[0];
            currentNet.NetState = image.NetStateList[0];

            bool   done = false;
            string line;

            string[] command;
            string   errorMessage;
            char     nextCharacter;

            while (!lineReader.EndOfFile && !foundEOF)
            {
                nextCharacter = lineReader.Read();
                switch (nextCharacter)
                {
                case ';':       // Comment.
                    line = lineReader.ReadLineToEnd();
                    break;

                case 'D':
                    lineReader.Position--;
                    line = lineReader.ReadLineToEnd();
                    if (line.Substring(0, 6) == "DETECT")
                    {
                        stats.Detect = line.Substring(6, (line.Length - 7));
                    }

                    else
                    {
                        errorMessage = String.Format(CultureInfo.CurrentCulture, "Undefined header line: {0}.\n", line);
                        stats.AddNewError(-1, errorMessage, GerberErrorType.GerberNote, lineReader.LineNumber, drillFileName);
                    }
                    break;

                case 'F':
                    lineReader.Position--;
                    line = lineReader.ReadLineToEnd();
                    if (line != "FMAT,2")
                    {
                        errorMessage = String.Format(CultureInfo.CurrentCulture, "Undefined header line: {0}.\n", line);
                        stats.AddNewError(-1, errorMessage, GerberErrorType.GerberNote, lineReader.LineNumber, drillFileName);
                    }
                    break;

                case 'G':
                    DrillGCode gCode = ParseGCode(lineReader, image);
                    switch (gCode)
                    {
                    case DrillGCode.Rout:
                        errorMessage = "Rout Mode not supported.\n";
                        stats.AddNewError(-1, errorMessage, GerberErrorType.GerberNote, lineReader.LineNumber, drillFileName);
                        break;

                    case DrillGCode.Drill:
                        break;

                    case DrillGCode.Slot:
                        nextCharacter = lineReader.Read();
                        ParseCoordinate(lineReader, nextCharacter, image, drillState);
                        currentNet.StopX = drillState.CurrentX;
                        currentNet.StopY = drillState.CurrentY;
                        if (drillState.Unit == GerberUnit.Millimeter)
                        {
                            currentNet.StopX /= 25.4;
                            currentNet.StopY /= 25.4;
                        }

                        currentNet.ApertureState = GerberApertureState.On;
                        break;

                    case DrillGCode.Absolute:
                        drillState.CoordinateMode = DrillCoordinateMode.Absolute;
                        break;

                    case DrillGCode.Incrementle:
                        drillState.CoordinateMode = DrillCoordinateMode.Incremental;
                        break;

                    case DrillGCode.ZeroSet:
                        nextCharacter = lineReader.Read();
                        ParseCoordinate(lineReader, nextCharacter, image, drillState);
                        drillState.OriginX = drillState.CurrentX;
                        drillState.OriginY = drillState.CurrentY;
                        break;

                    default:
                        line = lineReader.ReadLineToEnd();
                        break;
                    }

                    break;

                case 'I':       // Inch header.
                    if (drillState.CurrentSection != DrillFileSection.Header)
                    {
                        break;
                    }

                    nextCharacter = lineReader.Read();
                    switch (nextCharacter)
                    {
                    // Inch
                    case 'N':
                        lineReader.Position -= 2;
                        line    = lineReader.ReadLineToEnd();
                        command = line.Split(',');
                        if (command[0] == "INCH")
                        {
                            drillState.Unit = GerberUnit.Inch;
                        }

                        if (command.Length == 2)
                        {
                            if (command[1] == "TZ")
                            {
                                if (drillState.AutoDetect)
                                {
                                    image.Format.OmitZeros        = GerberOmitZero.OmitZerosLeading;
                                    drillState.HeaderNumberFormat = DrillNumberFormat.Format_00_0000;
                                    drillState.DecimalPlaces      = 4;
                                }
                            }

                            else if (command[1] == "LZ")
                            {
                                image.Format.OmitZeros        = GerberOmitZero.OmitZerosTrailing;
                                drillState.HeaderNumberFormat = DrillNumberFormat.Format_00_0000;
                                drillState.DecimalPlaces      = 4;
                            }

                            else
                            {
                                errorMessage = "Invalid zero suppression found after INCH.\n";
                                stats.AddNewError(-1, errorMessage, GerberErrorType.GerberWarning, lineReader.LineNumber, drillFileName);
                            }
                        }

                        else
                        {
                            // No TZ/LZ specified, use defaults.
                            if (drillState.AutoDetect)
                            {
                                image.Format.OmitZeros        = GerberOmitZero.OmitZerosLeading;
                                drillState.HeaderNumberFormat = DrillNumberFormat.Format_00_0000;
                                drillState.DecimalPlaces      = 4;
                            }
                        }

                        break;

                    case 'C':
                        lineReader.Position -= 2;
                        line    = lineReader.ReadLineToEnd();
                        command = line.Split(',');
                        if (command.Length == 2)
                        {
                            if (command[1] == "ON")
                            {
                                drillState.CoordinateMode = DrillCoordinateMode.Incremental;
                            }

                            else if (command[1] == "OFF")
                            {
                                drillState.CoordinateMode = DrillCoordinateMode.Absolute;
                            }

                            else
                            {
                                errorMessage = "Invalid coordinate data found.\n";
                                stats.AddNewError(-1, errorMessage, GerberErrorType.GerberWarning, lineReader.LineNumber, drillFileName);
                            }
                        }

                        else
                        {
                            errorMessage = "Invalid data found.\n";
                            stats.AddNewError(-1, errorMessage, GerberErrorType.GerberWarning, lineReader.LineNumber, drillFileName);
                        }

                        break;
                    }

                    break;

                case 'M':                             // M code or Metric
                    nextCharacter = lineReader.Read();
                    if (!Char.IsDigit(nextCharacter)) // Not a M## command.
                    {
                        // Should be a metric command in header.
                        // METRIC is only acceptable within the header section.
                        // The syntax is METRIC[,{TZ|LZ}][,{000.000|000.00|0000.00}] ??????
                        if (drillState.CurrentSection != DrillFileSection.Header)
                        {
                            break;
                        }

                        done = true;
                        lineReader.Position -= 2;       // Point back to the start on the line.
                        line    = lineReader.ReadLineToEnd();
                        command = line.Split(',');
                        if (command[0] == "METRIC")
                        {
                            drillState.Unit = GerberUnit.Millimeter;
                        }

                        if (command.Length > 1)
                        {
                            if (command[1] == "TZ")
                            {
                                if (drillState.AutoDetect)
                                {
                                    image.Format.OmitZeros = GerberOmitZero.OmitZerosLeading;
                                }

                                done = false;
                            }

                            else if (command[1] == "LZ")
                            {
                                if (drillState.AutoDetect)
                                {
                                    image.Format.OmitZeros = GerberOmitZero.OmitZerosTrailing;
                                }

                                done = false;
                            }

                            else
                            {
                                errorMessage = "Invalid zero suppression found after METRIC.\n";
                                stats.AddNewError(-1, errorMessage, GerberErrorType.GerberWarning, lineReader.LineNumber, drillFileName);
                                done = true;
                            }

                            // Number format may or may not be specified.
                            if (!done && command.Length == 3)
                            {
                                if (drillState.AutoDetect)
                                {
                                    drillState.HeaderNumberFormat = drillState.DataNumberFormat = DrillNumberFormat.Format_000_000;
                                    drillState.DecimalPlaces      = 3;
                                }

                                if (command[2] == "0000.00")
                                {
                                    drillState.DataNumberFormat = DrillNumberFormat.Format_0000_00;
                                    drillState.DecimalPlaces    = 2;
                                }

                                else if (command[2] == "000.000")
                                {
                                    drillState.DataNumberFormat = DrillNumberFormat.Format_000_000;
                                    drillState.DecimalPlaces    = 3;
                                }

                                else if (command[2] == "000.00")
                                {
                                    drillState.DataNumberFormat = DrillNumberFormat.Format_000_00;
                                    drillState.DecimalPlaces    = 2;
                                }

                                else
                                {
                                    errorMessage = "Invalid number format found after TZ/LZ.\n";
                                    stats.AddNewError(-1, errorMessage, GerberErrorType.GerberWarning, lineReader.LineNumber, drillFileName);
                                }
                            }
                        }

                        else
                        {
                            // No TZ/LZ or number format specified, use defaults.
                            if (drillState.AutoDetect)
                            {
                                image.Format.OmitZeros        = GerberOmitZero.OmitZerosLeading;
                                drillState.HeaderNumberFormat = DrillNumberFormat.Format_000_000;
                                drillState.DecimalPlaces      = 3;
                            }
                        }
                    }

                    else if (Char.IsDigit(nextCharacter))
                    {
                        // Must be an M## code.
                        lineReader.Position--;
                        DrillMCode mCode = ParseMCode(lineReader, drillState, image);
                        switch (mCode)
                        {
                        case DrillMCode.Header:
                            drillState.CurrentSection = DrillFileSection.Header;
                            break;

                        case DrillMCode.EndHeader:
                            drillState.CurrentSection = DrillFileSection.Data;
                            break;

                        case DrillMCode.Metric:
                            if (drillState.Unit == GerberUnit.Unspecified && drillState.CurrentSection != DrillFileSection.Header)
                            {
                                errorMessage = "M71 code found with no METRIC specification in header.\n";
                                stats.AddNewError(-1, errorMessage, GerberErrorType.GerberError, lineReader.LineNumber, drillFileName);

                                errorMessage = "Assuming all tool sizes are in millimeters.\n";
                                stats.AddNewError(-1, errorMessage, GerberErrorType.GerberWarning);


                                for (int toolNumber = ToolMin; toolNumber < ToolMax; toolNumber++)
                                {
                                    if (image.ApertureArray[toolNumber] != null)
                                    {
                                        double toolSize = image.ApertureArray[toolNumber].Parameters[0];
                                        stats.ModifyDrillList(toolNumber, toolSize, "MM");
                                        image.ApertureArray[toolNumber].Parameters[0] /= 25.4;
                                    }
                                }
                            }

                            if (drillState.AutoDetect)
                            {
                                drillState.DataNumberFormat = drillState.BackupNumberFormat;
                                drillState.Unit             = GerberUnit.Millimeter;
                            }

                            break;

                        case DrillMCode.Imperial:
                            if (drillState.AutoDetect)
                            {
                                if (drillState.DataNumberFormat != DrillNumberFormat.Format_00_0000)
                                {
                                    drillState.BackupNumberFormat = drillState.DataNumberFormat;            // Save format definition for later.
                                }
                                drillState.DataNumberFormat = DrillNumberFormat.Format_00_0000;
                                drillState.DecimalPlaces    = 4;
                                drillState.Unit             = GerberUnit.Inch;
                            }
                            break;

                        case DrillMCode.LongMessage:
                        case DrillMCode.Message:
                        case DrillMCode.CannedText:
                            line = lineReader.ReadLineToEnd();
                            // message here.
                            break;

                        case DrillMCode.NotImplemented:
                        case DrillMCode.EndPattern:
                        case DrillMCode.TipCheck:
                            break;

                        case DrillMCode.End:
                            line = lineReader.ReadLineToEnd();
                            break;

                        case DrillMCode.EndRewind:          // EOF.
                            //done = true;
                            foundEOF = true;
                            break;

                        default:
                            stats.AddNewError(-1, "Undefined M code.", GerberErrorType.GerberError, lineReader.LineNumber, drillFileName);
                            break;
                        }
                    }
                    break;

                case 'R':
                    if (drillState.CurrentSection == DrillFileSection.Header)
                    {
                        stats.AddNewError(-1, "R code not allowed in the header.", GerberErrorType.GerberError, lineReader.LineNumber, drillFileName);
                    }

                    else
                    {
                        double stepX = 0.0, stepY = 0.0;
                        int    length = 0;

                        image.DrillStats.R++;
                        double startX      = drillState.CurrentX;
                        double startY      = drillState.CurrentY;
                        int    repeatcount = lineReader.GetIntegerValue(ref length);
                        nextCharacter = lineReader.Read();
                        if (nextCharacter == 'X')
                        {
                            stepX         = GetDoubleValue(lineReader, drillState.DataNumberFormat, image.Format.OmitZeros, drillState.DecimalPlaces);
                            nextCharacter = lineReader.Read();
                        }

                        if (nextCharacter == 'Y')
                        {
                            stepY = GetDoubleValue(lineReader, drillState.DataNumberFormat, image.Format.OmitZeros, drillState.DecimalPlaces);
                        }

                        else
                        {
                            lineReader.Position--;
                        }

                        for (int i = 1; i < repeatcount; i++)
                        {
                            drillState.CurrentX = startX + i * stepX;
                            drillState.CurrentY = startY + i * stepY;
                            currentNet          = AddDrillHole(image, drillState, currentNet);
                        }
                    }
                    break;

                case 'S':
                    // Ignore spindle speed.
                    lineReader.ReadLineToEnd();
                    break;

                case 'T':
                    int tool = ParseTCode(lineReader, drillFileName, drillState, image);
                    break;

                case 'X':
                case 'Y':
                    // Hole coordinate found. Do some parsing.
                    ParseCoordinate(lineReader, nextCharacter, image, drillState);

                    // Add the new drill hole.
                    currentNet = AddDrillHole(image, drillState, currentNet);
                    break;

                case '%':
                    drillState.CurrentSection = DrillFileSection.Data;
                    break;

                // Ignore white space or null characters.
                case '\n':
                case '\r':
                case ' ':
                case '\t':
                case '\0':
                    break;
                }
            }

            return(foundEOF);
        }
Example #7
0
        /// <summary>
        /// Adds a gerber object to the selection buffer if it lies within the selection region.
        /// </summary>
        /// <param name="selectionInfo">current selection info</param>
        /// <param name="image">gerber image containing the net</param>
        /// <param name="net">net to add to the selection info</param>
        public void ObjectInSelectedRegion(SelectionInformation selectionInfo, ref int i, Graphics graphics)
        {
            bool        inSelect = false;
            GerberImage image    = selectionInfo.SelectionImage;
            GerberNet   net      = image.GerberNetList[i];
            float       x1       = (float)selectionInfo.LowerLeftX;
            float       y1       = (float)selectionInfo.LowerLeftY;
            float       x2       = (float)selectionInfo.UpperRightX;
            float       y2       = (float)selectionInfo.UpperRightY;

            if (selectionInfo.SelectionType == GerberSelection.PointClick)
            {
                if (net.BoundingBox != null)
                {
                    if (!net.BoundingBox.Contains(new PointD(x1, y1)))
                    {
                        return;
                    }

                    if (net.ApertureState == GerberApertureState.Flash)
                    {
                        inSelect = net.BoundingBox.Contains(new PointD(x1, y1));
                    }

                    else if (net.ApertureState == GerberApertureState.On)
                    {
                        switch (net.Interpolation)
                        {
                        case GerberInterpolation.PolygonAreaStart:
                            inSelect = net.BoundingBox.Contains(new PointD(x1, y1));
                            break;

                        case GerberInterpolation.LinearX10:
                        case GerberInterpolation.LinearX1:
                        case GerberInterpolation.LinearX01:
                        case GerberInterpolation.LinearX001:
                            using (GraphicsPath gp = new GraphicsPath())
                                using (Pen pen = new Pen(Color.Transparent))
                                {
                                    pen.Width    = (float)image.ApertureArray[net.Aperture].Parameters[0];
                                    pen.StartCap = pen.EndCap = LineCap.Round;
                                    PointF start = new PointF((float)(net.StartX), (float)(net.StartY));
                                    PointF end   = new PointF((float)(net.StopX), (float)(net.StopY));
                                    gp.AddLine(start, end);
                                    if (gp.IsOutlineVisible(new PointF(x1, y1), pen, graphics))
                                    {
                                        inSelect = true;
                                    }

                                    break;
                                }

                        case GerberInterpolation.ClockwiseCircular:
                        case GerberInterpolation.CounterClockwiseCircular:
                            using (GraphicsPath gp = new GraphicsPath())
                                using (Pen pen = new Pen(Color.Transparent))
                                {
                                    float centerX    = (float)net.CircleSegment.CenterX;
                                    float centerY    = (float)net.CircleSegment.CenterY;
                                    float width      = (float)net.CircleSegment.Width;
                                    float height     = (float)net.CircleSegment.Height;
                                    float startAngle = (float)net.CircleSegment.StartAngle;
                                    float sweepAngle = (float)net.CircleSegment.SweepAngle;
                                    if (image.ApertureArray[net.Aperture].ApertureType == GerberApertureType.Rectangle)
                                    {
                                        pen.StartCap = pen.EndCap = LineCap.Square;
                                    }

                                    else
                                    {
                                        pen.StartCap = pen.EndCap = LineCap.Round;
                                    }

                                    RectangleF arcRectangle = new RectangleF(centerX - (width / 2), centerY - (height / 2), width, height);
                                    pen.Width = width;

                                    gp.AddArc(arcRectangle, startAngle, sweepAngle);
                                    if (gp.IsOutlineVisible(new PointF(x1, y1), pen, graphics))
                                    {
                                        inSelect = true;
                                    }
                                }
                            break;
                        }
                    }
                }
            }

            else if (selectionInfo.SelectionType == GerberSelection.DragBox)
            {
                if (net.BoundingBox != null)
                {
                    double left   = Math.Min(selectionInfo.LowerLeftX, selectionInfo.UpperRightX);
                    double right  = Math.Max(selectionInfo.LowerLeftX, selectionInfo.UpperRightX);
                    double top    = Math.Min(selectionInfo.LowerLeftY, selectionInfo.UpperRightY);
                    double bottom = Math.Max(selectionInfo.LowerLeftY, selectionInfo.UpperRightY);

                    BoundingBox box = new BoundingBox(left, bottom, right, top);
                    if (!box.Contains(net.BoundingBox))
                    {
                        return;
                    }

                    if (net.ApertureState == GerberApertureState.Flash)
                    {
                        inSelect = box.Contains(net.BoundingBox);
                    }

                    else if (net.ApertureState == GerberApertureState.On)
                    {
                        inSelect = box.Contains(net.BoundingBox);
                    }
                }
            }

            if (inSelect)
            {
                selectionInfo.SelectedNetList.Add(net);
                selectionInfo.SelectionCount++;
                if (net.Interpolation == GerberInterpolation.PolygonAreaStart)  // Add all the poly points.
                {
                    do
                    {
                        i++;
                        net = image.GerberNetList[i];
                        selectionInfo.SelectedNetList.Add(net);
                    } while (net.Interpolation != GerberInterpolation.PolygonAreaEnd);
                }
            }
        }
Example #8
0
        // Renders a gerber image to the specified graphics target.
        private static void RenderToTarget(Graphics graphics, GerberImage gerberImage, Collection <GerberNet> gerberNetList, GerberUserTransform userTransform,
                                           Color foreGroundColor, Color backGroundColor, bool invert)
        {
            float dx, dy;
            float startX, startY, stopX, stopY;
            float p1, p2, p3, p4, p5;
            int   repeatX = 1, repeatY = 1;
            float repeatDistanceX = 0.0f, repeatDistanceY = 0.0f;

            Collection <SimplifiedApertureMacro> simplifiedMacroList;
            PointF     startPoint, endPoint;
            RectangleF apertureRectangle;

            int            netListIndex     = 0;
            GerberNet      currentNet       = null;
            GerberLevel    oldLevel         = null;
            GerberNetState oldState         = null;
            bool           useClearOperator = false;
            bool           invertPolarity   = false;

            SolidBrush brush = new SolidBrush(foreGroundColor);
            Pen        pen   = new Pen(foreGroundColor);

            // Apply user supplied transforations.
            double scaleX = userTransform.ScaleX;
            double scaleY = userTransform.ScaleY;

            if (userTransform.MirrorAroundX)
            {
                scaleY *= -1;
            }

            if (userTransform.MirrorAroundY)
            {
                scaleX *= -1;
            }

            graphics.TranslateTransform((float)userTransform.TranslateX, (float)userTransform.TranslateY);
            graphics.ScaleTransform((float)scaleX, (float)scaleY);
            graphics.RotateTransform((float)userTransform.Rotation);

            // Apply initial image transformations.
            graphics.TranslateTransform((float)gerberImage.ImageInfo.ImageJustifyOffsetActualA, (float)gerberImage.ImageInfo.ImageJustifyOffsetActualB);
            graphics.TranslateTransform((float)gerberImage.ImageInfo.OffsetA, (float)gerberImage.ImageInfo.OffsetB);
            graphics.RotateTransform((float)gerberImage.ImageInfo.ImageRotation);

            invertPolarity = invert;
            if (gerberImage.ImageInfo.Polarity == GerberPolarity.Negative)
            {
                invertPolarity = !invertPolarity;
            }

            if (invertPolarity)
            {
                graphics.Clear(foreGroundColor);
            }

            else
            {
                pen.Color = brush.Color = foreGroundColor;
            }

            for (netListIndex = 0; netListIndex < gerberNetList.Count; GetNextRenderObject(gerberNetList, ref netListIndex))
            {
                currentNet = gerberNetList[netListIndex];
                if (currentNet.Level != oldLevel)
                {
                    // Set the current net transformation and polarity.
                    graphics.RotateTransform((float)currentNet.Level.Rotation);
                    if (currentNet.Level.Polarity == GerberPolarity.Clear ^ invertPolarity)
                    {
                        pen.Color = brush.Color = backGroundColor;
                    }

                    else
                    {
                        pen.Color = brush.Color = foreGroundColor;
                    }

                    // Check for changes to step and repeat.
                    repeatX         = currentNet.Level.StepAndRepeat.X;
                    repeatY         = currentNet.Level.StepAndRepeat.Y;
                    repeatDistanceX = (float)currentNet.Level.StepAndRepeat.DistanceX;
                    repeatDistanceY = (float)currentNet.Level.StepAndRepeat.DistanceY;

                    // Draw any knockout areas.
                    if (currentNet.Level.Knockout.FirstInstance == true)
                    {
                        Color oldColor = foreGroundColor;
                        if (currentNet.Level.Knockout.Polarity == GerberPolarity.Clear)
                        {
                            pen.Color = brush.Color = backGroundColor;
                        }

                        else
                        {
                            pen.Color = brush.Color = foreGroundColor;
                        }

                        GraphicsPath knockoutPath = new GraphicsPath();
                        PointF       pf1          = new PointF((float)(currentNet.Level.Knockout.LowerLeftX - currentNet.Level.Knockout.Border),
                                                               (float)(currentNet.Level.Knockout.LowerLeftY - currentNet.Level.Knockout.Border));
                        PointF pf2 = new PointF(pf1.X + (float)(currentNet.Level.Knockout.Width + (currentNet.Level.Knockout.Border * 2)), pf1.Y);
                        PointF pf3 = new PointF(pf2.X, pf1.Y + (float)(currentNet.Level.Knockout.Height + (currentNet.Level.Knockout.Border * 2)));
                        PointF pf4 = new PointF(pf1.X, pf3.Y);

                        PointF[] points = new PointF[] { pf1, pf2, pf3, pf4 };
                        knockoutPath.AddLines(points);
                        knockoutPath.CloseFigure();
                        graphics.FillPath(brush, knockoutPath);

                        // Restore the polarity.
                        pen.Color = brush.Color = oldColor;
                    }

                    ApplyNetStateTransformation(graphics, currentNet.NetState);
                    oldLevel = currentNet.Level;
                }

                // Check if this is a new netstate.
                if (currentNet.NetState != oldState)
                {
                    // A new state, so recalculate the new transformation matrix.
                    ApplyNetStateTransformation(graphics, currentNet.NetState);
                    oldState = currentNet.NetState;
                }

                for (int rx = 0; rx < repeatX; rx++)
                {
                    for (int ry = 0; ry < repeatY; ry++)
                    {
                        float stepAndRepeatX = rx * repeatDistanceX;
                        float stepAndRepeatY = ry * repeatDistanceY;

                        startX = (float)currentNet.StartX + stepAndRepeatX;
                        startY = (float)currentNet.StartY + stepAndRepeatY;
                        stopX  = (float)currentNet.StopX + stepAndRepeatX;
                        stopY  = (float)currentNet.StopY + stepAndRepeatY;

                        switch (gerberNetList[netListIndex].Interpolation)
                        {
                        case GerberInterpolation.PolygonAreaStart:
                            FillPolygonArea(graphics, brush, gerberNetList, netListIndex, stepAndRepeatX, stepAndRepeatY);
                            continue;

                        case GerberInterpolation.Deleted:
                            continue;
                        }

                        switch (currentNet.ApertureState)
                        {
                        case GerberApertureState.On:
                            switch (currentNet.Interpolation)
                            {
                            case GerberInterpolation.LinearX10:
                            case GerberInterpolation.LinearX01:
                            case GerberInterpolation.LinearX001:
                            case GerberInterpolation.LinearX1:
                                pen.SetLineCap(LineCap.Round, LineCap.Round, DashCap.Round);
                                switch (gerberImage.ApertureArray[currentNet.Aperture].ApertureType)
                                {
                                case GerberApertureType.Circle:
                                    pen.Width  = (float)gerberImage.ApertureArray[currentNet.Aperture].Parameters[0];
                                    startPoint = new PointF(startX, startY);
                                    endPoint   = new PointF(stopX, stopY);
                                    graphics.DrawLine(pen, startPoint, endPoint);
                                    break;

                                case GerberApertureType.Rectangle:
                                    dx = (float)(gerberImage.ApertureArray[currentNet.Aperture].Parameters[0] / 2);
                                    dy = (float)(gerberImage.ApertureArray[currentNet.Aperture].Parameters[1] / 2);
                                    if (startX > stopX)
                                    {
                                        dx = -dx;
                                    }

                                    if (startY > stopY)
                                    {
                                        dy = -dy;
                                    }

                                    using (GraphicsPath path = new GraphicsPath())
                                    {
                                        path.AddLine(startX - dx, startY - dy, startX - dx, startY + dy);
                                        path.AddLine(startX - dx, startY + dy, stopX - dx, stopY + dy);
                                        path.AddLine(stopX - dx, stopY + dy, stopX + dx, stopY + dy);
                                        path.AddLine(stopX + dx, stopY + dy, stopX + dx, stopY - dy);
                                        path.AddLine(stopX + dx, stopY - dy, startX + dx, startY - dy);
                                        graphics.FillPath(brush, path);
                                    }
                                    break;

                                // For now, just render ovals or polygons like a circle.
                                case GerberApertureType.Oval:
                                case GerberApertureType.Polygon:
                                    pen.Width  = (float)gerberImage.ApertureArray[currentNet.Aperture].Parameters[0];
                                    startPoint = new PointF(startX, startY);
                                    endPoint   = new PointF(stopX, stopY);
                                    graphics.DrawLine(pen, startPoint, endPoint);
                                    break;

                                // Macros can only be flashed, so ignore any that might be here.
                                default:
                                    break;
                                }
                                break;

                            case GerberInterpolation.ClockwiseCircular:
                            case GerberInterpolation.CounterClockwiseCircular:
                                float centerX    = (float)currentNet.CircleSegment.CenterX;
                                float centerY    = (float)currentNet.CircleSegment.CenterY;
                                float width      = (float)currentNet.CircleSegment.Width;
                                float height     = (float)currentNet.CircleSegment.Height;
                                float startAngle = (float)currentNet.CircleSegment.StartAngle;
                                float sweepAngle = (float)currentNet.CircleSegment.SweepAngle;
                                if (gerberImage.ApertureArray[currentNet.Aperture].ApertureType == GerberApertureType.Rectangle)
                                {
                                    pen.SetLineCap(LineCap.Square, LineCap.Square, DashCap.Flat);
                                }

                                else
                                {
                                    pen.SetLineCap(LineCap.Round, LineCap.Round, DashCap.Round);
                                }

                                RectangleF arcRectangle = new RectangleF(centerX - (width / 2), centerY - (height / 2), width, height);
                                pen.Width = (float)gerberImage.ApertureArray[currentNet.Aperture].Parameters[0];
                                if (arcRectangle != RectangleF.Empty)
                                {
                                    graphics.DrawArc(pen, arcRectangle, startAngle, sweepAngle);
                                }

                                break;

                            default:
                                break;
                            }
                            break;

                        case GerberApertureState.Flash:
                            p1 = (float)gerberImage.ApertureArray[currentNet.Aperture].Parameters[0];
                            p2 = (float)gerberImage.ApertureArray[currentNet.Aperture].Parameters[1];
                            p3 = (float)gerberImage.ApertureArray[currentNet.Aperture].Parameters[2];
                            p4 = (float)gerberImage.ApertureArray[currentNet.Aperture].Parameters[3];
                            p5 = (float)gerberImage.ApertureArray[currentNet.Aperture].Parameters[4];

                            GraphicsState state = graphics.Save();
                            graphics.TranslateTransform(stopX, stopY);
                            using (GraphicsPath path = new GraphicsPath())
                            {
                                switch (gerberImage.ApertureArray[currentNet.Aperture].ApertureType)
                                {
                                case GerberApertureType.Circle:
                                    apertureRectangle = new RectangleF(-(p1 / 2), -(p1 / 2), p1, p1);
                                    path.AddEllipse(apertureRectangle);
                                    DrawAperatureHole(path, p2, p3);
                                    break;

                                case GerberApertureType.Rectangle:
                                    apertureRectangle = new RectangleF(-(p1 / 2), -(p2 / 2), p1, p2);
                                    path.AddRectangle(apertureRectangle);
                                    DrawAperatureHole(path, p3, p4);
                                    break;

                                case GerberApertureType.Oval:
                                    apertureRectangle = new RectangleF(-(p1 / 2), -(p2 / 2), p1, p2);
                                    CreateOblongPath(path, p1, p2);
                                    DrawAperatureHole(path, p3, p4);
                                    break;

                                case GerberApertureType.Polygon:
                                    CreatePolygon(graphics, path, p1, p2, p3);
                                    DrawAperatureHole(path, p4, p5);
                                    break;

                                case GerberApertureType.Macro:
                                    simplifiedMacroList = gerberImage.ApertureArray[currentNet.Aperture].SimplifiedMacroList;
                                    useClearOperator    = gerberImage.ApertureArray[currentNet.Aperture].Parameters[0] == 1.0 ? true : false;
                                    DrawApertureMacro(graphics, simplifiedMacroList, brush.Color, backGroundColor, useClearOperator);
                                    break;

                                default:
                                    break;
                                }

                                graphics.FillPath(brush, path);     // Fill the path.
                                graphics.Restore(state);
                            }

                            break;

                        default:
                            break;
                        }
                    }
                }
            }

            pen.Dispose();
            brush.Dispose();
        }
Example #9
0
        private static void FillPolygonArea(Graphics graphics, SolidBrush brush, Collection <GerberNet> gerberNetList, int netListIndex, float srX, float srY)
        {
            float      stopX, stopY, startX, startY;
            float      cpX = 0.0f, cpY = 0.0f;
            float      circleWidth = 0.0f, circleHeight = 0.0f;
            float      startAngle = 0.0f, sweepAngle = 0.0f;
            bool       done         = false;
            RectangleF arcRectangle = RectangleF.Empty;
            GerberNet  currentNet   = null;

            using (GraphicsPath path = new GraphicsPath())
            {
                while (netListIndex < gerberNetList.Count)
                {
                    currentNet = gerberNetList[netListIndex++];

                    // Translate for step and repeat.
                    startX = (float)currentNet.StartX + srX;
                    startY = (float)currentNet.StartY + srY;
                    stopX  = (float)currentNet.StopX + srX;
                    stopY  = (float)currentNet.StopY + srY;

                    // Translate circular x,y data as well.
                    if (currentNet.CircleSegment != null)
                    {
                        cpX          = (float)currentNet.CircleSegment.CenterX + srX;
                        cpY          = (float)currentNet.CircleSegment.CenterY + srY;
                        circleWidth  = (float)currentNet.CircleSegment.Width;
                        circleHeight = (float)currentNet.CircleSegment.Height;
                        startAngle   = (float)currentNet.CircleSegment.StartAngle;
                        sweepAngle   = (float)currentNet.CircleSegment.SweepAngle;
                        arcRectangle = new RectangleF(cpX - circleWidth / 2, cpY - circleHeight / 2, circleWidth, circleHeight);
                    }

                    switch (currentNet.Interpolation)
                    {
                    case GerberInterpolation.LinearX10:
                    case GerberInterpolation.LinearX01:
                    case GerberInterpolation.LinearX001:
                    case GerberInterpolation.LinearX1:
                        if (currentNet.ApertureState == GerberApertureState.On)
                        {
                            path.AddLine(startX, startY, stopX, stopY);
                        }

                        break;

                    case GerberInterpolation.ClockwiseCircular:
                    case GerberInterpolation.CounterClockwiseCircular:
                        if (arcRectangle != RectangleF.Empty)
                        {
                            path.AddArc(arcRectangle, startAngle, sweepAngle);
                        }

                        break;

                    case GerberInterpolation.PolygonAreaEnd:
                        if (path.PointCount > 0)
                        {
                            graphics.FillPath(brush, path);
                        }

                        done = true;
                        break;
                    }

                    if (done)
                    {
                        break;
                    }
                }
            }
        }