Fix case of 360° arc handling
A 360° arc will have the mid point on the opposite side of the circle from both the start and end points. This will make both slopes the same, leading to a degeneracy in the calculation. We address this by noting that the center will be halfway between the midpoint and the start point.
This commit is contained in:
parent
69d75b90b1
commit
3aeb3c8f99
|
@ -201,7 +201,7 @@ double ArcTangente( int dy, int dx )
|
||||||
}
|
}
|
||||||
|
|
||||||
// Of course dy and dx are treated as double
|
// Of course dy and dx are treated as double
|
||||||
return RAD2DECIDEG( atan2( (double) dy, (double) dx ) );
|
return RAD2DECIDEG( std::atan2( (double) dy, (double) dx ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -367,22 +367,30 @@ const VECTOR2D GetArcCenter( const VECTOR2D& aStart, const VECTOR2D& aMid, const
|
||||||
double aSlope = yDelta_21 / xDelta_21;
|
double aSlope = yDelta_21 / xDelta_21;
|
||||||
double bSlope = yDelta_32 / xDelta_32;
|
double bSlope = yDelta_32 / xDelta_32;
|
||||||
|
|
||||||
// If the points are colinear, the center is at infinity, so offset
|
if( ( aSlope == bSlope ) )
|
||||||
// the slope by a minimal amount
|
|
||||||
// Warning: This will induce a small error in the center location
|
|
||||||
if( yDelta_32 * xDelta_21 == yDelta_21 * xDelta_32 )
|
|
||||||
{
|
{
|
||||||
aSlope += std::numeric_limits<double>::epsilon();
|
if( aStart == aEnd )
|
||||||
bSlope -= std::numeric_limits<double>::epsilon();
|
{
|
||||||
|
// This is a special case for a 360° arc. In this case, the center is halfway between
|
||||||
|
// the midpoint and either end point
|
||||||
|
center.x = ( aStart.x + aMid.x ) / 2.0;
|
||||||
|
center.y = ( aStart.y + aMid.y ) / 2.0 ;
|
||||||
|
return center;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If the points are colinear, the center is at infinity, so offset
|
||||||
|
// the slope by a minimal amount
|
||||||
|
// Warning: This will induce a small error in the center location
|
||||||
|
aSlope += std::numeric_limits<double>::epsilon();
|
||||||
|
bSlope -= std::numeric_limits<double>::epsilon();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prevent divide by zero error
|
||||||
if( aSlope == 0.0 )
|
if( aSlope == 0.0 )
|
||||||
aSlope = std::numeric_limits<double>::epsilon();
|
aSlope = std::numeric_limits<double>::epsilon();
|
||||||
|
|
||||||
if( bSlope == 0.0 )
|
|
||||||
bSlope = -std::numeric_limits<double>::epsilon();
|
|
||||||
|
|
||||||
|
|
||||||
center.x = ( aSlope * bSlope * ( aStart.y - aEnd.y ) +
|
center.x = ( aSlope * bSlope * ( aStart.y - aEnd.y ) +
|
||||||
bSlope * ( aStart.x + aMid.x ) -
|
bSlope * ( aStart.x + aMid.x ) -
|
||||||
aSlope * ( aMid.x + aEnd.x ) ) / ( 2 * ( bSlope - aSlope ) );
|
aSlope * ( aMid.x + aEnd.x ) ) / ( 2 * ( bSlope - aSlope ) );
|
||||||
|
|
Loading…
Reference in New Issue