PNS: construct initial lines with arcs more precisely

This commit is contained in:
Jon Evans 2021-01-02 23:57:09 -05:00
parent f01297fedd
commit eaffacbc85
1 changed files with 35 additions and 28 deletions

View File

@ -86,8 +86,8 @@ const SHAPE_LINE_CHAIN DIRECTION_45::BuildInitialTrace( const VECTOR2I& aP0, con
// TODO: if tangentLength zero, we could still place a small arc at the start... // TODO: if tangentLength zero, we could still place a small arc at the start...
if( aFillet ) if( aFillet )
{ {
VECTOR2I arcStart; SHAPE_ARC arc;
VECTOR2D arcCenter; VECTOR2I arcEndpoint;
double diag2 = tangentLength >= 0 ? mp1.SquaredEuclideanNorm() : mp0.SquaredEuclideanNorm(); double diag2 = tangentLength >= 0 ? mp1.SquaredEuclideanNorm() : mp0.SquaredEuclideanNorm();
double diagLength = std::sqrt( ( 2 * diag2 ) - ( 2 * diag2 * std::cos( 3 * M_PI_4 ) ) ); double diagLength = std::sqrt( ( 2 * diag2 ) - ( 2 * diag2 * std::cos( 3 * M_PI_4 ) ) );
@ -100,38 +100,33 @@ const SHAPE_LINE_CHAIN DIRECTION_45::BuildInitialTrace( const VECTOR2I& aP0, con
if( startDiagonal ) if( startDiagonal )
{ {
int rotationSign = ( w > h ) ? ( sw * sh * -1 ) : ( sw * sh ); int rotationSign = ( w > h ) ? ( sw * sh * -1 ) : ( sw * sh );
VECTOR2D centerDir( mp0.Rotate( M_PI_2 * rotationSign ) );
if( tangentLength >= 0 ) if( tangentLength >= 0 )
{ {
// Positive tangentLength, diagonal start: arc goes at the start // Positive tangentLength, diagonal start: arc goes at the start
arcStart = aP0 + mp1 + mp0.Resize( mp1.EuclideanNorm() ); arcEndpoint = aP1 - mp0.Resize( tangentLength );
arcCenter = arcStart + centerDir.Resize( arcRadius ); arc.ConstructFromStartEndAngle( aP0, arcEndpoint, 45 * rotationSign );
SHAPE_ARC new_arc( arcCenter, aP0, 45 * rotationSign );
if( new_arc.GetP0() == new_arc.GetP1() ) if( arc.GetP0() == arc.GetP1() )
pl.Append( aP0 ); pl.Append( aP0 );
else else
pl.Append( new_arc ); pl.Append( arc );
pl.Append( aP1 ); pl.Append( aP1 );
} }
else else
{ {
// Negative tangentLength, diagonal start: arc goes at the end // Negative tangentLength, diagonal start: arc goes at the end
arcStart = aP0 + mp1.Resize( std::abs( tangentLength ) ); arcEndpoint = aP0 + mp1.Resize( std::abs( tangentLength ) );
arcCenter = aP1 + centerDir.Resize( arcRadius ); arc.ConstructFromStartEndAngle( arcEndpoint, aP1, 45 * rotationSign );
SHAPE_ARC new_arc;
new_arc.ConstructFromStartEndAngle( arcStart, aP1, 45 * rotationSign );
pl.Append( aP0 ); pl.Append( aP0 );
if( new_arc.GetP0() == new_arc.GetP1() ) if( arc.GetP0() == arc.GetP1() )
pl.Append( aP1 ); pl.Append( aP1 );
else else
pl.Append( new_arc ); pl.Append( arc );
} }
} }
else else
@ -142,30 +137,42 @@ const SHAPE_LINE_CHAIN DIRECTION_45::BuildInitialTrace( const VECTOR2I& aP0, con
if( tangentLength >= 0 ) if( tangentLength >= 0 )
{ {
// Positive tangentLength: arc goes at the end // Positive tangentLength: arc goes at the end
arcStart = aP0 + mp0.Resize( tangentLength ); arcEndpoint = aP0 + mp0.Resize( tangentLength );
arcCenter = arcStart + centerDir.Resize( arcRadius ); arc.ConstructFromStartEndAngle( arcEndpoint, aP1, 45 * rotationSign );
SHAPE_ARC new_arc;
new_arc.ConstructFromStartEndAngle( arcStart, aP1, 45 * rotationSign );
pl.Append( aP0 ); pl.Append( aP0 );
if( new_arc.GetP0() == new_arc.GetP1() ) if( arc.GetP0() == arc.GetP1() )
pl.Append( aP1 ); pl.Append( aP1 );
else else
pl.Append( new_arc ); pl.Append( arc );
} }
else else
{ {
// Negative tangentLength: arc goes at the start // Negative tangentLength: arc goes at the start
arcStart = aP0; VECTOR2I arcCenter = aP0 + centerDir.Resize( arcRadius );
arcCenter = arcStart + centerDir.Resize( arcRadius ); SHAPE_ARC ca( arcCenter, aP0, 45 * rotationSign );
SHAPE_ARC new_arc( arcCenter, arcStart, 45 * rotationSign );
if( new_arc.GetP0() == new_arc.GetP1() ) // Constructing with a center can lead to imprecise endpoint. We need to guarantee
// tangency of the endpoint.
// TODO: update the math above to calculate the proper endpoint directly
VECTOR2I endpoint( ca.GetP1() );
if( std::abs( endpoint.y - aP1.y ) < SHAPE_ARC::MIN_PRECISION_IU )
{
VECTOR2I fixedEnd( endpoint.x, aP1.y );
ca.ConstructFromStartEndAngle( ca.GetP0(), fixedEnd, 45 * rotationSign );
}
else if( std::abs( endpoint.x - aP1.x ) < SHAPE_ARC::MIN_PRECISION_IU )
{
VECTOR2I fixedEnd( aP1.x, endpoint.y );
ca.ConstructFromStartEndAngle( ca.GetP0(), fixedEnd, 45 * rotationSign );
}
if( ca.GetP0() == ca.GetP1() )
pl.Append( aP0 ); pl.Append( aP0 );
else else
pl.Append( new_arc ); pl.Append( ca );
pl.Append( aP1 ); pl.Append( aP1 );
} }