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); }
} // 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); }
// 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); }
// 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++; }
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); }
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); }
/// <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); } } }
// 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(); }
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; } } } }