Eeschema: fix a plot issue with arcs.

Arcs are really error prone, due to different Y axis orientation, and geometry transforms.
Probably we should remove plot and print functions using arc angles as parameters
that are a can of worms.
Fixes #12465
https://gitlab.com/kicad/code/kicad/issues/12465
This commit is contained in:
jean-pierre charras 2022-09-20 14:39:41 +02:00
parent 7e8b6083f4
commit bbaf5a21c2
2 changed files with 17 additions and 18 deletions

View File

@ -161,12 +161,12 @@ void PLOTTER::Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR
startAngle = startAngle.Normalize() - ANGLE_360; startAngle = startAngle.Normalize() - ANGLE_360;
} }
if( m_yaxisReversed ) // In Kicad code, call to Arc() using angles call this function after
{ // sawpping angles and negate them (to compensate the inverted Y axis).
std::swap( startAngle, endAngle ); // So to mimic the other calls in Kicad, do the same thing
startAngle = -startAngle; std::swap( startAngle, endAngle );
endAngle = -endAngle; startAngle = -startAngle;
} endAngle = -endAngle;
Arc( aCenter, startAngle, endAngle, radius, aFill, aWidth ); Arc( aCenter, startAngle, endAngle, radius, aFill, aWidth );
} }
@ -179,15 +179,15 @@ void PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
EDA_ANGLE endAngle( aEndAngle ); EDA_ANGLE endAngle( aEndAngle );
const EDA_ANGLE delta( 5.0, DEGREES_T ); // increment to draw arc const EDA_ANGLE delta( 5.0, DEGREES_T ); // increment to draw arc
VECTOR2I start, end; VECTOR2I start, end;
const int sign = -1;
if( startAngle > endAngle ) if( startAngle > endAngle )
std::swap( startAngle, endAngle ); std::swap( startAngle, endAngle );
SetCurrentLineWidth( aWidth ); SetCurrentLineWidth( aWidth );
/* Please NOTE the different sign due to Y-axis flip */ start.x = aCenter.x + KiROUND( aRadius * startAngle.Cos() );
start.x = aCenter.x + KiROUND( aRadius * -startAngle.Cos() ); start.y = aCenter.y + sign*KiROUND( aRadius * startAngle.Sin() );
start.y = aCenter.y + KiROUND( aRadius * -startAngle.Sin() );
if( aFill != FILL_T::NO_FILL ) if( aFill != FILL_T::NO_FILL )
{ {
@ -201,13 +201,13 @@ void PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
for( EDA_ANGLE ii = startAngle + delta; ii < endAngle; ii += delta ) for( EDA_ANGLE ii = startAngle + delta; ii < endAngle; ii += delta )
{ {
end.x = aCenter.x + KiROUND( aRadius * -ii.Cos() ); end.x = aCenter.x + KiROUND( aRadius * ii.Cos() );
end.y = aCenter.y + KiROUND( aRadius * -ii.Sin() ); end.y = aCenter.y + sign*KiROUND( aRadius * ii.Sin() );
LineTo( end ); LineTo( end );
} }
end.x = aCenter.x + KiROUND( aRadius * -endAngle.Cos() ); end.x = aCenter.x + KiROUND( aRadius * endAngle.Cos() );
end.y = aCenter.y + KiROUND( aRadius * -endAngle.Sin() ); end.y = aCenter.y + sign*KiROUND( aRadius * endAngle.Sin() );
if( aFill != FILL_T::NO_FILL ) if( aFill != FILL_T::NO_FILL )
{ {

View File

@ -233,11 +233,10 @@ void LIB_SHAPE::Plot( PLOTTER* aPlotter, bool aBackground, const VECTOR2I& aOffs
{ {
case SHAPE_T::ARC: case SHAPE_T::ARC:
{ {
EDA_ANGLE t1, t2; // 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
CalcArcAngles( t1, t2 ); int arc2segment_error = CircleToEndSegmentDeltaRadius( GetRadius(), 360/5 );
aTransform.MapAngles( &t1, &t2 ); aPlotter->Arc( center, start, end, fill, penWidth, arc2segment_error );
aPlotter->Arc( center, -t2, -t1, GetRadius(), fill, penWidth );
} }
break; break;