From 10e2e4a12d16f02340f80d7e5c26f0daa776078b Mon Sep 17 00:00:00 2001 From: Alex Shvartzkop Date: Tue, 22 Aug 2023 16:06:53 +0300 Subject: [PATCH] Another try at fixing arcs. Fixes https://gitlab.com/kicad/code/kicad/-/issues/15471 Fixes https://gitlab.com/kicad/code/kicad/-/issues/15469 --- common/gal/cairo/cairo_gal.cpp | 10 +- common/gal/opengl/opengl_gal.cpp | 12 +-- common/plotters/DXF_plotter.cpp | 10 +- common/plotters/GERBER_plotter.cpp | 62 ++--------- common/plotters/HPGL_plotter.cpp | 21 ++-- common/plotters/PDF_plotter.cpp | 61 +---------- common/plotters/PS_plotter.cpp | 31 +++--- common/plotters/SVG_plotter.cpp | 10 +- common/plotters/plotter.cpp | 127 ++++++++++------------- common/view/view_overlay.cpp | 2 +- eeschema/lib_shape.cpp | 6 +- eeschema/sch_painter.cpp | 4 +- eeschema/sch_shape.cpp | 16 +-- gerbview/gerbview_painter.cpp | 3 +- include/gal/cairo/cairo_gal.h | 9 +- include/gal/graphics_abstraction_layer.h | 10 +- include/gal/opengl/opengl_gal.h | 4 +- include/plotters/plotter.h | 44 ++++---- include/plotters/plotter_dxf.h | 7 +- include/plotters/plotter_gerber.h | 16 +-- include/plotters/plotter_hpgl.h | 4 +- include/plotters/plotters_pslike.h | 13 +-- pcbnew/pcb_painter.cpp | 15 ++- pcbnew/plot_board_layers.cpp | 16 +-- pcbnew/router/router_preview_item.cpp | 6 +- 25 files changed, 183 insertions(+), 336 deletions(-) diff --git a/common/gal/cairo/cairo_gal.cpp b/common/gal/cairo/cairo_gal.cpp index db288ad0cf..c4b436b899 100644 --- a/common/gal/cairo/cairo_gal.cpp +++ b/common/gal/cairo/cairo_gal.cpp @@ -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 ); diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp index 856626b82c..160e4cea16 100644 --- a/common/gal/opengl/opengl_gal.cpp +++ b/common/gal/opengl/opengl_gal.cpp @@ -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 ); diff --git a/common/plotters/DXF_plotter.cpp b/common/plotters/DXF_plotter.cpp index b7a5aa3c64..77a6bb3fac 100644 --- a/common/plotters/DXF_plotter.cpp +++ b/common/plotters/DXF_plotter.cpp @@ -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 ); diff --git a/common/plotters/GERBER_plotter.cpp b/common/plotters/GERBER_plotter.cpp index dc7d7d1ae2..72bbe9b519 100644 --- a/common/plotters/GERBER_plotter.cpp +++ b/common/plotters/GERBER_plotter.cpp @@ -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( aData ); + GBR_METADATA* gbr_metadata = static_cast( 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 ) { diff --git a/common/plotters/HPGL_plotter.cpp b/common/plotters/HPGL_plotter.cpp index dcb0056f9c..d669053af9 100644 --- a/common/plotters/HPGL_plotter.cpp +++ b/common/plotters/HPGL_plotter.cpp @@ -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", diff --git a/common/plotters/PDF_plotter.cpp b/common/plotters/PDF_plotter.cpp index a1f8551dca..1cf28eedfd 100644 --- a/common/plotters/PDF_plotter.cpp +++ b/common/plotters/PDF_plotter.cpp @@ -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 ); diff --git a/common/plotters/PS_plotter.cpp b/common/plotters/PS_plotter.cpp index 64e0ff44b8..14fd0aeabb 100644 --- a/common/plotters/PS_plotter.cpp +++ b/common/plotters/PS_plotter.cpp @@ -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& aCornerList, FILL_T aFill, int aWidth, diff --git a/common/plotters/SVG_plotter.cpp b/common/plotters/SVG_plotter.cpp index 15d54e6922..e2df1a31d5 100644 --- a/common/plotters/SVG_plotter.cpp +++ b/common/plotters/SVG_plotter.cpp @@ -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 ); diff --git a/common/plotters/plotter.cpp b/common/plotters/plotter.cpp index bb6954cc3f..b100fb2c6d 100644 --- a/common/plotters/plotter.cpp +++ b/common/plotters/plotter.cpp @@ -146,58 +146,53 @@ double PLOTTER::GetDashGapLenIU( int aLineWidth ) const } #include -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 ); } diff --git a/common/view/view_overlay.cpp b/common/view/view_overlay.cpp index 2dd666005e..49ae125e49 100644 --- a/common/view/view_overlay.cpp +++ b/common/view/view_overlay.cpp @@ -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; diff --git a/eeschema/lib_shape.cpp b/eeschema/lib_shape.cpp index 4be9b8f509..e28aa78549 100644 --- a/eeschema/lib_shape.cpp +++ b/eeschema/lib_shape.cpp @@ -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; } diff --git a/eeschema/sch_painter.cpp b/eeschema/sch_painter.cpp index 9d61c2a4b2..59a4c455f5 100644 --- a/eeschema/sch_painter.cpp +++ b/eeschema/sch_painter.cpp @@ -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; } diff --git a/eeschema/sch_shape.cpp b/eeschema/sch_shape.cpp index d2f41ef632..3cc1f1c9b9 100644 --- a/eeschema/sch_shape.cpp +++ b/eeschema/sch_shape.cpp @@ -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: diff --git a/gerbview/gerbview_painter.cpp b/gerbview/gerbview_painter.cpp index 3ec714bd9c..3ccf97b3dd 100644 --- a/gerbview/gerbview_painter.cpp +++ b/gerbview/gerbview_painter.cpp @@ -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 ); diff --git a/include/gal/cairo/cairo_gal.h b/include/gal/cairo/cairo_gal.h index 79346aad68..2497def852 100644 --- a/include/gal/cairo/cairo_gal.h +++ b/include/gal/cairo/cairo_gal.h @@ -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; diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h index 3d5eddddfa..6e35aaa48b 100644 --- a/include/gal/graphics_abstraction_layer.h +++ b/include/gal/graphics_abstraction_layer.h @@ -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. diff --git a/include/gal/opengl/opengl_gal.h b/include/gal/opengl/opengl_gal.h index c14fa8d026..59bba2414b 100644 --- a/include/gal/opengl/opengl_gal.h +++ b/include/gal/opengl/opengl_gal.h @@ -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; diff --git a/include/plotters/plotter.h b/include/plotters/plotter.h index 81206fb87e..637ebb9845 100644 --- a/include/plotters/plotter.h +++ b/include/plotters/plotter.h @@ -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 /** diff --git a/include/plotters/plotter_dxf.h b/include/plotters/plotter_dxf.h index f2f6af89d9..cd15b8b05e 100644 --- a/include/plotters/plotter_dxf.h +++ b/include/plotters/plotter_dxf.h @@ -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 ); diff --git a/include/plotters/plotter_gerber.h b/include/plotters/plotter_gerber.h index 363a59a2e1..62bdbe8954 100644 --- a/include/plotters/plotter_gerber.h +++ b/include/plotters/plotter_gerber.h @@ -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; /** diff --git a/include/plotters/plotter_hpgl.h b/include/plotters/plotter_hpgl.h index 2c3e51c6fc..594abe5df3 100644 --- a/include/plotters/plotter_hpgl.h +++ b/include/plotters/plotter_hpgl.h @@ -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; /** diff --git a/include/plotters/plotters_pslike.h b/include/plotters/plotters_pslike.h index 1c333a1296..88268c075c 100644 --- a/include/plotters/plotters_pslike.h +++ b/include/plotters/plotters_pslike.h @@ -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& 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, diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index fb927f7207..f8e7bb9c5f 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -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; } diff --git a/pcbnew/plot_board_layers.cpp b/pcbnew/plot_board_layers.cpp index c25ddb2abe..894f5b90b6 100644 --- a/pcbnew/plot_board_layers.cpp +++ b/pcbnew/plot_board_layers.cpp @@ -643,20 +643,10 @@ void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask, if( track->Type() == PCB_ARC_T ) { - const PCB_ARC* arc = static_cast( track ); + const PCB_ARC* arc = static_cast( 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 { diff --git a/pcbnew/router/router_preview_item.cpp b/pcbnew/router/router_preview_item.cpp index 3773cc7000..2d905b0abf 100644 --- a/pcbnew/router/router_preview_item.cpp +++ b/pcbnew/router/router_preview_item.cpp @@ -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; }