From 51ed01d765b681f30a7d2cfdfaba0d71c43a903c Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Sun, 3 Nov 2019 20:23:31 +0100 Subject: [PATCH] GERBER_PLOTTER: small change in code to manage the current selected aperture. Avoid using an iterator to store this aperture because iterators can be invalided when modifying a list. Enhancements in gerber_placefile_writer. --- common/plotters/GERBER_plotter.cpp | 103 +++++++++---------- include/plotter.h | 31 +++--- pcbnew/exporters/gerber_placefile_writer.cpp | 67 ++++++------ 3 files changed, 100 insertions(+), 101 deletions(-) diff --git a/common/plotters/GERBER_plotter.cpp b/common/plotters/GERBER_plotter.cpp index 086a85baba..1d2610426e 100644 --- a/common/plotters/GERBER_plotter.cpp +++ b/common/plotters/GERBER_plotter.cpp @@ -47,7 +47,7 @@ GERBER_PLOTTER::GERBER_PLOTTER() { workFile = NULL; finalFile = NULL; - currentAperture = apertures.end(); + m_currentApertureIdx = -1; m_apertureAttribute = 0; // number of digits after the point (number of digits of the mantissa @@ -65,7 +65,7 @@ GERBER_PLOTTER::GERBER_PLOTTER() void GERBER_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil, - double aScale, bool aMirror ) + double aScale, bool aMirror ) { wxASSERT( aMirror == false ); m_plotMirror = false; @@ -101,8 +101,7 @@ void GERBER_PLOTTER::SetGerberCoordinatesFormat( int aResolution, bool aUseInche void GERBER_PLOTTER::emitDcode( const DPOINT& pt, int dcode ) { - fprintf( outputFile, "X%dY%dD%02d*\n", - KiROUND( pt.x ), KiROUND( pt.y ), dcode ); + fprintf( outputFile, "X%dY%dD%02d*\n", KiROUND( pt.x ), KiROUND( pt.y ), dcode ); } void GERBER_PLOTTER::ClearAllAttributes() @@ -282,7 +281,7 @@ bool GERBER_PLOTTER::EndPlot() void GERBER_PLOTTER::SetDefaultLineWidth( int width ) { defaultPenWidth = width; - currentAperture = apertures.end(); + m_currentApertureIdx = -1; } @@ -306,23 +305,20 @@ void GERBER_PLOTTER::SetCurrentLineWidth( int width, void* aData ) } -std::vector::iterator GERBER_PLOTTER::getAperture( const wxSize& aSize, +int GERBER_PLOTTER::GetOrCreateAperture( const wxSize& aSize, APERTURE::APERTURE_TYPE aType, int aApertureAttribute ) { int last_D_code = 9; // Search an existing aperture - std::vector::iterator tool = apertures.begin(); - - while( tool != apertures.end() ) + for( int idx = 0; idx < (int)m_apertures.size(); ++idx ) { + APERTURE* tool = &m_apertures[idx]; last_D_code = tool->m_DCode; if( (tool->m_Type == aType) && (tool->m_Size == aSize) && (tool->m_ApertureAttribute == aApertureAttribute) ) - return tool; - - ++tool; + return idx; } // Allocate a new aperture @@ -332,9 +328,9 @@ std::vector::iterator GERBER_PLOTTER::getAperture( const wxSize& aSize new_tool.m_DCode = last_D_code + 1; new_tool.m_ApertureAttribute = aApertureAttribute; - apertures.push_back( new_tool ); + m_apertures.push_back( new_tool ); - return apertures.end() - 1; + return m_apertures.size() - 1; } @@ -342,20 +338,20 @@ void GERBER_PLOTTER::selectAperture( const wxSize& aSize, APERTURE::APERTURE_TYPE aType, int aApertureAttribute ) { - bool change = ( currentAperture == apertures.end() ) || - ( currentAperture->m_Type != aType ) || - ( currentAperture->m_Size != aSize ); + bool change = ( m_currentApertureIdx < 0 ) || + ( m_apertures[m_currentApertureIdx].m_Type != aType ) || + ( m_apertures[m_currentApertureIdx].m_Size != aSize ); if( !m_useNetAttributes ) aApertureAttribute = 0; - else - change = change || ( currentAperture->m_ApertureAttribute != aApertureAttribute ); + else if( !change ) + change = m_apertures[m_currentApertureIdx].m_ApertureAttribute != aApertureAttribute; if( change ) { // Pick an existing aperture or create a new one - currentAperture = getAperture( aSize, aType, aApertureAttribute ); - fprintf( outputFile, "D%d*\n", currentAperture->m_DCode ); + m_currentApertureIdx = GetOrCreateAperture( aSize, aType, aApertureAttribute ); + fprintf( outputFile, "D%d*\n", m_apertures[m_currentApertureIdx].m_DCode ); } } @@ -387,8 +383,7 @@ void GERBER_PLOTTER::writeApertureList() useX1StructuredComment = true; // Init - for( std::vector::iterator tool = apertures.begin(); - tool != apertures.end(); ++tool ) + for( APERTURE& tool : m_apertures ) { // apertude sizes are in inch or mm, regardless the // coordinates format @@ -397,7 +392,7 @@ void GERBER_PLOTTER::writeApertureList() if(! m_gerberUnitInch ) fscale *= 25.4; // size in mm - int attribute = tool->m_ApertureAttribute; + int attribute = tool.m_ApertureAttribute; if( attribute != m_apertureAttribute ) { @@ -406,7 +401,7 @@ void GERBER_PLOTTER::writeApertureList() useX1StructuredComment ).c_str(), outputFile ); } - char* text = cbuf + sprintf( cbuf, "%%ADD%d", tool->m_DCode ); + char* text = cbuf + sprintf( cbuf, "%%ADD%d", tool.m_DCode ); /* Please note: the Gerber specs for mass parameters say that exponential syntax is *not* allowed and the decimal point should @@ -415,24 +410,24 @@ void GERBER_PLOTTER::writeApertureList() can't remove trailing zeros but thats not a problem, since nothing forbid it (the file is only slightly longer) */ - switch( tool->m_Type ) + switch( tool.m_Type ) { case APERTURE::AT_CIRCLE: - sprintf( text, "C,%#f*%%\n", tool->GetDiameter() * fscale ); + sprintf( text, "C,%#f*%%\n", tool.GetDiameter() * fscale ); break; case APERTURE::AT_RECT: - sprintf( text, "R,%#fX%#f*%%\n", tool->m_Size.x * fscale, - tool->m_Size.y * fscale ); + sprintf( text, "R,%#fX%#f*%%\n", tool.m_Size.x * fscale, + tool.m_Size.y * fscale ); break; case APERTURE::AT_PLOTTING: - sprintf( text, "C,%#f*%%\n", tool->m_Size.x * fscale ); + sprintf( text, "C,%#f*%%\n", tool.m_Size.x * fscale ); break; case APERTURE::AT_OVAL: - sprintf( text, "O,%#fX%#f*%%\n", tool->m_Size.x * fscale, - tool->m_Size.y * fscale ); + sprintf( text, "O,%#fX%#f*%%\n", tool.m_Size.x * fscale, + tool.m_Size.y * fscale ); break; case APERTURE::AT_REGULAR_POLY: @@ -446,8 +441,8 @@ void GERBER_PLOTTER::writeApertureList() case APERTURE::AT_REGULAR_POLY10: case APERTURE::AT_REGULAR_POLY11: case APERTURE::AT_REGULAR_POLY12: - sprintf( text, "P,%#fX%dX%#f*%%\n", tool->GetDiameter() * fscale, - tool->GetVerticeCount(), tool->GetRotation() ); + sprintf( text, "P,%#fX%dX%#f*%%\n", tool.GetDiameter() * fscale, + tool.GetVerticeCount(), tool.GetRotation() ); break; } @@ -695,7 +690,7 @@ void GERBER_PLOTTER::ThickRect( const wxPoint& p1, const wxPoint& p2, int width, wxPoint offsetp1( p1.x - (width - currentPenWidth) / 2, p1.y - (width - currentPenWidth) / 2 ); wxPoint offsetp2( p2.x + (width - currentPenWidth) / 2, - p2.y + (width - currentPenWidth) / 2 ); + p2.y + (width - currentPenWidth) / 2 ); Rect( offsetp1, offsetp2, NO_FILL, -1 ); offsetp1.x += (width - currentPenWidth); offsetp1.y += (width - currentPenWidth); @@ -858,27 +853,27 @@ void GERBER_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& aSize, break; default: // plot pad shape as polygon - { - // XXX to do: use an aperture macro to declare the rotated pad - wxPoint coord[4]; - // coord[0] is assumed the lower left - // coord[1] is assumed the upper left - // coord[2] is assumed the upper right - // coord[3] is assumed the lower right + { + // XXX to do: use an aperture macro to declare the rotated pad + wxPoint coord[4]; + // coord[0] is assumed the lower left + // coord[1] is assumed the upper left + // coord[2] is assumed the upper right + // coord[3] is assumed the lower right - /* Trace the outline. */ - coord[0].x = -size.x/2; // lower left - coord[0].y = size.y/2; - coord[1].x = -size.x/2; // upper left - coord[1].y = -size.y/2; - coord[2].x = size.x/2; // upper right - coord[2].y = -size.y/2; - coord[3].x = size.x/2; // lower right - coord[3].y = size.y/2; + /* Trace the outline. */ + coord[0].x = -size.x/2; // lower left + coord[0].y = size.y/2; + coord[1].x = -size.x/2; // upper left + coord[1].y = -size.y/2; + coord[2].x = size.x/2; // upper right + coord[2].y = -size.y/2; + coord[3].x = size.x/2; // lower right + coord[3].y = size.y/2; - FlashPadTrapez( pos, coord, orient, trace_mode, aData ); - } - break; + FlashPadTrapez( pos, coord, orient, trace_mode, aData ); + } + break; } } diff --git a/include/plotter.h b/include/plotter.h index 11cbd0001d..8a4ab2ea1c 100644 --- a/include/plotter.h +++ b/include/plotter.h @@ -1281,6 +1281,17 @@ public: */ void ClearAllAttributes(); + /** + * @return a index to the aperture in aperture list which meets the size and type of tool + * if the aperture does not exist, it is created and entered in aperture list + * @param aSize = the size of tool + * @param aType = the type ( shape ) of tool + * @param aApertureAttribute = an aperture attribute of the tool (a tool can have onlu one attribute) + * 0 = no specific attribute + */ + int GetOrCreateAperture( const wxSize& aSize, + APERTURE::APERTURE_TYPE aType, int aApertureAttribute ); + protected: /** * Pick an existing aperture or create a new one, matching the @@ -1321,20 +1332,8 @@ protected: */ void clearNetAttribute(); - // Remove all attributes from object attributes dictionary (TO. and TA commands) - /** - * Function getAperture returns a reference to the aperture which meets the size anf type of tool - * if the aperture does not exist, it is created and entered in aperture list - * @param aSize = the size of tool - * @param aType = the type ( shape ) of tool - * @param aApertureAttribute = an aperture attribute of the tool (a tool can have onlu one attribute) - * 0 = no specific attribute - */ - std::vector::iterator getAperture( const wxSize& aSize, - APERTURE::APERTURE_TYPE aType, int aApertureAttribute ); - - // the attributes dictionary created/modifed by %TO, attached the objects, when they are created - // by D01, D03 G36/G37 commands + // the attributes dictionary created/modifed by %TO, attached to objects, when they are created + // by D01, D03, G36/G37 commands // standard attributes are .P, .C and .N // this is used by gerber readers when creating a new object. Cleared by %TD command // Note: m_objectAttributesDictionnary can store more than one attribute @@ -1354,8 +1353,8 @@ protected: */ void writeApertureList(); - std::vector apertures; - std::vector::iterator currentAperture; + std::vector m_apertures; // The list of available apertures + int m_currentApertureIdx; // The index of the current aperture in m_apertures bool m_gerberUnitInch; // true if the gerber units are inches, false for mm int m_gerberUnitFmt; // number of digits in mantissa. diff --git a/pcbnew/exporters/gerber_placefile_writer.cpp b/pcbnew/exporters/gerber_placefile_writer.cpp index 74b4e95268..cfb8c7ae1d 100644 --- a/pcbnew/exporters/gerber_placefile_writer.cpp +++ b/pcbnew/exporters/gerber_placefile_writer.cpp @@ -109,31 +109,22 @@ int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, plotter.StartPlot(); - if( aIncludeBrdEdges ) - { - brd_plotter.SetLayerSet( LSET( Edge_Cuts ) ); - - // Plot edge layer and graphic items - brd_plotter.PlotBoardGraphicItems(); - - // Draw footprint other graphic items: - for( MODULE* footprint : fp_list ) - { - for( auto item : footprint->GraphicalItems() ) - { - if( item->Type() == PCB_MODULE_EDGE_T && item->GetLayer() == Edge_Cuts ) - brd_plotter.Plot_1_EdgeModule( (EDGE_MODULE*) item ); - } - } - } + // Some tools in P&P files have the type and size defined. + // they are position flash (round), pad1 flash (diamond), other pads flash (round) + // and component outline thickness (polyline) + int flash_position_shape_diam = Millimeter2iu( 0.3 ); // defined size for position shape (circle) + int pad1_mark_size = Millimeter2iu( 0.36 ); // defined size for pad 1 position (diamond) + int other_pads_mark_size = 0; // defined size for position shape (circle) + int line_thickness = Millimeter2iu( 0.1 ); // defined size for component outlines brd_plotter.SetLayerSet( LSET( aLayer ) ); int cmp_count = 0; bool allowUtf8 = true; + // Plot components data: position, outlines, pad1 and other pads. for( MODULE* footprint : fp_list ) { - // Manage the aperture attributes: in drill files 3 attributes can be used: + // Manage the aperture attribute component position: GBR_METADATA gbr_metadata; gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CMP_POSITION ); @@ -178,8 +169,7 @@ int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, wxPoint flash_pos = footprint->GetPosition() + m_offset; - int flash_diam = Millimeter2iu( 0.3 ); // arbitrary but reasonable value - plotter.FlashPadCircle( flash_pos, flash_diam, FILLED, &gbr_metadata ); + plotter.FlashPadCircle( flash_pos, flash_position_shape_diam, FILLED, &gbr_metadata ); gbr_metadata.m_NetlistMetadata.ClearExtraData(); // Now some extra metadata is output, avoid blindly clearing the full metadata list @@ -191,7 +181,6 @@ int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, if( footprint->BuildPolyCourtyard() ) { - int thickness = Millimeter2iu( 0.1 ); // arbitrary but reasonable value gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CMP_COURTYARD ); SHAPE_POLY_SET& courtyard = aLayer == B_Cu ? @@ -207,13 +196,12 @@ int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, poly.Move( m_offset ); useFpPadsBbox = false; - plotter.PLOTTER::PlotPoly( poly, NO_FILL, thickness, &gbr_metadata ); + plotter.PLOTTER::PlotPoly( poly, NO_FILL, line_thickness, &gbr_metadata ); } } if( useFpPadsBbox ) { - int thickness = Millimeter2iu( 0.1 ); // arbitrary but reasonable value gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CMP_FOOTPRINT ); // bbox of fp pads, pos 0, rot 0, non flipped @@ -232,7 +220,7 @@ int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, poly.Rotate( -footprint->GetOrientationRadians(), VECTOR2I( 0, 0 ) ); poly.Move( footprint->GetPosition() + m_offset ); - plotter.PLOTTER::PlotPoly( poly, NO_FILL, thickness, &gbr_metadata ); + plotter.PLOTTER::PlotPoly( poly, NO_FILL, line_thickness, &gbr_metadata ); } std::vectorpad_key_list; @@ -249,11 +237,9 @@ int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, gbr_metadata.SetPadName( pad1->GetName() ); gbr_metadata.SetNetAttribType( GBR_NETLIST_METADATA::GBR_NETINFO_PAD ); - // Flashes a diamond at pad position: use a slightly bigger size than the - // round spot to be able to see these 2 shapes when drawn at the same location - int mark_size = (flash_diam*6)/5; - plotter.FlashRegularPolygon( pad1->GetPosition() + m_offset, mark_size, 4, - 0.0, FILLED, &gbr_metadata ); + // Flashes a diamond at pad position: + plotter.FlashRegularPolygon( pad1->GetPosition() + m_offset, pad1_mark_size, + 4, 0.0, FILLED, &gbr_metadata ); } } @@ -288,8 +274,7 @@ int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, gbr_metadata.SetPadName( pad->GetName() ); // Flashes a round, 0 sized round shape at pad position - int mark_size = 0; - plotter.FlashPadCircle( pad->GetPosition() + m_offset, mark_size, + plotter.FlashPadCircle( pad->GetPosition() + m_offset, other_pads_mark_size, FILLED, &gbr_metadata ); } } @@ -299,6 +284,26 @@ int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, cmp_count++; } + // Plot board outlines, if requested + if( aIncludeBrdEdges ) + { + brd_plotter.SetLayerSet( LSET( Edge_Cuts ) ); + + // Plot edge layer and graphic items + brd_plotter.PlotBoardGraphicItems(); + + // Draw footprint other graphic items: + for( MODULE* footprint : fp_list ) + { + for( auto item : footprint->GraphicalItems() ) + { + if( item->Type() == PCB_MODULE_EDGE_T && item->GetLayer() == Edge_Cuts ) + brd_plotter.Plot_1_EdgeModule( (EDGE_MODULE*) item ); + } + } + } + + plotter.EndPlot(); return cmp_count;