@ -520,16 +520,29 @@ void GERBER_PLOTTER::Arc( const wxPoint& aCenter, double aStAngle, double aEndAn
{
SetCurrentLineWidth ( aWidth ) ;
// aFill is not used here.
plotArc ( aCenter , aStAngle , aEndAngle , aRadius , false ) ;
}
void GERBER_PLOTTER : : plotArc ( const wxPoint & aCenter , double aStAngle , double aEndAngle ,
int aRadius , bool aPlotInRegion )
{
wxPoint start , end ;
start . x = aCenter . x + KiROUND ( cosdecideg ( aRadius , aStAngle ) ) ;
start . y = aCenter . y - KiROUND ( sindecideg ( aRadius , aStAngle ) ) ;
MoveTo ( start ) ;
if ( ! aPlotInRegion )
MoveTo ( start ) ;
else
LineTo ( start ) ;
end . x = aCenter . x + KiROUND ( cosdecideg ( aRadius , aEndAngle ) ) ;
end . y = aCenter . y - KiROUND ( sindecideg ( aRadius , aEndAngle ) ) ;
DPOINT devEnd = userToDeviceCoordinates ( end ) ;
DPOINT devCenter = userToDeviceCoordinates ( aCenter ) - userToDeviceCoordinates ( start ) ;
fprintf ( outputFile , " G75* \n " ) ; // Multiquadrant (360 degrees) mode
fprintf ( outputFile , " G75* \n " ) ; // Multiquadrant (360 degrees) mode
if ( aStAngle < aEndAngle )
fprintf ( outputFile , " G03* \n " ) ; // Active circular interpolation, CCW
@ -855,16 +868,14 @@ void GERBER_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& aSize,
}
break ;
default : // plot pad shape as polyg on
default : // plot pad shape as Gerber regi on
{
// 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
@ -887,35 +898,172 @@ void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS
{
GBR_METADATA * gbr_metadata = static_cast < GBR_METADATA * > ( aData ) ;
// Currently, a Pad RoundRect is plotted as polygon.
// TODO: use Aperture macro and flash it
SHAPE_POLY_SET outline ;
TransformRoundChamferedRectToPolygon ( outline , aPadPos , aSize , aOrient ,
aCornerRadius , 0.0 , 0 , GetPlotterArcHighDef ( ) ) ;
if ( aTraceMode ! = FILLED )
{
SHAPE_POLY_SET outline ;
TransformRoundChamferedRectToPolygon ( outline , aPadPos , aSize , aOrient ,
aCornerRadius , 0.0 , 0 , GetPlotterArcHighDef ( ) ) ;
SetCurrentLineWidth ( USE_DEFAULT_LINE_WIDTH , & gbr_metadata ) ;
outline . Inflate ( - GetCurrentLineWidth ( ) / 2 , 16 ) ;
}
std : : vector < wxPoint > cornerList ;
// TransformRoundRectToPolygon creates only one convex polygon
SHAPE_LINE_CHAIN & poly = outline . Outline ( 0 ) ;
cornerList . reserve ( poly . PointCount ( ) + 1 ) ;
std : : vector < wxPoint > cornerList ;
// TransformRoundRectToPolygon creates only one convex polygon
SHAPE_LINE_CHAIN & poly = outline . Outline ( 0 ) ;
cornerList . reserve ( poly . PointCount ( ) + 1 ) ;
for ( int ii = 0 ; ii < poly . PointCount ( ) ; + + ii )
cornerList . emplace_back ( poly . CPoint ( ii ) . x , poly . CPoint ( ii ) . y ) ;
for ( int ii = 0 ; ii < poly . PointCount ( ) ; + + ii )
cornerList . emplace_back ( poly . CPoint ( ii ) . x , poly . CPoint ( ii ) . y ) ;
// Close polygon
cornerList . push_back ( cornerList [ 0 ] ) ;
// Close polygon
cornerList . push_back ( cornerList [ 0 ] ) ;
if ( aTraceMode = = SKETCH )
// plot outlines
PlotPoly ( cornerList , NO_FILL , GetCurrentLineWidth ( ) , gbr_metadata ) ;
}
else
PlotGerberRegion ( cornerList , gbr_metadata ) ;
{
// A Pad RoundRect is plotted as a Gerber region.
// Initialize region metadata:
bool clearTA_AperFunction = false ; // true if a TA.AperFunction is used
if ( gbr_metadata )
{
formatNetAttribute ( & gbr_metadata - > m_NetlistMetadata ) ;
std : : string attrib = gbr_metadata - > m_ApertureMetadata . FormatAttribute ( ! m_useX2format ) ;
if ( ! attrib . empty ( ) )
{
fputs ( attrib . c_str ( ) , outputFile ) ;
clearTA_AperFunction = true ;
}
}
// Plot the region using arcs in corners.
plotRoundRectAsRegion ( aPadPos , aSize , aCornerRadius , aOrient ) ;
// 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 : : plotRoundRectAsRegion ( const wxPoint & aRectCenter , const wxSize & aSize ,
int aCornerRadius , double aOrient )
{
// The region outline is generated by 4 sides and 4 90 deg arcs
// 1 --- 2
// | c |
// 4 --- 3
// Note also in user coordinates the Y axis is from top to bottom
// for historical reasons.
// A helper structure to handle outlines coordinates (segments and arcs)
// in user coordinates
struct RR_EDGE
{
wxPoint m_start ;
wxPoint m_end ;
wxPoint m_center ;
// in decidegrees: angle start. angle end = m_arc_angle_start+arc_angle
double m_arc_angle_start ;
} ;
const double arc_angle = - 900.0 ; // in decidegrees
int hsizeX = aSize . x / 2 ;
int hsizeY = aSize . y / 2 ;
RR_EDGE curr_edge ;
std : : vector < RR_EDGE > rr_outline ;
// Build outline coordinates, relative to rectangle center, rotation 0:
// Top left corner 1 (and 4 to 1 left vertical side @ x=-hsizeX)
curr_edge . m_start . x = - hsizeX ;
curr_edge . m_start . y = hsizeY - aCornerRadius ;
curr_edge . m_end . x = curr_edge . m_start . x ;
curr_edge . m_end . y = - hsizeY + aCornerRadius ;
curr_edge . m_center . x = - hsizeX + aCornerRadius ;
curr_edge . m_center . y = curr_edge . m_end . y ;
curr_edge . m_arc_angle_start = aOrient + 1800.0 ; // En decidegree
rr_outline . push_back ( curr_edge ) ;
// Top right corner 2 (and 1 to 2 top horizontal side @ y=-hsizeY)
curr_edge . m_start . x = - hsizeX + aCornerRadius ;
curr_edge . m_start . y = - hsizeY ;
curr_edge . m_end . x = hsizeX - aCornerRadius ;
curr_edge . m_end . y = curr_edge . m_start . y ;
curr_edge . m_center . x = curr_edge . m_end . x ;
curr_edge . m_center . y = - hsizeY + aCornerRadius ;
curr_edge . m_arc_angle_start = aOrient + 900.0 ; // En decidegree
rr_outline . push_back ( curr_edge ) ;
// bottom right corner 3 (and 2 to 3 right vertical side @ x=hsizeX)
curr_edge . m_start . x = hsizeX ;
curr_edge . m_start . y = - hsizeY + aCornerRadius ;
curr_edge . m_end . x = curr_edge . m_start . x ;
curr_edge . m_end . y = hsizeY - aCornerRadius ;
curr_edge . m_center . x = hsizeX - aCornerRadius ;
curr_edge . m_center . y = curr_edge . m_end . y ;
curr_edge . m_arc_angle_start = aOrient + 0.0 ; // En decidegree
rr_outline . push_back ( curr_edge ) ;
// bottom left corner 4 (and 3 to 4 bottom horizontal side @ y=hsizeY)
curr_edge . m_start . x = hsizeX - aCornerRadius ;
curr_edge . m_start . y = hsizeY ;
curr_edge . m_end . x = - hsizeX + aCornerRadius ;
curr_edge . m_end . y = curr_edge . m_start . y ;
curr_edge . m_center . x = curr_edge . m_end . x ;
curr_edge . m_center . y = hsizeY - aCornerRadius ;
curr_edge . m_arc_angle_start = aOrient - 900.0 ; // En decidegree
rr_outline . push_back ( curr_edge ) ;
// Move relative coordinates to the actual location and rotation:
for ( RR_EDGE & rr_edge : rr_outline )
{
RotatePoint ( & rr_edge . m_start , aOrient ) ;
RotatePoint ( & rr_edge . m_end , aOrient ) ;
RotatePoint ( & rr_edge . m_center , aOrient ) ;
rr_edge . m_start + = aRectCenter ;
rr_edge . m_end + = aRectCenter ;
rr_edge . m_center + = aRectCenter ;
}
fputs ( " G36* \n " , outputFile ) ; // Start region
fputs ( " G01* \n " , outputFile ) ; // Set linear interpolation.
MoveTo ( rr_outline [ 0 ] . m_start ) ; // Start point of region
for ( RR_EDGE & rr_edge : rr_outline )
{
if ( aCornerRadius ) // Guard: ensure we do not create arcs with radius = 0
{
// LineTo( rr_edge.m_end ); // made in plotArc()
plotArc ( rr_edge . m_center , rr_edge . m_arc_angle_start , rr_edge . m_arc_angle_start + arc_angle ,
aCornerRadius , true ) ;
}
else
LineTo ( rr_edge . m_end ) ;
}
fputs ( " G37* \n " , outputFile ) ; // Close region
}
void GERBER_PLOTTER : : FlashPadCustom ( const wxPoint & aPadPos , const wxSize & aSize ,
SHAPE_POLY_SET * aPolygons ,
EDA_DRAW_MODE_T aTraceMode , void * aData )