cairo: Prevent arch shaking in pcbnew
Arc pixel adjustment needs to be limited to +/-1 pixel. But making this adjustment to nearby points and then using the projection to correct the center point accumulates errors that are large for angles near 0 and near 360. This is a compromise that aligns _most_ arcs and provides stable generation for all angles. Fixes: lp:1817226 * https://bugs.launchpad.net/kicad/+bug/1817226
This commit is contained in:
parent
f14cf5cbc7
commit
2305c5458e
|
@ -261,22 +261,15 @@ void CAIRO_GAL_BASE::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, doub
|
||||||
SWAP( aStartAngle, >, aEndAngle );
|
SWAP( aStartAngle, >, aEndAngle );
|
||||||
auto startAngleS = angle_xform( aStartAngle );
|
auto startAngleS = angle_xform( aStartAngle );
|
||||||
auto endAngleS = angle_xform( aEndAngle );
|
auto endAngleS = angle_xform( aEndAngle );
|
||||||
double centerAngle = endAngleS - startAngleS;
|
auto r = xform( aRadius );
|
||||||
|
|
||||||
auto startPointS = roundp( xform ( aCenterPoint +
|
// N.B. This is backwards. We set this because we want to adjust the center
|
||||||
VECTOR2D( aRadius, 0.0 ).Rotate( startAngleS ) ) );
|
// point that changes both endpoints. In the worst case, this is twice as far.
|
||||||
auto endPointS = roundp( xform ( aCenterPoint +
|
// We cannot adjust radius or center based on the other because this causes the
|
||||||
VECTOR2D( aRadius, 0.0 ).Rotate( endAngleS ) ) );
|
// whole arc to change position/size
|
||||||
auto mid = ( startPointS + endPointS ) * 0.5;
|
lineWidthIsOdd = !( static_cast<int>( aRadius ) % 1 );
|
||||||
auto chord = endPointS - startPointS;
|
|
||||||
double c = chord.EuclideanNorm() / 2.0;
|
|
||||||
auto d = chord.Rotate( M_PI / 2.0 ).Resize( c );
|
|
||||||
auto tan_angle = tan( centerAngle / 2.0 );
|
|
||||||
|
|
||||||
if( tan_angle != 0.0 )
|
auto mid = roundp( xform( aCenterPoint ) );
|
||||||
mid += d * ( 1.0 / tan_angle );
|
|
||||||
|
|
||||||
auto rS = ( mid - startPointS ).EuclideanNorm();
|
|
||||||
|
|
||||||
cairo_set_line_width( currentContext, lineWidthInPixels );
|
cairo_set_line_width( currentContext, lineWidthInPixels );
|
||||||
cairo_new_sub_path( currentContext );
|
cairo_new_sub_path( currentContext );
|
||||||
|
@ -284,7 +277,7 @@ void CAIRO_GAL_BASE::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, doub
|
||||||
if( isFillEnabled )
|
if( isFillEnabled )
|
||||||
cairo_move_to( currentContext, mid.x, mid.y );
|
cairo_move_to( currentContext, mid.x, mid.y );
|
||||||
|
|
||||||
cairo_arc( currentContext, mid.x, mid.y, rS, startAngleS, endAngleS );
|
cairo_arc( currentContext, mid.x, mid.y, r, startAngleS, endAngleS );
|
||||||
|
|
||||||
if( isFillEnabled )
|
if( isFillEnabled )
|
||||||
cairo_close_path( currentContext );
|
cairo_close_path( currentContext );
|
||||||
|
@ -311,13 +304,18 @@ void CAIRO_GAL_BASE::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadiu
|
||||||
|
|
||||||
syncLineWidth();
|
syncLineWidth();
|
||||||
SWAP( aStartAngle, >, aEndAngle );
|
SWAP( aStartAngle, >, aEndAngle );
|
||||||
|
|
||||||
auto width = ::roundp( xform( aWidth / 2.0 ) );
|
|
||||||
auto r = ::roundp( xform( aRadius ) );
|
|
||||||
auto startAngleS = angle_xform( aStartAngle );
|
auto startAngleS = angle_xform( aStartAngle );
|
||||||
auto endAngleS = angle_xform( aEndAngle );
|
auto endAngleS = angle_xform( aEndAngle );
|
||||||
|
auto r = xform( aRadius );
|
||||||
|
|
||||||
|
// N.B. This is backwards. We set this because we want to adjust the center
|
||||||
|
// point that changes both endpoints. In the worst case, this is twice as far.
|
||||||
|
// We cannot adjust radius or center based on the other because this causes the
|
||||||
|
// whole arc to change position/size
|
||||||
|
lineWidthIsOdd = !( static_cast<int>( aRadius ) % 1 );
|
||||||
|
|
||||||
auto mid = roundp( xform( aCenterPoint ) );
|
auto mid = roundp( xform( aCenterPoint ) );
|
||||||
|
auto width = xform( aWidth / 2.0 );
|
||||||
auto startPointS = VECTOR2D( r, 0.0 ).Rotate( startAngleS );
|
auto startPointS = VECTOR2D( r, 0.0 ).Rotate( startAngleS );
|
||||||
auto endPointS = VECTOR2D( r, 0.0 ).Rotate( endAngleS );
|
auto endPointS = VECTOR2D( r, 0.0 ).Rotate( endAngleS );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue