Add Gerber plot for SHAPE_ARC and SHAPE_LINE_CHAIN
This commit is contained in:
parent
013209046b
commit
3d4ce0796e
|
@ -826,6 +826,35 @@ void GERBER_PLOTTER::Arc( const wxPoint& aCenter, double aStAngle, double aEndAn
|
|||
}
|
||||
|
||||
|
||||
void GERBER_PLOTTER::plotArc( const SHAPE_ARC& aArc, bool aPlotInRegion )
|
||||
{
|
||||
wxPoint start( aArc.GetP0() );
|
||||
wxPoint end( aArc.GetP1() );
|
||||
wxPoint center( aArc.GetCenter() );
|
||||
double start_angle = aArc.GetStartAngle();
|
||||
double end_angle = aArc.GetEndAngle();
|
||||
|
||||
if( !aPlotInRegion )
|
||||
MoveTo( start);
|
||||
else
|
||||
LineTo( start );
|
||||
|
||||
DPOINT devEnd = userToDeviceCoordinates( end );
|
||||
DPOINT devCenter = userToDeviceCoordinates( center ) - userToDeviceCoordinates( start );
|
||||
|
||||
if( start_angle < end_angle )
|
||||
fprintf( m_outputFile, "G03*\n" ); // Active circular interpolation, CCW
|
||||
else
|
||||
fprintf( m_outputFile, "G02*\n" ); // Active circular interpolation, CW
|
||||
|
||||
fprintf( m_outputFile, "X%dY%dI%dJ%dD01*\n",
|
||||
KiROUND( devEnd.x ), KiROUND( devEnd.y ),
|
||||
KiROUND( devCenter.x ), KiROUND( devCenter.y ) );
|
||||
|
||||
fprintf( m_outputFile, "G01*\n" ); // Back to linear interpol (perhaps useless here).
|
||||
}
|
||||
|
||||
|
||||
void GERBER_PLOTTER::plotArc( const wxPoint& aCenter, double aStAngle, double aEndAngle,
|
||||
int aRadius, bool aPlotInRegion )
|
||||
{
|
||||
|
@ -858,8 +887,46 @@ void GERBER_PLOTTER::plotArc( const wxPoint& aCenter, double aStAngle, double aE
|
|||
}
|
||||
|
||||
|
||||
void GERBER_PLOTTER::PlotGerberRegion( const SHAPE_LINE_CHAIN& aPoly,
|
||||
void* aData )
|
||||
{
|
||||
if( aPoly.PointCount() <= 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(), m_outputFile );
|
||||
clearTA_AperFunction = true;
|
||||
}
|
||||
}
|
||||
|
||||
PlotPoly( aPoly, FILL_TYPE::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", m_outputFile );
|
||||
}
|
||||
else
|
||||
{
|
||||
fputs( "G04 #@! TD.AperFunction*\n", m_outputFile );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GERBER_PLOTTER::PlotGerberRegion( const std::vector< wxPoint >& aCornerList,
|
||||
void * aData )
|
||||
void* aData )
|
||||
{
|
||||
if( aCornerList.size() <= 2 )
|
||||
return;
|
||||
|
@ -895,6 +962,84 @@ void GERBER_PLOTTER::PlotGerberRegion( const std::vector< wxPoint >& aCornerList
|
|||
}
|
||||
}
|
||||
|
||||
void GERBER_PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aPoly,
|
||||
FILL_TYPE aFill, int aWidth, void* aData )
|
||||
{
|
||||
if( aPoly.CPoints().size() <= 1 )
|
||||
return;
|
||||
|
||||
// Gerber format does not know filled polygons with thick outline
|
||||
// Therefore, to plot a filled polygon with outline having a thickness,
|
||||
// one should plot outline as thick segments
|
||||
GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
|
||||
|
||||
if( gbr_metadata )
|
||||
formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
|
||||
|
||||
if( aFill != FILL_TYPE::NO_FILL )
|
||||
{
|
||||
fputs( "G36*\n", m_outputFile );
|
||||
|
||||
MoveTo( wxPoint( aPoly.CPoint( 0 ) ) );
|
||||
|
||||
fputs( "G01*\n", m_outputFile ); // Set linear interpolation.
|
||||
|
||||
for( int ii = 1; ii < aPoly.PointCount(); ii++ )
|
||||
{
|
||||
int arcindex = aPoly.ArcIndex( ii );
|
||||
|
||||
if( arcindex < 0 )
|
||||
{
|
||||
/// Plain point
|
||||
LineTo( wxPoint( aPoly.CPoint( ii ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
const SHAPE_ARC& arc = aPoly.Arc( arcindex );
|
||||
|
||||
plotArc( arc, ii > 0 );
|
||||
}
|
||||
}
|
||||
|
||||
// If the polygon is not closed, close it:
|
||||
if( aPoly.CPoint( 0 ) != aPoly.CPoint( -1 ) )
|
||||
FinishTo( wxPoint( aPoly.CPoint( 0 ) ) );
|
||||
|
||||
fputs( "G37*\n", m_outputFile );
|
||||
}
|
||||
|
||||
if( aWidth > 0 ) // Draw the polyline/polygon outline
|
||||
{
|
||||
SetCurrentLineWidth( aWidth, gbr_metadata );
|
||||
|
||||
MoveTo( wxPoint( aPoly.CPoint( 0 ) ) );
|
||||
|
||||
for( int ii = 1; ii < aPoly.PointCount(); ii++ )
|
||||
{
|
||||
int arcindex = aPoly.ArcIndex( ii );
|
||||
|
||||
if( arcindex < 0 )
|
||||
{
|
||||
/// Plain point
|
||||
LineTo( wxPoint( aPoly.CPoint( ii ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
const SHAPE_ARC& arc = aPoly.Arc( arcindex );
|
||||
|
||||
plotArc( arc, ii > 0 );
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the thick outline is closed for filled polygons
|
||||
// (if not filled, could be only a polyline)
|
||||
if( aFill != FILL_TYPE::NO_FILL && ( aPoly.CPoint( 0 ) != aPoly.CPoint( -1 ) ) )
|
||||
LineTo( wxPoint( aPoly.CPoint( 0 ) ) );
|
||||
|
||||
PenFinish();
|
||||
}
|
||||
}
|
||||
|
||||
void GERBER_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList,
|
||||
FILL_TYPE aFill, int aWidth, void * aData )
|
||||
{
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <plotter.h>
|
||||
#include "gbr_plotter_apertures.h"
|
||||
|
||||
class SHAPE_ARC;
|
||||
|
||||
class GERBER_PLOTTER : public PLOTTER
|
||||
{
|
||||
|
@ -97,6 +98,9 @@ public:
|
|||
FILL_TYPE aFill, int aWidth = USE_DEFAULT_LINE_WIDTH,
|
||||
void* aData = nullptr ) override;
|
||||
|
||||
virtual void PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_TYPE aFill,
|
||||
int aWidth = USE_DEFAULT_LINE_WIDTH, void * aData = NULL ) override;
|
||||
|
||||
virtual void PenTo( const wxPoint& pos, char plume ) override;
|
||||
|
||||
virtual void Text( const wxPoint& aPos,
|
||||
|
@ -166,6 +170,9 @@ public:
|
|||
void PlotGerberRegion( const std::vector< wxPoint >& aCornerList,
|
||||
void * aData = NULL );
|
||||
|
||||
void PlotGerberRegion( const SHAPE_LINE_CHAIN& aPoly,
|
||||
void * aData = NULL );
|
||||
|
||||
/**
|
||||
* Change the plot polarity and begin a new layer
|
||||
* Used to 'scratch off' silk screen away from solder mask
|
||||
|
@ -262,6 +269,7 @@ protected:
|
|||
*/
|
||||
void plotArc( const wxPoint& aCenter, double aStAngle, double aEndAngle,
|
||||
int aRadius, bool aPlotInRegion );
|
||||
void plotArc( const SHAPE_ARC& aArc, bool aPlotInRegion );
|
||||
|
||||
/**
|
||||
* Pick an existing aperture or create a new one, matching the
|
||||
|
|
|
@ -657,14 +657,7 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
|||
cornerList.clear();
|
||||
const SHAPE_LINE_CHAIN& path = (kk == 0) ? outlines.COutline( ii ) : outlines.CHole( ii, kk - 1 );
|
||||
|
||||
for( int jj = 0; jj < path.PointCount(); jj++ )
|
||||
cornerList.emplace_back( (wxPoint) path.CPoint( jj ) );
|
||||
|
||||
// Ensure the polygon is closed
|
||||
if( cornerList[0] != cornerList[cornerList.size() - 1] )
|
||||
cornerList.push_back( cornerList[0] );
|
||||
|
||||
aPlotter->PlotPoly( cornerList, FILL_TYPE::NO_FILL );
|
||||
aPlotter->PlotPoly( path, FILL_TYPE::NO_FILL );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -905,12 +898,8 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
|||
// Plot each initial shape (pads and polygons on mask layer), with suitable attributes:
|
||||
PlotStandardLayer( aBoard, aPlotter, aLayerMask, aPlotOpt );
|
||||
|
||||
// Add shapes corresponding to areas having too small thickness.
|
||||
std::vector<wxPoint> cornerList;
|
||||
|
||||
for( int ii = 0; ii < areas.OutlineCount(); ii++ )
|
||||
{
|
||||
cornerList.clear();
|
||||
const SHAPE_LINE_CHAIN& path = areas.COutline( ii );
|
||||
|
||||
// polygon area in mm^2 :
|
||||
|
@ -924,14 +913,7 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
|||
if( curr_area < poly_min_area_mm2 )
|
||||
continue;
|
||||
|
||||
for( int jj = 0; jj < path.PointCount(); jj++ )
|
||||
cornerList.emplace_back( (wxPoint) path.CPoint( jj ) );
|
||||
|
||||
// Ensure the polygon is closed
|
||||
if( cornerList[0] != cornerList[cornerList.size() - 1] )
|
||||
cornerList.push_back( cornerList[0] );
|
||||
|
||||
aPlotter->PlotPoly( cornerList, FILL_TYPE::FILLED_SHAPE );
|
||||
aPlotter->PlotPoly( path, FILL_TYPE::FILLED_SHAPE );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -779,9 +779,6 @@ void BRDITEMS_PLOTTER::PlotFilledAreas( const ZONE* aZone, const SHAPE_POLY_SET&
|
|||
}
|
||||
}
|
||||
|
||||
// We need a buffer to store corners coordinates:
|
||||
std::vector< wxPoint > cornerList;
|
||||
|
||||
m_plotter->SetColor( getColor( aZone->GetLayer() ) );
|
||||
|
||||
m_plotter->StartBlock( nullptr ); // Clean current object attributes
|
||||
|
@ -798,55 +795,42 @@ void BRDITEMS_PLOTTER::PlotFilledAreas( const ZONE* aZone, const SHAPE_POLY_SET&
|
|||
{
|
||||
const SHAPE_LINE_CHAIN& outline = polysList.Outline( idx );
|
||||
|
||||
cornerList.clear();
|
||||
cornerList.reserve( outline.PointCount() );
|
||||
|
||||
for( int ic = 0; ic < outline.PointCount(); ++ic )
|
||||
// Plot the current filled area (as region for Gerber plotter
|
||||
// to manage attributes) and its outline for thick outline
|
||||
if( GetPlotMode() == FILLED )
|
||||
{
|
||||
cornerList.emplace_back( wxPoint( outline.CPoint( ic ) ) );
|
||||
}
|
||||
|
||||
if( cornerList.size() ) // Plot the current filled area outline
|
||||
{
|
||||
// First, close the outline
|
||||
if( cornerList[0] != cornerList[cornerList.size() - 1] )
|
||||
cornerList.push_back( cornerList[0] );
|
||||
|
||||
// Plot the current filled area (as region for Gerber plotter
|
||||
// to manage attributes) and its outline for thick outline
|
||||
if( GetPlotMode() == FILLED )
|
||||
if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
|
||||
{
|
||||
if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
|
||||
if( outline_thickness > 0 )
|
||||
{
|
||||
if( outline_thickness > 0 )
|
||||
{
|
||||
m_plotter->PlotPoly( cornerList, FILL_TYPE::NO_FILL, outline_thickness,
|
||||
&gbr_metadata );
|
||||
}
|
||||
m_plotter->PlotPoly( outline, FILL_TYPE::NO_FILL,
|
||||
outline_thickness, &gbr_metadata );
|
||||
}
|
||||
|
||||
static_cast<GERBER_PLOTTER*>( m_plotter )->PlotGerberRegion( cornerList,
|
||||
&gbr_metadata );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_plotter->PlotPoly( cornerList, FILL_TYPE::FILLED_SHAPE, outline_thickness,
|
||||
&gbr_metadata );
|
||||
}
|
||||
static_cast<GERBER_PLOTTER*>( m_plotter )->PlotGerberRegion(
|
||||
outline, &gbr_metadata );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( outline_thickness )
|
||||
{
|
||||
for( unsigned jj = 1; jj < cornerList.size(); jj++ )
|
||||
{
|
||||
m_plotter->ThickSegment( cornerList[jj -1], cornerList[jj],
|
||||
outline_thickness, GetPlotMode(), &gbr_metadata );
|
||||
}
|
||||
}
|
||||
|
||||
m_plotter->SetCurrentLineWidth( -1 );
|
||||
m_plotter->PlotPoly( outline, FILL_TYPE::FILLED_SHAPE,
|
||||
outline_thickness, &gbr_metadata );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( outline_thickness )
|
||||
{
|
||||
for( int jj = 1; jj < outline.PointCount(); jj++ )
|
||||
{
|
||||
m_plotter->ThickSegment( wxPoint( outline.CPoint( jj - 1) ),
|
||||
wxPoint( outline.CPoint( jj ) ),
|
||||
outline_thickness,
|
||||
GetPlotMode(), &gbr_metadata );
|
||||
}
|
||||
}
|
||||
|
||||
m_plotter->SetCurrentLineWidth( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
m_plotter->EndBlock( nullptr ); // Clear object attributes
|
||||
|
|
Loading…
Reference in New Issue