Alex Shvartzkop 2023-08-22 16:06:53 +03:00
parent e98dfa2bfc
commit 10e2e4a12d
25 changed files with 183 additions and 336 deletions

View File

@ -339,12 +339,12 @@ void CAIRO_GAL_BASE::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
void CAIRO_GAL_BASE::DrawArc( const VECTOR2D& aCenterPoint, double aRadius,
const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aEndAngle )
const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aAngle )
{
syncLineWidth();
double startAngle = aStartAngle.AsRadians();
double endAngle = aEndAngle.AsRadians();
double endAngle = startAngle + aAngle.AsRadians();
// calculate start and end arc angles according to the rotation transform matrix
// and normalize:
@ -378,7 +378,7 @@ void CAIRO_GAL_BASE::DrawArc( const VECTOR2D& aCenterPoint, double aRadius,
void CAIRO_GAL_BASE::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aEndAngle,
const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aAngle,
double aWidth, double aMaxError )
{
// Note: aMaxError is not used because Cairo can draw true arcs
@ -387,7 +387,7 @@ void CAIRO_GAL_BASE::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadiu
m_lineWidth = aWidth;
m_isStrokeEnabled = true;
m_isFillEnabled = false;
DrawArc( aCenterPoint, aRadius, aStartAngle, aEndAngle );
DrawArc( aCenterPoint, aRadius, aStartAngle, aAngle );
m_isFillEnabled = true;
m_isStrokeEnabled = false;
return;
@ -398,7 +398,7 @@ void CAIRO_GAL_BASE::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadiu
// calculate start and end arc angles according to the rotation transform matrix
// and normalize:
double startAngleS = aStartAngle.AsRadians();
double endAngleS = aEndAngle.AsRadians();
double endAngleS = startAngleS + aAngle.AsRadians();
arc_angles_xform_and_normalize( startAngleS, endAngleS );
double r = xform( aRadius );

View File

@ -892,16 +892,16 @@ void OPENGL_GAL::drawCircle( const VECTOR2D& aCenterPoint, double aRadius, bool
void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius,
const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aEndAngle )
const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aAngle )
{
if( aRadius <= 0 )
return;
double startAngle = aStartAngle.AsRadians();
double endAngle = aEndAngle.AsRadians();
double endAngle = startAngle + aAngle.AsRadians();
while( endAngle < startAngle )
endAngle += M_PI * 2;
// Normalize arc angles
SWAP( startAngle, >, endAngle );
const double alphaIncrement = calcAngleStep( aRadius );
@ -964,7 +964,7 @@ void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius,
void OPENGL_GAL::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aEndAngle,
const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aAngle,
double aWidth, double aMaxError )
{
if( aRadius <= 0 )
@ -977,7 +977,7 @@ void OPENGL_GAL::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
}
double startAngle = aStartAngle.AsRadians();
double endAngle = aEndAngle.AsRadians();
double endAngle = startAngle + aAngle.AsRadians();
// Swap the angles, if start angle is greater than end angle
SWAP( startAngle, >, endAngle );

View File

@ -657,20 +657,20 @@ void DXF_PLOTTER::ThickSegment( const VECTOR2I& aStart, const VECTOR2I& aEnd, in
void DXF_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill, int aWidth )
const EDA_ANGLE& aAngle, double aRadius, FILL_T aFill, int aWidth )
{
wxASSERT( m_outputFile );
if( aRadius <= 0 )
return;
EDA_ANGLE startAngle( aStartAngle );
EDA_ANGLE endAngle( aEndAngle );
EDA_ANGLE startAngle = -aStartAngle;
EDA_ANGLE endAngle = startAngle - aAngle;
// In DXF, arcs are drawn CCW.
// If startAngle > endAngle, it is CW. So transform it to CCW
while( endAngle < startAngle )
endAngle += ANGLE_360;
if( endAngle < startAngle )
std::swap( startAngle, endAngle );
VECTOR2D centre_device = userToDeviceCoordinates( aCenter );
double radius_device = userToDeviceSize( aRadius );

View File

@ -818,14 +818,11 @@ void GERBER_PLOTTER::Circle( const VECTOR2I& aCenter, int aDiameter, FILL_T aFil
void GERBER_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill, int aWidth )
const EDA_ANGLE& aAngle, double aRadius, FILL_T aFill, int aWidth )
{
SetCurrentLineWidth( aWidth );
EDA_ANGLE endAngle( aEndAngle );
while( endAngle < aStartAngle )
endAngle += ANGLE_360;
EDA_ANGLE endAngle = aStartAngle + aAngle;
// aFill is not used here.
plotArc( aCenter, aStartAngle, endAngle, aRadius, false );
@ -875,7 +872,7 @@ void GERBER_PLOTTER::plotArc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAn
{
VECTOR2I start, end;
start.x = aCenter.x + KiROUND( aRadius * aStartAngle.Cos() );
start.y = aCenter.y - KiROUND( aRadius * aStartAngle.Sin() );
start.y = aCenter.y + KiROUND( aRadius * aStartAngle.Sin() );
if( !aPlotInRegion )
MoveTo( start );
@ -883,14 +880,14 @@ void GERBER_PLOTTER::plotArc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAn
LineTo( start );
end.x = aCenter.x + KiROUND( aRadius * aEndAngle.Cos() );
end.y = aCenter.y - KiROUND( aRadius * aEndAngle.Sin() );
end.y = aCenter.y + KiROUND( aRadius * aEndAngle.Sin() );
VECTOR2D devEnd = userToDeviceCoordinates( end );
// devRelCenter is the position on arc center relative to the arc start, in Gerber coord.
VECTOR2D devRelCenter = userToDeviceCoordinates( aCenter ) - userToDeviceCoordinates( start );
fprintf( m_outputFile, "G75*\n" ); // Multiquadrant (360 degrees) mode
if( aStartAngle < aEndAngle )
if( aStartAngle > aEndAngle )
fprintf( m_outputFile, "G03*\n" ); // Active circular interpolation, CCW
else
fprintf( m_outputFile, "G02*\n" ); // Active circular interpolation, CW
@ -1145,11 +1142,12 @@ void GERBER_PLOTTER::ThickSegment( const VECTOR2I& start, const VECTOR2I& end, i
}
}
void GERBER_PLOTTER::ThickArc( const VECTOR2D& aCentre, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aEndAngle, double aRadius, int aWidth,
const EDA_ANGLE& aAngle, double aRadius, int aWidth,
OUTLINE_MODE aTraceMode, void* aData )
{
GBR_METADATA *gbr_metadata = static_cast<GBR_METADATA*>( aData );
GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
SetCurrentLineWidth( aWidth, gbr_metadata );
if( gbr_metadata )
@ -1157,57 +1155,19 @@ void GERBER_PLOTTER::ThickArc( const VECTOR2D& aCentre, const EDA_ANGLE& aStartA
if( aTraceMode == FILLED )
{
Arc( aCentre, aStartAngle, aEndAngle, aRadius, FILL_T::NO_FILL, DO_NOT_SET_LINE_WIDTH );
Arc( aCentre, aStartAngle, aAngle, aRadius, FILL_T::NO_FILL, DO_NOT_SET_LINE_WIDTH );
}
else
{
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH );
Arc( aCentre, aStartAngle, aEndAngle, aRadius - ( aWidth - m_currentPenWidth ) / 2,
Arc( aCentre, aStartAngle, aAngle, aRadius - ( aWidth - m_currentPenWidth ) / 2,
FILL_T::NO_FILL, DO_NOT_SET_LINE_WIDTH );
Arc( aCentre, aStartAngle, aEndAngle, aRadius + ( aWidth - m_currentPenWidth ) / 2,
Arc( aCentre, aStartAngle, aAngle, aRadius + ( aWidth - m_currentPenWidth ) / 2,
FILL_T::NO_FILL, DO_NOT_SET_LINE_WIDTH );
}
}
void GERBER_PLOTTER::ThickArc( const VECTOR2I& aCentre, const VECTOR2I& aStart,
const VECTOR2I& aEnd, int aWidth,
OUTLINE_MODE aTraceMode, void* aData )
{
EDA_ANGLE start_angle( aStart - aCentre );
EDA_ANGLE end_angle( aEnd - aCentre );
if( start_angle > end_angle )
{
if( end_angle < ANGLE_0 )
end_angle.Normalize();
else
start_angle = start_angle.Normalize() - ANGLE_360;
}
int radius = (aStart - aCentre).EuclideanNorm();
if( !m_yaxisReversed ) // should be always the case
{
std::swap( end_angle, start_angle );
end_angle = -end_angle;
start_angle = -start_angle;
}
ThickArc( aCentre, start_angle, end_angle, radius, aWidth, aTraceMode, aData );
}
void GERBER_PLOTTER::ThickArc( const EDA_SHAPE& aArcShape,
OUTLINE_MODE aTraceMode, void* aData )
{
wxASSERT( aArcShape.GetShape() == SHAPE_T::ARC );
ThickArc( aArcShape.getCenter(), aArcShape.GetStart(), aArcShape.GetEnd(),
aArcShape.GetWidth(), aTraceMode, aData );
}
void GERBER_PLOTTER::ThickRect( const VECTOR2I& p1, const VECTOR2I& p2, int width,
OUTLINE_MODE tracemode, void* aData )
{

View File

@ -568,7 +568,7 @@ void HPGL_PLOTTER::ThickSegment( const VECTOR2I& start, const VECTOR2I& end,
void HPGL_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill, int aWidth )
const EDA_ANGLE& aAngle, double aRadius, FILL_T aFill, int aWidth )
{
if( aRadius <= 0 )
return;
@ -581,23 +581,16 @@ void HPGL_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
chord_angle = std::max( m_arcMinChordDegrees, std::min( chord_angle, ANGLE_45 ) );
VECTOR2D centre_device = userToDeviceCoordinates( aCenter );
EDA_ANGLE angle = aAngle;
EDA_ANGLE startAngle( aStartAngle );
EDA_ANGLE endAngle( aEndAngle );
if( !m_plotMirror )
angle = -angle;
while( endAngle < startAngle )
endAngle += ANGLE_360;
EDA_ANGLE angle;
if( m_plotMirror )
angle = startAngle - endAngle;
else
angle = endAngle - startAngle;
EDA_ANGLE startAngle = -aStartAngle;
// Calculate arc start point:
VECTOR2I cmap( aCenter.x + KiROUND( aRadius * aStartAngle.Cos() ),
aCenter.y - KiROUND( aRadius * aStartAngle.Sin() ) );
VECTOR2I cmap( aCenter.x + KiROUND( aRadius * startAngle.Cos() ),
aCenter.y - KiROUND( aRadius * startAngle.Sin() ) );
VECTOR2D cmap_dev = userToDeviceCoordinates( cmap );
startOrAppendItem( cmap_dev, wxString::Format( "AA %.0f,%.0f,%.0f,%g",

View File

@ -284,59 +284,8 @@ void PDF_PLOTTER::Circle( const VECTOR2I& pos, int diametre, FILL_T aFill, int w
}
void PDF_PLOTTER::Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR2I& aEnd,
FILL_T aFill, int aWidth, int aMaxError )
{
wxASSERT( m_workFile );
/*
* Arcs are not so easily approximated by beziers (in the general case), so we approximate
* them in the old way
*/
EDA_ANGLE startAngle( aStart - aCenter );
EDA_ANGLE endAngle( aEnd - aCenter );
int radius = ( aStart - aCenter ).EuclideanNorm();
int numSegs = GetArcToSegmentCount( radius, aMaxError, FULL_CIRCLE );
EDA_ANGLE delta = ANGLE_360 / std::max( 8, numSegs );
VECTOR2I start( aStart );
VECTOR2I end( aEnd );
VECTOR2I pt;
while( endAngle < startAngle )
endAngle += ANGLE_360;
SetCurrentLineWidth( aWidth );
VECTOR2D pos_dev = userToDeviceCoordinates( start );
fprintf( m_workFile, "%g %g m ", pos_dev.x, pos_dev.y );
for( EDA_ANGLE ii = delta; startAngle + ii < endAngle; ii += delta )
{
pt = start;
RotatePoint( pt, aCenter, -ii );
pos_dev = userToDeviceCoordinates( pt );
fprintf( m_workFile, "%g %g l ", pos_dev.x, pos_dev.y );
}
pos_dev = userToDeviceCoordinates( end );
fprintf( m_workFile, "%g %g l ", pos_dev.x, pos_dev.y );
// The arc is drawn... if not filled we stroke it, otherwise we finish
// closing the pie at the center
if( aFill == FILL_T::NO_FILL )
{
fputs( "S\n", m_workFile );
}
else
{
pos_dev = userToDeviceCoordinates( aCenter );
fprintf( m_workFile, "%g %g l b\n", pos_dev.x, pos_dev.y );
}
}
void PDF_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill, int aWidth )
const EDA_ANGLE& aAngle, double aRadius, FILL_T aFill, int aWidth )
{
wxASSERT( m_workFile );
@ -350,14 +299,14 @@ void PDF_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
* Arcs are not so easily approximated by beziers (in the general case), so we approximate
* them in the old way
*/
EDA_ANGLE startAngle( aStartAngle );
EDA_ANGLE endAngle( aEndAngle );
EDA_ANGLE startAngle = -aStartAngle;
EDA_ANGLE endAngle = startAngle - aAngle;
VECTOR2I start;
VECTOR2I end;
const EDA_ANGLE delta( 5, DEGREES_T ); // increment to draw circles
while( endAngle < startAngle )
endAngle += ANGLE_360;
if( startAngle > endAngle )
std::swap( startAngle, endAngle );
SetCurrentLineWidth( aWidth );

View File

@ -521,31 +521,34 @@ VECTOR2D mapCoords( const VECTOR2D& aSource )
}
void PS_PLOTTER::Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR2I& aEnd,
FILL_T aFill, int aWidth, int aMaxError )
void PS_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aAngle, double aRadius, FILL_T aFill, int aWidth )
{
wxASSERT( m_outputFile );
VECTOR2D center_device = userToDeviceCoordinates( aCenter );
VECTOR2D start_device = userToDeviceCoordinates( aStart );
VECTOR2D end_device = userToDeviceCoordinates( aEnd );
double radius_device = ( start_device - center_device ).EuclideanNorm();
VECTOR2D center_device = userToDeviceCoordinates( aCenter );
double radius_device = userToDeviceSize( aRadius );
EDA_ANGLE endA = aStartAngle + aAngle;
VECTOR2D start( aRadius * aStartAngle.Cos(), aRadius * aStartAngle.Sin() );
VECTOR2D end( aRadius * endA.Cos(), aRadius * endA.Sin() );
start += aCenter;
end += aCenter;
VECTOR2D start_device = userToDeviceCoordinates( start );
VECTOR2D end_device = userToDeviceCoordinates( end );
EDA_ANGLE startAngle( mapCoords( start_device - center_device ) );
EDA_ANGLE endAngle( mapCoords( end_device - center_device ) );
// userToDeviceCoordinates gets our start/ends out of order
if( !m_plotMirror )
if( !m_plotMirror ^ ( aAngle < ANGLE_0 ) )
std::swap( startAngle, endAngle );
SetCurrentLineWidth( aWidth );
fprintf( m_outputFile, "%g %g %g %g %g arc%d\n",
center_device.x,
center_device.y,
radius_device,
startAngle.AsDegrees(),
endAngle.AsDegrees(),
getFillId( aFill ) );
fprintf( m_outputFile, "%g %g %g %g %g arc%d\n", center_device.x, center_device.y,
radius_device, startAngle.AsDegrees(), endAngle.AsDegrees(), getFillId( aFill ) );
}
void PS_PLOTTER::PlotPoly( const std::vector<VECTOR2I>& aCornerList, FILL_T aFill, int aWidth,

View File

@ -428,7 +428,7 @@ void SVG_PLOTTER::Circle( const VECTOR2I& pos, int diametre, FILL_T fill, int wi
void SVG_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill, int aWidth )
const EDA_ANGLE& aAngle, double aRadius, FILL_T aFill, int aWidth )
{
/* Draws an arc of a circle, centered on (xc,yc), with starting point (x1, y1) and ending
* at (x2, y2). The current pen is used for the outline and the current brush for filling
@ -443,11 +443,11 @@ void SVG_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
return;
}
EDA_ANGLE startAngle( aStartAngle );
EDA_ANGLE endAngle( aEndAngle );
EDA_ANGLE startAngle = -aStartAngle;
EDA_ANGLE endAngle = startAngle - aAngle;
while( endAngle < startAngle )
endAngle += ANGLE_360;
if( endAngle < startAngle )
std::swap( startAngle, endAngle );
// Calculate start point.
VECTOR2D centre_device = userToDeviceCoordinates( aCenter );

View File

@ -146,58 +146,53 @@ double PLOTTER::GetDashGapLenIU( int aLineWidth ) const
}
#include <wx/log.h>
void PLOTTER::Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR2I& aEnd,
FILL_T aFill, int aWidth, int aMaxError )
void PLOTTER::Arc( const VECTOR2D& aStart, const VECTOR2D& aMid, const VECTOR2D& aEnd, FILL_T aFill,
int aWidth )
{
// Recalculate aCenter using double to be sure we will use a exact value, from aStart and aEnd
// it must be on the line passing by the middle of segment {aStart, aEnd}
// To simplify calculations, use aStart as origin in intermediate calculations
VECTOR2D center = aCenter - aStart;
VECTOR2D end = aEnd - aStart;
EDA_ANGLE segAngle( end );
VECTOR2D aCenter = CalcArcCenter( aStart, aMid, aEnd );
// Rotate end and center, to make segment {aStart, aEnd} horizontal
RotatePoint( end, segAngle );
RotatePoint( center, segAngle );
EDA_ANGLE startAngle( aStart - aCenter );
EDA_ANGLE endAngle( aEnd - aCenter );
// center.x must be at end.x/2 coordinate
center.x = end.x / 2;
// < 0: left, 0 : on the line, > 0 : right
double det = ( aEnd - aStart ).Cross( aMid - aStart );
// Now calculate the right center position
RotatePoint( center, -segAngle );
center += aStart;
int cw = det <= 0;
EDA_ANGLE angle = endAngle - startAngle;
EDA_ANGLE startAngle( VECTOR2D( aStart ) - center );
EDA_ANGLE endAngle( VECTOR2D( aEnd ) - center );
double radius = ( VECTOR2D( aStart ) - center ).EuclideanNorm();
if( cw )
angle.Normalize();
else
angle.NormalizeNegative();
// In old Kicad code, calls to Arc() using angles calls this function after
// swapping angles and negate them (to compensate the inverted Y axis).
// So to be compatible with Arc() calls with angles, do the same thing
std::swap( startAngle, endAngle );
startAngle = -startAngle;
endAngle = -endAngle;
Arc( aCenter, startAngle, endAngle, radius, aFill, aWidth );
double radius = ( aStart - aCenter ).EuclideanNorm();
Arc( aCenter, startAngle, angle, radius, aFill, aWidth );
}
void PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill, int aWidth )
void PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aAngle,
double aRadius, FILL_T aFill, int aWidth )
{
EDA_ANGLE startAngle( aStartAngle );
EDA_ANGLE endAngle( aEndAngle );
polyArc( aCenter, aStartAngle, aAngle, aRadius, aFill, aWidth );
}
void PLOTTER::polyArc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aAngle, double aRadius, FILL_T aFill, int aWidth )
{
EDA_ANGLE startAngle = aStartAngle;
EDA_ANGLE endAngle = startAngle + aAngle;
const EDA_ANGLE delta( 5.0, DEGREES_T ); // increment to draw arc
VECTOR2I start, end;
const int sign = -1;
const int sign = 1;
while( endAngle < startAngle )
endAngle += ANGLE_360;
if( aAngle < ANGLE_0 )
std::swap( startAngle, endAngle );
SetCurrentLineWidth( aWidth );
start.x = aCenter.x + KiROUND( aRadius * startAngle.Cos() );
start.y = aCenter.y + sign*KiROUND( aRadius * startAngle.Sin() );
start.y = aCenter.y + sign * KiROUND( aRadius * startAngle.Sin() );
if( aFill != FILL_T::NO_FILL )
{
@ -212,12 +207,12 @@ void PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
for( EDA_ANGLE ii = startAngle + delta; ii < endAngle; ii += delta )
{
end.x = aCenter.x + KiROUND( aRadius * ii.Cos() );
end.y = aCenter.y + sign*KiROUND( aRadius * ii.Sin() );
end.y = aCenter.y + sign * KiROUND( aRadius * ii.Sin() );
LineTo( end );
}
end.x = aCenter.x + KiROUND( aRadius * endAngle.Cos() );
end.y = aCenter.y + sign*KiROUND( aRadius * endAngle.Sin() );
end.y = aCenter.y + sign * KiROUND( aRadius * endAngle.Sin() );
if( aFill != FILL_T::NO_FILL )
{
@ -581,57 +576,47 @@ void PLOTTER::ThickSegment( const VECTOR2I& start, const VECTOR2I& end, int widt
void PLOTTER::ThickArc( const VECTOR2D& centre, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aEndAngle, double aRadius, int aWidth,
const EDA_ANGLE& aAngle, double aRadius, int aWidth,
OUTLINE_MODE aTraceMode, void* aData )
{
if( aTraceMode == FILLED )
{
Arc( centre, aStartAngle, aEndAngle, aRadius, FILL_T::NO_FILL, aWidth );
Arc( centre, aStartAngle, aAngle, aRadius, FILL_T::NO_FILL, aWidth );
}
else
{
SetCurrentLineWidth( -1 );
Arc( centre, aStartAngle, aEndAngle, aRadius - ( aWidth - m_currentPenWidth ) / 2,
Arc( centre, aStartAngle, aAngle, aRadius - ( aWidth - m_currentPenWidth ) / 2,
FILL_T::NO_FILL, -1 );
Arc( centre, aStartAngle, aEndAngle, aRadius + ( aWidth - m_currentPenWidth ) / 2,
Arc( centre, aStartAngle, aAngle, aRadius + ( aWidth - m_currentPenWidth ) / 2,
FILL_T::NO_FILL, -1 );
}
}
void PLOTTER::ThickArc( const VECTOR2I& aCentre, const VECTOR2I& aStart,
const VECTOR2I& aEnd, int aWidth,
OUTLINE_MODE aTraceMode, void* aData )
{
if( aTraceMode == FILLED )
{
Arc( aCentre, aStart, aEnd, FILL_T::NO_FILL, aWidth, GetPlotterArcHighDef() );
}
else
{
SetCurrentLineWidth( -1 );
int radius = ( aStart - aCentre ).EuclideanNorm();
int new_radius = radius - ( aWidth - m_currentPenWidth ) / 2;
VECTOR2I start = ( aStart - aCentre ).Resize( new_radius ) + aCentre;
VECTOR2I end = ( aEnd - aCentre ).Resize( new_radius ) + aCentre;
Arc( aCentre, start, end, FILL_T::NO_FILL, -1, GetPlotterArcHighDef() );
new_radius = radius + ( aWidth - m_currentPenWidth ) / 2;
start = ( aStart - aCentre ).Resize( new_radius ) + aCentre;
end = ( aEnd - aCentre ).Resize( new_radius ) + aCentre;
Arc( aCentre, start, end, FILL_T::NO_FILL, -1, GetPlotterArcHighDef() );
}
}
void PLOTTER::ThickArc( const EDA_SHAPE& aArcShape,
OUTLINE_MODE aTraceMode, void* aData )
{
ThickArc( aArcShape.getCenter(),aArcShape.GetStart(), aArcShape.GetEnd(),
aArcShape.GetWidth(), aTraceMode, aData );
VECTOR2D center = aArcShape.getCenter();
VECTOR2D mid = aArcShape.GetArcMid();
VECTOR2D start = aArcShape.GetStart();
VECTOR2D end = aArcShape.GetEnd();
EDA_ANGLE startAngle( start - center );
EDA_ANGLE endAngle( end - center );
EDA_ANGLE angle = endAngle - startAngle;
// < 0: left, 0 : on the line, > 0 : right
double det = ( end - start ).Cross( mid - start );
if( det <= 0 ) // cw
angle.Normalize();
else
angle.NormalizeNegative();
double radius = ( start - center ).EuclideanNorm();
ThickArc( center, startAngle, angle, radius, aArcShape.GetWidth(), aTraceMode, aData );
}

View File

@ -104,7 +104,7 @@ struct VIEW_OVERLAY::COMMAND_ARC : public VIEW_OVERLAY::COMMAND
virtual void Execute( VIEW* aView ) const override
{
aView->GetGAL()->DrawArc( m_center, m_radius, m_startAngle, m_endAngle );
aView->GetGAL()->DrawArc( m_center, m_radius, m_startAngle, m_endAngle - m_startAngle );
}
VECTOR2D m_center;

View File

@ -223,12 +223,8 @@ void LIB_SHAPE::Plot( PLOTTER* aPlotter, bool aBackground, const VECTOR2I& aOffs
case SHAPE_T::ARC:
{
VECTOR2I mid = aTransform.TransformCoordinate( GetArcMid() ) + aOffset;
VECTOR2I center = CalcArcCenter( start, mid, end );
EDA_ANGLE startAngle = EDA_ANGLE( start - center );
EDA_ANGLE endAngle = EDA_ANGLE( end - center );
aPlotter->Arc( center, -startAngle, -endAngle, GetRadius(), fill, penWidth );
aPlotter->Arc( start, mid, end, fill, penWidth );
break;
}

View File

@ -900,7 +900,7 @@ void SCH_PAINTER::draw( const LIB_SHAPE* aShape, int aLayer, bool aDimmed )
std::swap( startAngle, endAngle );
m_gal->DrawArc( center, shape->GetRadius(), startAngle, endAngle );
m_gal->DrawArc( center, shape->GetRadius(), startAngle, endAngle - startAngle );
}
break;
@ -1988,7 +1988,7 @@ void SCH_PAINTER::draw( const SCH_SHAPE* aShape, int aLayer )
aShape->CalcArcAngles( startAngle, endAngle );
m_gal->DrawArc( aShape->GetCenter(), aShape->GetRadius(), startAngle,
endAngle );
endAngle - startAngle );
break;
}

View File

@ -140,13 +140,7 @@ void SCH_SHAPE::Plot( PLOTTER* aPlotter, bool aBackground ) const
switch( GetShape() )
{
case SHAPE_T::ARC:
{
// In some plotters (not all) the arc is approximated by segments, and
// a error max is needed. We try to approximate by 360/5 segments by 360 deg
int arc2segment_error = CircleToEndSegmentDeltaRadius( GetRadius(), 360/5 );
aPlotter->Arc( getCenter(), GetStart(), GetEnd(), m_fill, 0, arc2segment_error );
}
aPlotter->Arc( GetStart(), GetArcMid(), GetEnd(), m_fill, 0 );
break;
case SHAPE_T::CIRCLE:
@ -183,13 +177,7 @@ void SCH_SHAPE::Plot( PLOTTER* aPlotter, bool aBackground ) const
switch( GetShape() )
{
case SHAPE_T::ARC:
{
// In some plotters (not all) the arc is approximated by segments, and
// a error max is needed. We try to approximate by 360/5 segments by 360 deg
int arc2segment_error = CircleToEndSegmentDeltaRadius( GetRadius(), 360/5 );
aPlotter->Arc( getCenter(), GetStart(), GetEnd(), FILL_T::NO_FILL, pen_size, arc2segment_error );
}
aPlotter->Arc( GetStart(), GetArcMid(), GetEnd(), m_fill, pen_size );
break;
case SHAPE_T::CIRCLE:

View File

@ -337,7 +337,8 @@ void GERBVIEW_PAINTER::draw( /*const*/ GERBER_DRAW_ITEM* aItem, int aLayer )
// Adjust the allowed approx error to convert arcs to segments:
int arc_to_seg_error = gerbIUScale.mmToIU( 0.005 ); // Allow 5 microns
m_gal->DrawArcSegment( center, radius, startAngle, endAngle, width, arc_to_seg_error );
m_gal->DrawArcSegment( center, radius, startAngle, endAngle - startAngle, width,
arc_to_seg_error );
#if 0 // Arc Debugging only
m_gal->SetIsFill( false );

View File

@ -78,14 +78,13 @@ public:
void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) override;
/// @copydoc GAL::DrawArc()
void DrawArc( const VECTOR2D& aCenterPoint, double aRadius,
const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aEndAngle ) override;
void DrawArc( const VECTOR2D& aCenterPoint, double aRadius, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aAngle ) override;
/// @copydoc GAL::DrawArcSegment()
/// Note: aMaxError is not used in Cairo, because Cairo can draw true arcs
void DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aEndAngle, double aWidth,
double aMaxError ) override;
void DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aAngle, double aWidth, double aMaxError ) override;
/// @copydoc GAL::DrawRectangle()
void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) override;

