Improve moving, rendering and plotting of very small angle arcs.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/17110


(cherry picked from commit b905b4eac8)
This commit is contained in:
Alex Shvartzkop 2024-04-03 00:39:55 +03:00 committed by dsa-t
parent e0381f25f7
commit bac0820864
5 changed files with 42 additions and 12 deletions

View File

@ -1067,8 +1067,20 @@ void OPENGL_GAL::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
if( seg_count % 2 != 0 )
seg_count += 1;
// Our shaders have trouble rendering null line quads, so delegate this task to DrawSegment.
if( seg_count == 0 )
{
VECTOR2D p_start( aCenterPoint.x + cos( startAngle ) * aRadius,
aCenterPoint.y + sin( startAngle ) * aRadius );
VECTOR2D p_end( aCenterPoint.x + cos( endAngle ) * aRadius,
aCenterPoint.y + sin( endAngle ) * aRadius );
DrawSegment( p_start, p_end, aWidth );
return;
}
// Recalculate alphaIncrement with a even integer number of segment
if( seg_count )
alphaIncrement = ( endAngle - startAngle ) / seg_count;
Save();

View File

@ -833,11 +833,22 @@ void GERBER_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
{
SetCurrentLineWidth( aWidth );
double arcLength = std::abs( aRadius * aAngle.AsRadians() );
if( arcLength < 100 || std::abs( aAngle.AsDegrees() ) < 0.1 )
{
// Prevent plotting very short arcs as full circles, especially with 4.5 mm precision.
// Also reduce the risk of integer overflow issues.
polyArc( aCenter, aStartAngle, aAngle, aRadius, aFill, aWidth );
}
else
{
EDA_ANGLE endAngle = aStartAngle + aAngle;
// aFill is not used here.
plotArc( aCenter, aStartAngle, endAngle, aRadius, false );
}
}
void GERBER_PLOTTER::plotArc( const SHAPE_ARC& aArc, bool aPlotInRegion )

View File

@ -565,6 +565,13 @@ void HPGL_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
if( aRadius <= 0 )
return;
// Avoid integer overflow when calculating the center point
if( std::abs( aAngle.AsDegrees() ) < 5 )
{
polyArc( aCenter, aStartAngle, aAngle, aRadius, aFill, aWidth );
return;
}
double const radius_device = userToDeviceSize( aRadius );
double const circumf_device = 2.0 * M_PI * radius_device;
double const target_chord_length = m_arcTargetChordLength;

View File

@ -191,8 +191,8 @@ void PLOTTER::polyArc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
SetCurrentLineWidth( aWidth );
start.x = aCenter.x + KiROUND( aRadius * startAngle.Cos() );
start.y = aCenter.y + sign * KiROUND( aRadius * startAngle.Sin() );
start.x = KiROUND( aCenter.x + aRadius * startAngle.Cos() );
start.y = KiROUND( aCenter.y + sign * aRadius * startAngle.Sin() );
if( aFill != FILL_T::NO_FILL )
{
@ -206,13 +206,13 @@ void PLOTTER::polyArc( 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.x = KiROUND( aCenter.x + aRadius * ii.Cos() );
end.y = KiROUND( aCenter.y + sign * aRadius * ii.Sin() );
LineTo( end );
}
end.x = aCenter.x + KiROUND( aRadius * endAngle.Cos() );
end.y = aCenter.y + sign * KiROUND( aRadius * endAngle.Sin() );
end.x = KiROUND( aCenter.x + aRadius * endAngle.Cos() );
end.y = KiROUND( aCenter.y + sign * aRadius * endAngle.Sin() );
if( aFill != FILL_T::NO_FILL )
{

View File

@ -141,7 +141,7 @@ protected:
double Distance( const VECTOR2I& aP ) const
{
return ( aP - pos ).EuclideanNorm();
return VECTOR2D( (double) aP.x - pos.x, (double) aP.y - pos.y ).EuclideanNorm();
}
};