diff --git a/libs/kimath/src/geometry/seg.cpp b/libs/kimath/src/geometry/seg.cpp index 71ba16d0b4..2f596237e2 100644 --- a/libs/kimath/src/geometry/seg.cpp +++ b/libs/kimath/src/geometry/seg.cpp @@ -412,7 +412,16 @@ SEG::ecoord SEG::SquaredDistance( const VECTOR2I& aP ) const if( e >= f ) return VECTOR2L( aP.x - B.x, aP.y - B.y ).SquaredEuclideanNorm(); - return KiROUND( ap.SquaredEuclideanNorm() - ( double( e ) * e ) / f ); + const double g = ( double( e ) * e ) / f; + + //Squared distance can't be negative + if( g > ap.SquaredEuclideanNorm() ) + { + return (ecoord) std::numeric_limits::max() + * std::numeric_limits::max(); + } + + return KiROUND( ap.SquaredEuclideanNorm() - g ); } diff --git a/qa/tests/libs/kimath/geometry/test_segment.cpp b/qa/tests/libs/kimath/geometry/test_segment.cpp index 918167be21..65a82f3fcd 100644 --- a/qa/tests/libs/kimath/geometry/test_segment.cpp +++ b/qa/tests/libs/kimath/geometry/test_segment.cpp @@ -103,6 +103,9 @@ bool SegDistanceCorrect( const SEG& aSegA, const SEG& aSegB, int aExp ) */ bool SegVecDistanceCorrect( const SEG& aSeg, const VECTOR2I& aVec, int aExp ) { + const SEG::ecoord squaredDistance = aSeg.SquaredDistance( aVec ); + BOOST_REQUIRE( std::signbit( squaredDistance ) == false ); + const int dist = aSeg.Distance( aVec ); bool ok = ( dist == aExp ); @@ -342,6 +345,12 @@ static const std::vector seg_vec_dist_cases = { { 1000 + 200, 200 }, 282, // sqrt(200^2 + 200^2) = 282.8, rounded to nearest }, + { + "Issue 18473 (distance negative)", + { { 187360000, 42510000 }, { 105796472, 42510000 } }, + { 106645000, 42510000 }, + std::numeric_limits::max(), // maximal distance + } }; // clang-format on