static DrillGCode ParseGCode(GerberLineReader lineReader, GerberImage image) { DrillFileStats stats = image.DrillStats; DrillGCode result = DrillGCode.Unknown; int length = 0; int value = lineReader.GetIntegerValue(ref length); if (length == 2) { switch (value) { case 0: stats.G00++; result = DrillGCode.Rout; break; case 1: stats.G01++; result = DrillGCode.LinearMove; break; case 2: stats.G02++; result = DrillGCode.ClockwiseMove; break; case 3: stats.G03++; result = DrillGCode.CounterClockwiseMove; break; case 5: image.DrillStats.G05++; result = DrillGCode.Drill; break; case 90: stats.G90++; result = DrillGCode.Absolute; break; case 91: stats.G91++; result = DrillGCode.Incrementle; break; case 93: stats.G93++; result = DrillGCode.ZeroSet; break; default: stats.GUnknown++; break; } } return(result); }
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); }
} // Scale factor in the B axis (usually this is the Y axis) /// <summary> /// Creates a new gerber net state and intialize with defaults. /// </summary> public GerberNetState(GerberImage gerberImage) { Unit = GerberUnit.Inch; ScaleA = 1.0; ScaleB = 1.0; gerberImage.NetStateList.Add(this); }
private static void AddFileToProject(GerberProject project, GerberImage parsedImage, string fullPathName, bool reloading) { int fileIndex = project.FileInfo.Count - 1; int colorIndex = 0; GerberVerifyError error = GerberVerifyError.ImageOK; //Debug.WriteLine("Integrity check on image....\n"); error = parsedImage.GerberImageVerify(); if (error != GerberVerifyError.ImageOK) { project.FileInfo.RemoveAt(fileIndex); // Image has errors, remove it from the file list. if ((error & GerberVerifyError.MissingNetList) > 0) { throw new GerberImageException("Missing image net list."); } if ((error & GerberVerifyError.MissingFormat) > 0) { throw new GerberImageException("Missing format information in file."); } if ((error & GerberVerifyError.MissingApertures) > 0) { throw new GerberImageException("Missing apertures/drill sizes."); } if ((error & GerberVerifyError.MissingImageInfo) > 0) { throw new GerberImageException("Missing image information."); } } project.FileInfo[fileIndex].Image = parsedImage; if (reloading) // If reload, just exchange the image and return. { return; } project.FileInfo[fileIndex].FullPathName = fullPathName; project.FileInfo[fileIndex].FileName = Path.GetFileName(fullPathName); colorIndex = defaultColorIndex % NumberOfDefaultColors; project.FileInfo[fileIndex].Color = Color.FromArgb(defaultColors[colorIndex, 1], defaultColors[colorIndex, 2], defaultColors[colorIndex, 3]); project.FileInfo[fileIndex].Alpha = defaultColors[colorIndex, 0]; project.FileInfo[fileIndex].IsVisible = true; defaultColorIndex++; }
private static bool OpenImage(GerberProject project, string fullPathName, bool reloading, int index) { GerberImage parsedImage = null; string displayFileName = String.Empty; bool success = false; int numberOfAttributes = 0; List <GerberHIDAttribute> attributesList = null; if (Gerber.IsGerberRS427X(fullPathName)) { parsedImage = Gerber.ParseGerber(fullPathName); } else if (Drill.IsDrillFile(fullPathName)) { parsedImage = Drill.ParseDrillFile(fullPathName, attributesList, numberOfAttributes, reloading); } else { throw new GerberFileException("Unknown file format " + fullPathName); } if (parsedImage != null) { if (!reloading) { project.FileInfo.Add(new GerberFileInformation()); AddFileToProject(project, parsedImage, fullPathName, reloading); } else { AddFileToProject(project, parsedImage, fullPathName, reloading); } } return(success); }
} // The level name (NULL for none). /// <summary> /// Create a new Gerber Level. /// </summary> public GerberLevel(GerberImage gerberImage) { Knockout = new GerberKnockout(); StepAndRepeat = new GerberStepAndRepeat(); Rotation = 0.0; Polarity = GerberPolarity.Dark; LevelName = String.Empty; // If not the first then copy the previous level values into the new one. if (gerberImage.LevelList.Count > 0) { int previous = gerberImage.LevelList.Count - 1; this.LevelName = gerberImage.LevelList[previous].LevelName; this.StepAndRepeat = gerberImage.LevelList[previous].StepAndRepeat; this.Polarity = gerberImage.LevelList[previous].Polarity; this.Knockout = gerberImage.LevelList[previous].Knockout; // Clear this boolean so we only draw the knockout once. this.Knockout.FirstInstance = false; } gerberImage.LevelList.Add(this); }
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 void ParseCoordinate(GerberLineReader lineReader, char firstCharacter, GerberImage image, DrillState drillState) { if (drillState.CoordinateMode == DrillCoordinateMode.Absolute) { if (firstCharacter == 'X') { drillState.CurrentX = GetDoubleValue(lineReader, drillState.DataNumberFormat, image.Format.OmitZeros, drillState.DecimalPlaces); if (lineReader.Read() == 'Y') { drillState.CurrentY = GetDoubleValue(lineReader, drillState.DataNumberFormat, image.Format.OmitZeros, drillState.DecimalPlaces); } else { lineReader.Position--; } } else { drillState.CurrentY = GetDoubleValue(lineReader, drillState.DataNumberFormat, image.Format.OmitZeros, drillState.DecimalPlaces); } } else { if (firstCharacter == 'X') { drillState.CurrentX += GetDoubleValue(lineReader, drillState.DataNumberFormat, image.Format.OmitZeros, drillState.DecimalPlaces); if (lineReader.Read() == 'Y') { drillState.CurrentY += GetDoubleValue(lineReader, drillState.DataNumberFormat, image.Format.OmitZeros, drillState.DecimalPlaces); } } else { drillState.CurrentY += GetDoubleValue(lineReader, drillState.DataNumberFormat, image.Format.OmitZeros, drillState.DecimalPlaces); } } }
static int ParseTCode(GerberLineReader lineReader, string drillFileName, DrillState drillState, GerberImage image) { int drillNumber; double drillSize = 0.0; int length = 0; char nextCharacter; bool done = false; DrillFileStats stats = image.DrillStats; string line = String.Empty; string errorMessage = String.Empty; nextCharacter = lineReader.Read(); if (!Char.IsDigit(nextCharacter)) { if (nextCharacter == 'C') { lineReader.Position -= 2; line = lineReader.ReadLineToEnd(); if (line == "TCST") { errorMessage = "Tool change stop switch found."; stats.AddNewError(-1, errorMessage, GerberErrorType.GerberNote, lineReader.LineNumber, drillFileName); } return(-1); } } lineReader.Position--; drillNumber = lineReader.GetIntegerValue(ref length); // T00 is a tool unload command. if (drillNumber == 0) { return(drillNumber); } if (drillNumber < ToolMin && drillNumber >= ToolMax) { errorMessage = String.Format(CultureInfo.CurrentCulture, "Drill number out of bounds:{0}.\n", drillNumber); stats.AddNewError(-1, errorMessage, GerberErrorType.GerberError, lineReader.LineNumber, drillFileName); } drillState.CurrentTool = drillNumber; // Tool definition following tool number. if (lineReader.Position > 0) { while (!done) { nextCharacter = lineReader.Read(); switch (nextCharacter) { case 'C': drillSize = GetDoubleValue(lineReader, drillState.HeaderNumberFormat, GerberOmitZero.OmitZerosTrailing, drillState.DecimalPlaces); if (drillState.Unit == GerberUnit.Millimeter) { drillSize /= 25.4; } else if (drillSize >= 4.0) { drillSize /= 1000.0; } if (drillSize <= 0 || drillSize >= 10000) { errorMessage = "Unreasonable drill size found."; stats.AddNewError(-1, errorMessage, GerberErrorType.GerberError, lineReader.LineNumber, drillFileName); } else { // Allow a redefinition of a tool only if all parameters are the same. if (image.ApertureArray[drillNumber] != null) { if (image.ApertureArray[drillNumber].Parameters[0] != drillSize || image.ApertureArray[drillNumber].ApertureType != GerberApertureType.Circle || image.ApertureArray[drillNumber].ParameterCount != 1 || image.ApertureArray[drillNumber].Unit != GerberUnit.Inch) { errorMessage = String.Format(CultureInfo.CurrentCulture, "Found redefinition if drill {0}.\n", drillNumber); stats.AddNewError(-1, errorMessage, GerberErrorType.GerberError); } } else { image.ApertureArray[drillNumber] = new ApertureDefinition(); image.ApertureArray[drillNumber].Parameters[0] = drillSize; image.ApertureArray[drillNumber].ApertureType = GerberApertureType.Circle; image.ApertureArray[drillNumber].ParameterCount = 1; image.ApertureArray[drillNumber].Unit = GerberUnit.Inch; } } string drillUnit = (drillState.Unit == GerberUnit.Millimeter) ? "MM" : "INCH"; stats.AddToDrillList(drillNumber, (drillState.Unit == GerberUnit.Millimeter) ? drillSize * 25.4 : drillSize, drillUnit); break; case 'F': case 'S': lineReader.GetIntegerValue(ref length); break; default: lineReader.Position--; done = true; break; } } } return(drillNumber); }
static DrillMCode ParseMCode(GerberLineReader lineReader, DrillState drillState, GerberImage image) { DrillFileStats stats = image.DrillStats; DrillMCode result = DrillMCode.Unknown; int length = 0; string line = String.Empty; int value = lineReader.GetIntegerValue(ref length); switch (value) { case 0: stats.M00++; result = DrillMCode.End; break; case 1: stats.M01++; result = DrillMCode.EndPattern; break; case 18: stats.M18++; result = DrillMCode.TipCheck; break; case 25: stats.M25++; result = DrillMCode.BeginPattern; break; case 30: stats.M30++; result = DrillMCode.EndRewind; break; case 31: stats.M31++; result = DrillMCode.BeginPattern; break; case 45: stats.M45++; result = DrillMCode.LongMessage; break; case 47: stats.M47++; result = DrillMCode.Message; break; case 48: stats.M48++; result = DrillMCode.Header; break; case 71: stats.M71++; result = DrillMCode.Metric; break; case 72: stats.M72++; result = DrillMCode.Imperial; break; case 95: stats.M95++; result = DrillMCode.EndHeader; break; case 97: stats.M97++; result = DrillMCode.CannedText; break; case 98: stats.M98++; result = DrillMCode.CannedText; break; default: stats.MUnknown++; break; } return(result); }
private static List <GerberHIDAttribute> drillAttributeList = new List <GerberHIDAttribute>(); /* <---- NOT SURE IF WE NEED THIS.*/ public static GerberImage ParseDrillFile(string drillFileName, List <GerberHIDAttribute> attributeList, int numberOfAttributes, bool reload) { bool foundEOF = false; string errorMessage = String.Empty; DrillState drillState = new DrillState(); GerberImage image = new GerberImage("Excellon Drill File"); CreateDefaultAttributeList(); if (reload & attributeList != null) { image.ImageInfo.NumberOfAttribute = numberOfAttributes; image.ImageInfo.AttributeList = new List <GerberHIDAttribute>(); for (int i = 0; i < numberOfAttributes; i++) { GerberHIDAttribute attribute = new GerberHIDAttribute(attributeList[i]); image.ImageInfo.AttributeList.Add(attribute); } } else { // Load default attributes. image.ImageInfo.NumberOfAttribute = drillAttributeList.Count; image.ImageInfo.AttributeList = new List <GerberHIDAttribute>(); for (int i = 0; i < image.ImageInfo.NumberOfAttribute; i++) { GerberHIDAttribute attribute = new GerberHIDAttribute(drillAttributeList[i]); image.ImageInfo.AttributeList.Add(attribute); } } DrillAttributeMerge(image.ImageInfo.AttributeList, image.ImageInfo.NumberOfAttribute, attributeList, numberOfAttributes); image.FileType = GerberFileType.Drill; image.DrillStats = new DrillFileStats(); image.Format = new GerberFormat(); image.Format.OmitZeros = GerberOmitZero.OmitZerosUnspecified; if (image.ImageInfo.AttributeList[(int)HA.AutoDetect].DefaultValue.IntValue > 0) { drillState.AutoDetect = false; drillState.DataNumberFormat = DrillNumberFormat.UserDefined; drillState.DecimalPlaces = image.ImageInfo.AttributeList[(int)HA.Digits].DefaultValue.IntValue; if (image.ImageInfo.AttributeList[(int)HA.ZeroSuppression].DefaultValue.IntValue == (int)Units.Millimeters) { drillState.Unit = GerberUnit.Millimeter; } switch (image.ImageInfo.AttributeList[(int)HA.ZeroSuppression].DefaultValue.IntValue) { case (int)ZeroSuppression.Leading: image.Format.OmitZeros = GerberOmitZero.OmitZerosLeading; break; case (int)ZeroSuppression.Trailing: image.Format.OmitZeros = GerberOmitZero.OmitZerosTrailing; break; default: image.Format.OmitZeros = GerberOmitZero.OmitZerosExplicit; break; } } //Debug.WriteLine(String.Format("Starting to parse drill file {0}", drillFileName)); using (StreamReader drillFileStream = new StreamReader(drillFileName, Encoding.ASCII)) { GerberLineReader lineReader = new GerberLineReader(drillFileStream); foundEOF = ParseDrillSegment(drillFileName, lineReader, image, drillState); } if (!foundEOF) { errorMessage = String.Format(CultureInfo.CurrentCulture, "File {0} is missing Excellon Drill EOF code./n", drillFileName); image.DrillStats.AddNewError(-1, errorMessage, GerberErrorType.GerberError); } //Debug.WriteLine("... done parsing Excellon Drill file."); return(image); }
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(); }