From 542c57ff27feed2c20ad98e362e25cf1d7703333 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Mon, 26 Nov 2018 10:55:36 +0100 Subject: [PATCH] Gerbview, Excellon (NC) drill files reader: routing mode: better handling of malformed files. Routing mode starts by M15 (or G01, G02, G03) and ends by M16 or M17. Accept now a end routing if a G00 (start move) G05 (switch to drill mode) or M30 (end of file) is encountered. --- gerbview/excellon_image.h | 5 +- gerbview/excellon_read_drill_file.cpp | 117 +++++++++++++++----------- gerbview/files.cpp | 2 +- 3 files changed, 74 insertions(+), 50 deletions(-) diff --git a/gerbview/excellon_image.h b/gerbview/excellon_image.h index ea316e8bca..c2670ad020 100644 --- a/gerbview/excellon_image.h +++ b/gerbview/excellon_image.h @@ -31,7 +31,7 @@ enum drill_M_code_t { DRILL_M_END, DRILL_M_TOOL_DOWN, // tool down (starting a routed hole) DRILL_M_TOOL_UP, // tool up (ending a routed hole) - DRILL_M_ENDREWIND, + DRILL_M_ENDFILE, DRILL_M_MESSAGE, DRILL_M_LONGMESSAGE, DRILL_M_HEADER, @@ -187,6 +187,9 @@ private: return DCodeNumber( aText ); } + /** Ends a route command started by M15 ot G01, G02 or G03 command + */ + void FinishRouteCommand(); void SelectUnits( bool aMetric ); }; diff --git a/gerbview/excellon_read_drill_file.cpp b/gerbview/excellon_read_drill_file.cpp index 6a986d6ec0..85c4016b06 100644 --- a/gerbview/excellon_read_drill_file.cpp +++ b/gerbview/excellon_read_drill_file.cpp @@ -197,7 +197,7 @@ static EXCELLON_CMD excellonHeaderCmdList[] = { "M15", DRILL_M_TOOL_DOWN, 0 }, // tool down (starting a routed hole) { "M16", DRILL_M_TOOL_UP, 0 }, // tool up (ending a routed hole) { "M17", DRILL_M_TOOL_UP, 0 }, // tool up similar to M16 for a viewer - { "M30", DRILL_M_ENDREWIND, -1 }, // End of Program Rewind + { "M30", DRILL_M_ENDFILE, -1 }, // End of File (last line of NC drill) { "M47", DRILL_M_MESSAGE, -1 }, // Operator Message { "M45", DRILL_M_LONGMESSAGE, -1 }, // Long Operator message (use more than one line) { "M48", DRILL_M_HEADER, 0 }, // beginning of a header @@ -446,9 +446,11 @@ bool EXCELLON_IMAGE::Execute_HEADER_And_M_Command( char*& text ) break; case DRILL_M_END: - break; + case DRILL_M_ENDFILE: + // if a route command is in progress, finish it + if( m_RouteModeOn ) + FinishRouteCommand(); - case DRILL_M_ENDREWIND: break; case DRILL_M_MESSAGE: @@ -553,51 +555,7 @@ bool EXCELLON_IMAGE::Execute_HEADER_And_M_Command( char*& text ) break; case DRILL_M_TOOL_UP: // tool up (ending a routed polyline) - { - D_CODE* tool = GetDCODE( m_Current_Tool ); - - if( !tool ) - { - AddMessageToList( wxString::Format( "Unknown tool code %d", m_Current_Tool ) ); - break; - } - - for( size_t ii = 1; ii < m_RoutePositions.size(); ii++ ) - { - GERBER_DRAW_ITEM* gbritem = new GERBER_DRAW_ITEM( this ); - - if( m_RoutePositions[ii].m_rmode == 0 ) // linear routing - { - fillLineGBRITEM( gbritem, tool->m_Num_Dcode, - m_RoutePositions[ii-1].GetPos(), m_RoutePositions[ii].GetPos(), - tool->m_Size, false ); - } - else // circular (cw or ccw) routing - { - bool rot_ccw = m_RoutePositions[ii].m_rmode == ROUTE_CW; - int radius = m_RoutePositions[ii].m_radius; // Can be adjusted by computeCenter. - wxPoint center; - - if( m_RoutePositions[ii].m_arc_type_info == ARC_INFO_TYPE_CENTER ) - center = wxPoint( m_RoutePositions[ii].m_cx, m_RoutePositions[ii].m_cy ); - else - center = computeCenter( m_RoutePositions[ii-1].GetPos(), - m_RoutePositions[ii].GetPos(), radius, rot_ccw ); - - fillArcGBRITEM( gbritem, tool->m_Num_Dcode, - m_RoutePositions[ii-1].GetPos(), m_RoutePositions[ii].GetPos(), - center - m_RoutePositions[ii-1].GetPos(), - tool->m_Size, not rot_ccw , true, - false ); - } - - m_Drawings.Append( gbritem ); - - StepAndRepeatItem( *gbritem ); - } - - m_RoutePositions.clear(); - } + FinishRouteCommand(); break; } @@ -824,6 +782,10 @@ bool EXCELLON_IMAGE::Execute_EXCELLON_G_Command( char*& text ) case DRILL_G_ROUT: m_SlotOn = false; + + if( m_RouteModeOn ) + FinishRouteCommand(); + m_RouteModeOn = true; m_RoutePositions.clear(); m_LastArcDataType = ARC_INFO_TYPE_NONE; @@ -834,6 +796,10 @@ bool EXCELLON_IMAGE::Execute_EXCELLON_G_Command( char*& text ) case DRILL_G_DRILL: m_SlotOn = false; + + if( m_RouteModeOn ) + FinishRouteCommand(); + m_RouteModeOn = false; m_RoutePositions.clear(); m_LastArcDataType = ARC_INFO_TYPE_NONE; @@ -924,3 +890,58 @@ void EXCELLON_IMAGE::SelectUnits( bool aMetric ) m_FmtLen.x = m_FmtLen.y = fmtIntegerInch+fmtMantissaInch; } } + + +void EXCELLON_IMAGE::FinishRouteCommand() +{ + // Ends a route command started by M15 ot G01, G02 or G03 command + // if a route command is not in progress, do nothing + + if( !m_RouteModeOn ) + return; + + D_CODE* tool = GetDCODE( m_Current_Tool ); + + if( !tool ) + { + AddMessageToList( wxString::Format( "Unknown tool code %d", m_Current_Tool ) ); + return; + } + + for( size_t ii = 1; ii < m_RoutePositions.size(); ii++ ) + { + GERBER_DRAW_ITEM* gbritem = new GERBER_DRAW_ITEM( this ); + + if( m_RoutePositions[ii].m_rmode == 0 ) // linear routing + { + fillLineGBRITEM( gbritem, tool->m_Num_Dcode, + m_RoutePositions[ii-1].GetPos(), m_RoutePositions[ii].GetPos(), + tool->m_Size, false ); + } + else // circular (cw or ccw) routing + { + bool rot_ccw = m_RoutePositions[ii].m_rmode == ROUTE_CW; + int radius = m_RoutePositions[ii].m_radius; // Can be adjusted by computeCenter. + wxPoint center; + + if( m_RoutePositions[ii].m_arc_type_info == ARC_INFO_TYPE_CENTER ) + center = wxPoint( m_RoutePositions[ii].m_cx, m_RoutePositions[ii].m_cy ); + else + center = computeCenter( m_RoutePositions[ii-1].GetPos(), + m_RoutePositions[ii].GetPos(), radius, rot_ccw ); + + fillArcGBRITEM( gbritem, tool->m_Num_Dcode, + m_RoutePositions[ii-1].GetPos(), m_RoutePositions[ii].GetPos(), + center - m_RoutePositions[ii-1].GetPos(), + tool->m_Size, not rot_ccw , true, + false ); + } + + m_Drawings.Append( gbritem ); + + StepAndRepeatItem( *gbritem ); + } + + m_RoutePositions.clear(); + m_RouteModeOn = false; +} diff --git a/gerbview/files.cpp b/gerbview/files.cpp index 07d51aedfa..49345d06b0 100644 --- a/gerbview/files.cpp +++ b/gerbview/files.cpp @@ -378,7 +378,7 @@ bool GERBVIEW_FRAME::LoadExcellonFiles( const wxString& aFullFileName ) else currentPath = m_mruPath; - wxFileDialog dlg( this, _( "Open Excellon Drill File(s)" ), + wxFileDialog dlg( this, _( "Open NC (Excellon) Drill File(s)" ), currentPath, filename.GetFullName(), filetypes, wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE | wxFD_CHANGE_DIR );