/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// Revisits the excellon lines and figures out the pad center points /// </summary> public void SetPadCenterPointList() { // create a dummy statemachine We can only get a lot of the information from the DCodes // by simulating a run. They use the results of the previous DCode a lot ExcellonFileStateMachine workingStateMachine = new ExcellonFileStateMachine(); workingStateMachine.ToolCollection = stateMachine.ToolCollection; // run through all of the DCode lines foreach (ExcellonLine gLineObj in SourceLines) { if ((gLineObj is ExcellonLine_ToolChange) == true) { ExcellonLine_ToolTable toolTabObj = null; // see if we can find the tool table object for this change toolTabObj = workingStateMachine.GetToolTableObjectByToolNumber((gLineObj as ExcellonLine_ToolChange).ToolNumber); if (toolTabObj != null) { workingStateMachine.LastDrillWidth = toolTabObj.DrillDiameter; } continue; } else if ((gLineObj is ExcellonLine_XYCode) == true) { // set this now for convenience ExcellonLine_XYCode elObj = (ExcellonLine_XYCode)gLineObj; // record these centerpoints to our list, note that we save to the current statemachine but use the aperture from the working one stateMachine.PadCenterPointList.Add(new GerberPad(elObj.XCoord, elObj.YCoord, workingStateMachine.LastDrillWidth)); } } }
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// Revisits the excellon lines and figures out the absolute X and Y offsets /// The coordinates in the file will have been much adjusted so as to make them /// all positive and near the plot 0,0 origin point. The absolute offset /// is how these modified points relate to the original hard coords of the /// excellon file. This enables us to line up the gcode in different files /// such as edgeCuts, drills and isoCuts etc. /// /// NOTE: this code only works after the excellon file has been plotted. Before /// then we do not have enough information /// /// </summary> public bool GetAbsoluteOffsets(out float absoluteOffset_X, out float absoluteOffset_Y) { absoluteOffset_X = 0; absoluteOffset_Y = 0; // run through all of the DCode lines foreach (ExcellonLine gLineObj in SourceLines) { // we only process XY Codes if ((gLineObj is ExcellonLine_XYCode) == false) { continue; } // set this now for convenience ExcellonLine_XYCode elObj = (ExcellonLine_XYCode)gLineObj; // we use the first nonzero plottable DCode we find. The end value is always the transformation of the original DCode // coordinates into plot coordinates. if ((elObj.LastPlotXCoordEnd == 0) && (elObj.LastPlotYCoordEnd == 0)) { continue; } // ok we know we have one and we can figure out a transformation, scale the dcodeXY to plot coords float scaledOriginal_X = elObj.XCoord * StateMachine.IsoPlotPointsPerAppUnit; float scaledOriginal_Y = elObj.YCoord * StateMachine.IsoPlotPointsPerAppUnit; // the difference between the what we ended up as and what we started with is indicative of the absolute offset of that // point in the excellon file. These should all be the same absoluteOffset_X = scaledOriginal_X - (float)elObj.LastPlotXCoordEnd; absoluteOffset_Y = scaledOriginal_Y - (float)elObj.LastPlotYCoordEnd; //DebugMessage("dCodeObj.LastPlotXCoordEnd=" + elObj.LastPlotXCoordEnd.ToString() + ", dCodeObj.LastPlotYCoordEnd=" + elObj.LastPlotYCoordEnd.ToString()); //DebugMessage("scaledOriginalDCode_X=" + scaledOriginal_X.ToString() + ", scaledOriginalDCode_Y=" + scaledOriginal_Y.ToString() + ", absoluteOffset_X=" + absoluteOffset_X.ToString() + ", absoluteOffset_Y=" + absoluteOffset_Y.ToString()); return(true); } // if we get here we failed to find an absoluet offset return(false); }
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// Adds a Excellon file line to the SourceLines /// </summary> /// <param name="lineStr">The line to add</param> /// <param name="lineNumber">The line number</param> public int AddLine(string lineStr, int lineNumber) { int retInt; string tmpLine1; if (lineStr == null) { return(100); } // trim it up, remove comments tmpLine1 = GerberParseUtils.RemoveTrailingCommentsFromString(lineStr, ANSI349COMMENTDELIMITER).Trim(); // Are we a INCH header Code? if (tmpLine1.StartsWith("INCH") == true) { ExcellonLine_Misc mObj = new ExcellonLine_Misc(lineStr, tmpLine1, lineNumber); retInt = mObj.ParseLine(tmpLine1, StateMachine); if (retInt != 0) { LogMessage("lineStr(INCH), call to ParseLine returned " + retInt.ToString() + " Error on line " + lineNumber.ToString()); return(702); } // it is good, add it sourceLines.Add(mObj); // set the dimension mode now StateMachine.ExcellonFileUnits = ApplicationUnitsEnum.INCHES; return(0); } // Are we a METRIC header Code? else if (tmpLine1.StartsWith("METRIC") == true) { ExcellonLine_Misc mObj = new ExcellonLine_Misc(lineStr, tmpLine1, lineNumber); retInt = mObj.ParseLine(tmpLine1, StateMachine); if (retInt != 0) { LogMessage("lineStr(METRIC), call to ParseLine returned " + retInt.ToString() + " Error on line " + lineNumber.ToString()); return(703); } // it is good, add it sourceLines.Add(mObj); // set the dimension mode now StateMachine.ExcellonFileUnits = ApplicationUnitsEnum.MILLIMETERS; return(0); } else if (tmpLine1.StartsWith("M") == true) { ExcellonLine_MCode mObj = new ExcellonLine_MCode(lineStr, tmpLine1, lineNumber); retInt = mObj.ParseLine(tmpLine1, StateMachine); if (retInt != 0) { LogMessage("lineStr(M), call to ParseLine returned " + retInt.ToString() + " Error on line " + lineNumber.ToString()); return(700); } // it is good, add it sourceLines.Add(mObj); // are we M72? if (mObj.CurrentMCode == 72) { // set the dimension mode now StateMachine.ExcellonFileUnits = ApplicationUnitsEnum.INCHES; } // are we M71? if (mObj.CurrentMCode == 71) { // set the dimension mode now StateMachine.ExcellonFileUnits = ApplicationUnitsEnum.MILLIMETERS; } return(0); } else if (tmpLine1.StartsWith("G") == true) { ExcellonLine_GCode gObj = new ExcellonLine_GCode(lineStr, tmpLine1, lineNumber); retInt = gObj.ParseLine(tmpLine1, StateMachine); if (retInt != 0) { LogMessage("lineStr(G), call to ParseLine returned " + retInt.ToString() + " Error on line " + lineNumber.ToString()); return(7001); } // it is good, add it sourceLines.Add(gObj); return(0); } else if (tmpLine1.StartsWith("ICI") == true) { // this is Incremental Input of Part Program Coordinates if (tmpLine1.Contains("OFF") == false) { LogMessage("lIncremental coordinate mode not supported. Error on line " + lineNumber.ToString()); return(3001); } else { // we just ignore this ExcellonLine_Misc mObj = new ExcellonLine_Misc(lineStr, tmpLine1, lineNumber); retInt = mObj.ParseLine(tmpLine1, StateMachine); if (retInt != 0) { LogMessage("lineStr(ICI), call to ParseLine returned " + retInt.ToString() + " Error on line " + lineNumber.ToString()); return(3002); } // it is good, add it sourceLines.Add(mObj); return(0); } } // Are we a T Code? else if (tmpLine1.StartsWith("T") == true) { // Are we a "TCST" flag if (tmpLine1.Contains("TCST") == true) { // we just ignore this ExcellonLine_Misc mObj = new ExcellonLine_Misc(lineStr, tmpLine1, lineNumber); retInt = mObj.ParseLine(tmpLine1, StateMachine); if (retInt != 0) { LogMessage("lineStr(TCST), call to ParseLine returned " + retInt.ToString() + " Error on line " + lineNumber.ToString()); return(807); } // it is good, add it sourceLines.Add(mObj); return(0); } else { // this is a tool change, have we seen the end of the header? if (lineNumber > StateMachine.HeaderEndLine) { // yes, we have. This must be a tool change ExcellonLine_ToolChange tObj = new ExcellonLine_ToolChange(lineStr, tmpLine1, lineNumber); retInt = tObj.ParseLine(tmpLine1, StateMachine); if (retInt != 0) { LogMessage("lineStr(ToolChange), call to ParseLine returned " + retInt.ToString() + " Error on line " + lineNumber.ToString()); return(7011); } // it is good, add it sourceLines.Add(tObj); } else { // no, we have not. This must be a tool table definition ExcellonLine_ToolTable tObj = new ExcellonLine_ToolTable(lineStr, tmpLine1, lineNumber); retInt = tObj.ParseLine(tmpLine1, StateMachine); if (retInt != 0) { LogMessage("lineStr(ToolTable), call to ParseLine returned " + retInt.ToString() + " Error on line " + lineNumber.ToString()); return(7012); } // it is good, add it sourceLines.Add(tObj); // add this to the tool collection StateMachine.ToolCollection.Add(tObj); } return(0); } } // Are we a "%" header Stop Code? else if (tmpLine1.StartsWith("%") == true) { ExcellonLine_Misc mObj = new ExcellonLine_Misc(lineStr, tmpLine1, lineNumber); retInt = mObj.ParseLine(tmpLine1, StateMachine); if (retInt != 0) { LogMessage("lineStr(%), call to ParseLine returned " + retInt.ToString() + " Error on line " + lineNumber.ToString()); return(704); } // it is good, add it sourceLines.Add(mObj); // note this now StateMachine.HeaderEndLine = lineNumber; return(0); } else if ((tmpLine1.StartsWith("X") || (tmpLine1.StartsWith("Y"))) == true) { ExcellonLine_XYCode xyObj = new ExcellonLine_XYCode(lineStr, tmpLine1, lineNumber); retInt = xyObj.ParseLine(tmpLine1, StateMachine); if (retInt != 0) { LogMessage("lineStr(XY), call to ParseLine returned " + retInt.ToString() + " Error on line " + lineNumber.ToString()); return(705); } // it is good, add it sourceLines.Add(xyObj); // record this RecordMinMaxXYCoords(xyObj.XCoord, xyObj.YCoord); return(0); } else if (tmpLine1.StartsWith("R") == true) { // several commands can start with R if ((tmpLine1.Contains("R,T") == true) || (tmpLine1.Contains("R,C") == true) || (tmpLine1.Contains("R,D") == true) || (tmpLine1.Contains("R,H") == true)) { // "R,T" just Reset Tool Data - ignore // "R,C" just Reset clocks - ignore // "R,CP" just Reset program clocks - ignore // "R,CR" just Reset run clocks - ignore // "R,D" just Reset All Cutter Distances - ignore // "R,H" just RReset All Hit Counters - ignore ExcellonLine_Misc mObj = new ExcellonLine_Misc(lineStr, tmpLine1, lineNumber); retInt = mObj.ParseLine(tmpLine1, StateMachine); if (retInt != 0) { LogMessage("lineStr(R,), call to ParseLine returned " + retInt.ToString() + " Error on line " + lineNumber.ToString()); return(804); } // it is good, add it sourceLines.Add(mObj); return(0); } else { // assume this ExcellonLine_RCode rObj = new ExcellonLine_RCode(lineStr, tmpLine1, lineNumber); retInt = rObj.ParseLine(tmpLine1, StateMachine); if (retInt != 0) { LogMessage("lineStr(R), call to ParseLine returned " + retInt.ToString() + " Error on line " + lineNumber.ToString()); return(706); } // it is good, add it sourceLines.Add(rObj); } return(0); } // Are we a "VER" flag else if (tmpLine1.StartsWith("VER") == true) { // we just ignore this ExcellonLine_Misc mObj = new ExcellonLine_Misc(lineStr, tmpLine1, lineNumber); retInt = mObj.ParseLine(tmpLine1, StateMachine); if (retInt != 0) { LogMessage("lineStr(ver), call to ParseLine returned " + retInt.ToString() + " Error on line " + lineNumber.ToString()); return(805); } // it is good, add it sourceLines.Add(mObj); return(0); } // Are we a "FMAT" flag else if (tmpLine1.StartsWith("FMAT") == true) { // we just ignore this ExcellonLine_Misc mObj = new ExcellonLine_Misc(lineStr, tmpLine1, lineNumber); retInt = mObj.ParseLine(tmpLine1, StateMachine); if (retInt != 0) { LogMessage("lineStr(FMAT), call to ParseLine returned " + retInt.ToString() + " Error on line " + lineNumber.ToString()); return(806); } // it is good, add it sourceLines.Add(mObj); return(0); } // Are we a "ATC" flag else if (tmpLine1.StartsWith("ATC") == true) { // we just ignore this ExcellonLine_Misc mObj = new ExcellonLine_Misc(lineStr, tmpLine1, lineNumber); retInt = mObj.ParseLine(tmpLine1, StateMachine); if (retInt != 0) { LogMessage("lineStr(ATC), call to ParseLine returned " + retInt.ToString() + " Error on line " + lineNumber.ToString()); return(8071); } // it is good, add it sourceLines.Add(mObj); return(0); } else if (tmpLine1.Length == 0) { // probably all comments or blank ExcellonLine_Misc mObj = new ExcellonLine_Misc(lineStr, tmpLine1, lineNumber); retInt = mObj.ParseLine(tmpLine1, StateMachine); if (retInt != 0) { LogMessage("lineStr(%), call to ParseLine returned " + retInt.ToString() + " Error on line " + lineNumber.ToString()); return(704); } // it is good, add it sourceLines.Add(mObj); return(0); } else { // if we get here we are a line of unknown type LogMessage("Unknown Excellon line type >" + lineStr + "< on line " + lineNumber.ToString()); if (lineStr.Length > 20) { throw new NotImplementedException("Cannot cope with unknown Excellon code on line " + lineNumber.ToString() + " code is >" + lineStr.Substring(0, 20) + "<"); } else { throw new NotImplementedException("Cannot cope with unknown Excellon code on line " + lineNumber.ToString() + " code is >" + lineStr + "<"); } } }