View File

@ -148,10 +148,10 @@ public:
* @param aCenterPoint is the center point of the arc.
* @param aRadius is the arc radius.
* @param aStartAngle is the start angle of the arc.
* @param aEndAngle is the end angle of the arc.
* @param aAngle is the angle of the arc.
*/
virtual void DrawArc( const VECTOR2D& aCenterPoint, double aRadius,
const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aEndAngle ) {};
const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aAngle ){};
/**
* Draw an arc segment.
@ -166,14 +166,14 @@ public:
* @param aCenterPoint is the center point of the arc.
* @param aRadius is the arc radius.
* @param aStartAngle is the start angle of the arc.
* @param aEndAngle is the end angle of the arc.
* @param aAngle is the angle of the arc.
* @param aWidth is the thickness of the arc (pen size).
* @param aMaxError is the max allowed error to create segments to approximate a circle.
* It has meaning only for back ends that can't draw a true arc, and use segments to approximate.
*/
virtual void DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aEndAngle,
double aWidth, double aMaxError ) {};
const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aAngle,
double aWidth, double aMaxError ){};
/**
* Draw a rectangle.

View File

@ -131,11 +131,11 @@ public:
/// @copydoc GAL::DrawArc()
void DrawArc( const VECTOR2D& aCenterPoint, double aRadius, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aEndAngle ) override;
const EDA_ANGLE& aAngle ) override;
/// @copydoc GAL::DrawArcSegment()
void DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aEndAngle, double aWidth, double aMaxError ) override;
const EDA_ANGLE& aAngle, double aWidth, double aMaxError ) override;
/// @copydoc GAL::DrawRectangle()
void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) override;

View File

@ -212,25 +212,11 @@ public:
virtual void Circle( const VECTOR2I& pos, int diametre, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) = 0;
/**
* Generic fallback: arc rendered as a polyline.
* Winding direction: clockwise in right-down coordinate system.
*/
virtual void Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR2I& aEnd,
FILL_T aFill, int aWidth, int aMaxError );
virtual void Arc( const VECTOR2D& aStart, const VECTOR2D& aMid, const VECTOR2D& aEnd,
FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH );
/**
* Generic fallback: arc rendered as a polyline.
* Note also aCentre and aRadius are double to avoid creating rounding issues due
* to the fact a arc is defined in Kicad by a start point, a end point and third point
* not angles and radius.
* In some plotters (i.e. dxf) whe need a good precision when calculating an arc
* without error introduced by rounding, to avoid moving the end points,
* usually important in outlines when plotting an arc given by center, radius and angles.
* Winding direction: counter-clockwise in right-down coordinate system.
*/
virtual void Arc( const VECTOR2D& aCentre, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill,
virtual void Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aAngle, double aRadius, FILL_T aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH );
/**
@ -313,11 +299,11 @@ public:
virtual void ThickSegment( const VECTOR2I& start, const VECTOR2I& end, int width,
OUTLINE_MODE tracemode, void* aData );
virtual void ThickArc( const VECTOR2I& aCentre, const VECTOR2I& aStart,
const VECTOR2I& aEnd, int aWidth,
virtual void ThickArc( const EDA_SHAPE& aArcShape,
OUTLINE_MODE aTraceMode, void* aData );
virtual void ThickArc( const EDA_SHAPE& aArcShape,
virtual void ThickArc( const VECTOR2D& aCentre, const EDA_ANGLE& aStAngle,
const EDA_ANGLE& aAngle, double aRadius, int aWidth,
OUTLINE_MODE aTraceMode, void* aData );
virtual void ThickRect( const VECTOR2I& p1, const VECTOR2I& p2, int width, OUTLINE_MODE tracemode,
@ -559,9 +545,19 @@ public:
protected:
virtual void ThickArc( const VECTOR2D& aCentre, const EDA_ANGLE& StAngle,
const EDA_ANGLE& EndAngle, double aRadius, int aWidth,
OUTLINE_MODE aTraceMode, void* aData );
/**
* Generic fallback: arc rendered as a polyline.
* Note also aCentre and aRadius are double to avoid creating rounding issues due
* to the fact a arc is defined in Kicad by a start point, a end point and third point
* not angles and radius.
* In some plotters (i.e. dxf) whe need a good precision when calculating an arc
* without error introduced by rounding, to avoid moving the end points,
* usually important in outlines when plotting an arc given by center, radius and angles.
* Winding direction: counter-clockwise in right-down coordinate system.
*/
virtual void polyArc( const VECTOR2D& aCentre, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aAngle, double aRadius, FILL_T aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH );
// These are marker subcomponents
/**

View File

@ -95,6 +95,9 @@ public:
virtual void Circle( const VECTOR2I& pos, int diametre, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aAngle, double aRadius, FILL_T aFill, int aWidth ) override;
/**
* DXF polygon: doesn't fill it but at least it close the filled ones
* DXF does not know thick outline.
@ -208,10 +211,6 @@ public:
}
protected:
virtual void Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
void plotOneLineOfText( const VECTOR2I& aPos, const COLOR4D& aColor, const wxString& aText,
const TEXT_ATTRIBUTES& aAttrs );

View File

@ -64,18 +64,14 @@ public:
int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void Circle( const VECTOR2I& pos, int diametre, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aAngle, double aRadius, FILL_T aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
// These functions plot an item and manage X2 gerber attributes
virtual void ThickSegment( const VECTOR2I& start, const VECTOR2I& end, int width,
OUTLINE_MODE tracemode, void* aData ) override;
virtual void ThickArc( const VECTOR2I& aCentre, const VECTOR2I& aStart,
const VECTOR2I& aEnd, int aWidth,
OUTLINE_MODE aTraceMode, void* aData ) override;
virtual void ThickArc( const EDA_SHAPE& aArcShape,
OUTLINE_MODE aTraceMode, void* aData ) override;
virtual void ThickRect( const VECTOR2I& p1, const VECTOR2I& p2, int width,
OUTLINE_MODE tracemode, void* aData ) override;
@ -268,12 +264,8 @@ public:
APERTURE::APERTURE_TYPE aType, int aApertureAttribute );
protected:
virtual void Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
virtual void ThickArc( const VECTOR2D& aCentre, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aEndAngle, double aRadius, int aWidth,
const EDA_ANGLE& aAngle, double aRadius, int aWidth,
OUTLINE_MODE aTraceMode, void* aData ) override;
/**

View File

@ -139,11 +139,11 @@ protected:
*
* center is the center of the arc.
* StAngled is the start angle of the arc.
* aEndAngle is end angle the arc.
* aAngle is angle the arc.
* Radius is the radius of the arc.
*/
virtual void Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill,
const EDA_ANGLE& aAngle, double aRadius, FILL_T aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
/**

View File

@ -192,8 +192,9 @@ public:
int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void Circle( const VECTOR2I& pos, int diametre, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR2I& aEnd,
FILL_T aFill, int aWidth, int aMaxError ) override;
virtual void Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aAngle, double aRadius, FILL_T aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
virtual void PlotPoly( const std::vector<VECTOR2I>& aCornerList, FILL_T aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override;
@ -326,11 +327,8 @@ public:
/**
* The PDF engine can't directly plot arcs so we use polygonization.
*/
virtual void Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR2I& aEnd,
FILL_T aFill, int aWidth, int aMaxError ) override;
virtual void Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill,
const EDA_ANGLE& aAngle, double aRadius, FILL_T aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
/**
@ -552,9 +550,8 @@ public:
int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void Circle( const VECTOR2I& pos, int diametre, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill,
const EDA_ANGLE& aAngle, double aRadius, FILL_T aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
virtual void BezierCurve( const VECTOR2I& aStart, const VECTOR2I& aControl1,

View File

@ -844,8 +844,7 @@ void PCB_PAINTER::draw( const PCB_ARC* aArc, int aLayer )
if( aLayer == LAYER_LOCKED_ITEM_SHADOW )
width = width + m_lockedShadowMargin;
m_gal->DrawArcSegment( center, radius, start_angle, start_angle + angle, width,
m_maxError );
m_gal->DrawArcSegment( center, radius, start_angle, angle, width, m_maxError );
}
// Clearance lines
@ -859,8 +858,8 @@ void PCB_PAINTER::draw( const PCB_ARC* aArc, int aLayer )
m_gal->SetIsStroke( true );
m_gal->SetStrokeColor( color );
m_gal->DrawArcSegment( center, radius, start_angle, start_angle + angle,
width + clearance * 2, m_maxError );
m_gal->DrawArcSegment( center, radius, start_angle, angle, width + clearance * 2,
m_maxError );
}
// Debug only: enable this code only to test the TransformArcToPolygon function
@ -1074,11 +1073,11 @@ void PCB_PAINTER::draw( const PCB_VIA* aVia, int aLayer )
m_gal->SetStrokeColor( m_pcbSettings.GetColor( aVia, layerTop ) );
m_gal->SetFillColor( m_pcbSettings.GetColor( aVia, layerTop ) );
m_gal->DrawArc( center, radius, EDA_ANGLE( 240, DEGREES_T ), EDA_ANGLE( 300, DEGREES_T ) );
m_gal->DrawArc( center, radius, EDA_ANGLE( 240, DEGREES_T ), EDA_ANGLE( 60, DEGREES_T ) );
m_gal->SetStrokeColor( m_pcbSettings.GetColor( aVia, layerBottom ) );
m_gal->SetFillColor( m_pcbSettings.GetColor( aVia, layerBottom ) );
m_gal->DrawArc( center, radius, EDA_ANGLE( 60, DEGREES_T ), EDA_ANGLE( 120, DEGREES_T ) );
m_gal->DrawArc( center, radius, EDA_ANGLE( 60, DEGREES_T ), EDA_ANGLE( 60, DEGREES_T ) );
m_gal->SetStrokeColor( color );
m_gal->SetFillColor( color );
@ -1806,7 +1805,7 @@ void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer )
if( outline_mode )
{
m_gal->DrawArcSegment( aShape->GetCenter(), aShape->GetRadius(), startAngle,
endAngle, thickness, m_maxError );
endAngle - startAngle, thickness, m_maxError );
}
else
{
@ -1814,7 +1813,7 @@ void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer )
m_gal->SetIsStroke( false );
m_gal->DrawArcSegment( aShape->GetCenter(), aShape->GetRadius(), startAngle,
endAngle, thickness, m_maxError );
endAngle - startAngle, thickness, m_maxError );
}
break;
}

View File

@ -643,20 +643,10 @@ void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
if( track->Type() == PCB_ARC_T )
{
const PCB_ARC* arc = static_cast<const PCB_ARC*>( track );
const PCB_ARC* arc = static_cast<const PCB_ARC*>( track );
// ThickArc expects only positive angle arcs, so flip start/end if
// we are negative
if( arc->GetAngle() < ANGLE_0 )
{
aPlotter->ThickArc( arc->GetCenter(), arc->GetEnd(), arc->GetStart(),
width, plotMode, &gbr_metadata );
}
else
{
aPlotter->ThickArc( arc->GetCenter(), arc->GetStart(), arc->GetEnd(),
width, plotMode, &gbr_metadata );
}
aPlotter->ThickArc( arc->GetCenter(), arc->GetArcAngleStart(), arc->GetAngle(),
arc->GetRadius(), width, plotMode, &gbr_metadata );
}
else
{

View File

@ -239,7 +239,7 @@ void ROUTER_PREVIEW_ITEM::drawLineChain( const SHAPE_LINE_CHAIN_BASE* aL, KIGFX:
EDA_ANGLE start_angle = arc.GetStartAngle();
EDA_ANGLE angle = arc.GetCentralAngle();
gal->DrawArc( arc.GetCenter(), arc.GetRadius(), start_angle, start_angle + angle);
gal->DrawArc( arc.GetCenter(), arc.GetRadius(), start_angle, angle);
}
if( aL->IsClosed() )
@ -414,14 +414,14 @@ void ROUTER_PREVIEW_ITEM::drawShape( const SHAPE* aShape, KIGFX::GAL* gal ) cons
if( m_showClearance && m_clearance > 0 )
{
gal->SetLineWidth( w + 2 * m_clearance );
gal->DrawArc( arc->GetCenter(), arc->GetRadius(), start_angle, start_angle + angle );
gal->DrawArc( arc->GetCenter(), arc->GetRadius(), start_angle, angle );
}
gal->SetLayerDepth( m_depth );
gal->SetStrokeColor( m_color );
gal->SetFillColor( m_color );
gal->SetLineWidth( w );
gal->DrawArc( arc->GetCenter(), arc->GetRadius(), start_angle, start_angle + angle );
gal->DrawArc( arc->GetCenter(), arc->GetRadius(), start_angle, angle );
break;
}