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:
parent
e0381f25f7
commit
bac0820864
|
@ -1067,8 +1067,20 @@ void OPENGL_GAL::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
|
||||||
if( seg_count % 2 != 0 )
|
if( seg_count % 2 != 0 )
|
||||||
seg_count += 1;
|
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
|
// Recalculate alphaIncrement with a even integer number of segment
|
||||||
if( seg_count )
|
|
||||||
alphaIncrement = ( endAngle - startAngle ) / seg_count;
|
alphaIncrement = ( endAngle - startAngle ) / seg_count;
|
||||||
|
|
||||||
Save();
|
Save();
|
||||||
|
|
|
@ -833,11 +833,22 @@ void GERBER_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||||
{
|
{
|
||||||
SetCurrentLineWidth( aWidth );
|
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;
|
EDA_ANGLE endAngle = aStartAngle + aAngle;
|
||||||
|
|
||||||
// aFill is not used here.
|
// aFill is not used here.
|
||||||
plotArc( aCenter, aStartAngle, endAngle, aRadius, false );
|
plotArc( aCenter, aStartAngle, endAngle, aRadius, false );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void GERBER_PLOTTER::plotArc( const SHAPE_ARC& aArc, bool aPlotInRegion )
|
void GERBER_PLOTTER::plotArc( const SHAPE_ARC& aArc, bool aPlotInRegion )
|
||||||
|
|
|
@ -565,6 +565,13 @@ void HPGL_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||||
if( aRadius <= 0 )
|
if( aRadius <= 0 )
|
||||||
return;
|
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 radius_device = userToDeviceSize( aRadius );
|
||||||
double const circumf_device = 2.0 * M_PI * radius_device;
|
double const circumf_device = 2.0 * M_PI * radius_device;
|
||||||
double const target_chord_length = m_arcTargetChordLength;
|
double const target_chord_length = m_arcTargetChordLength;
|
||||||
|
|
|
@ -191,8 +191,8 @@ void PLOTTER::polyArc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||||
|
|
||||||
SetCurrentLineWidth( aWidth );
|
SetCurrentLineWidth( aWidth );
|
||||||
|
|
||||||
start.x = aCenter.x + KiROUND( aRadius * startAngle.Cos() );
|
start.x = KiROUND( aCenter.x + aRadius * startAngle.Cos() );
|
||||||
start.y = aCenter.y + sign * KiROUND( aRadius * startAngle.Sin() );
|
start.y = KiROUND( aCenter.y + sign * aRadius * startAngle.Sin() );
|
||||||
|
|
||||||
if( aFill != FILL_T::NO_FILL )
|
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 )
|
for( EDA_ANGLE ii = startAngle + delta; ii < endAngle; ii += delta )
|
||||||
{
|
{
|
||||||
end.x = aCenter.x + KiROUND( aRadius * ii.Cos() );
|
end.x = KiROUND( aCenter.x + aRadius * ii.Cos() );
|
||||||
end.y = aCenter.y + sign * KiROUND( aRadius * ii.Sin() );
|
end.y = KiROUND( aCenter.y + sign * aRadius * ii.Sin() );
|
||||||
LineTo( end );
|
LineTo( end );
|
||||||
}
|
}
|
||||||
|
|
||||||
end.x = aCenter.x + KiROUND( aRadius * endAngle.Cos() );
|
end.x = KiROUND( aCenter.x + aRadius * endAngle.Cos() );
|
||||||
end.y = aCenter.y + sign * KiROUND( aRadius * endAngle.Sin() );
|
end.y = KiROUND( aCenter.y + sign * aRadius * endAngle.Sin() );
|
||||||
|
|
||||||
if( aFill != FILL_T::NO_FILL )
|
if( aFill != FILL_T::NO_FILL )
|
||||||
{
|
{
|
||||||
|
|
|
@ -141,7 +141,7 @@ protected:
|
||||||
|
|
||||||
double Distance( const VECTOR2I& aP ) const
|
double Distance( const VECTOR2I& aP ) const
|
||||||
{
|
{
|
||||||
return ( aP - pos ).EuclideanNorm();
|
return VECTOR2D( (double) aP.x - pos.x, (double) aP.y - pos.y ).EuclideanNorm();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue