From 42e53ee8e96e4613fce44e75e20a239b73dd284b Mon Sep 17 00:00:00 2001 From: Tomasz Wlostowski Date: Fri, 27 May 2022 17:41:05 +0200 Subject: [PATCH] kimath: fix regression in BuildInitialTrace()/CalcArcCenter causing incorrect arcs in routed traces --- libs/kimath/src/geometry/direction_45.cpp | 11 ++++++----- libs/kimath/src/trigo.cpp | 16 +++++++++++----- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/libs/kimath/src/geometry/direction_45.cpp b/libs/kimath/src/geometry/direction_45.cpp index 5fbb24b9ec..dc94e23b24 100644 --- a/libs/kimath/src/geometry/direction_45.cpp +++ b/libs/kimath/src/geometry/direction_45.cpp @@ -144,7 +144,7 @@ const SHAPE_LINE_CHAIN DIRECTION_45::BuildInitialTrace( const VECTOR2I& aP0, con { // Positive tangentLength, diagonal start: arc goes at the start arcEndpoint = aP1 - mp0.Resize( tangentLength ); - arc.ConstructFromStartEndAngle( aP0, arcEndpoint, ANGLE_45 * rotationSign ); + arc.ConstructFromStartEndAngle( aP0, arcEndpoint, - ANGLE_45 * rotationSign ); if( arc.GetP0() == arc.GetP1() ) pl.Append( aP0 ); @@ -157,7 +157,7 @@ const SHAPE_LINE_CHAIN DIRECTION_45::BuildInitialTrace( const VECTOR2I& aP0, con { // Negative tangentLength, diagonal start: arc goes at the end arcEndpoint = aP0 + mp1.Resize( std::abs( tangentLength ) ); - arc.ConstructFromStartEndAngle( arcEndpoint, aP1, ANGLE_45 * rotationSign ); + arc.ConstructFromStartEndAngle( arcEndpoint, aP1, - ANGLE_45 * rotationSign ); pl.Append( aP0 ); @@ -191,7 +191,8 @@ const SHAPE_LINE_CHAIN DIRECTION_45::BuildInitialTrace( const VECTOR2I& aP0, con { // Negative tangentLength: arc goes at the start VECTOR2I arcCenter = aP0 + centerDir.Resize( arcRadius ); - SHAPE_ARC ca( arcCenter, aP0, ANGLE_45 * rotationSign ); + SHAPE_ARC ca( arcCenter, aP0, -ANGLE_45 * rotationSign ); + // Constructing with a center can lead to imprecise endpoint. We need to guarantee // tangency of the endpoint. @@ -201,12 +202,12 @@ const SHAPE_LINE_CHAIN DIRECTION_45::BuildInitialTrace( const VECTOR2I& aP0, con if( std::abs( endpoint.y - aP1.y ) < SHAPE_ARC::MIN_PRECISION_IU ) { VECTOR2I fixedEnd( endpoint.x, aP1.y ); - ca.ConstructFromStartEndAngle( ca.GetP0(), fixedEnd, ANGLE_45 * rotationSign ); + ca.ConstructFromStartEndAngle( ca.GetP0(), fixedEnd, - ANGLE_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, ANGLE_45 * rotationSign ); + ca.ConstructFromStartEndAngle( ca.GetP0(), fixedEnd, - ANGLE_45 * rotationSign ); } if( ca.GetP0() == ca.GetP1() ) diff --git a/libs/kimath/src/trigo.cpp b/libs/kimath/src/trigo.cpp index 33ecce14cb..afd9fe2b49 100644 --- a/libs/kimath/src/trigo.cpp +++ b/libs/kimath/src/trigo.cpp @@ -314,17 +314,23 @@ const VECTOR2D CalcArcCenter( const VECTOR2D& aStart, const VECTOR2D& aEnd, if( angle > ANGLE_180 ) { std::swap( start, end ); - angle = ANGLE_360 - angle; + angle = ANGLE_180 - angle; } double chord = ( start - end ).EuclideanNorm(); double r = ( chord / 2.0 ) / ( angle / 2.0 ).Sin(); + double d_squared = r * r - chord* chord / 4.0; + double d = 0.0; - VECTOR2D vec = end - start; - vec = vec.Resize( r ); - RotatePoint( vec, -( ANGLE_180 - angle ) / 2 ); + if( d_squared > 0.0 ) + d = sqrt( d_squared ); - return VECTOR2D( start + vec ); + VECTOR2D vec2 = (end - start).Resize( d ); + VECTOR2D vc = (end - start).Resize( chord / 2 ); + + RotatePoint( vec2, ANGLE_90 ); + + return VECTOR2D( start + vc + vec2 ); }