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:
parent
fb1570d290
commit
2cd43aee0a
|
@ -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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue