111 int64_t dX_a, dY_a, dX_b, dY_b, dX_ab, dY_ab;
112 int64_t num_a, num_b, den;
120 dX_a = int64_t{ a_p2_l1.
x } - a_p1_l1.
x;
121 dY_a = int64_t{ a_p2_l1.
y } - a_p1_l1.
y;
122 dX_b = int64_t{ a_p2_l2.
x } - a_p1_l2.
x;
123 dY_b = int64_t{ a_p2_l2.
y } - a_p1_l2.
y;
124 dX_ab = int64_t{ a_p1_l2.
x } - a_p1_l1.
x;
125 dY_ab = int64_t{ a_p1_l2.
y } - a_p1_l1.
y;
127 den = dY_a * dX_b - dY_b * dX_a ;
133 num_a = dY_ab * dX_b - dY_b * dX_ab;
134 num_b = dY_ab * dX_a - dY_a * dX_ab;
137 if( aIntersectionPoint )
139 *aIntersectionPoint = a_p1_l1;
140 aIntersectionPoint->
x +=
KiROUND( dX_a * (
double )num_a / (
double )den );
141 aIntersectionPoint->
y +=
KiROUND( dY_a * (
double )num_b / (
double )den );
375 constexpr double kClusterExtent = 5.0;
380 constexpr double kCoincidentRadius = 2.0;
381 constexpr double kCoincidentRadiusSquared = kCoincidentRadius * kCoincidentRadius;
383 auto [minX, maxX] = std::minmax( { aStart.
x, aMid.
x, aEnd.
x } );
384 auto [minY, maxY] = std::minmax( { aStart.
y, aMid.
y, aEnd.
y } );
386 if( maxX - minX < kClusterExtent && maxY - minY < kClusterExtent )
388 return VECTOR2D( ( aStart.
x + aMid.
x + aEnd.
x ) / 3.0,
389 ( aStart.
y + aMid.
y + aEnd.
y ) / 3.0 );
394 return ( a - b ).SquaredEuclideanNorm() < kCoincidentRadiusSquared;
398 if( coincident( aStart, aMid ) || coincident( aMid, aEnd ) )
399 return VECTOR2D( ( aStart.
x + aEnd.
x ) / 2.0, ( aStart.
y + aEnd.
y ) / 2.0 );
401 if( coincident( aStart, aEnd ) )
402 return VECTOR2D( ( aStart.
x + aMid.
x ) / 2.0, ( aStart.
y + aMid.
y ) / 2.0 );
406 double yDelta_21 = aMid.
y - aStart.
y;
407 double xDelta_21 = aMid.
x - aStart.
x;
408 double yDelta_32 = aEnd.
y - aMid.
y;
409 double xDelta_32 = aEnd.
x - aMid.
x;
414 if( ( ( xDelta_21 == 0.0 ) && ( yDelta_32 == 0.0 ) ) ||
415 ( ( yDelta_21 == 0.0 ) && ( xDelta_32 == 0.0 ) ) )
417 center.x = ( aStart.
x + aEnd.
x ) / 2.0;
418 center.y = ( aStart.
y + aEnd.
y ) / 2.0 ;
423 if( xDelta_21 == 0.0 )
424 xDelta_21 = std::numeric_limits<double>::epsilon();
426 if( xDelta_32 == 0.0 )
427 xDelta_32 = -std::numeric_limits<double>::epsilon();
429 double aSlope = yDelta_21 / xDelta_21;
430 double bSlope = yDelta_32 / xDelta_32;
434 if( yDelta_21 == 0.0 )
435 yDelta_21 = std::numeric_limits<double>::epsilon();
437 if( yDelta_32 == 0.0 )
438 yDelta_32 = std::numeric_limits<double>::epsilon();
443 if( aSlope == bSlope )
449 center.x = ( aStart.
x + aMid.
x ) / 2.0;
450 center.y = ( aStart.
y + aMid.
y ) / 2.0 ;
458 aSlope += std::numeric_limits<double>::epsilon();
459 bSlope -= std::numeric_limits<double>::epsilon();
462#ifdef USE_ALTERNATE_CENTER_ALGO
485 double abSlopeStartEndY = aSlope * bSlope * ( aStart.
y - aEnd.
y );
486 double dabSlopeStartEndY = abSlopeStartEndY *
487 std::sqrt( ( daSlope / aSlope * daSlope / aSlope )
488 + ( dbSlope / bSlope * dbSlope / bSlope )
489 + ( M_SQRT1_2 / ( aStart.
y - aEnd.
y )
490 * M_SQRT1_2 / ( aStart.
y - aEnd.
y ) ) );
492 double bSlopeStartMidX = bSlope * ( aStart.
x + aMid.
x );
493 double dbSlopeStartMidX = bSlopeStartMidX * std::sqrt( ( dbSlope / bSlope * dbSlope / bSlope )
494 + ( M_SQRT1_2 / ( aStart.
x + aMid.
x )
495 * M_SQRT1_2 / ( aStart.
x + aMid.
x ) ) );
497 double aSlopeMidEndX = aSlope * ( aMid.
x + aEnd.
x );
498 double daSlopeMidEndX = aSlopeMidEndX * std::sqrt( ( daSlope / aSlope * daSlope / aSlope )
499 + ( M_SQRT1_2 / ( aMid.
x + aEnd.
x )
500 * M_SQRT1_2 / ( aMid.
x + aEnd.
x ) ) );
502 double twiceBASlopeDiff = 2 * ( bSlope - aSlope );
503 double dtwiceBASlopeDiff = 2 * std::sqrt( dbSlope * dbSlope + daSlope * daSlope );
505 double centerNumeratorX = abSlopeStartEndY + bSlopeStartMidX - aSlopeMidEndX;
506 double dCenterNumeratorX = std::sqrt( dabSlopeStartEndY * dabSlopeStartEndY
507 + dbSlopeStartMidX * dbSlopeStartMidX
508 + daSlopeMidEndX * daSlopeMidEndX );
510 double centerX = ( abSlopeStartEndY + bSlopeStartMidX - aSlopeMidEndX ) / twiceBASlopeDiff;
511 double dCenterX = centerX * std::sqrt( ( dCenterNumeratorX / centerNumeratorX *
512 dCenterNumeratorX / centerNumeratorX )
513 + ( dtwiceBASlopeDiff / twiceBASlopeDiff *
514 dtwiceBASlopeDiff / twiceBASlopeDiff ) );
517 double centerNumeratorY = ( ( aStart.
x + aMid.
x ) / 2.0 - centerX );
518 double dCenterNumeratorY = std::sqrt( 1.0 / 8.0 + dCenterX * dCenterX );
520 double centerFirstTerm = centerNumeratorY / aSlope;
521 double dcenterFirstTermY = centerFirstTerm * std::sqrt(
522 ( dCenterNumeratorY/ centerNumeratorY *
523 dCenterNumeratorY / centerNumeratorY )
524 + ( daSlope / aSlope * daSlope / aSlope ) );
526 double centerY = centerFirstTerm + ( aStart.
y + aMid.
y ) / 2.0;
527 double dCenterY = std::sqrt( dcenterFirstTermY * dcenterFirstTermY + 1.0 / 8.0 );
529 double rounded100CenterX = std::floor( ( centerX + 50.0 ) / 100.0 ) * 100.0;
530 double rounded100CenterY = std::floor( ( centerY + 50.0 ) / 100.0 ) * 100.0;
531 double rounded10CenterX = std::floor( ( centerX + 5.0 ) / 10.0 ) * 10.0;
532 double rounded10CenterY = std::floor( ( centerY + 5.0 ) / 10.0 ) * 10.0;
539 if(
std::abs( rounded100CenterX - centerX ) < dCenterX &&
540 std::abs( rounded100CenterY - centerY ) < dCenterY )
542 center.x = rounded100CenterX;
543 center.y = rounded100CenterY;
545 else if(
std::abs( rounded10CenterX - centerX ) < dCenterX &&
546 std::abs( rounded10CenterY - centerY ) < dCenterY )
548 center.x = rounded10CenterX;
549 center.y = rounded10CenterY;