| 466 | } |
| 467 | |
| 468 | MeasureResult Binary<Primitives::Sphere, Primitives::Sphere>::measure( const Primitives::Sphere& a, const Primitives::Sphere& b ) const |
| 469 | { |
| 470 | MeasureResult ret; |
| 471 | |
| 472 | // Distance. |
| 473 | |
| 474 | Vector3f dir = b.center - a.center; |
| 475 | float dirLen = dir.length(); |
| 476 | ret.distance.status = MeasureResult::Status::ok; |
| 477 | ret.distance.distance = dirLen - a.radius - b.radius; |
| 478 | if ( dirLen > 0 ) |
| 479 | dir /= dirLen; |
| 480 | else |
| 481 | dir = Vector3f( 1, 0, 0 ); // An arbitrary default direction. |
| 482 | ret.distance.closestPointA = a.center + a.radius * dir; |
| 483 | ret.distance.closestPointB = b.center - b.radius * dir; |
| 484 | |
| 485 | // Angle. |
| 486 | |
| 487 | if ( a.radius == 0 || b.radius == 0 ) |
| 488 | { |
| 489 | ret.angle.status = MeasureResult::Status::badFeaturePair; |
| 490 | } |
| 491 | else |
| 492 | { |
| 493 | float s = ( dirLen + a.radius + b.radius ) / 2; // https://en.wikipedia.org/wiki/Altitude_(triangle) |
| 494 | float intersectionSideOffset = std::sqrt( s * ( s - dirLen ) * ( s - a.radius ) * ( s - b.radius ) ) * 2 / dirLen; |
| 495 | if ( !std::isfinite( intersectionSideOffset ) ) |
| 496 | { |
| 497 | ret.angle.status = MeasureResult::Status::badRelativeLocation; |
| 498 | } |
| 499 | else |
| 500 | { |
| 501 | ret.angle.status = MeasureResult::Status::ok; |
| 502 | |
| 503 | float intersectionFwdOffset = std::sqrt( a.radius * a.radius - intersectionSideOffset * intersectionSideOffset ); |
| 504 | Vector3f sideDir = cross( dir, dir.furthestBasisVector() ).normalized(); |
| 505 | |
| 506 | ret.angle.pointA = ret.angle.pointB = a.center + dir * intersectionFwdOffset + sideDir * intersectionSideOffset; |
| 507 | ret.angle.dirA = ( ret.angle.pointA - a.center ).normalized(); |
| 508 | ret.angle.dirB = ( ret.angle.pointB - b.center ).normalized(); |
| 509 | ret.angle.isSurfaceNormalA = ret.angle.isSurfaceNormalB = true; |
| 510 | |
| 511 | // The circle at the intersection. |
| 512 | ret.intersections.push_back( primitiveCircle( a.center + dir * intersectionFwdOffset, dir, intersectionSideOffset ) ); |
| 513 | } |
| 514 | } |
| 515 | |
| 516 | // Center distance. |
| 517 | ret.centerDistance.status = MeasureResult::Status::ok; |
| 518 | ret.centerDistance.distance = dirLen; |
| 519 | ret.centerDistance.closestPointA = a.center; |
| 520 | ret.centerDistance.closestPointB = b.center; |
| 521 | |
| 522 | return ret; |
| 523 | } |
| 524 | |
| 525 | MeasureResult Binary<Primitives::ConeSegment, Primitives::Sphere>::measure( const Primitives::ConeSegment& a, const Primitives::Sphere& b ) const |
no test coverage detected