Gerber output: fix some (minor) issues related to attributes when plotting polygonal pads.

rect (when not horizontal or vertical), trapezoid and custom shapes are draw as polygons.

The dummy pad used to give attributes is removed, and TO attributes are used in Regions (polygons in Gerber dialect)

This is due to some modifications in Gerber format since the attributes are added in Kicad.
This commit is contained in:
jean-pierre charras 2019-10-23 18:57:21 +02:00
parent fb1570d290
commit 2cd43aee0a
2 changed files with 71 additions and 87 deletions

View File

@ -498,7 +498,45 @@ void GERBER_PLOTTER::Arc( const wxPoint& aCenter, double aStAngle, double aEndAn
} }
void GERBER_PLOTTER:: PlotPoly( const std::vector< wxPoint >& aCornerList, void GERBER_PLOTTER::PlotGerberRegion( const std::vector< wxPoint >& aCornerList,
void * aData )
{
if( aCornerList.size() <= 2 )
return;
GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
bool clearTA_AperFunction = false; // true if a TA.AperFunction is used
if( gbr_metadata )
{
std::string attrib = gbr_metadata->m_ApertureMetadata.FormatAttribute( !m_useX2format );
if( !attrib.empty() )
{
fputs( attrib.c_str(), outputFile );
clearTA_AperFunction = true;
}
}
PlotPoly( aCornerList, FILLED_SHAPE, 0 , gbr_metadata );
// Clear the TA attribute, to avoid the next item to inherit it:
if( clearTA_AperFunction )
{
if( m_useX2format )
{
fputs( "%TD.AperFunction*%\n", outputFile );
}
else
{
fputs( "G04 #@! TD.AperFunction*\n", outputFile );
}
}
}
void GERBER_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList,
FILL_T aFill, int aWidth, void * aData ) FILL_T aFill, int aWidth, void * aData )
{ {
if( aCornerList.size() <= 1 ) if( aCornerList.size() <= 1 )
@ -679,7 +717,7 @@ void GERBER_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, doub
wxSize size( aSize ); wxSize size( aSize );
GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData ); GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
/* Plot a flashed shape. */ // Flash a vertical or horizontal shape (this is a basic aperture).
if( ( orient == 0 || orient == 900 || orient == 1800 || orient == 2700 ) if( ( orient == 0 || orient == 900 || orient == 1800 || orient == 2700 )
&& trace_mode == FILLED ) && trace_mode == FILLED )
{ {
@ -695,7 +733,8 @@ void GERBER_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, doub
emitDcode( pos_dev, 3 ); emitDcode( pos_dev, 3 );
} }
else /* Plot pad as a segment. */ else // Plot pad as region.
// Only regions and flashed items accept a object attribute TO.P for the pin name
{ {
if( size.x > size.y ) if( size.x > size.y )
{ {
@ -710,10 +749,8 @@ void GERBER_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, doub
if( trace_mode == FILLED ) if( trace_mode == FILLED )
{ {
// TODO: use an aperture macro to declare the rotated pad // TODO: use an aperture macro to declare the rotated pad
// to be able to flash the shape
// Flash a pad anchor, if a netlist attribute is set // For now, the pad is drawn as segment
if( aData )
FlashPadCircle( pos, size.x, trace_mode, aData );
// The pad is reduced to an segment with dy > dx // The pad is reduced to an segment with dy > dx
int delta = size.y - size.x; int delta = size.y - size.x;
@ -744,9 +781,7 @@ void GERBER_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, doub
size.x, trace_mode, &metadata ); size.x, trace_mode, &metadata );
} }
else else
{
sketchOval( pos, size, orient, -1 ); sketchOval( pos, size, orient, -1 );
}
} }
} }
@ -824,22 +859,7 @@ void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS
EDA_DRAW_MODE_T aTraceMode, void* aData ) EDA_DRAW_MODE_T aTraceMode, void* aData )
{ {
GBR_METADATA gbr_metadata; GBR_METADATA *gbr_metadata = static_cast<GBR_METADATA*>( aData );
if( aData )
{
gbr_metadata = *static_cast<GBR_METADATA*>( aData );
// If the pad is drawn on a copper layer,
// set attribute to GBR_APERTURE_ATTRIB_CONDUCTOR
if( gbr_metadata.IsCopper() )
gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CONDUCTOR );
wxString attrname( ".P" );
gbr_metadata.m_NetlistMetadata.ClearAttribute( &attrname ); // not allowed on inner layers
}
if( aTraceMode != FILLED )
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, &gbr_metadata );
// Currently, a Pad RoundRect is plotted as polygon. // Currently, a Pad RoundRect is plotted as polygon.
// TODO: use Aperture macro and flash it // TODO: use Aperture macro and flash it
@ -849,7 +869,10 @@ void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS
aCornerRadius, segmentToCircleCount ); aCornerRadius, segmentToCircleCount );
if( aTraceMode != FILLED ) if( aTraceMode != FILLED )
{
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, &gbr_metadata );
outline.Inflate( -GetCurrentLineWidth()/2, 16 ); outline.Inflate( -GetCurrentLineWidth()/2, 16 );
}
std::vector< wxPoint > cornerList; std::vector< wxPoint > cornerList;
// TransformRoundRectToPolygon creates only one convex polygon // TransformRoundRectToPolygon creates only one convex polygon
@ -862,45 +885,24 @@ void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS
// Close polygon // Close polygon
cornerList.push_back( cornerList[0] ); cornerList.push_back( cornerList[0] );
PlotPoly( cornerList, aTraceMode == FILLED ? FILLED_SHAPE : NO_FILL, if( aTraceMode == SKETCH )
aTraceMode == FILLED ? 0 : GetCurrentLineWidth(), &gbr_metadata ); PlotPoly( cornerList, NO_FILL, GetCurrentLineWidth(), gbr_metadata );
else
// Now, flash a pad anchor, if a netlist attribute is set PlotGerberRegion( cornerList, gbr_metadata );
// (remove me when a Aperture macro will be used)
if( aData && aTraceMode == FILLED )
{
int diameter = std::min( aSize.x, aSize.y );
FlashPadCircle( aPadPos, diameter, aTraceMode , aData );
}
} }
void GERBER_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, void GERBER_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize,
SHAPE_POLY_SET* aPolygons, SHAPE_POLY_SET* aPolygons,
EDA_DRAW_MODE_T aTraceMode, void* aData ) EDA_DRAW_MODE_T aTraceMode, void* aData )
{ {
// A Pad custom is plotted as polygon. // A Pad custom is plotted as Gerber region.
// A flashed circle @aPadPos is added (anchor pad)
// However, because the anchor pad can be circle or rect, we use only
// a circle not bigger than the rect.
// the main purpose is to print a flashed DCode as pad anchor
if( aTraceMode == FILLED )
FlashPadCircle( aPadPos, std::min( aSize.x, aSize.y ), aTraceMode, aData );
GBR_METADATA gbr_metadata; GBR_METADATA gbr_metadata;
if( aData ) if( aData )
{
gbr_metadata = *static_cast<GBR_METADATA*>( aData ); gbr_metadata = *static_cast<GBR_METADATA*>( aData );
// If the pad is drawn on a copper layer,
// set attribute to GBR_APERTURE_ATTRIB_CONDUCTOR
if( gbr_metadata.IsCopper() )
gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CONDUCTOR );
wxString attrname( ".P" );
gbr_metadata.m_NetlistMetadata.ClearAttribute( &attrname ); // not allowed on inner layers
}
SHAPE_POLY_SET polyshape = *aPolygons; SHAPE_POLY_SET polyshape = *aPolygons;
@ -924,9 +926,10 @@ void GERBER_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize
// Close polygon // Close polygon
cornerList.push_back( cornerList[0] ); cornerList.push_back( cornerList[0] );
PlotPoly( cornerList, if( aTraceMode == SKETCH )
aTraceMode == FILLED ? FILLED_SHAPE : NO_FILL, PlotPoly( cornerList, NO_FILL, GetCurrentLineWidth(), &gbr_metadata );
aTraceMode == FILLED ? 0 : GetCurrentLineWidth(), &gbr_metadata ); else
PlotGerberRegion( cornerList, &gbr_metadata );
} }
} }
@ -944,25 +947,6 @@ void GERBER_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint* aCo
for( int ii = 0; ii < 4; ii++ ) for( int ii = 0; ii < 4; ii++ )
cornerList.push_back( aCorners[ii] ); cornerList.push_back( aCorners[ii] );
// Now, flash a pad anchor, if a netlist attribute is set
// (remove me when a Aperture macro will be used)
if( aData && ( aTrace_Mode == FILLED ) )
{
// Calculate the radius of the circle inside the shape
// It is the smaller dist from shape pos to edges
int radius = INT_MAX;
for( unsigned ii = 0, jj = cornerList.size()-1; ii < cornerList.size();
jj = ii, ii++ )
{
SEG segment( aCorners[ii], aCorners[jj] );
int dist = segment.LineDistance( VECTOR2I( 0, 0) );
radius = std::min( radius, dist );
}
FlashPadCircle( aPadPos, radius*2, aTrace_Mode, aData );
}
// Draw the polygon and fill the interior as required // Draw the polygon and fill the interior as required
for( unsigned ii = 0; ii < 4; ii++ ) for( unsigned ii = 0; ii < 4; ii++ )
{ {
@ -977,21 +961,12 @@ void GERBER_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint* aCo
GBR_METADATA metadata; GBR_METADATA metadata;
if( gbr_metadata ) if( gbr_metadata )
{
metadata = *gbr_metadata; metadata = *gbr_metadata;
// If the pad is drawn on a copper layer,
// set attribute to GBR_APERTURE_ATTRIB_CONDUCTOR
if( metadata.IsCopper() )
metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CONDUCTOR );
wxString attrname( ".P" ); if( aTrace_Mode == SKETCH )
metadata.m_NetlistMetadata.ClearAttribute( &attrname ); // not allowed on inner layers PlotPoly( cornerList, NO_FILL, USE_DEFAULT_LINE_WIDTH, &metadata );
} else
PlotGerberRegion( cornerList, &metadata );
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, &metadata );
PlotPoly( cornerList, aTrace_Mode == FILLED ? FILLED_SHAPE : NO_FILL,
aTrace_Mode == FILLED ? 0 : GetCurrentLineWidth(),
&metadata );
} }

View File

@ -1135,6 +1135,14 @@ public:
virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners, virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners,
double aPadOrient, EDA_DRAW_MODE_T aTraceMode, void* aData ) override; double aPadOrient, EDA_DRAW_MODE_T aTraceMode, void* aData ) override;
/**
* Plot a Gerber region: similar to PlotPoly but plot only filled polygon,
* and add the TA.AperFunction if aData contains this attribute, and clear it
* after plotting
*/
void PlotGerberRegion( const std::vector< wxPoint >& aCornerList,
void * aData = NULL );
/** /**
* Change the plot polarity and begin a new layer * Change the plot polarity and begin a new layer
* Used to 'scratch off' silk screen away from solder mask * Used to 'scratch off' silk screen away from solder mask
@ -1171,6 +1179,7 @@ public:
*/ */
virtual void EndBlock( void* aData ) override; virtual void EndBlock( void* aData ) override;
protected: protected:
/** /**
* Pick an existing aperture or create a new one, matching the * Pick an existing aperture or create a new one, matching the