< Summary

Line coverage
100%
Covered lines: 1842
Uncovered lines: 0
Coverable lines: 1842
Total lines: 4309
Line coverage: 100%
Branch coverage
100%
Covered branches: 376
Total branches: 376
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
File 1: TryGetDistanceToCenteredAxis(...)100%11100%
File 1: TryGetDistanceBetweenCenteredAxes(...)100%11100%
File 1: DoCenteredCapsulesOverlap(...)100%44100%
File 1: TryGetCenteredAxisEndpoint(...)100%11100%
File 1: TryGetCenteredCapsuleSupport(...)100%22100%
File 1: TryGetCenteredCapsuleSupportOffset(...)100%22100%
File 1: GetCenteredCapsuleSupportAnchor(...)100%66100%
File 1: TryGetCenteredFiniteCylinderSupport(...)100%66100%
File 1: TryGetCenteredFiniteCylinderSupportOffset(...)100%66100%
File 1: GetCenteredFiniteCylinderSupportAnchor(...)100%66100%
File 1: TryGetCenteredFiniteConeSupport(...)100%66100%
File 1: TryGetCenteredFiniteConeSupportOffset(...)100%66100%
File 1: GetCenteredFiniteConeSupportAnchor(...)100%66100%
File 1: GetCenteredFiniteConeSupportAnchor(...)100%66100%
File 1: ContainsPointInCenteredFiniteCylinder(...)100%66100%
File 1: ContainsPointInCenteredFiniteCylinder(...)100%1010100%
File 1: GetDistanceToCenteredCapsule(...)100%11100%
File 1: TryGetDistanceToCenteredCapsule(...)100%22100%
File 1: ContainsPointInCenteredCapsule(...)100%11100%
File 1: ContainsPointInCenteredCapsule(...)100%11100%
File 1: ContainsPointInCenteredCapsule(...)100%11100%
File 1: ContainsPointInCenteredCapsule(...)100%44100%
File 1: GetDirectionFromCenteredAxis(...)100%11100%
File 1: TryGetClosestPointsBetweenCenteredAxes(...)100%11100%
File 1: TryGetClosestOffsetsBetweenCenteredAxes(...)100%11100%
File 1: GetClosestDirectionBetweenCenteredAxes(...)100%11100%
File 1: TryGetCenteredCapsulesContact(...)100%22100%
File 1: ValidateNormalizedRotation(...)100%22100%
File 1: ValidateCenteredCapsulesContact(...)100%66100%
File 1: ValidateCenteredAxis(...)100%11100%
File 1: ValidateCenteredAxis(...)100%44100%
File 2: DoCenteredFiniteCylinderAndCapsuleOverlapOnAxis(...)100%11100%
File 2: TryGetCenteredFiniteCylinderCapsuleAxisPenetration(...)100%11100%
File 2: TryGetCenteredFiniteCylinderCapsuleAxisPenetration(...)100%11100%
File 2: DoCenteredFiniteCylindersOverlapOnAxis(...)100%11100%
File 2: TryGetCenteredFiniteCylindersAxisPenetration(...)100%11100%
File 2: TryGetCenteredFiniteCylindersAxisPenetration(...)100%11100%
File 2: DoesCenteredFiniteCylinderOverlapSphere(...)100%88100%
File 2: TryGetClosestPointOnCenteredFiniteCylinderSurface(...)100%11100%
File 2: TryGetClosestCenteredFiniteCylinderSurfaceOffset(...)100%11100%
File 2: DoesCenteredFiniteConeOverlapSphere(...)100%22100%
File 2: TryGetClosestPointOnCenteredFiniteConeSurface(...)100%11100%
File 2: TryGetClosestCenteredFiniteConeSurfaceOffset(...)100%11100%
File 2: ValidateCenteredCone(...)100%66100%
File 2: ValidateCylinderCapsuleProjection(...)100%66100%
File 2: ValidateCylinderProjection(...)100%88100%
File 2: ValidateCenteredSurface(...)100%1010100%
File 2: TryGetSurfacePointOnCenteredCapsule(...)100%11100%
File 2: TryGetSurfaceOffsetOnCenteredCapsule(...)100%11100%
File 2: GetSurfaceAnchorOnCenteredCapsule(...)100%11100%
File 2: GetSurfaceAnchorOnCenteredCapsule(...)100%22100%
File 2: ValidateCenteredCapsuleSurface(...)100%44100%
File 2: TryGetClosestCenteredCapsuleSurfaceAnchor(...)100%44100%
File 2: TryGetClosestCenteredFiniteCylinderSurfaceAnchor(...)100%11100%
File 2: TryGetClosestCenteredFiniteConeSurfaceAnchor(...)100%11100%
File 2: ValidateCenteredSurfaceFrame(...)100%22100%
File 3: .ctor(...)100%11100%
File 3: get_Delta()100%11100%
File 3: get_Length()100%11100%
File 3: get_LengthSquared()100%11100%
File 3: get_Bounds()100%11100%
File 3: ClosestPoint(...)100%11100%
File 3: DistanceSquared(...)100%11100%
File 3: TryGetCapsuleIntersectionInterval(...)100%11100%
File 3: TryGetCapsuleIntersectionInterval(...)100%11100%
File 3: TryGetCapsuleIntersectionInterval(...)100%44100%
File 3: TryGetCapsuleIntersectionInterval(...)100%11100%
File 3: TryGetCapsuleIntersectionInterval(...)100%11100%
File 3: TryGetCapsuleIntersectionInterval(...)100%88100%
File 3: TryGetFiniteCylinderIntersectionInterval(...)100%11100%
File 3: TryGetFiniteCylinderIntersectionInterval(...)100%11100%
File 3: TryGetFiniteCylinderIntersectionInterval(...)100%66100%
File 3: TryGetFiniteCylinderIntersectionInterval(...)100%11100%
File 3: TryGetFiniteCylinderIntersectionInterval(...)100%1010100%
File 3: GetClosestPoints(...)100%2626100%
File 3: SolveClosestParameters(...)100%4444100%
File 3: ClampParameter(...)100%44100%
File 3: GetDifferenceDot(...)100%11100%
File 3: PointOnSegment(...)100%1212100%
File 3: Interpolate(...)100%11100%
File 3: Deconstruct(...)100%11100%
File 3: op_Equality(...)100%11100%
File 3: op_Inequality(...)100%11100%
File 3: Equals(...)100%22100%
File 3: Equals(...)100%22100%
File 3: GetHashCode()100%11100%
File 4: TryGetSphereIntersectionDistanceInterval(...)100%11100%
File 4: TryGetSphereIntersectionDistanceInterval(...)100%22100%
File 4: TryGetCapsuleIntersectionDistanceInterval(...)100%11100%
File 4: TryGetCapsuleIntersectionDistanceInterval(...)100%44100%
File 4: TryGetCapsuleIntersectionDistanceInterval(...)100%11100%
File 4: TryGetCapsuleIntersectionDistanceInterval(...)100%44100%
File 4: TryGetFiniteCylinderIntersectionDistanceInterval(...)100%11100%
File 4: TryGetFiniteCylinderIntersectionDistanceInterval(...)100%66100%
File 4: TryGetFiniteCylinderIntersectionDistanceInterval(...)100%1010100%
File 4: TryGetSweptSphereFiniteCylinderIntersectionDistance(...)100%11100%
File 4: TryGetSweptSphereCenteredFiniteCylinderIntersectionDistanceFromHalfAxisLength(...)100%44100%
File 4: TryGetSweptSphereBoxIntersectionDistance(...)100%22100%
File 4: TryGetSweptSphereOrientedBoxIntersectionDistance(...)100%22100%
File 4: TryGetSweptSphereFiniteCylinderIntersectionDistanceInterval(...)100%11100%
File 4: ValidateSphericallyExpandedFiniteCylinderArguments(...)100%66100%
File 4: GetPointAtDistance(...)100%44100%
File 4: ValidateDistance(...)100%44100%
File 4: ValidateTotalDistance(...)100%66100%
File 5: TryGetCenteredCapsuleCapsuleSlabAxisPenetration(...)100%11100%
File 5: TryGetCenteredFiniteCylinderCapsuleSlabAxisPenetration(...)100%11100%
File 5: TryGetCenteredFiniteConeCapsuleSlabAxisPenetration(...)100%11100%
File 5: ValidateCapsuleSlabProjection(...)100%1818100%
File 5: TryGetFiniteConeIntersectionInterval(...)100%11100%
File 5: TryGetFiniteConeIntersectionInterval(...)100%11100%
File 5: TryGetCenteredFiniteConeIntersectionInterval(...)100%11100%
File 5: TryGetCenteredFiniteConeIntersectionInterval(...)100%11100%
File 5: TryGetFiniteConeIntersectionDistanceInterval(...)100%11100%
File 5: TryGetFiniteConeIntersectionDistanceInterval(...)100%11100%
File 5: TryGetCenteredFiniteConeIntersectionDistanceInterval(...)100%11100%
File 5: TryGetCenteredFiniteConeIntersectionDistanceInterval(...)100%11100%
File 5: TryGetFiniteConeIntersectionPointInterval(...)100%44100%
File 5: TryGetFiniteConeIntersectionMinimumAxialPoint(...)100%66100%
File 5: TryGetCenteredFiniteConeIntersectionPointInterval(...)100%44100%
File 5: ContainsPointInFiniteCone(...)100%11100%
File 5: ContainsPointInCenteredFiniteCone(...)100%11100%
File 5: ValidateFiniteCone(...)100%66100%
File 6: TryGetCapsuleIntersectionDistanceInterval(...)100%11100%
File 6: TryGetFiniteCylinderIntersectionDistanceInterval(...)100%22100%
File 6: TryGetCenteredFiniteConeIntersectionDistanceInterval(...)100%11100%
File 6: ValidateRigidFiniteAxisQuery(...)100%1010100%
File 6: TryGetCenteredFiniteCylindersContact(...)100%11100%
File 6: TryGetCenteredFiniteCylinderCapsuleContact(...)100%11100%
File 6: ValidateRigidFiniteShape(...)100%1010100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Primitives/Segments/FixedSegment.CenteredAxis.cs

#LineLine coverage
 1//=======================================================================
 2// FixedSegment.CenteredAxis.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024–present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System;
 9
 10namespace FixedMathSharp.Geometry;
 11
 12/// <content>
 13/// Contains methods for computing the distance, support, and point containment
 14/// of centered 3D capsules, finite cylinders, and finite cones without narrowing their conceptual axes.
 15/// </content>
 16public partial struct FixedSegment
 17{
 18    /// <summary>
 19    /// Attempts to return the rounded distance from a point to a conceptual
 20    /// centered finite axis without materializing its endpoints.
 21    /// </summary>
 22    /// <returns>
 23    /// True when the final distance is representable; otherwise false and
 24    /// <paramref name="distance"/> is <see cref="Fixed64.MaxValue"/>.
 25    /// </returns>
 26    public static bool TryGetDistanceToCenteredAxis(
 27        Vector3d point,
 28        Vector3d center,
 29        Vector3d axisDirection,
 30        Fixed64 axisLength,
 31        out Fixed64 distance)
 32    {
 333        ValidateCenteredAxis(axisDirection, axisLength);
 334        return WideFiniteAxisIntersection.TryGetDistanceToCenteredAxis(
 335            point,
 336            center,
 337            axisDirection,
 338            axisLength,
 339            out distance);
 40    }
 41
 42    /// <summary>
 43    /// Attempts to return the rounded distance between two conceptual
 44    /// centered finite axes without materializing either pair of endpoints.
 45    /// </summary>
 46    /// <returns>
 47    /// True when the final distance is representable; otherwise false and
 48    /// <paramref name="distance"/> is <see cref="Fixed64.MaxValue"/>.
 49    /// </returns>
 50    public static bool TryGetDistanceBetweenCenteredAxes(
 51        Vector3d firstCenter,
 52        Vector3d firstAxisDirection,
 53        Fixed64 firstAxisLength,
 54        Vector3d secondCenter,
 55        Vector3d secondAxisDirection,
 56        Fixed64 secondAxisLength,
 57        out Fixed64 distance)
 58    {
 26359        ValidateCenteredAxis(
 26360            firstAxisDirection,
 26361            firstAxisLength,
 26362            nameof(firstAxisDirection),
 26363            nameof(firstAxisLength));
 26364        ValidateCenteredAxis(
 26365            secondAxisDirection,
 26366            secondAxisLength,
 26367            nameof(secondAxisDirection),
 26368            nameof(secondAxisLength));
 26369        return WideFiniteAxisIntersection.TryGetDistanceBetweenCenteredAxes(
 26370            firstCenter,
 26371            firstAxisDirection,
 26372            firstAxisLength,
 26373            secondCenter,
 26374            secondAxisDirection,
 26375            secondAxisLength,
 26376            out distance);
 77    }
 78
 79    /// <summary>
 80    /// Returns whether two conceptual centered capsules overlap, including
 81    /// exact tangency, without narrowing their axis distance or radius sum.
 82    /// </summary>
 83    public static bool DoCenteredCapsulesOverlap(
 84        Vector3d firstCenter,
 85        Vector3d firstAxisDirection,
 86        Fixed64 firstAxisLength,
 87        Fixed64 firstRadius,
 88        Vector3d secondCenter,
 89        Vector3d secondAxisDirection,
 90        Fixed64 secondAxisLength,
 91        Fixed64 secondRadius)
 92    {
 25993        ValidateCenteredAxis(
 25994            firstAxisDirection,
 25995            firstAxisLength,
 25996            nameof(firstAxisDirection),
 25997            nameof(firstAxisLength));
 25998        if (firstRadius < Fixed64.Zero)
 199            throw new ArgumentOutOfRangeException(nameof(firstRadius));
 258100        ValidateCenteredAxis(
 258101            secondAxisDirection,
 258102            secondAxisLength,
 258103            nameof(secondAxisDirection),
 258104            nameof(secondAxisLength));
 258105        if (secondRadius < Fixed64.Zero)
 1106            throw new ArgumentOutOfRangeException(nameof(secondRadius));
 107
 257108        return WideFiniteAxisIntersection.DoCenteredCapsulesOverlap(
 257109            firstCenter,
 257110            firstAxisDirection,
 257111            firstAxisLength,
 257112            firstRadius,
 257113            secondCenter,
 257114            secondAxisDirection,
 257115            secondAxisLength,
 257116            secondRadius);
 117    }
 118
 119    /// <summary>
 120    /// Attempts to materialize one endpoint of a conceptual centered finite
 121    /// axis from its normalized direction and full length.
 122    /// </summary>
 123    /// <remarks>
 124    /// The endpoint is rounded only after combining its center and half-length
 125    /// contribution. Failure is atomic.
 126    /// </remarks>
 127    public static bool TryGetCenteredAxisEndpoint(
 128        Vector3d center,
 129        Vector3d axisDirection,
 130        Fixed64 axisLength,
 131        bool positive,
 132        out Vector3d endpoint)
 133    {
 140134        ValidateCenteredAxis(axisDirection, axisLength);
 138135        return WideFiniteAxisIntersection.TryGetCenteredAxisEndpoint(
 138136            center,
 138137            axisDirection,
 138138            axisLength,
 138139            positive,
 138140            out endpoint);
 141    }
 142
 143    /// <summary>
 144    /// Attempts to materialize the support point of a conceptual centered
 145    /// capsule in a world-space direction.
 146    /// </summary>
 147    /// <remarks>
 148    /// The direction need not be normalized. A zero direction and an exact
 149    /// axial tie select the axis center.
 150    /// </remarks>
 151    public static bool TryGetCenteredCapsuleSupport(
 152        Vector3d center,
 153        Vector3d axisDirection,
 154        Fixed64 axisLength,
 155        Fixed64 radius,
 156        Vector3d direction,
 157        out Vector3d support)
 158    {
 141159        ValidateCenteredAxis(axisDirection, axisLength);
 141160        if (radius < Fixed64.Zero)
 1161            throw new ArgumentOutOfRangeException(nameof(radius));
 162
 140163        return WideFiniteAxisIntersection.TryGetCenteredCapsuleSupport(
 140164            center,
 140165            axisDirection,
 140166            axisLength,
 140167            radius,
 140168            direction,
 140169            out support);
 170    }
 171
 172    /// <summary>
 173    /// Attempts to return the support offset of a conceptual centered capsule
 174    /// relative to its center.
 175    /// </summary>
 176    /// <remarks>
 177    /// The direction need not be normalized. A zero direction and an exact
 178    /// axial tie select the axis center.
 179    /// </remarks>
 180    public static bool TryGetCenteredCapsuleSupportOffset(
 181        Vector3d axisDirection,
 182        Fixed64 axisLength,
 183        Fixed64 radius,
 184        Vector3d direction,
 185        out Vector3d supportOffset)
 186    {
 2187        ValidateCenteredAxis(axisDirection, axisLength);
 2188        if (radius < Fixed64.Zero)
 1189            throw new ArgumentOutOfRangeException(nameof(radius));
 190
 1191        return WideFiniteAxisIntersection.TryGetCenteredCapsuleSupport(
 1192            Vector3d.Zero,
 1193            axisDirection,
 1194            axisLength,
 1195            radius,
 1196            direction,
 1197            out supportOffset);
 198    }
 199
 200    /// <summary>
 201    /// Returns the support anchor of a centered capsule whose local positive Y
 202    /// axis is its conceptual center axis.
 203    /// </summary>
 204    /// <remarks>
 205    /// The rigid frame remains authoritative, so support construction does not
 206    /// feed the rounded derived world axis back into the geometry. The
 207    /// direction need not be normalized. A zero direction and an exact axial
 208    /// tie select the axis center.
 209    /// </remarks>
 210    public static FixedPointAnchor GetCenteredCapsuleSupportAnchor(
 211        Vector3d center,
 212        FixedQuaternion rotation,
 213        Fixed64 axisLength,
 214        Fixed64 radius,
 215        Vector3d direction)
 216    {
 9217        if (!rotation.IsNormalized())
 218        {
 1219            throw new ArgumentException(
 1220                "Capsule rotation must be normalized.",
 1221                nameof(rotation));
 222        }
 8223        if (axisLength < Fixed64.Zero)
 1224            throw new ArgumentOutOfRangeException(nameof(axisLength));
 7225        if (radius < Fixed64.Zero)
 1226            throw new ArgumentOutOfRangeException(nameof(radius));
 227
 6228        return WideGeometry.GetCenteredCapsuleSupportAnchor(
 6229            center,
 6230            rotation,
 6231            axisLength,
 6232            radius,
 6233            direction);
 234    }
 235
 236    /// <summary>
 237    /// Attempts to materialize the support point of a conceptual centered
 238    /// finite cylinder in a world-space direction.
 239    /// </summary>
 240    /// <remarks>
 241    /// The direction need not be normalized. A zero direction and an exact
 242    /// axial tie select the negative cap center. A direction parallel to the
 243    /// axis selects the cap center rather than an arbitrary rim point.
 244    /// </remarks>
 245    public static bool TryGetCenteredFiniteCylinderSupport(
 246        Vector3d center,
 247        Vector3d axisDirection,
 248        Fixed64 axisLength,
 249        Fixed64 radius,
 250        Vector3d direction,
 251        out Vector3d support)
 252    {
 139253        if (!axisDirection.IsNormalized())
 1254            throw new ArgumentException("Finite cylinder axis direction must be normalized.", nameof(axisDirection));
 138255        if (axisLength <= Fixed64.Zero)
 1256            throw new ArgumentOutOfRangeException(nameof(axisLength));
 137257        if (radius < Fixed64.Zero)
 1258            throw new ArgumentOutOfRangeException(nameof(radius));
 259
 136260        return WideFiniteAxisIntersection.TryGetCenteredFiniteCylinderSupport(
 136261            center,
 136262            axisDirection,
 136263            axisLength,
 136264            radius,
 136265            direction,
 136266            out support);
 267    }
 268
 269    /// <summary>
 270    /// Attempts to return the support offset of a conceptual centered finite
 271    /// cylinder relative to its center.
 272    /// </summary>
 273    public static bool TryGetCenteredFiniteCylinderSupportOffset(
 274        Vector3d axisDirection,
 275        Fixed64 axisLength,
 276        Fixed64 radius,
 277        Vector3d direction,
 278        out Vector3d supportOffset)
 279    {
 4280        if (!axisDirection.IsNormalized())
 1281            throw new ArgumentException("Finite cylinder axis direction must be normalized.", nameof(axisDirection));
 3282        if (axisLength <= Fixed64.Zero)
 1283            throw new ArgumentOutOfRangeException(nameof(axisLength));
 2284        if (radius < Fixed64.Zero)
 1285            throw new ArgumentOutOfRangeException(nameof(radius));
 286
 1287        return WideFiniteAxisIntersection.TryGetCenteredFiniteCylinderSupport(
 1288            Vector3d.Zero,
 1289            axisDirection,
 1290            axisLength,
 1291            radius,
 1292            direction,
 1293            out supportOffset);
 294    }
 295
 296    /// <summary>
 297    /// Returns the support anchor of a centered finite cylinder whose local
 298    /// positive Y axis is its conceptual center axis.
 299    /// </summary>
 300    /// <remarks>
 301    /// The rigid frame remains authoritative. Axial full-length/2 and radial
 302    /// direction-times-radius terms remain exact through final world-point or
 303    /// relative-offset materialization.
 304    /// </remarks>
 305    public static FixedPointAnchor GetCenteredFiniteCylinderSupportAnchor(
 306        Vector3d center,
 307        FixedQuaternion rotation,
 308        Fixed64 axisLength,
 309        Fixed64 radius,
 310        Vector3d direction)
 311    {
 4312        if (!rotation.IsNormalized())
 313        {
 1314            throw new ArgumentException(
 1315                "Finite cylinder rotation must be normalized.",
 1316                nameof(rotation));
 317        }
 3318        if (axisLength <= Fixed64.Zero)
 1319            throw new ArgumentOutOfRangeException(nameof(axisLength));
 2320        if (radius < Fixed64.Zero)
 1321            throw new ArgumentOutOfRangeException(nameof(radius));
 322
 1323        return WideGeometry.GetCenteredCylinderSupportAnchor(
 1324            center,
 1325            rotation,
 1326            axisLength,
 1327            radius,
 1328            direction);
 329    }
 330
 331    /// <summary>
 332    /// Attempts to materialize the support point of a conceptual centered
 333    /// finite cone in a world-space direction.
 334    /// </summary>
 335    /// <remarks>
 336    /// The axis points from the base toward the apex. The direction need not
 337    /// be normalized. Equal apex and base projections, including a zero
 338    /// direction, select the base.
 339    /// </remarks>
 340    public static bool TryGetCenteredFiniteConeSupport(
 341        Vector3d center,
 342        Vector3d axisDirection,
 343        Fixed64 height,
 344        Fixed64 radius,
 345        Vector3d direction,
 346        out Vector3d support)
 347    {
 138348        if (!axisDirection.IsNormalized())
 1349            throw new ArgumentException("Finite cone axis direction must be normalized.", nameof(axisDirection));
 137350        if (height <= Fixed64.Zero)
 1351            throw new ArgumentOutOfRangeException(nameof(height));
 136352        if (radius < Fixed64.Zero)
 1353            throw new ArgumentOutOfRangeException(nameof(radius));
 354
 135355        return WideFiniteAxisIntersection.TryGetCenteredFiniteConeSupport(
 135356            center,
 135357            axisDirection,
 135358            height,
 135359            radius,
 135360            direction,
 135361            out support);
 362    }
 363
 364    /// <summary>
 365    /// Attempts to return the support offset of a conceptual centered finite
 366    /// cone relative to its center.
 367    /// </summary>
 368    public static bool TryGetCenteredFiniteConeSupportOffset(
 369        Vector3d axisDirection,
 370        Fixed64 height,
 371        Fixed64 radius,
 372        Vector3d direction,
 373        out Vector3d supportOffset)
 374    {
 4375        if (!axisDirection.IsNormalized())
 1376            throw new ArgumentException("Finite cone axis direction must be normalized.", nameof(axisDirection));
 3377        if (height <= Fixed64.Zero)
 1378            throw new ArgumentOutOfRangeException(nameof(height));
 2379        if (radius < Fixed64.Zero)
 1380            throw new ArgumentOutOfRangeException(nameof(radius));
 381
 1382        return WideFiniteAxisIntersection.TryGetCenteredFiniteConeSupport(
 1383            Vector3d.Zero,
 1384            axisDirection,
 1385            height,
 1386            radius,
 1387            direction,
 1388            out supportOffset);
 389    }
 390
 391    /// <summary>
 392    /// Returns the support point of a centered finite cone as a local point in
 393    /// its rigid frame without materializing an absolute world coordinate.
 394    /// </summary>
 395    /// <remarks>
 396    /// The cone's local positive Y axis points from the base toward the apex.
 397    /// The direction need not be normalized. Equal apex and base projections,
 398    /// including a zero direction, select the base.
 399    /// </remarks>
 400    public static FixedPointAnchor GetCenteredFiniteConeSupportAnchor(
 401        Vector3d center,
 402        FixedQuaternion rotation,
 403        Fixed64 height,
 404        Fixed64 radius,
 405        Vector3d direction)
 406    {
 6407        if (!rotation.IsNormalized())
 408        {
 1409            throw new ArgumentException(
 1410                "Finite cone rotation must be normalized.",
 1411                nameof(rotation));
 412        }
 5413        if (height <= Fixed64.Zero)
 1414            throw new ArgumentOutOfRangeException(nameof(height));
 4415        if (radius < Fixed64.Zero)
 1416            throw new ArgumentOutOfRangeException(nameof(radius));
 417
 3418        return WideGeometry.GetCenteredConeSupportAnchor(
 3419            center,
 3420            rotation,
 3421            height,
 3422            radius,
 3423            direction);
 424    }
 425
 426    /// <summary>
 427    /// Returns the support point of a centered finite cone in a deterministic
 428    /// canonical axis frame without materializing an absolute world
 429    /// coordinate.
 430    /// </summary>
 431    public static FixedPointAnchor GetCenteredFiniteConeSupportAnchor(
 432        Vector3d center,
 433        Vector3d axisDirection,
 434        Fixed64 height,
 435        Fixed64 radius,
 436        Vector3d direction)
 437    {
 6438        if (!axisDirection.IsNormalized())
 439        {
 1440            throw new ArgumentException(
 1441                "Finite cone axis direction must be normalized.",
 1442                nameof(axisDirection));
 443        }
 5444        if (height <= Fixed64.Zero)
 1445            throw new ArgumentOutOfRangeException(nameof(height));
 4446        if (radius < Fixed64.Zero)
 1447            throw new ArgumentOutOfRangeException(nameof(radius));
 448
 3449        FixedQuaternion rotation =
 3450            WideGeometry.GetCanonicalAxisRotation(axisDirection);
 3451        return WideGeometry.GetCenteredConeSupportAnchor(
 3452            center,
 3453            rotation,
 3454            height,
 3455            radius,
 3456            direction);
 457    }
 458
 459    /// <summary>
 460    /// Returns whether a point lies in a centered finite cylinder whose flat
 461    /// caps are defined without constructing scalar coordinates.
 462    /// </summary>
 463    /// <param name="point">The point to classify.</param>
 464    /// <param name="center">The cylinder center.</param>
 465    /// <param name="axisDirection">The normalized cap-normal direction.</param>
 466    /// <param name="axisLength">The positive full physical axis length.</param>
 467    /// <param name="radius">The nonnegative radial extent.</param>
 468    /// <param name="strict">
 469    /// <see langword="true"/> to exclude the side and both flat caps;
 470    /// otherwise, boundaries are included.
 471    /// </param>
 472    /// <exception cref="ArgumentException">
 473    /// <paramref name="axisDirection"/> is zero or not normalized.
 474    /// </exception>
 475    /// <exception cref="ArgumentOutOfRangeException">
 476    /// <paramref name="axisLength"/> is not positive or
 477    /// <paramref name="radius"/> is negative.
 478    /// </exception>
 479    public static bool ContainsPointInCenteredFiniteCylinder(
 480        Vector3d point,
 481        Vector3d center,
 482        Vector3d axisDirection,
 483        Fixed64 axisLength,
 484        Fixed64 radius,
 485        bool strict = false)
 486    {
 13487        if (!axisDirection.IsNormalized())
 1488            throw new ArgumentException("Finite cylinder axis direction must be normalized.", nameof(axisDirection));
 12489        if (axisLength <= Fixed64.Zero)
 1490            throw new ArgumentOutOfRangeException(nameof(axisLength));
 11491        if (radius < Fixed64.Zero)
 1492            throw new ArgumentOutOfRangeException(nameof(radius));
 493
 10494        return WideFiniteAxisIntersection.ContainsPointInCenteredFiniteCylinder(
 10495            point,
 10496            center,
 10497            axisDirection,
 10498            axisLength,
 10499            radius,
 10500            strict);
 501    }
 502
 503    /// <summary>
 504    /// Returns whether a point lies in a centered finite cylinder after
 505    /// independently expanding its flat caps and radial side.
 506    /// </summary>
 507    /// <param name="point">The point to classify.</param>
 508    /// <param name="center">The cylinder center.</param>
 509    /// <param name="axisDirection">The normalized cylinder axis.</param>
 510    /// <param name="axisLength">The positive full cylinder length.</param>
 511    /// <param name="radius">The nonnegative cylinder radius.</param>
 512    /// <param name="axialTolerance">
 513    /// The nonnegative distance added beyond each flat cap.
 514    /// </param>
 515    /// <param name="radialTolerance">
 516    /// The nonnegative distance added to the radial extent.
 517    /// </param>
 518    /// <param name="strict">
 519    /// <see langword="true"/> to exclude every expanded boundary.
 520    /// </param>
 521    public static bool ContainsPointInCenteredFiniteCylinder(
 522        Vector3d point,
 523        Vector3d center,
 524        Vector3d axisDirection,
 525        Fixed64 axisLength,
 526        Fixed64 radius,
 527        Fixed64 axialTolerance,
 528        Fixed64 radialTolerance,
 529        bool strict = false)
 530    {
 8531        if (!axisDirection.IsNormalized())
 1532            throw new ArgumentException("Finite cylinder axis direction must be normalized.", nameof(axisDirection));
 7533        if (axisLength <= Fixed64.Zero)
 1534            throw new ArgumentOutOfRangeException(nameof(axisLength));
 6535        if (radius < Fixed64.Zero)
 1536            throw new ArgumentOutOfRangeException(nameof(radius));
 5537        if (axialTolerance < Fixed64.Zero)
 1538            throw new ArgumentOutOfRangeException(nameof(axialTolerance));
 4539        if (radialTolerance < Fixed64.Zero)
 1540            throw new ArgumentOutOfRangeException(nameof(radialTolerance));
 541
 3542        return WideFiniteAxisIntersection.ContainsPointInCenteredFiniteCylinder(
 3543            point,
 3544            center,
 3545            axisDirection,
 3546            axisLength,
 3547            radius,
 3548            axialTolerance,
 3549            radialTolerance,
 3550            strict);
 551    }
 552
 553    /// <summary>
 554    /// Returns the rounded nonnegative distance from a point to a conceptual
 555    /// centered capsule surface, saturating to <see cref="Fixed64.MaxValue"/>
 556    /// when the distance is not representable.
 557    /// </summary>
 558    /// <remarks>
 559    /// The final value uses round-half-to-even. Points inside or on the capsule
 560    /// return zero.
 561    /// </remarks>
 562    /// <exception cref="ArgumentException">
 563    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 564    /// </exception>
 565    /// <exception cref="ArgumentOutOfRangeException">
 566    /// Thrown when <paramref name="axisLength"/> or <paramref name="radius"/>
 567    /// is negative.
 568    /// </exception>
 569    public static Fixed64 GetDistanceToCenteredCapsule(
 570        Vector3d point,
 571        Vector3d center,
 572        Vector3d axisDirection,
 573        Fixed64 axisLength,
 574        Fixed64 radius)
 575    {
 2576        TryGetDistanceToCenteredCapsule(
 2577            point,
 2578            center,
 2579            axisDirection,
 2580            axisLength,
 2581            radius,
 2582            out Fixed64 distance);
 2583        return distance;
 584    }
 585
 586    /// <summary>
 587    /// Attempts to return the rounded nonnegative distance from a point to a
 588    /// conceptual centered capsule surface.
 589    /// </summary>
 590    /// <remarks>The final value uses round-half-to-even.</remarks>
 591    /// <returns>
 592    /// True when the final distance is representable; otherwise false and
 593    /// <paramref name="distance"/> is <see cref="Fixed64.MaxValue"/>.
 594    /// Points inside or on the capsule return zero.
 595    /// </returns>
 596    /// <exception cref="ArgumentException">
 597    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 598    /// </exception>
 599    /// <exception cref="ArgumentOutOfRangeException">
 600    /// Thrown when <paramref name="axisLength"/> or <paramref name="radius"/>
 601    /// is negative.
 602    /// </exception>
 603    public static bool TryGetDistanceToCenteredCapsule(
 604        Vector3d point,
 605        Vector3d center,
 606        Vector3d axisDirection,
 607        Fixed64 axisLength,
 608        Fixed64 radius,
 609        out Fixed64 distance)
 610    {
 5611        ValidateCenteredAxis(axisDirection, axisLength);
 5612        if (radius < Fixed64.Zero)
 1613            throw new ArgumentOutOfRangeException(nameof(radius));
 614
 4615        return WideFiniteAxisIntersection.TryGetDistanceToCenteredCapsule(
 4616            point,
 4617            center,
 4618            axisDirection,
 4619            axisLength,
 4620            radius,
 4621            out distance);
 622    }
 623
 624    /// <summary>
 625    /// Returns whether a point lies inside or on a conceptual centered capsule.
 626    /// </summary>
 627    /// <exception cref="ArgumentException">
 628    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 629    /// </exception>
 630    /// <exception cref="ArgumentOutOfRangeException">
 631    /// Thrown when <paramref name="axisLength"/> or <paramref name="radius"/>
 632    /// is negative.
 633    /// </exception>
 634    public static bool ContainsPointInCenteredCapsule(
 635        Vector3d point,
 636        Vector3d center,
 637        Vector3d axisDirection,
 638        Fixed64 axisLength,
 639        Fixed64 radius) =>
 5640        ContainsPointInCenteredCapsule(
 5641            point,
 5642            center,
 5643            axisDirection,
 5644            axisLength,
 5645            radius,
 5646            Fixed64.Zero,
 5647            strict: false);
 648
 649    /// <summary>
 650    /// Returns whether a point lies strictly inside or inclusively within a
 651    /// conceptual centered capsule.
 652    /// </summary>
 653    public static bool ContainsPointInCenteredCapsule(
 654        Vector3d point,
 655        Vector3d center,
 656        Vector3d axisDirection,
 657        Fixed64 axisLength,
 658        Fixed64 radius,
 659        bool strict) =>
 3660        ContainsPointInCenteredCapsule(
 3661            point,
 3662            center,
 3663            axisDirection,
 3664            axisLength,
 3665            radius,
 3666            Fixed64.Zero,
 3667            strict);
 668
 669    /// <summary>
 670    /// Returns whether a point lies inside or on a conceptual centered capsule,
 671    /// including a nonnegative radial expansion.
 672    /// </summary>
 673    /// <exception cref="ArgumentException">
 674    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 675    /// </exception>
 676    /// <exception cref="ArgumentOutOfRangeException">
 677    /// Thrown when <paramref name="axisLength"/>, <paramref name="radius"/>,
 678    /// or <paramref name="radiusExpansion"/> is negative.
 679    /// </exception>
 680    public static bool ContainsPointInCenteredCapsule(
 681        Vector3d point,
 682        Vector3d center,
 683        Vector3d axisDirection,
 684        Fixed64 axisLength,
 685        Fixed64 radius,
 686        Fixed64 radiusExpansion) =>
 2687        ContainsPointInCenteredCapsule(
 2688            point,
 2689            center,
 2690            axisDirection,
 2691            axisLength,
 2692            radius,
 2693            radiusExpansion,
 2694            strict: false);
 695
 696    /// <summary>
 697    /// Returns whether a point lies strictly inside or inclusively within a
 698    /// conceptual centered capsule with nonnegative radial expansion.
 699    /// </summary>
 700    public static bool ContainsPointInCenteredCapsule(
 701        Vector3d point,
 702        Vector3d center,
 703        Vector3d axisDirection,
 704        Fixed64 axisLength,
 705        Fixed64 radius,
 706        Fixed64 radiusExpansion,
 707        bool strict)
 708    {
 12709        ValidateCenteredAxis(axisDirection, axisLength);
 12710        if (radius < Fixed64.Zero)
 1711            throw new ArgumentOutOfRangeException(nameof(radius));
 11712        if (radiusExpansion < Fixed64.Zero)
 1713            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 714
 10715        return WideFiniteAxisIntersection.ContainsPointInCenteredCapsule(
 10716            point,
 10717            center,
 10718            axisDirection,
 10719            axisLength,
 10720            radius,
 10721            radiusExpansion,
 10722            strict);
 723    }
 724
 725    /// <summary>
 726    /// Returns the normalized direction from the closest point on a conceptual
 727    /// centered finite axis toward <paramref name="point"/>, or zero when the
 728    /// point lies on that axis.
 729    /// </summary>
 730    /// <remarks>
 731    /// The conceptual endpoints are
 732    /// <c>center +/- axisDirection * (axisLength / 2)</c>. They are never
 733    /// constructed or narrowed before the closest-feature decision.
 734    /// </remarks>
 735    /// <exception cref="ArgumentException">
 736    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 737    /// </exception>
 738    /// <exception cref="ArgumentOutOfRangeException">
 739    /// Thrown when <paramref name="axisLength"/> is negative.
 740    /// </exception>
 741    public static Vector3d GetDirectionFromCenteredAxis(
 742        Vector3d point,
 743        Vector3d center,
 744        Vector3d axisDirection,
 745        Fixed64 axisLength)
 746    {
 6747        ValidateCenteredAxis(axisDirection, axisLength);
 748
 4749        return WideFiniteAxisIntersection.GetDirectionFromCenteredAxis(
 4750            point,
 4751            center,
 4752            axisDirection,
 4753            axisLength);
 754    }
 755
 756    /// <summary>
 757    /// Attempts to return the closest points on two conceptual centered finite
 758    /// axes described by normalized directions and full lengths.
 759    /// </summary>
 760    /// <returns>
 761    /// <see langword="true"/> when both final world points are representable;
 762    /// otherwise <see langword="false"/> and both outputs are zero.
 763    /// </returns>
 764    public static bool TryGetClosestPointsBetweenCenteredAxes(
 765        Vector3d firstCenter,
 766        Vector3d firstAxisDirection,
 767        Fixed64 firstAxisLength,
 768        Vector3d secondCenter,
 769        Vector3d secondAxisDirection,
 770        Fixed64 secondAxisLength,
 771        out Vector3d firstPoint,
 772        out Vector3d secondPoint)
 773    {
 139774        ValidateCenteredAxis(
 139775            firstAxisDirection,
 139776            firstAxisLength,
 139777            nameof(firstAxisDirection),
 139778            nameof(firstAxisLength));
 138779        ValidateCenteredAxis(
 138780            secondAxisDirection,
 138781            secondAxisLength,
 138782            nameof(secondAxisDirection),
 138783            nameof(secondAxisLength));
 137784        return WideFiniteAxisIntersection.TryGetClosestPointsBetweenCenteredAxes(
 137785            firstCenter,
 137786            firstAxisDirection,
 137787            firstAxisLength,
 137788            secondCenter,
 137789            secondAxisDirection,
 137790            secondAxisLength,
 137791            out firstPoint,
 137792            out secondPoint);
 793    }
 794
 795    /// <summary>
 796    /// Attempts to return the closest offsets on two conceptual centered
 797    /// finite axes, each relative to its own center.
 798    /// </summary>
 799    /// <remarks>
 800    /// This relation remains usable when either absolute closest point would
 801    /// exceed the public scalar coordinate range.
 802    /// </remarks>
 803    public static bool TryGetClosestOffsetsBetweenCenteredAxes(
 804        Vector3d firstCenter,
 805        Vector3d firstAxisDirection,
 806        Fixed64 firstAxisLength,
 807        Vector3d secondCenter,
 808        Vector3d secondAxisDirection,
 809        Fixed64 secondAxisLength,
 810        out Vector3d firstCenterOffset,
 811        out Vector3d secondCenterOffset)
 812    {
 1813        ValidateCenteredAxis(
 1814            firstAxisDirection,
 1815            firstAxisLength,
 1816            nameof(firstAxisDirection),
 1817            nameof(firstAxisLength));
 1818        ValidateCenteredAxis(
 1819            secondAxisDirection,
 1820            secondAxisLength,
 1821            nameof(secondAxisDirection),
 1822            nameof(secondAxisLength));
 1823        return WideFiniteAxisIntersection.TryGetClosestOffsetsBetweenCenteredAxes(
 1824            firstCenter,
 1825            firstAxisDirection,
 1826            firstAxisLength,
 1827            secondCenter,
 1828            secondAxisDirection,
 1829            secondAxisLength,
 1830            out firstCenterOffset,
 1831            out secondCenterOffset);
 832    }
 833
 834    /// <summary>
 835    /// Returns the normalized direction from the closest point on the first
 836    /// conceptual centered axis to the closest point on the second.
 837    /// </summary>
 838    /// <remarks>
 839    /// Coincident closest points return zero. The direction is resolved from
 840    /// the exact wide relation without materializing either world point.
 841    /// </remarks>
 842    public static Vector3d GetClosestDirectionBetweenCenteredAxes(
 843        Vector3d firstCenter,
 844        Vector3d firstAxisDirection,
 845        Fixed64 firstAxisLength,
 846        Vector3d secondCenter,
 847        Vector3d secondAxisDirection,
 848        Fixed64 secondAxisLength)
 849    {
 1850        ValidateCenteredAxis(
 1851            firstAxisDirection,
 1852            firstAxisLength,
 1853            nameof(firstAxisDirection),
 1854            nameof(firstAxisLength));
 1855        ValidateCenteredAxis(
 1856            secondAxisDirection,
 1857            secondAxisLength,
 1858            nameof(secondAxisDirection),
 1859            nameof(secondAxisLength));
 1860        return WideFiniteAxisIntersection.GetClosestDirectionBetweenCenteredAxes(
 1861            firstCenter,
 1862            firstAxisDirection,
 1863            firstAxisLength,
 1864            secondCenter,
 1865            secondAxisDirection,
 1866            secondAxisLength);
 867    }
 868
 869    /// <summary>
 870    /// Attempts to build the exact contact relation between two conceptual
 871    /// centered capsules without narrowing either finite axis.
 872    /// </summary>
 873    /// <remarks>
 874    /// Each capsule axis is expressed in its normalized rigid frame. The
 875    /// returned normal points from the first capsule toward the second.
 876    /// <paramref name="fallbackNormal"/> is used only when the closest axis
 877    /// points coincide. Axial and radial terms remain separate in each anchor,
 878    /// so classification does not depend on materializing a combined world
 879    /// point or center-relative offset.
 880    /// </remarks>
 881    /// <returns>
 882    /// <see langword="true"/> when the capsules overlap; otherwise
 883    /// <see langword="false"/>.
 884    /// </returns>
 885    public static bool TryGetCenteredCapsulesContact(
 886        Vector3d firstCenter,
 887        FixedQuaternion firstRotation,
 888        Vector3d firstLocalAxisDirection,
 889        Fixed64 firstAxisLength,
 890        Fixed64 firstRadius,
 891        Vector3d secondCenter,
 892        FixedQuaternion secondRotation,
 893        Vector3d secondLocalAxisDirection,
 894        Fixed64 secondAxisLength,
 895        Fixed64 secondRadius,
 896        Vector3d fallbackNormal,
 897        out FixedContactAnchors contact)
 898    {
 36899        ValidateNormalizedRotation(firstRotation, nameof(firstRotation));
 35900        ValidateNormalizedRotation(secondRotation, nameof(secondRotation));
 35901        ValidateCenteredCapsulesContact(
 35902            firstLocalAxisDirection,
 35903            firstAxisLength,
 35904            firstRadius,
 35905            secondLocalAxisDirection,
 35906            secondAxisLength,
 35907            secondRadius,
 35908            fallbackNormal);
 32909        if (!WideOrientedBox.DoCenteredRigidCapsulesOverlap(
 32910                firstCenter,
 32911                firstRotation,
 32912                firstLocalAxisDirection,
 32913                firstAxisLength,
 32914                firstRadius,
 32915                secondCenter,
 32916                secondRotation,
 32917                secondLocalAxisDirection,
 32918                secondAxisLength,
 32919                secondRadius))
 920        {
 12921            contact = default;
 12922            return false;
 923        }
 20924        _ = firstRotation.TryRotate(
 20925            firstLocalAxisDirection,
 20926            out Vector3d firstAxisDirection);
 20927        _ = secondRotation.TryRotate(
 20928            secondLocalAxisDirection,
 20929            out Vector3d secondAxisDirection);
 20930        firstAxisDirection = firstAxisDirection.Normalized;
 20931        secondAxisDirection = secondAxisDirection.Normalized;
 932
 20933        return WideFiniteAxisIntersection.TryGetCenteredCapsulesContact(
 20934            firstCenter,
 20935            firstRotation,
 20936            firstLocalAxisDirection,
 20937            firstAxisDirection,
 20938            firstAxisLength,
 20939            firstRadius,
 20940            secondCenter,
 20941            secondRotation,
 20942            secondLocalAxisDirection,
 20943            secondAxisDirection,
 20944            secondAxisLength,
 20945            secondRadius,
 20946            fallbackNormal,
 20947            out contact);
 948    }
 949
 950    private static void ValidateNormalizedRotation(
 951        FixedQuaternion rotation,
 952        string parameterName)
 953    {
 71954        if (!rotation.IsNormalized())
 955        {
 1956            throw new ArgumentException(
 1957                "Capsule rotation must be normalized.",
 1958                parameterName);
 959        }
 70960    }
 961
 962    private static void ValidateCenteredCapsulesContact(
 963        Vector3d firstAxisDirection,
 964        Fixed64 firstAxisLength,
 965        Fixed64 firstRadius,
 966        Vector3d secondAxisDirection,
 967        Fixed64 secondAxisLength,
 968        Fixed64 secondRadius,
 969        Vector3d fallbackNormal)
 970    {
 35971        ValidateCenteredAxis(
 35972            firstAxisDirection,
 35973            firstAxisLength,
 35974            nameof(firstAxisDirection),
 35975            nameof(firstAxisLength));
 35976        ValidateCenteredAxis(
 35977            secondAxisDirection,
 35978            secondAxisLength,
 35979            nameof(secondAxisDirection),
 35980            nameof(secondAxisLength));
 35981        if (firstRadius < Fixed64.Zero)
 1982            throw new ArgumentOutOfRangeException(nameof(firstRadius));
 34983        if (secondRadius < Fixed64.Zero)
 1984            throw new ArgumentOutOfRangeException(nameof(secondRadius));
 33985        if (!fallbackNormal.IsNormalized())
 1986            throw new ArgumentException("Fallback normal must be normalized.", nameof(fallbackNormal));
 32987    }
 988
 989    private static void ValidateCenteredAxis(
 990        Vector3d axisDirection,
 991        Fixed64 axisLength) =>
 481992        ValidateCenteredAxis(
 481993            axisDirection,
 481994            axisLength,
 481995            nameof(axisDirection),
 481996            nameof(axisLength));
 997
 998    private static void ValidateCenteredAxis(
 999        Vector3d axisDirection,
 1000        Fixed64 axisLength,
 1001        string directionParameterName,
 1002        string lengthParameterName)
 1003    {
 18751004        if (!axisDirection.IsNormalized())
 51005            throw new ArgumentException("Axis direction must be normalized.", directionParameterName);
 18701006        if (axisLength < Fixed64.Zero)
 41007            throw new ArgumentOutOfRangeException(lengthParameterName);
 18661008    }
 1009}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Primitives/Segments/FixedSegment.CenteredSurfaces.cs

#LineLine coverage
 1//=======================================================================
 2// FixedSegment.CenteredSurfaces.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024–present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System;
 9
 10namespace FixedMathSharp.Geometry;
 11
 12/// <content>
 13/// Contains methods for computing the nearest surface feature of a
 14/// centered 3D capsule, finite cylinder, or finite cone in its authoritative rigid frame.
 15/// </content>
 16public partial struct FixedSegment
 17{
 18    /// <summary>
 19    /// Returns whether a centered finite cylinder and centered capsule have
 20    /// inclusive projections on a normalized separating axis.
 21    /// </summary>
 22    public static bool DoCenteredFiniteCylinderAndCapsuleOverlapOnAxis(
 23        Vector3d projectionAxis,
 24        Vector3d cylinderCenter,
 25        Vector3d cylinderAxisDirection,
 26        Fixed64 cylinderAxisLength,
 27        Fixed64 cylinderRadius,
 28        Vector3d capsuleCenter,
 29        Vector3d capsuleAxisDirection,
 30        Fixed64 capsuleAxisLength,
 31        Fixed64 capsuleRadius)
 32    {
 1033        ValidateCylinderCapsuleProjection(
 1034            projectionAxis,
 1035            cylinderAxisDirection,
 1036            cylinderAxisLength,
 1037            cylinderRadius,
 1038            capsuleAxisDirection,
 1039            capsuleAxisLength,
 1040            capsuleRadius);
 341        return WideFiniteAxisProjection.DoCylinderCapsuleOverlapOnAxis(
 342            projectionAxis,
 343            cylinderCenter,
 344            cylinderAxisDirection,
 345            cylinderAxisLength,
 346            cylinderRadius,
 347            capsuleCenter,
 348            capsuleAxisDirection,
 349            capsuleAxisLength,
 350            capsuleRadius);
 51    }
 52
 53    /// <summary>
 54    /// Attempts to return the oriented minimum translation and rounded depth
 55    /// for a centered finite-cylinder/capsule projection overlap.
 56    /// </summary>
 57    /// <remarks>
 58    /// The returned axis points from the cylinder toward the capsule; an exact
 59    /// center-projection tie retains <paramref name="projectionAxis"/>.
 60    /// Classification is independent of final depth representability through
 61    /// <see cref="DoCenteredFiniteCylinderAndCapsuleOverlapOnAxis"/>.
 62    /// </remarks>
 63    public static bool TryGetCenteredFiniteCylinderCapsuleAxisPenetration(
 64        Vector3d projectionAxis,
 65        Vector3d cylinderCenter,
 66        Vector3d cylinderAxisDirection,
 67        Fixed64 cylinderAxisLength,
 68        Fixed64 cylinderRadius,
 69        Vector3d capsuleCenter,
 70        Vector3d capsuleAxisDirection,
 71        Fixed64 capsuleAxisLength,
 72        Fixed64 capsuleRadius,
 73        out Vector3d orientedAxis,
 74        out Fixed64 depth)
 75    {
 776        ValidateCylinderCapsuleProjection(
 777            projectionAxis,
 778            cylinderAxisDirection,
 779            cylinderAxisLength,
 780            cylinderRadius,
 781            capsuleAxisDirection,
 782            capsuleAxisLength,
 783            capsuleRadius);
 784        return WideFiniteAxisProjection.TryGetCylinderCapsuleAxisPenetration(
 785            projectionAxis,
 786            cylinderCenter,
 787            cylinderAxisDirection,
 788            cylinderAxisLength,
 789            cylinderRadius,
 790            capsuleCenter,
 791            capsuleAxisDirection,
 792            capsuleAxisLength,
 793            capsuleRadius,
 794            out orientedAxis,
 795            out depth);
 96    }
 97
 98    /// <summary>
 99    /// Attempts to return the oriented minimum translation for a centered
 100    /// finite-cylinder/capsule projection overlap, clamping an otherwise
 101    /// unrepresentable positive depth to <see cref="Fixed64.MaxValue"/>.
 102    /// </summary>
 103    public static bool TryGetCenteredFiniteCylinderCapsuleAxisPenetration(
 104        Vector3d projectionAxis,
 105        Vector3d cylinderCenter,
 106        Vector3d cylinderAxisDirection,
 107        Fixed64 cylinderAxisLength,
 108        Fixed64 cylinderRadius,
 109        Vector3d capsuleCenter,
 110        Vector3d capsuleAxisDirection,
 111        Fixed64 capsuleAxisLength,
 112        Fixed64 capsuleRadius,
 113        out Vector3d orientedAxis,
 114        out Fixed64 depth,
 115        out bool depthIsClamped)
 116    {
 6117        ValidateCylinderCapsuleProjection(
 6118            projectionAxis,
 6119            cylinderAxisDirection,
 6120            cylinderAxisLength,
 6121            cylinderRadius,
 6122            capsuleAxisDirection,
 6123            capsuleAxisLength,
 6124            capsuleRadius);
 6125        return WideFiniteAxisProjection.TryGetCylinderCapsuleAxisPenetration(
 6126            projectionAxis,
 6127            cylinderCenter,
 6128            cylinderAxisDirection,
 6129            cylinderAxisLength,
 6130            cylinderRadius,
 6131            capsuleCenter,
 6132            capsuleAxisDirection,
 6133            capsuleAxisLength,
 6134            capsuleRadius,
 6135            out orientedAxis,
 6136            out depth,
 6137            out depthIsClamped);
 138    }
 139
 140    /// <summary>
 141    /// Returns whether two centered finite cylinders have inclusive
 142    /// projections on a normalized separating axis.
 143    /// </summary>
 144    public static bool DoCenteredFiniteCylindersOverlapOnAxis(
 145        Vector3d projectionAxis,
 146        Vector3d firstCenter,
 147        Vector3d firstAxisDirection,
 148        Fixed64 firstAxisLength,
 149        Fixed64 firstRadius,
 150        Vector3d secondCenter,
 151        Vector3d secondAxisDirection,
 152        Fixed64 secondAxisLength,
 153        Fixed64 secondRadius)
 154    {
 217155        ValidateCylinderProjection(
 217156            projectionAxis,
 217157            firstAxisDirection,
 217158            firstAxisLength,
 217159            firstRadius,
 217160            nameof(firstAxisDirection),
 217161            nameof(firstAxisLength),
 217162            nameof(firstRadius));
 217163        ValidateCylinderProjection(
 217164            projectionAxis,
 217165            secondAxisDirection,
 217166            secondAxisLength,
 217167            secondRadius,
 217168            nameof(secondAxisDirection),
 217169            nameof(secondAxisLength),
 217170            nameof(secondRadius));
 217171        return WideFiniteAxisProjection.DoCylindersOverlapOnAxis(
 217172            projectionAxis,
 217173            firstCenter,
 217174            firstAxisDirection,
 217175            firstAxisLength,
 217176            firstRadius,
 217177            secondCenter,
 217178            secondAxisDirection,
 217179            secondAxisLength,
 217180            secondRadius);
 181    }
 182
 183    /// <summary>
 184    /// Attempts to return the oriented minimum translation and rounded depth
 185    /// for two centered finite-cylinder projections.
 186    /// </summary>
 187    public static bool TryGetCenteredFiniteCylindersAxisPenetration(
 188        Vector3d projectionAxis,
 189        Vector3d firstCenter,
 190        Vector3d firstAxisDirection,
 191        Fixed64 firstAxisLength,
 192        Fixed64 firstRadius,
 193        Vector3d secondCenter,
 194        Vector3d secondAxisDirection,
 195        Fixed64 secondAxisLength,
 196        Fixed64 secondRadius,
 197        out Vector3d orientedAxis,
 198        out Fixed64 depth)
 199    {
 116200        ValidateCylinderProjection(
 116201            projectionAxis,
 116202            firstAxisDirection,
 116203            firstAxisLength,
 116204            firstRadius,
 116205            nameof(firstAxisDirection),
 116206            nameof(firstAxisLength),
 116207            nameof(firstRadius));
 116208        ValidateCylinderProjection(
 116209            projectionAxis,
 116210            secondAxisDirection,
 116211            secondAxisLength,
 116212            secondRadius,
 116213            nameof(secondAxisDirection),
 116214            nameof(secondAxisLength),
 116215            nameof(secondRadius));
 116216        return WideFiniteAxisProjection.TryGetCylindersAxisPenetration(
 116217            projectionAxis,
 116218            firstCenter,
 116219            firstAxisDirection,
 116220            firstAxisLength,
 116221            firstRadius,
 116222            secondCenter,
 116223            secondAxisDirection,
 116224            secondAxisLength,
 116225            secondRadius,
 116226            out orientedAxis,
 116227            out depth);
 228    }
 229
 230    /// <summary>
 231    /// Attempts to return the oriented minimum translation for two centered
 232    /// finite-cylinder projections, clamping an otherwise unrepresentable
 233    /// positive depth to <see cref="Fixed64.MaxValue"/>.
 234    /// </summary>
 235    public static bool TryGetCenteredFiniteCylindersAxisPenetration(
 236        Vector3d projectionAxis,
 237        Vector3d firstCenter,
 238        Vector3d firstAxisDirection,
 239        Fixed64 firstAxisLength,
 240        Fixed64 firstRadius,
 241        Vector3d secondCenter,
 242        Vector3d secondAxisDirection,
 243        Fixed64 secondAxisLength,
 244        Fixed64 secondRadius,
 245        out Vector3d orientedAxis,
 246        out Fixed64 depth,
 247        out bool depthIsClamped)
 248    {
 1249        ValidateCylinderProjection(
 1250            projectionAxis,
 1251            firstAxisDirection,
 1252            firstAxisLength,
 1253            firstRadius,
 1254            nameof(firstAxisDirection),
 1255            nameof(firstAxisLength),
 1256            nameof(firstRadius));
 1257        ValidateCylinderProjection(
 1258            projectionAxis,
 1259            secondAxisDirection,
 1260            secondAxisLength,
 1261            secondRadius,
 1262            nameof(secondAxisDirection),
 1263            nameof(secondAxisLength),
 1264            nameof(secondRadius));
 1265        return WideFiniteAxisProjection.TryGetCylindersAxisPenetration(
 1266            projectionAxis,
 1267            firstCenter,
 1268            firstAxisDirection,
 1269            firstAxisLength,
 1270            firstRadius,
 1271            secondCenter,
 1272            secondAxisDirection,
 1273            secondAxisLength,
 1274            secondRadius,
 1275            out orientedAxis,
 1276            out depth,
 1277            out depthIsClamped);
 278    }
 279
 280    /// <summary>
 281    /// Returns whether a conceptual centered finite cylinder inclusively
 282    /// overlaps a sphere without materializing a contact witness.
 283    /// </summary>
 284    public static bool DoesCenteredFiniteCylinderOverlapSphere(
 285        Vector3d cylinderCenter,
 286        Vector3d cylinderAxisDirection,
 287        Fixed64 cylinderAxisLength,
 288        Fixed64 cylinderRadius,
 289        Vector3d sphereCenter,
 290        Fixed64 sphereRadius)
 291    {
 6292        if (!cylinderAxisDirection.IsNormalized())
 293        {
 1294            throw new ArgumentException(
 1295                "Cylinder axis direction must be normalized.",
 1296                nameof(cylinderAxisDirection));
 297        }
 5298        if (cylinderAxisLength <= Fixed64.Zero)
 1299            throw new ArgumentOutOfRangeException(nameof(cylinderAxisLength));
 4300        if (cylinderRadius < Fixed64.Zero)
 1301            throw new ArgumentOutOfRangeException(nameof(cylinderRadius));
 3302        if (sphereRadius < Fixed64.Zero)
 1303            throw new ArgumentOutOfRangeException(nameof(sphereRadius));
 304
 2305        return WideFiniteAxisIntersection.DoesCenteredFiniteCylinderOverlapSphere(
 2306            cylinderCenter,
 2307            cylinderAxisDirection,
 2308            cylinderAxisLength,
 2309            cylinderRadius,
 2310            sphereCenter,
 2311            sphereRadius);
 312    }
 313
 314    /// <summary>
 315    /// Attempts to return the nearest representable surface witness, outward
 316    /// normal, and signed distance for a conceptual centered finite cylinder.
 317    /// </summary>
 318    /// <remarks>
 319    /// Distance is positive outside, zero on the selected surface lattice
 320    /// witness, and negative inside. <paramref name="fallbackRadialDirection"/>
 321    /// selects the side normal only when the point lies on the cylinder axis.
 322    /// </remarks>
 323    public static bool TryGetClosestPointOnCenteredFiniteCylinderSurface(
 324        Vector3d point,
 325        Vector3d center,
 326        Vector3d axisDirection,
 327        Fixed64 axisLength,
 328        Fixed64 radius,
 329        Vector3d fallbackRadialDirection,
 330        out Vector3d surfacePoint,
 331        out Vector3d outwardNormal,
 332        out Fixed64 signedDistance)
 333    {
 18334        ValidateCenteredSurface(
 18335            axisDirection,
 18336            axisLength,
 18337            radius,
 18338            fallbackRadialDirection,
 18339            nameof(axisDirection),
 18340            nameof(axisLength),
 18341            nameof(radius),
 18342            nameof(fallbackRadialDirection));
 13343        return WideFiniteAxisIntersection.TryGetClosestPointOnCenteredFiniteCylinderSurface(
 13344            point,
 13345            center,
 13346            axisDirection,
 13347            axisLength,
 13348            radius,
 13349            fallbackRadialDirection,
 13350            out surfacePoint,
 13351            out outwardNormal,
 13352            out signedDistance);
 353    }
 354
 355    /// <summary>
 356    /// Attempts to return the nearest cylinder-surface offset relative to the
 357    /// cylinder center, together with its outward normal and signed distance.
 358    /// </summary>
 359    /// <remarks>
 360    /// Unlike the absolute-witness overload, this relation remains usable when
 361    /// adding the returned offset to <paramref name="center"/> would exceed the
 362    /// public scalar range.
 363    /// </remarks>
 364    public static bool TryGetClosestCenteredFiniteCylinderSurfaceOffset(
 365        Vector3d point,
 366        Vector3d center,
 367        Vector3d axisDirection,
 368        Fixed64 axisLength,
 369        Fixed64 radius,
 370        Vector3d fallbackRadialDirection,
 371        out Vector3d surfaceOffset,
 372        out Vector3d outwardNormal,
 373        out Fixed64 signedDistance)
 374    {
 3375        ValidateCenteredSurface(
 3376            axisDirection,
 3377            axisLength,
 3378            radius,
 3379            fallbackRadialDirection,
 3380            nameof(axisDirection),
 3381            nameof(axisLength),
 3382            nameof(radius),
 3383            nameof(fallbackRadialDirection));
 3384        return WideFiniteAxisIntersection.TryGetClosestCenteredFiniteCylinderSurfaceOffset(
 3385            point,
 3386            center,
 3387            axisDirection,
 3388            axisLength,
 3389            radius,
 3390            fallbackRadialDirection,
 3391            out surfaceOffset,
 3392            out outwardNormal,
 3393            out signedDistance);
 394    }
 395
 396    /// <summary>
 397    /// Returns whether a conceptual centered finite cone inclusively overlaps
 398    /// a sphere without materializing a contact witness.
 399    /// </summary>
 400    public static bool DoesCenteredFiniteConeOverlapSphere(
 401        Vector3d coneCenter,
 402        Vector3d baseToApexDirection,
 403        Fixed64 coneHeight,
 404        Fixed64 coneRadius,
 405        Vector3d sphereCenter,
 406        Fixed64 sphereRadius)
 407    {
 9408        ValidateCenteredCone(
 9409            baseToApexDirection,
 9410            coneHeight,
 9411            coneRadius);
 6412        if (sphereRadius < Fixed64.Zero)
 1413            throw new ArgumentOutOfRangeException(nameof(sphereRadius));
 414
 5415        return WideFiniteAxisIntersection.DoesCenteredFiniteConeOverlapSphere(
 5416            coneCenter,
 5417            baseToApexDirection,
 5418            coneHeight,
 5419            coneRadius,
 5420            sphereCenter,
 5421            sphereRadius);
 422    }
 423
 424    /// <summary>
 425    /// Attempts to return the nearest representable surface witness, outward
 426    /// normal, and signed distance for a conceptual centered finite cone.
 427    /// </summary>
 428    /// <remarks>
 429    /// The axis points from the base toward the apex. Distance is positive
 430    /// outside, zero on the selected surface lattice witness, and negative
 431    /// inside. <paramref name="fallbackRadialDirection"/> selects the side
 432    /// normal only for an axial point or apex tie.
 433    /// </remarks>
 434    public static bool TryGetClosestPointOnCenteredFiniteConeSurface(
 435        Vector3d point,
 436        Vector3d center,
 437        Vector3d baseToApexDirection,
 438        Fixed64 height,
 439        Fixed64 radius,
 440        Vector3d fallbackRadialDirection,
 441        out Vector3d surfacePoint,
 442        out Vector3d outwardNormal,
 443        out Fixed64 signedDistance)
 444    {
 11445        ValidateCenteredSurface(
 11446            baseToApexDirection,
 11447            height,
 11448            radius,
 11449            fallbackRadialDirection,
 11450            nameof(baseToApexDirection),
 11451            nameof(height),
 11452            nameof(radius),
 11453            nameof(fallbackRadialDirection));
 11454        return WideFiniteAxisIntersection.TryGetClosestPointOnCenteredFiniteConeSurface(
 11455            point,
 11456            center,
 11457            baseToApexDirection,
 11458            height,
 11459            radius,
 11460            fallbackRadialDirection,
 11461            out surfacePoint,
 11462            out outwardNormal,
 11463            out signedDistance);
 464    }
 465
 466    /// <summary>
 467    /// Attempts to return the nearest cone-surface offset relative to the cone
 468    /// center, together with its outward normal and signed distance.
 469    /// </summary>
 470    /// <remarks>
 471    /// Unlike the absolute-witness overload, this relation remains usable when
 472    /// adding the returned offset to <paramref name="center"/> would exceed the
 473    /// public scalar range.
 474    /// </remarks>
 475    public static bool TryGetClosestCenteredFiniteConeSurfaceOffset(
 476        Vector3d point,
 477        Vector3d center,
 478        Vector3d baseToApexDirection,
 479        Fixed64 height,
 480        Fixed64 radius,
 481        Vector3d fallbackRadialDirection,
 482        out Vector3d surfaceOffset,
 483        out Vector3d outwardNormal,
 484        out Fixed64 signedDistance)
 485    {
 3486        ValidateCenteredSurface(
 3487            baseToApexDirection,
 3488            height,
 3489            radius,
 3490            fallbackRadialDirection,
 3491            nameof(baseToApexDirection),
 3492            nameof(height),
 3493            nameof(radius),
 3494            nameof(fallbackRadialDirection));
 3495        return WideFiniteAxisIntersection.TryGetClosestCenteredFiniteConeSurfaceOffset(
 3496            point,
 3497            center,
 3498            baseToApexDirection,
 3499            height,
 3500            radius,
 3501            fallbackRadialDirection,
 3502            out surfaceOffset,
 3503            out outwardNormal,
 3504            out signedDistance);
 505    }
 506
 507    private static void ValidateCenteredCone(
 508        Vector3d axisDirection,
 509        Fixed64 height,
 510        Fixed64 radius)
 511    {
 9512        if (!axisDirection.IsNormalized())
 513        {
 1514            throw new ArgumentException(
 1515                "Cone axis direction must be normalized.",
 1516                nameof(axisDirection));
 517        }
 8518        if (height <= Fixed64.Zero)
 1519            throw new ArgumentOutOfRangeException(nameof(height));
 7520        if (radius < Fixed64.Zero)
 1521            throw new ArgumentOutOfRangeException(nameof(radius));
 6522    }
 523
 524    private static void ValidateCylinderCapsuleProjection(
 525        Vector3d projectionAxis,
 526        Vector3d cylinderAxisDirection,
 527        Fixed64 cylinderAxisLength,
 528        Fixed64 cylinderRadius,
 529        Vector3d capsuleAxisDirection,
 530        Fixed64 capsuleAxisLength,
 531        Fixed64 capsuleRadius)
 532    {
 23533        ValidateCylinderProjection(
 23534            projectionAxis,
 23535            cylinderAxisDirection,
 23536            cylinderAxisLength,
 23537            cylinderRadius,
 23538            nameof(cylinderAxisDirection),
 23539            nameof(cylinderAxisLength),
 23540            nameof(cylinderRadius));
 19541        if (!capsuleAxisDirection.IsNormalized())
 542        {
 1543            throw new ArgumentException(
 1544                "Capsule axis direction must be normalized.",
 1545                nameof(capsuleAxisDirection));
 546        }
 18547        if (capsuleAxisLength < Fixed64.Zero)
 1548            throw new ArgumentOutOfRangeException(nameof(capsuleAxisLength));
 17549        if (capsuleRadius < Fixed64.Zero)
 1550            throw new ArgumentOutOfRangeException(nameof(capsuleRadius));
 16551    }
 552
 553    private static void ValidateCylinderProjection(
 554        Vector3d projectionAxis,
 555        Vector3d cylinderAxisDirection,
 556        Fixed64 cylinderAxisLength,
 557        Fixed64 cylinderRadius,
 558        string axisParameterName,
 559        string lengthParameterName,
 560        string radiusParameterName)
 561    {
 691562        if (!projectionAxis.IsNormalized())
 1563            throw new ArgumentException("Projection axis must be normalized.", nameof(projectionAxis));
 690564        if (!cylinderAxisDirection.IsNormalized())
 1565            throw new ArgumentException("Cylinder axis direction must be normalized.", axisParameterName);
 689566        if (cylinderAxisLength <= Fixed64.Zero)
 1567            throw new ArgumentOutOfRangeException(lengthParameterName);
 688568        if (cylinderRadius < Fixed64.Zero)
 1569            throw new ArgumentOutOfRangeException(radiusParameterName);
 687570    }
 571
 572    private static void ValidateCenteredSurface(
 573        Vector3d axisDirection,
 574        Fixed64 axisLength,
 575        Fixed64 radius,
 576        Vector3d fallbackRadialDirection,
 577        string axisParameterName,
 578        string lengthParameterName,
 579        string radiusParameterName,
 580        string fallbackParameterName)
 581    {
 56582        if (!axisDirection.IsNormalized())
 2583            throw new ArgumentException("Axis direction must be normalized.", axisParameterName);
 54584        if (axisLength <= Fixed64.Zero)
 1585            throw new ArgumentOutOfRangeException(lengthParameterName);
 53586        if (radius < Fixed64.Zero)
 1587            throw new ArgumentOutOfRangeException(radiusParameterName);
 52588        if (!fallbackRadialDirection.IsNormalized())
 589        {
 1590            throw new ArgumentException(
 1591                "Fallback radial direction must be normalized.",
 1592                fallbackParameterName);
 593        }
 51594        if (Vector3d.Cross(axisDirection, fallbackRadialDirection).IsZero)
 595        {
 1596            throw new ArgumentException(
 1597                "Fallback radial direction must not be parallel to the axis.",
 1598                fallbackParameterName);
 599        }
 50600    }
 601
 602    /// <summary>
 603    /// Attempts to return the selected point on a conceptual centered capsule
 604    /// surface without narrowing its axis point before applying the radial
 605    /// offset.
 606    /// </summary>
 607    public static bool TryGetSurfacePointOnCenteredCapsule(
 608        Vector3d point,
 609        Vector3d center,
 610        Vector3d axisDirection,
 611        Fixed64 axisLength,
 612        Fixed64 radius,
 613        Vector3d surfaceDirection,
 614        out Vector3d surfacePoint)
 615    {
 8616        ValidateCenteredAxis(axisDirection, axisLength);
 8617        ValidateCenteredCapsuleSurface(radius, surfaceDirection);
 6618        return WideFiniteAxisIntersection.TryGetSurfacePointOnCenteredCapsule(
 6619            point,
 6620            center,
 6621            axisDirection,
 6622            axisLength,
 6623            radius,
 6624            surfaceDirection,
 6625            out surfacePoint);
 626    }
 627
 628    /// <summary>
 629    /// Attempts to return a centered-capsule surface offset relative to the
 630    /// capsule center.
 631    /// </summary>
 632    public static bool TryGetSurfaceOffsetOnCenteredCapsule(
 633        Vector3d point,
 634        Vector3d center,
 635        Vector3d axisDirection,
 636        Fixed64 axisLength,
 637        Fixed64 radius,
 638        Vector3d surfaceDirection,
 639        out Vector3d surfaceOffset)
 640    {
 5641        ValidateCenteredAxis(axisDirection, axisLength);
 5642        ValidateCenteredCapsuleSurface(radius, surfaceDirection);
 3643        return WideFiniteAxisIntersection.TryGetSurfaceOffsetOnCenteredCapsule(
 3644            point,
 3645            center,
 3646            axisDirection,
 3647            axisLength,
 3648            radius,
 3649            surfaceDirection,
 3650            out surfaceOffset);
 651    }
 652
 653    /// <summary>
 654    /// Returns the centered-capsule surface anchor nearest to a world-space
 655    /// point in the supplied normalized world-space surface direction.
 656    /// </summary>
 657    /// <remarks>
 658    /// The closest axial offset and radial offset remain separate in an
 659    /// identity-rotation frame, avoiding an inverse-/forward-rotation
 660    /// round-trip when the caller already owns the world-space direction.
 661    /// </remarks>
 662    public static FixedPointAnchor GetSurfaceAnchorOnCenteredCapsule(
 663        Vector3d point,
 664        Vector3d center,
 665        Vector3d axisDirection,
 666        Fixed64 axisLength,
 667        Fixed64 radius,
 668        Vector3d surfaceDirection)
 669    {
 1670        ValidateCenteredAxis(axisDirection, axisLength);
 1671        ValidateCenteredCapsuleSurface(radius, surfaceDirection);
 1672        return WideFiniteAxisIntersection.GetSurfaceAnchorOnCenteredCapsule(
 1673            point,
 1674            center,
 1675            axisDirection,
 1676            axisLength,
 1677            radius,
 1678            surfaceDirection);
 679    }
 680
 681    /// <summary>
 682    /// Returns the centered-capsule surface anchor nearest to a world-space
 683    /// point in the supplied normalized local-space surface direction.
 684    /// </summary>
 685    public static FixedPointAnchor GetSurfaceAnchorOnCenteredCapsule(
 686        Vector3d point,
 687        Vector3d center,
 688        FixedQuaternion frameRotation,
 689        Vector3d localAxisDirection,
 690        Fixed64 axisLength,
 691        Fixed64 radius,
 692        Vector3d localSurfaceDirection)
 693    {
 91694        if (!frameRotation.IsNormalized())
 695        {
 1696            throw new ArgumentException(
 1697                "Frame rotation must be normalized.",
 1698                nameof(frameRotation));
 699        }
 90700        ValidateCenteredAxis(localAxisDirection, axisLength);
 90701        ValidateCenteredCapsuleSurface(radius, localSurfaceDirection);
 89702        return WideFiniteAxisIntersection.GetSurfaceAnchorOnCenteredCapsule(
 89703            point,
 89704            center,
 89705            frameRotation,
 89706            localAxisDirection,
 89707            axisLength,
 89708            radius,
 89709            localSurfaceDirection);
 710    }
 711
 712    private static void ValidateCenteredCapsuleSurface(
 713        Fixed64 radius,
 714        Vector3d surfaceDirection)
 715    {
 110716        if (radius < Fixed64.Zero)
 2717            throw new ArgumentOutOfRangeException(nameof(radius));
 108718        if (!surfaceDirection.IsNormalized())
 719        {
 3720            throw new ArgumentException(
 3721                "Surface direction must be normalized.",
 3722                nameof(surfaceDirection));
 723        }
 105724    }
 725
 726    /// <summary>
 727    /// Attempts to return the nearest centered-capsule surface feature in its
 728    /// authoritative rigid frame.
 729    /// </summary>
 730    /// <remarks>
 731    /// The returned anchor retains odd full-length cap positions and its
 732    /// radial feature until final materialization. Distance is positive
 733    /// outside, zero on the selected surface lattice witness, and negative
 734    /// inside.
 735    /// </remarks>
 736    public static bool TryGetClosestCenteredCapsuleSurfaceAnchor(
 737        Vector3d point,
 738        Vector3d center,
 739        FixedQuaternion frameRotation,
 740        Vector3d localAxisDirection,
 741        Fixed64 axisLength,
 742        Fixed64 radius,
 743        Vector3d localFallbackRadialDirection,
 744        out FixedPointAnchor surfaceAnchor,
 745        out Vector3d outwardNormal,
 746        out Fixed64 signedDistance)
 747    {
 7748        if (!frameRotation.IsNormalized())
 749        {
 1750            throw new ArgumentException(
 1751                "Frame rotation must be normalized.",
 1752                nameof(frameRotation));
 753        }
 6754        ValidateCenteredAxis(localAxisDirection, axisLength);
 6755        ValidateCenteredCapsuleSurface(
 6756            radius,
 6757            localFallbackRadialDirection);
 6758        if (Vector3d.Cross(
 6759                localAxisDirection,
 6760                localFallbackRadialDirection).IsZero)
 761        {
 1762            throw new ArgumentException(
 1763                "Fallback radial direction must not be parallel to the axis.",
 1764                nameof(localFallbackRadialDirection));
 765        }
 766
 5767        return WideFiniteAxisIntersection
 5768            .TryGetClosestCenteredCapsuleSurfaceAnchor(
 5769                point,
 5770                center,
 5771                frameRotation,
 5772                localAxisDirection,
 5773                axisLength,
 5774                radius,
 5775                localFallbackRadialDirection,
 5776                out surfaceAnchor,
 5777                out outwardNormal,
 5778                out signedDistance);
 779    }
 780
 781    /// <summary>
 782    /// Attempts to return the nearest centered finite-cylinder surface feature
 783    /// in its authoritative rigid frame.
 784    /// </summary>
 785    /// <remarks>
 786    /// The returned anchor retains axial and radial feature terms separately,
 787    /// so callers do not need to inverse-rotate an already rounded world-space
 788    /// offset. Distance is positive outside, zero on the selected surface
 789    /// witness, and negative inside.
 790    /// </remarks>
 791    public static bool TryGetClosestCenteredFiniteCylinderSurfaceAnchor(
 792        Vector3d point,
 793        Vector3d center,
 794        FixedQuaternion frameRotation,
 795        Vector3d localAxisDirection,
 796        Fixed64 axisLength,
 797        Fixed64 radius,
 798        Vector3d localFallbackRadialDirection,
 799        out FixedPointAnchor surfaceAnchor,
 800        out Vector3d outwardNormal,
 801        out Fixed64 signedDistance)
 802    {
 12803        ValidateCenteredSurfaceFrame(
 12804            frameRotation,
 12805            localAxisDirection,
 12806            axisLength,
 12807            radius,
 12808            localFallbackRadialDirection);
 11809        return WideFiniteAxisIntersection
 11810            .TryGetClosestCenteredFiniteCylinderSurfaceAnchor(
 11811                point,
 11812                center,
 11813                frameRotation,
 11814                localAxisDirection,
 11815                axisLength,
 11816                radius,
 11817                localFallbackRadialDirection,
 11818                out surfaceAnchor,
 11819                out outwardNormal,
 11820                out signedDistance);
 821    }
 822
 823    /// <summary>
 824    /// Attempts to return the nearest centered finite-cone surface feature in
 825    /// its authoritative rigid frame.
 826    /// </summary>
 827    /// <remarks>
 828    /// The local axis points from the base toward the apex. The returned anchor
 829    /// retains the selected meridian feature without a rounded world-offset
 830    /// round trip. Distance is positive outside, zero on the selected surface
 831    /// witness, and negative inside.
 832    /// </remarks>
 833    public static bool TryGetClosestCenteredFiniteConeSurfaceAnchor(
 834        Vector3d point,
 835        Vector3d center,
 836        FixedQuaternion frameRotation,
 837        Vector3d localAxisDirection,
 838        Fixed64 height,
 839        Fixed64 radius,
 840        Vector3d localFallbackRadialDirection,
 841        out FixedPointAnchor surfaceAnchor,
 842        out Vector3d outwardNormal,
 843        out Fixed64 signedDistance)
 844    {
 10845        ValidateCenteredSurfaceFrame(
 10846            frameRotation,
 10847            localAxisDirection,
 10848            height,
 10849            radius,
 10850            localFallbackRadialDirection);
 9851        return WideFiniteAxisIntersection
 9852            .TryGetClosestCenteredFiniteConeSurfaceAnchor(
 9853                point,
 9854                center,
 9855                frameRotation,
 9856                localAxisDirection,
 9857                height,
 9858                radius,
 9859                localFallbackRadialDirection,
 9860                out surfaceAnchor,
 9861                out outwardNormal,
 9862                out signedDistance);
 863    }
 864
 865    private static void ValidateCenteredSurfaceFrame(
 866        FixedQuaternion frameRotation,
 867        Vector3d localAxisDirection,
 868        Fixed64 axisLength,
 869        Fixed64 radius,
 870        Vector3d localFallbackRadialDirection)
 871    {
 22872        if (!frameRotation.IsNormalized())
 873        {
 1874            throw new ArgumentException(
 1875                "Frame rotation must be normalized.",
 1876                nameof(frameRotation));
 877        }
 21878        ValidateCenteredSurface(
 21879            localAxisDirection,
 21880            axisLength,
 21881            radius,
 21882            localFallbackRadialDirection,
 21883            nameof(localAxisDirection),
 21884            nameof(axisLength),
 21885            nameof(radius),
 21886            nameof(localFallbackRadialDirection));
 20887    }
 888}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Primitives/Segments/FixedSegment.cs

#LineLine coverage
 1//=======================================================================
 2// FixedSegment.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024–present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System;
 9using System.Runtime.CompilerServices;
 10using System.Text.Json.Serialization;
 11using MemoryPack;
 12
 13namespace FixedMathSharp.Geometry;
 14
 15/// <summary>
 16/// Represents a finite line segment in three-dimensional fixed-point space.
 17/// </summary>
 18[Serializable]
 19[MemoryPackable]
 20public partial struct FixedSegment : IEquatable<FixedSegment>
 21{
 22    #region Fields
 23
 24    /// <summary>
 25    /// The start point of the segment.
 26    /// </summary>
 27    [JsonInclude]
 28    [MemoryPackOrder(0)]
 29    public Vector3d Start;
 30
 31    /// <summary>
 32    /// The end point of the segment.
 33    /// </summary>
 34    [JsonInclude]
 35    [MemoryPackOrder(1)]
 36    public Vector3d End;
 37
 38    #endregion
 39
 40    #region Constructors
 41
 42    /// <summary>
 43    /// Initializes a new segment from start and end points.
 44    /// </summary>
 45    [JsonConstructor]
 46    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 47    public FixedSegment(Vector3d start, Vector3d end)
 48    {
 56349        Start = start;
 56350        End = end;
 56351    }
 52
 53    #endregion
 54
 55    #region Properties
 56
 57    /// <summary>
 58    /// The vector from <see cref="Start"/> to <see cref="End"/>.
 59    /// </summary>
 60    /// <remarks>
 61    /// This is ordinary component-wise <see cref="Fixed64"/> subtraction and
 62    /// therefore uses the public saturating vector-arithmetic contract. Use the
 63    /// segment query methods when endpoint differences may span the complete raw
 64    /// domain; their wider intermediate contract does not extend to this property.
 65    /// </remarks>
 66    [JsonIgnore]
 67    [MemoryPackIgnore]
 68    public Vector3d Delta
 69    {
 70        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 771        get => End - Start;
 72    }
 73
 74    /// <summary>
 75    /// The segment length.
 76    /// </summary>
 77    [JsonIgnore]
 78    [MemoryPackIgnore]
 79    public Fixed64 Length
 80    {
 81        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 282        get => Delta.Magnitude;
 83    }
 84
 85    /// <summary>
 86    /// The squared segment length.
 87    /// </summary>
 88    [JsonIgnore]
 89    [MemoryPackIgnore]
 90    public Fixed64 LengthSquared
 91    {
 92        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 393        get => Delta.MagnitudeSquared;
 94    }
 95
 96    /// <summary>
 97    /// The normalized axis-aligned box that contains this segment.
 98    /// </summary>
 99    [JsonIgnore]
 100    [MemoryPackIgnore]
 101    public FixedBoundBox Bounds
 102    {
 103        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 5104        get => FixedBoundBox.FromMinMax(Start, End);
 105    }
 106
 107    #endregion
 108
 109    #region Spatial Queries
 110
 111    /// <summary>
 112    /// Finds the closest point on this finite segment to the supplied point.
 113    /// </summary>
 114    /// <remarks>
 115    /// Endpoint differences and projection products are evaluated across the
 116    /// complete raw domain before the parameter is clamped and rounded. A
 117    /// direction whose exact Q64.64 squared-length total is at most 2^31 raw
 118    /// units rounds to zero in Q32.32 and deterministically returns
 119    /// <see cref="Start"/>.
 120    /// </remarks>
 121    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 88122    public Vector3d ClosestPoint(Vector3d point) => Vector3d.ClosestPointOnLineSegment(point, Start, End);
 123
 124    /// <summary>
 125    /// Computes the squared distance from the supplied point to this finite segment.
 126    /// </summary>
 127    /// <remarks>
 128    /// Component differences and their exact squared sum are evaluated across the
 129    /// complete raw domain before one final round-half-to-even conversion. Results
 130    /// outside the positive <see cref="Fixed64"/> range saturate to
 131    /// <see cref="Fixed64.MaxValue"/>.
 132    /// </remarks>
 133    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 134    public Fixed64 DistanceSquared(Vector3d point)
 135    {
 15136        Vector3d closest = ClosestPoint(point);
 15137        return Fixed64.RoundSquaredDistance(GetDifferenceDot(point, closest, point, closest));
 138    }
 139
 140    /// <summary>
 141    /// Finds the closed parameter interval where this segment intersects a capsule.
 142    /// </summary>
 143    /// <remarks>
 144    /// The capsule is described by its finite center-line segment and radius.
 145    /// Returned parameters are clamped to [0, 1]. A zero-length capsule axis is
 146    /// treated as a sphere.
 147    /// </remarks>
 148    /// <exception cref="ArgumentOutOfRangeException">
 149    /// Thrown when <paramref name="radius"/> is negative.
 150    /// </exception>
 151    public readonly bool TryGetCapsuleIntersectionInterval(
 152        FixedSegment capsuleAxis,
 153        Fixed64 radius,
 154        out Fixed64 entryParameter,
 155        out Fixed64 exitParameter) =>
 2156        TryGetCapsuleIntersectionInterval(
 2157            capsuleAxis,
 2158            radius,
 2159            Fixed64.Zero,
 2160            out entryParameter,
 2161            out exitParameter);
 162
 163    /// <summary>
 164    /// Finds the closed parameter interval where this segment intersects a radially
 165    /// expanded capsule.
 166    /// </summary>
 167    /// <remarks>
 168    /// The authored radius and sweep expansion remain separate until the exact
 169    /// finite-axis solve. Returned parameters are clamped to [0, 1]. A zero-length
 170    /// capsule axis is treated as a sphere.
 171    /// </remarks>
 172    /// <exception cref="ArgumentOutOfRangeException">
 173    /// Thrown when <paramref name="radius"/> or <paramref name="radiusExpansion"/>
 174    /// is negative.
 175    /// </exception>
 176    public readonly bool TryGetCapsuleIntersectionInterval(
 177        FixedSegment capsuleAxis,
 178        Fixed64 radius,
 179        Fixed64 radiusExpansion,
 180        out Fixed64 entryParameter,
 181        out Fixed64 exitParameter) =>
 4182        TryGetCapsuleIntersectionInterval(
 4183            capsuleAxis,
 4184            radius,
 4185            radiusExpansion,
 4186            out entryParameter,
 4187            out exitParameter,
 4188            out _,
 4189            out _);
 190
 191    /// <summary>
 192    /// Finds the closed parameter interval where this segment intersects a capsule
 193    /// and reports exact endpoint containment.
 194    /// </summary>
 195    /// <remarks>
 196    /// <paramref name="startContained"/> is inclusive of the capsule boundary.
 197    /// <paramref name="endContainedStrict"/> is true only for the mathematical
 198    /// interior. Both classifications use the wide solve inputs rather than rounded
 199    /// parameters or reconstructed points. A zero-length capsule axis is treated as
 200    /// a sphere.
 201    /// </remarks>
 202    /// <exception cref="ArgumentOutOfRangeException">
 203    /// Thrown when <paramref name="radius"/> or <paramref name="radiusExpansion"/>
 204    /// is negative.
 205    /// </exception>
 206    public readonly bool TryGetCapsuleIntersectionInterval(
 207        FixedSegment capsuleAxis,
 208        Fixed64 radius,
 209        Fixed64 radiusExpansion,
 210        out Fixed64 entryParameter,
 211        out Fixed64 exitParameter,
 212        out bool startContained,
 213        out bool endContainedStrict)
 214    {
 11215        if (radius < Fixed64.Zero)
 1216            throw new ArgumentOutOfRangeException(nameof(radius));
 10217        if (radiusExpansion < Fixed64.Zero)
 1218            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 219
 9220        return WideFiniteAxisIntersection.TryGetCapsuleInterval(
 9221            this,
 9222            capsuleAxis,
 9223            radius,
 9224            radiusExpansion,
 9225            out entryParameter,
 9226            out exitParameter,
 9227            out startContained,
 9228            out endContainedStrict);
 229    }
 230
 231    /// <summary>
 232    /// Finds the closed parameter interval where this segment intersects a
 233    /// centered capsule.
 234    /// </summary>
 235    /// <remarks>
 236    /// The normalized axis defines the conceptual center-line endpoints as
 237    /// <c>center +/- axisDirection * (axisLength / 2)</c> without constructing or
 238    /// narrowing either endpoint.
 239    /// </remarks>
 240    /// <exception cref="ArgumentException">
 241    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 242    /// </exception>
 243    /// <exception cref="ArgumentOutOfRangeException">
 244    /// Thrown when <paramref name="axisLength"/> or
 245    /// <paramref name="radius"/> is negative.
 246    /// </exception>
 247    public readonly bool TryGetCapsuleIntersectionInterval(
 248        Vector3d center,
 249        Vector3d axisDirection,
 250        Fixed64 axisLength,
 251        Fixed64 radius,
 252        out Fixed64 entryParameter,
 253        out Fixed64 exitParameter) =>
 7254        TryGetCapsuleIntersectionInterval(
 7255            center,
 7256            axisDirection,
 7257            axisLength,
 7258            radius,
 7259            Fixed64.Zero,
 7260            out entryParameter,
 7261            out exitParameter);
 262
 263    /// <summary>
 264    /// Finds the closed parameter interval where this segment intersects a
 265    /// centered, radially expanded capsule.
 266    /// </summary>
 267    /// <exception cref="ArgumentException">
 268    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 269    /// </exception>
 270    /// <exception cref="ArgumentOutOfRangeException">
 271    /// Thrown when <paramref name="axisLength"/>,
 272    /// <paramref name="radius"/> or <paramref name="radiusExpansion"/> is
 273    /// negative.
 274    /// </exception>
 275    public readonly bool TryGetCapsuleIntersectionInterval(
 276        Vector3d center,
 277        Vector3d axisDirection,
 278        Fixed64 axisLength,
 279        Fixed64 radius,
 280        Fixed64 radiusExpansion,
 281        out Fixed64 entryParameter,
 282        out Fixed64 exitParameter) =>
 8283        TryGetCapsuleIntersectionInterval(
 8284            center,
 8285            axisDirection,
 8286            axisLength,
 8287            radius,
 8288            radiusExpansion,
 8289            out entryParameter,
 8290            out exitParameter,
 8291            out _,
 8292            out _);
 293
 294    /// <summary>
 295    /// Finds the closed parameter interval where this segment intersects a
 296    /// centered, radially expanded capsule and reports exact endpoint
 297    /// containment.
 298    /// </summary>
 299    /// <remarks>
 300    /// <paramref name="startContained"/> includes the capsule boundary;
 301    /// <paramref name="endContainedStrict"/> excludes it. The side projection,
 302    /// conceptual spherical caps, and containment classifications remain wide
 303    /// until the final deterministic parameter conversion.
 304    /// </remarks>
 305    /// <exception cref="ArgumentException">
 306    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 307    /// </exception>
 308    /// <exception cref="ArgumentOutOfRangeException">
 309    /// Thrown when <paramref name="axisLength"/>,
 310    /// <paramref name="radius"/> or <paramref name="radiusExpansion"/> is
 311    /// negative.
 312    /// </exception>
 313    public readonly bool TryGetCapsuleIntersectionInterval(
 314        Vector3d center,
 315        Vector3d axisDirection,
 316        Fixed64 axisLength,
 317        Fixed64 radius,
 318        Fixed64 radiusExpansion,
 319        out Fixed64 entryParameter,
 320        out Fixed64 exitParameter,
 321        out bool startContained,
 322        out bool endContainedStrict)
 323    {
 11324        if (!axisDirection.IsNormalized())
 2325            throw new ArgumentException("Capsule axis direction must be normalized.", nameof(axisDirection));
 9326        if (axisLength < Fixed64.Zero)
 1327            throw new ArgumentOutOfRangeException(nameof(axisLength));
 8328        if (radius < Fixed64.Zero)
 1329            throw new ArgumentOutOfRangeException(nameof(radius));
 7330        if (radiusExpansion < Fixed64.Zero)
 1331            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 332
 6333        return WideFiniteAxisIntersection.TryGetCapsuleInterval(
 6334            this,
 6335            center,
 6336            axisDirection,
 6337            axisLength,
 6338            radius,
 6339            radiusExpansion,
 6340            out entryParameter,
 6341            out exitParameter,
 6342            out startContained,
 6343            out endContainedStrict);
 344    }
 345
 346    /// <summary>
 347    /// Finds the closed parameter interval where this segment intersects a finite cylinder.
 348    /// </summary>
 349    /// <remarks>
 350    /// The cylinder is described by the centers of its flat end caps and its
 351    /// radius. Returned parameters are clamped to [0, 1].
 352    /// </remarks>
 353    /// <exception cref="ArgumentException">
 354    /// Thrown when <paramref name="cylinderAxis"/> has zero length because the
 355    /// segment alone cannot retain a flat-cap normal.
 356    /// </exception>
 357    /// <exception cref="ArgumentOutOfRangeException">
 358    /// Thrown when <paramref name="radius"/> is negative.
 359    /// </exception>
 360    public readonly bool TryGetFiniteCylinderIntersectionInterval(
 361        FixedSegment cylinderAxis,
 362        Fixed64 radius,
 363        out Fixed64 entryParameter,
 364        out Fixed64 exitParameter) =>
 5365        TryGetFiniteCylinderIntersectionInterval(
 5366            cylinderAxis,
 5367            radius,
 5368            Fixed64.Zero,
 5369            out entryParameter,
 5370            out exitParameter);
 371
 372    /// <summary>
 373    /// Finds the closed parameter interval where this segment intersects a radially
 374    /// expanded finite cylinder.
 375    /// </summary>
 376    /// <remarks>
 377    /// The authored radius and radial expansion remain separate until the exact
 378    /// finite-axis solve. Returned parameters are clamped to [0, 1].
 379    /// </remarks>
 380    /// <exception cref="ArgumentException">
 381    /// Thrown when <paramref name="cylinderAxis"/> has zero length.
 382    /// </exception>
 383    /// <exception cref="ArgumentOutOfRangeException">
 384    /// Thrown when <paramref name="radius"/> or <paramref name="radiusExpansion"/>
 385    /// is negative.
 386    /// </exception>
 387    public readonly bool TryGetFiniteCylinderIntersectionInterval(
 388        FixedSegment cylinderAxis,
 389        Fixed64 radius,
 390        Fixed64 radiusExpansion,
 391        out Fixed64 entryParameter,
 392        out Fixed64 exitParameter) =>
 55393        TryGetFiniteCylinderIntersectionInterval(
 55394            cylinderAxis,
 55395            radius,
 55396            radiusExpansion,
 55397            out entryParameter,
 55398            out exitParameter,
 55399            out _,
 55400            out _);
 401
 402    /// <summary>
 403    /// Finds the closed parameter interval where this segment intersects a finite
 404    /// cylinder and reports exact endpoint containment.
 405    /// </summary>
 406    /// <remarks>
 407    /// The cylinder is described by its flat-cap centers and radius.
 408    /// <paramref name="startContained"/> includes side and cap boundaries, while
 409    /// <paramref name="endContainedStrict"/> excludes every boundary. Both flags
 410    /// are evaluated from the wide axial projection and radial polynomial constant,
 411    /// independently of rounded interval parameters.
 412    /// </remarks>
 413    /// <exception cref="ArgumentException">
 414    /// Thrown when <paramref name="cylinderAxis"/> has zero length.
 415    /// </exception>
 416    /// <exception cref="ArgumentOutOfRangeException">
 417    /// Thrown when <paramref name="radius"/> or <paramref name="radiusExpansion"/>
 418    /// is negative.
 419    /// </exception>
 420    public readonly bool TryGetFiniteCylinderIntersectionInterval(
 421        FixedSegment cylinderAxis,
 422        Fixed64 radius,
 423        Fixed64 radiusExpansion,
 424        out Fixed64 entryParameter,
 425        out Fixed64 exitParameter,
 426        out bool startContained,
 427        out bool endContainedStrict)
 428    {
 58429        if (cylinderAxis.Start == cylinderAxis.End)
 1430            throw new ArgumentException("A finite cylinder axis must have nonzero length.", nameof(cylinderAxis));
 57431        if (radius < Fixed64.Zero)
 1432            throw new ArgumentOutOfRangeException(nameof(radius));
 56433        if (radiusExpansion < Fixed64.Zero)
 1434            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 435
 55436        return WideFiniteAxisIntersection.TryGetFiniteCylinderInterval(
 55437            this,
 55438            cylinderAxis,
 55439            radius,
 55440            radiusExpansion,
 55441            out entryParameter,
 55442            out exitParameter,
 55443            out startContained,
 55444            out endContainedStrict);
 445    }
 446
 447    /// <summary>
 448    /// Finds the closed parameter interval where this segment intersects a
 449    /// centered, affinely expanded finite cylinder.
 450    /// </summary>
 451    /// <remarks>
 452    /// <paramref name="axisDirection"/> must be normalized. The authored flat
 453    /// caps are defined parametrically by
 454    /// <c>center +/- axisDirection * (axisLength / 2)</c>; neither cap is
 455    /// constructed or narrowed. <paramref name="axialExpansion"/> extends each
 456    /// cap outward, while <paramref name="radiusExpansion"/> expands only the
 457    /// radial surface. Returned parameters use deterministic
 458    /// round-half-to-even conversion and are clamped to [0, 1].
 459    /// </remarks>
 460    /// <exception cref="ArgumentException">
 461    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 462    /// </exception>
 463    /// <exception cref="ArgumentOutOfRangeException">
 464    /// Thrown when <paramref name="axisLength"/> is not positive, or when
 465    /// <paramref name="radius"/>, <paramref name="radiusExpansion"/>, or
 466    /// <paramref name="axialExpansion"/> is negative.
 467    /// </exception>
 468    public readonly bool TryGetFiniteCylinderIntersectionInterval(
 469        Vector3d center,
 470        Vector3d axisDirection,
 471        Fixed64 axisLength,
 472        Fixed64 radius,
 473        Fixed64 radiusExpansion,
 474        Fixed64 axialExpansion,
 475        out Fixed64 entryParameter,
 476        out Fixed64 exitParameter) =>
 29477        TryGetFiniteCylinderIntersectionInterval(
 29478            center,
 29479            axisDirection,
 29480            axisLength,
 29481            radius,
 29482            radiusExpansion,
 29483            axialExpansion,
 29484            out entryParameter,
 29485            out exitParameter,
 29486            out _,
 29487            out _);
 488
 489    /// <summary>
 490    /// Finds the closed parameter interval where this segment intersects a
 491    /// centered, affinely expanded finite cylinder and reports exact endpoint
 492    /// containment.
 493    /// </summary>
 494    /// <remarks>
 495    /// <paramref name="startContained"/> includes side and cap boundaries;
 496    /// <paramref name="endContainedStrict"/> excludes every boundary. The
 497    /// normalized axis defines authored caps parametrically as
 498    /// <c>center +/- axisDirection * (axisLength / 2)</c> without constructing
 499    /// either endpoint. Interval and containment calculations remain wide until
 500    /// the final deterministic parameter conversion.
 501    /// </remarks>
 502    /// <exception cref="ArgumentException">
 503    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 504    /// </exception>
 505    /// <exception cref="ArgumentOutOfRangeException">
 506    /// Thrown when <paramref name="axisLength"/> is not positive, or when
 507    /// <paramref name="radius"/>, <paramref name="radiusExpansion"/>, or
 508    /// <paramref name="axialExpansion"/> is negative.
 509    /// </exception>
 510    public readonly bool TryGetFiniteCylinderIntersectionInterval(
 511        Vector3d center,
 512        Vector3d axisDirection,
 513        Fixed64 axisLength,
 514        Fixed64 radius,
 515        Fixed64 radiusExpansion,
 516        Fixed64 axialExpansion,
 517        out Fixed64 entryParameter,
 518        out Fixed64 exitParameter,
 519        out bool startContained,
 520        out bool endContainedStrict)
 521    {
 30522        if (!axisDirection.IsNormalized())
 2523            throw new ArgumentException("Finite cylinder axis direction must be normalized.", nameof(axisDirection));
 28524        if (axisLength <= Fixed64.Zero)
 1525            throw new ArgumentOutOfRangeException(nameof(axisLength));
 27526        if (radius < Fixed64.Zero)
 1527            throw new ArgumentOutOfRangeException(nameof(radius));
 26528        if (radiusExpansion < Fixed64.Zero)
 1529            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 25530        if (axialExpansion < Fixed64.Zero)
 1531            throw new ArgumentOutOfRangeException(nameof(axialExpansion));
 532
 24533        return WideFiniteAxisIntersection.TryGetFiniteCylinderInterval(
 24534            this,
 24535            center,
 24536            axisDirection,
 24537            axisLength,
 24538            radius,
 24539            radiusExpansion,
 24540            axialExpansion,
 24541            out entryParameter,
 24542            out exitParameter,
 24543            out startContained,
 24544            out endContainedStrict);
 545    }
 546
 547    /// <summary>
 548    /// Returns the closest finite points on this segment and another segment.
 549    /// </summary>
 550    /// <remarks>
 551    /// Endpoint differences, dot products, determinants, and parameter numerators
 552    /// are evaluated across the complete raw domain. A direction whose exact
 553    /// Q64.64 squared-length total is at most 2^31 raw units rounds to zero in
 554    /// Q32.32 and is treated as a point at its start. The established
 555    /// near-parallel policy compares the exact determinant magnitude with
 556    /// <see cref="Fixed64.Epsilon"/> before division. Parameters are rounded
 557    /// half-to-even and deterministically clamped to the closed interval [0, 1].
 558    /// When the mathematical zero-separation contact is an existing endpoint,
 559    /// both returned points preserve that endpoint bit-for-bit.
 560    /// </remarks>
 561    public readonly (Vector3d ThisPoint, Vector3d OtherPoint) GetClosestPoints(FixedSegment other)
 562    {
 71563        Signed192 firstLengthSquared = GetDifferenceDot(End, Start, End, Start);
 71564        Signed192 secondLengthSquared = GetDifferenceDot(
 71565            other.End,
 71566            other.Start,
 71567            other.End,
 71568            other.Start);
 569
 71570        if (WideGeometry.IsSquaredLengthDegenerate(firstLengthSquared))
 571        {
 9572            if (WideGeometry.IsSquaredLengthDegenerate(secondLengthSquared))
 2573                return (Start, other.Start);
 7574            if (PointOnSegment(Start, other, secondLengthSquared))
 3575                return (Start, Start);
 4576            return (Start, other.ClosestPoint(Start));
 577        }
 578
 62579        if (WideGeometry.IsSquaredLengthDegenerate(secondLengthSquared))
 580        {
 5581            if (PointOnSegment(other.Start, this, firstLengthSquared))
 2582                return (other.Start, other.Start);
 3583            return (Vector3d.ClosestPointOnLineSegment(other.Start, Start, End), other.Start);
 584        }
 585
 57586        Signed192 directionsDot = GetDifferenceDot(End, Start, other.End, other.Start);
 57587        Signed192 firstDirectionDotDifference = GetDifferenceDot(End, Start, Start, other.Start);
 57588        Signed192 secondDirectionDotDifference = GetDifferenceDot(
 57589            other.End,
 57590            other.Start,
 57591            Start,
 57592            other.Start);
 57593        Signed320 determinant = WideArithmetic.MultiplySubtract(
 57594            firstLengthSquared,
 57595            secondLengthSquared,
 57596            directionsDot,
 57597            directionsDot);
 598
 57599        (Fixed64 firstParameter, Fixed64 secondParameter, byte endpointCandidates) = SolveClosestParameters(
 57600            firstLengthSquared,
 57601            directionsDot,
 57602            secondLengthSquared,
 57603            firstDirectionDotDifference,
 57604            secondDirectionDotDifference,
 57605            determinant);
 606
 57607        if ((endpointCandidates & 1) != 0 && PointOnSegment(Start, other, secondLengthSquared))
 3608            return (Start, Start);
 54609        if ((endpointCandidates & 2) != 0 && PointOnSegment(End, other, secondLengthSquared))
 2610            return (End, End);
 52611        if ((endpointCandidates & 4) != 0 && PointOnSegment(other.Start, this, firstLengthSquared))
 2612            return (other.Start, other.Start);
 50613        if ((endpointCandidates & 8) != 0 && PointOnSegment(other.End, this, firstLengthSquared))
 2614            return (other.End, other.End);
 615
 48616        return (
 48617            Interpolate(this, firstParameter),
 48618            Interpolate(other, secondParameter));
 619    }
 620
 621    private static (Fixed64 First, Fixed64 Second, byte EndpointCandidates) SolveClosestParameters(
 622        Signed192 firstLengthSquared,
 623        Signed192 directionsDot,
 624        Signed192 secondLengthSquared,
 625        Signed192 firstDirectionDotDifference,
 626        Signed192 secondDirectionDotDifference,
 627        Signed320 determinant)
 628    {
 629        Fixed64 firstParameter;
 630        bool firstParameterIsClamped;
 57631        Signed320 firstNumerator = default;
 57632        Signed320 secondNumerator = default;
 57633        Signed320 secondDenominator = default;
 57634        Signed192 narrowSecondNumerator = default;
 57635        Signed192 narrowSecondDenominator = default;
 636        bool secondRatioIsWide;
 57637        byte endpointCandidates = 0;
 57638        bool isNearParallel = WideGeometry.IsSegmentDeterminantNearParallel(determinant);
 639
 57640        if (isNearParallel)
 641        {
 18642            firstParameter = Fixed64.Zero;
 18643            firstParameterIsClamped = true;
 18644            endpointCandidates = 1;
 18645            bool useDirectionsDot = directionsDot.Sign > 0
 18646                && WideArithmetic.CompareMagnitude(directionsDot, secondLengthSquared) > 0;
 18647            narrowSecondNumerator = useDirectionsDot
 18648                ? firstDirectionDotDifference
 18649                : secondDirectionDotDifference;
 18650            narrowSecondDenominator = useDirectionsDot ? directionsDot : secondLengthSquared;
 18651            secondRatioIsWide = false;
 652        }
 653        else
 654        {
 39655            firstNumerator = WideArithmetic.MultiplySubtract(
 39656                directionsDot,
 39657                secondDirectionDotDifference,
 39658                secondLengthSquared,
 39659                firstDirectionDotDifference);
 39660            int firstNumeratorComparison = firstNumerator.Sign < 0
 39661                ? -1
 39662                : WideArithmetic.CompareMagnitude(firstNumerator, determinant);
 663
 39664            if (firstNumerator.Sign < 0)
 665            {
 5666                firstParameter = Fixed64.Zero;
 5667                firstParameterIsClamped = true;
 5668                endpointCandidates = 0;
 5669                narrowSecondNumerator = secondDirectionDotDifference;
 5670                narrowSecondDenominator = secondLengthSquared;
 5671                secondRatioIsWide = false;
 672            }
 34673            else if (firstNumeratorComparison > 0)
 674            {
 7675                firstParameter = Fixed64.One;
 7676                firstParameterIsClamped = true;
 7677                endpointCandidates = 0;
 7678                narrowSecondNumerator = WideArithmetic.AddSigned192(
 7679                    secondDirectionDotDifference,
 7680                    directionsDot);
 7681                narrowSecondDenominator = secondLengthSquared;
 7682                secondRatioIsWide = false;
 683            }
 684            else
 685            {
 27686                firstParameter = default;
 27687                firstParameterIsClamped = false;
 27688                secondNumerator = WideArithmetic.MultiplySubtract(
 27689                    firstLengthSquared,
 27690                    secondDirectionDotDifference,
 27691                    directionsDot,
 27692                    firstDirectionDotDifference);
 27693                secondDenominator = determinant;
 27694                secondRatioIsWide = true;
 695
 27696                int secondNumeratorComparison = secondNumerator.Sign < 0
 27697                    ? -1
 27698                    : WideArithmetic.CompareMagnitude(secondNumerator, determinant);
 27699                if (secondNumerator.Sign >= 0 && secondNumeratorComparison <= 0)
 700                {
 22701                    if (firstNumerator.IsZero)
 3702                        endpointCandidates |= 1;
 19703                    else if (firstNumeratorComparison == 0)
 3704                        endpointCandidates |= 2;
 22705                    if (secondNumerator.IsZero)
 2706                        endpointCandidates |= 4;
 20707                    else if (secondNumeratorComparison == 0)
 3708                        endpointCandidates |= 8;
 709                }
 710            }
 711        }
 712
 57713        int secondNumeratorSign = secondRatioIsWide
 57714            ? secondNumerator.Sign
 57715            : narrowSecondNumerator.Sign;
 57716        if (secondNumeratorSign < 0)
 11717            return (
 11718                ClampParameter(
 11719                    WideArithmetic.SubtractSigned192(default, firstDirectionDotDifference),
 11720                    firstLengthSquared),
 11721                Fixed64.Zero,
 11722                isNearParallel ? (byte)4 : (byte)0);
 723
 46724        int secondRatioComparison = secondRatioIsWide
 46725            ? WideArithmetic.CompareMagnitude(secondNumerator, secondDenominator)
 46726            : WideArithmetic.CompareMagnitude(narrowSecondNumerator, narrowSecondDenominator);
 46727        if (secondRatioComparison > 0)
 6728            return (
 6729                ClampParameter(
 6730                    WideArithmetic.SubtractSigned192(directionsDot, firstDirectionDotDifference),
 6731                    firstLengthSquared),
 6732                Fixed64.One,
 6733                isNearParallel ? (byte)8 : (byte)0);
 734
 735        Fixed64 secondParameter;
 40736        if (secondRatioIsWide)
 737        {
 22738            _ = Fixed64.TryGetUnitIntervalRatio(
 22739                secondNumerator,
 22740                secondDenominator,
 22741                out secondParameter);
 742        }
 743        else
 744        {
 18745            _ = Fixed64.TryGetUnitIntervalRatio(
 18746                narrowSecondNumerator,
 18747                narrowSecondDenominator,
 18748                out secondParameter);
 749        }
 40750        if (!firstParameterIsClamped)
 22751            _ = Fixed64.TryGetUnitIntervalRatio(firstNumerator, determinant, out firstParameter);
 752
 40753        return (firstParameter, secondParameter, endpointCandidates);
 754    }
 755
 756    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 757    private static Fixed64 ClampParameter(Signed192 numerator, Signed192 denominator)
 758    {
 17759        if (numerator.Sign <= 0)
 5760            return Fixed64.Zero;
 12761        if (WideArithmetic.CompareMagnitude(numerator, denominator) >= 0)
 7762            return Fixed64.One;
 5763        _ = Fixed64.TryGetUnitIntervalRatio(numerator, denominator, out Fixed64 parameter);
 5764        return parameter;
 765    }
 766
 767    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 768    private static Signed192 GetDifferenceDot(
 769        Vector3d leftEnd,
 770        Vector3d leftStart,
 771        Vector3d rightEnd,
 772        Vector3d rightStart)
 773    {
 358774        return WideGeometry.GetDifferenceDotProduct3D(
 358775            leftEnd.X, leftStart.X, leftEnd.Y, leftStart.Y, leftEnd.Z, leftStart.Z,
 358776            rightEnd.X, rightStart.X, rightEnd.Y, rightStart.Y, rightEnd.Z, rightStart.Z);
 777    }
 778
 779    private static bool PointOnSegment(
 780        Vector3d point,
 781        FixedSegment segment,
 782        Signed192 lengthSquared)
 783    {
 41784        long pointX = point.X.m_rawValue;
 41785        long pointY = point.Y.m_rawValue;
 41786        long pointZ = point.Z.m_rawValue;
 41787        if (pointX < Math.Min(segment.Start.X.m_rawValue, segment.End.X.m_rawValue)
 41788            || pointX > Math.Max(segment.Start.X.m_rawValue, segment.End.X.m_rawValue)
 41789            || pointY < Math.Min(segment.Start.Y.m_rawValue, segment.End.Y.m_rawValue)
 41790            || pointY > Math.Max(segment.Start.Y.m_rawValue, segment.End.Y.m_rawValue)
 41791            || pointZ < Math.Min(segment.Start.Z.m_rawValue, segment.End.Z.m_rawValue)
 41792            || pointZ > Math.Max(segment.Start.Z.m_rawValue, segment.End.Z.m_rawValue))
 793        {
 26794            return false;
 795        }
 796
 15797        Signed192 projection = GetDifferenceDot(
 15798            point,
 15799            segment.Start,
 15800            segment.End,
 15801            segment.Start);
 15802        Signed192 pointDistanceSquared = GetDifferenceDot(
 15803            point,
 15804            segment.Start,
 15805            point,
 15806            segment.Start);
 15807        return WideArithmetic.MultiplySubtract(
 15808            lengthSquared,
 15809            pointDistanceSquared,
 15810            projection,
 15811            projection).IsZero;
 812    }
 813
 814    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 815    private static Vector3d Interpolate(FixedSegment segment, Fixed64 parameter)
 816    {
 96817        return new Vector3d(
 96818            FixedMath.Lerp(segment.Start.X, segment.End.X, parameter),
 96819            FixedMath.Lerp(segment.Start.Y, segment.End.Y, parameter),
 96820            FixedMath.Lerp(segment.Start.Z, segment.End.Z, parameter));
 821    }
 822
 823    #endregion
 824
 825    #region Deconstruction
 826
 827    /// <summary>
 828    /// Deconstructs the segment into start and end points.
 829    /// </summary>
 830    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 831    public void Deconstruct(out Vector3d start, out Vector3d end)
 832    {
 1833        start = Start;
 1834        end = End;
 1835    }
 836
 837    #endregion
 838
 839    #region Operators
 840
 841    /// <summary>
 842    /// Determines whether two segments have the same ordered endpoints.
 843    /// </summary>
 844    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 2845    public static bool operator ==(FixedSegment left, FixedSegment right) => left.Equals(right);
 846
 847    /// <summary>
 848    /// Determines whether two segments have different ordered endpoints.
 849    /// </summary>
 850    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 2851    public static bool operator !=(FixedSegment left, FixedSegment right) => !left.Equals(right);
 852
 853    #endregion
 854
 855    #region Equality
 856
 857    /// <inheritdoc />
 858    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 859    public bool Equals(FixedSegment other)
 860    {
 11861        return Start == other.Start && End == other.End;
 862    }
 863
 864    /// <inheritdoc />
 865    public override bool Equals(object? obj)
 866    {
 2867        return obj is FixedSegment other && Equals(other);
 868    }
 869
 870    /// <inheritdoc />
 871    public override int GetHashCode()
 872    {
 873        unchecked
 874        {
 2875            int hash = 17;
 2876            hash = (hash * 31) + Start.StateHash;
 2877            hash = (hash * 31) + End.StateHash;
 2878            return hash;
 879        }
 880    }
 881
 882    #endregion
 883}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Primitives/Segments/FixedSegment.Distance.cs

#LineLine coverage
 1//=======================================================================
 2// FixedSegment.Distance.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024–present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System;
 9using System.Runtime.CompilerServices;
 10
 11namespace FixedMathSharp.Geometry;
 12
 13/// <content>
 14/// Distance and intersection-interval queries for <see cref="FixedSegment"/>,
 15/// including sphere, capsule, and finite-axis intersection tests.
 16/// </content>
 17public partial struct FixedSegment
 18{
 19    /// <summary>
 20    /// Finds the physical-distance interval where this segment intersects a
 21    /// sphere, mapped to the caller-supplied total distance.
 22    /// </summary>
 23    public readonly bool TryGetSphereIntersectionDistanceInterval(
 24        FixedBoundSphere sphere,
 25        Fixed64 totalDistance,
 26        out Fixed64 entryDistance,
 27        out Fixed64 exitDistance) =>
 428        TryGetSphereIntersectionDistanceInterval(
 429            sphere,
 430            Fixed64.Zero,
 431            totalDistance,
 432            out entryDistance,
 433            out exitDistance,
 434            out _,
 435            out _);
 36
 37    /// <summary>
 38    /// Finds the physical-distance interval where this segment intersects a
 39    /// radially expanded sphere and reports exact endpoint containment.
 40    /// </summary>
 41    /// <remarks>
 42    /// The exact segment interval maps to <c>[0, totalDistance]</c> with one
 43    /// final round-half-to-even conversion. Start containment is inclusive;
 44    /// end containment is strict and is classified before distance rounding.
 45    /// </remarks>
 46    public readonly bool TryGetSphereIntersectionDistanceInterval(
 47        FixedBoundSphere sphere,
 48        Fixed64 radiusExpansion,
 49        Fixed64 totalDistance,
 50        out Fixed64 entryDistance,
 51        out Fixed64 exitDistance,
 52        out bool startContained,
 53        out bool endContainedStrict)
 54    {
 855        ValidateTotalDistance(totalDistance);
 756        if (radiusExpansion < Fixed64.Zero)
 157            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 58
 659        return WideFiniteAxisIntersection.TryGetSphereDistanceInterval(
 660            this,
 661            sphere,
 662            radiusExpansion,
 663            totalDistance,
 664            out entryDistance,
 665            out exitDistance,
 666            out startContained,
 667            out endContainedStrict);
 68    }
 69
 70    /// <summary>
 71    /// Finds the physical-distance interval where this segment intersects an
 72    /// endpoint-authored capsule.
 73    /// </summary>
 74    public readonly bool TryGetCapsuleIntersectionDistanceInterval(
 75        FixedSegment capsuleAxis,
 76        Fixed64 radius,
 77        Fixed64 totalDistance,
 78        out Fixed64 entryDistance,
 79        out Fixed64 exitDistance) =>
 180        TryGetCapsuleIntersectionDistanceInterval(
 181            capsuleAxis,
 182            radius,
 183            Fixed64.Zero,
 184            totalDistance,
 185            out entryDistance,
 186            out exitDistance,
 187            out _,
 188            out _);
 89
 90    /// <summary>
 91    /// Finds the physical-distance interval where this segment intersects an
 92    /// endpoint-authored, radially expanded capsule and reports exact endpoint
 93    /// containment.
 94    /// </summary>
 95    public readonly bool TryGetCapsuleIntersectionDistanceInterval(
 96        FixedSegment capsuleAxis,
 97        Fixed64 radius,
 98        Fixed64 radiusExpansion,
 99        Fixed64 totalDistance,
 100        out Fixed64 entryDistance,
 101        out Fixed64 exitDistance,
 102        out bool startContained,
 103        out bool endContainedStrict)
 104    {
 5105        ValidateTotalDistance(totalDistance);
 4106        if (radius < Fixed64.Zero)
 1107            throw new ArgumentOutOfRangeException(nameof(radius));
 3108        if (radiusExpansion < Fixed64.Zero)
 1109            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 110
 2111        return WideFiniteAxisIntersection.TryGetCapsuleDistanceInterval(
 2112            this,
 2113            capsuleAxis,
 2114            radius,
 2115            radiusExpansion,
 2116            totalDistance,
 2117            out entryDistance,
 2118            out exitDistance,
 2119            out startContained,
 2120            out endContainedStrict);
 121    }
 122
 123    /// <summary>
 124    /// Finds the physical-distance interval where this segment intersects a
 125    /// centered capsule.
 126    /// </summary>
 127    public readonly bool TryGetCapsuleIntersectionDistanceInterval(
 128        Vector3d center,
 129        Vector3d axisDirection,
 130        Fixed64 axisLength,
 131        Fixed64 radius,
 132        Fixed64 totalDistance,
 133        out Fixed64 entryDistance,
 134        out Fixed64 exitDistance) =>
 1135        TryGetCapsuleIntersectionDistanceInterval(
 1136            center,
 1137            axisDirection,
 1138            axisLength,
 1139            radius,
 1140            Fixed64.Zero,
 1141            totalDistance,
 1142            out entryDistance,
 1143            out exitDistance,
 1144            out _,
 1145            out _);
 146
 147    /// <summary>
 148    /// Finds the physical-distance interval where this segment intersects a
 149    /// centered, radially expanded capsule and reports exact endpoint
 150    /// containment.
 151    /// </summary>
 152    public readonly bool TryGetCapsuleIntersectionDistanceInterval(
 153        Vector3d center,
 154        Vector3d axisDirection,
 155        Fixed64 axisLength,
 156        Fixed64 radius,
 157        Fixed64 radiusExpansion,
 158        Fixed64 totalDistance,
 159        out Fixed64 entryDistance,
 160        out Fixed64 exitDistance,
 161        out bool startContained,
 162        out bool endContainedStrict)
 163    {
 12164        ValidateTotalDistance(totalDistance);
 12165        ValidateCenteredAxis(axisDirection, axisLength);
 10166        if (radius < Fixed64.Zero)
 1167            throw new ArgumentOutOfRangeException(nameof(radius));
 9168        if (radiusExpansion < Fixed64.Zero)
 1169            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 170
 8171        return WideFiniteAxisIntersection.TryGetCapsuleDistanceInterval(
 8172            this,
 8173            center,
 8174            axisDirection,
 8175            axisLength,
 8176            radius,
 8177            radiusExpansion,
 8178            totalDistance,
 8179            out entryDistance,
 8180            out exitDistance,
 8181            out startContained,
 8182            out endContainedStrict);
 183    }
 184
 185    /// <summary>
 186    /// Finds the physical-distance interval where this segment intersects an
 187    /// endpoint-authored finite cylinder.
 188    /// </summary>
 189    public readonly bool TryGetFiniteCylinderIntersectionDistanceInterval(
 190        FixedSegment cylinderAxis,
 191        Fixed64 radius,
 192        Fixed64 totalDistance,
 193        out Fixed64 entryDistance,
 194        out Fixed64 exitDistance) =>
 1195        TryGetFiniteCylinderIntersectionDistanceInterval(
 1196            cylinderAxis,
 1197            radius,
 1198            Fixed64.Zero,
 1199            totalDistance,
 1200            out entryDistance,
 1201            out exitDistance,
 1202            out _,
 1203            out _);
 204
 205    /// <summary>
 206    /// Finds the physical-distance interval where this segment intersects an
 207    /// endpoint-authored, radially expanded finite cylinder and reports exact
 208    /// endpoint containment.
 209    /// </summary>
 210    public readonly bool TryGetFiniteCylinderIntersectionDistanceInterval(
 211        FixedSegment cylinderAxis,
 212        Fixed64 radius,
 213        Fixed64 radiusExpansion,
 214        Fixed64 totalDistance,
 215        out Fixed64 entryDistance,
 216        out Fixed64 exitDistance,
 217        out bool startContained,
 218        out bool endContainedStrict)
 219    {
 6220        ValidateTotalDistance(totalDistance);
 6221        if (cylinderAxis.Start == cylinderAxis.End)
 1222            throw new ArgumentException("A finite cylinder axis must have nonzero length.", nameof(cylinderAxis));
 5223        if (radius < Fixed64.Zero)
 1224            throw new ArgumentOutOfRangeException(nameof(radius));
 4225        if (radiusExpansion < Fixed64.Zero)
 1226            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 227
 3228        return WideFiniteAxisIntersection.TryGetFiniteCylinderDistanceInterval(
 3229            this,
 3230            cylinderAxis,
 3231            radius,
 3232            radiusExpansion,
 3233            totalDistance,
 3234            out entryDistance,
 3235            out exitDistance,
 3236            out startContained,
 3237            out endContainedStrict);
 238    }
 239
 240    /// <summary>
 241    /// Finds the physical-distance interval where this segment intersects a
 242    /// centered, affinely expanded finite cylinder and reports exact endpoint
 243    /// containment.
 244    /// </summary>
 245    public readonly bool TryGetFiniteCylinderIntersectionDistanceInterval(
 246        Vector3d center,
 247        Vector3d axisDirection,
 248        Fixed64 axisLength,
 249        Fixed64 radius,
 250        Fixed64 radiusExpansion,
 251        Fixed64 axialExpansion,
 252        Fixed64 totalDistance,
 253        out Fixed64 entryDistance,
 254        out Fixed64 exitDistance,
 255        out bool startContained,
 256        out bool endContainedStrict)
 257    {
 8258        ValidateTotalDistance(totalDistance);
 8259        if (!axisDirection.IsNormalized())
 1260            throw new ArgumentException("Finite cylinder axis direction must be normalized.", nameof(axisDirection));
 7261        if (axisLength <= Fixed64.Zero)
 1262            throw new ArgumentOutOfRangeException(nameof(axisLength));
 6263        if (radius < Fixed64.Zero)
 1264            throw new ArgumentOutOfRangeException(nameof(radius));
 5265        if (radiusExpansion < Fixed64.Zero)
 1266            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 4267        if (axialExpansion < Fixed64.Zero)
 1268            throw new ArgumentOutOfRangeException(nameof(axialExpansion));
 269
 3270        return WideFiniteAxisIntersection.TryGetFiniteCylinderDistanceInterval(
 3271            this,
 3272            center,
 3273            axisDirection,
 3274            axisLength,
 3275            radius,
 3276            radiusExpansion,
 3277            axialExpansion,
 3278            totalDistance,
 3279            out entryDistance,
 3280            out exitDistance,
 3281            out startContained,
 3282            out endContainedStrict);
 283    }
 284
 285    /// <summary>
 286    /// Finds the first physical distance where this segment intersects the
 287    /// exact spherical dilation of a centered finite cylinder.
 288    /// </summary>
 289    /// <param name="center">Cylinder center.</param>
 290    /// <param name="axisDirection">Normalized cylinder axis direction.</param>
 291    /// <param name="axisLength">Positive unexpanded cylinder axis length.</param>
 292    /// <param name="radius">Nonnegative unexpanded cylinder radius.</param>
 293    /// <param name="sphericalExpansion">Nonnegative spherical dilation radius.</param>
 294    /// <param name="totalDistance">Nonnegative physical length represented by this segment.</param>
 295    /// <param name="distance">First intersection distance when one exists.</param>
 296    /// <exception cref="ArgumentException">
 297    /// Thrown when <paramref name="axisDirection"/> is not normalized, or when
 298    /// <paramref name="totalDistance"/> is zero for a non-point segment.
 299    /// </exception>
 300    /// <exception cref="ArgumentOutOfRangeException">
 301    /// Thrown when the axis length is not positive, or when the radius,
 302    /// expansion, or total distance is negative.
 303    /// </exception>
 304    public readonly bool TryGetSweptSphereFiniteCylinderIntersectionDistance(
 305        Vector3d center,
 306        Vector3d axisDirection,
 307        Fixed64 axisLength,
 308        Fixed64 radius,
 309        Fixed64 sphericalExpansion,
 310        Fixed64 totalDistance,
 311        out Fixed64 distance)
 312    {
 5313        ValidateSphericallyExpandedFiniteCylinderArguments(
 5314            axisDirection,
 5315            axisLength,
 5316            radius,
 5317            sphericalExpansion,
 5318            totalDistance);
 5319        return WideFiniteAxisIntersection.TryGetSphericallyExpandedFiniteCylinderFirstDistance(
 5320            this,
 5321            center,
 5322            axisDirection,
 5323            axisLength,
 5324            radius,
 5325            sphericalExpansion,
 5326            totalDistance,
 5327            out distance);
 328    }
 329
 330    /// <summary>
 331    /// Finds the first physical distance where this segment intersects the
 332    /// exact spherical dilation of a centered finite cylinder described by
 333    /// its nonnegative half-axis length.
 334    /// </summary>
 335    /// <remarks>
 336    /// This explicit half-axis contract retains the conceptual full length in
 337    /// wide arithmetic, so half lengths greater than
 338    /// <see cref="Fixed64.MaxValue"/> / 2 remain valid.
 339    /// </remarks>
 340    /// <param name="center">Cylinder center.</param>
 341    /// <param name="axisDirection">Normalized cylinder axis direction.</param>
 342    /// <param name="halfAxisLength">Nonnegative distance from the center to either flat cap.</param>
 343    /// <param name="radius">Nonnegative unexpanded cylinder radius.</param>
 344    /// <param name="sphericalExpansion">Nonnegative spherical dilation radius.</param>
 345    /// <param name="totalDistance">Nonnegative physical length represented by this segment.</param>
 346    /// <param name="distance">First intersection distance when one exists.</param>
 347    /// <exception cref="ArgumentException">
 348    /// Thrown when <paramref name="axisDirection"/> is not normalized, or when
 349    /// <paramref name="totalDistance"/> is zero for a non-point segment.
 350    /// </exception>
 351    /// <exception cref="ArgumentOutOfRangeException">
 352    /// Thrown when the half-axis length, radius, expansion, or total distance
 353    /// is negative.
 354    /// </exception>
 355    public readonly bool TryGetSweptSphereCenteredFiniteCylinderIntersectionDistanceFromHalfAxisLength(
 356        Vector3d center,
 357        Vector3d axisDirection,
 358        Fixed64 halfAxisLength,
 359        Fixed64 radius,
 360        Fixed64 sphericalExpansion,
 361        Fixed64 totalDistance,
 362        out Fixed64 distance)
 363    {
 6364        ValidateTotalDistance(totalDistance);
 6365        ValidateCenteredAxis(axisDirection, halfAxisLength);
 6366        if (radius < Fixed64.Zero)
 1367            throw new ArgumentOutOfRangeException(nameof(radius));
 5368        if (sphericalExpansion < Fixed64.Zero)
 1369            throw new ArgumentOutOfRangeException(nameof(sphericalExpansion));
 370
 4371        return WideFiniteAxisIntersection
 4372            .TryGetSphericallyExpandedFiniteCylinderFirstDistanceFromHalfAxisLength(
 4373                this,
 4374                center,
 4375                axisDirection,
 4376                halfAxisLength,
 4377                radius,
 4378                sphericalExpansion,
 4379                totalDistance,
 4380                out distance);
 381    }
 382
 383    /// <summary>
 384    /// Finds the first physical distance where this segment intersects the
 385    /// exact spherical dilation of an axis-aligned box.
 386    /// </summary>
 387    /// <param name="box">Unexpanded axis-aligned box.</param>
 388    /// <param name="sphericalExpansion">Nonnegative spherical dilation radius.</param>
 389    /// <param name="totalDistance">Nonnegative physical length represented by this segment.</param>
 390    /// <param name="distance">First intersection distance when one exists.</param>
 391    /// <exception cref="ArgumentException">
 392    /// Thrown when <paramref name="totalDistance"/> is zero for a non-point segment.
 393    /// </exception>
 394    /// <exception cref="ArgumentOutOfRangeException">
 395    /// Thrown when the expansion or total distance is negative.
 396    /// </exception>
 397    public readonly bool TryGetSweptSphereBoxIntersectionDistance(
 398        FixedBoundBox box,
 399        Fixed64 sphericalExpansion,
 400        Fixed64 totalDistance,
 401        out Fixed64 distance)
 402    {
 17403        ValidateTotalDistance(totalDistance);
 15404        if (sphericalExpansion < Fixed64.Zero)
 1405            throw new ArgumentOutOfRangeException(nameof(sphericalExpansion));
 406
 14407        return WideFiniteAxisIntersection.TryGetSphericallyExpandedBoxFirstDistance(
 14408            this,
 14409            box,
 14410            sphericalExpansion,
 14411            totalDistance,
 14412            out distance);
 413    }
 414
 415    /// <summary>
 416    /// Finds the first physical distance where this segment intersects the
 417    /// exact spherical dilation of an oriented box.
 418    /// </summary>
 419    /// <param name="box">Unexpanded oriented box.</param>
 420    /// <param name="sphericalExpansion">Nonnegative spherical dilation radius.</param>
 421    /// <param name="totalDistance">Nonnegative physical length represented by this segment.</param>
 422    /// <param name="distance">First intersection distance when one exists.</param>
 423    /// <exception cref="ArgumentException">
 424    /// Thrown when <paramref name="totalDistance"/> is zero for a non-point segment.
 425    /// </exception>
 426    /// <exception cref="ArgumentOutOfRangeException">
 427    /// Thrown when the expansion or total distance is negative.
 428    /// </exception>
 429    public readonly bool TryGetSweptSphereOrientedBoxIntersectionDistance(
 430        FixedOrientedBox box,
 431        Fixed64 sphericalExpansion,
 432        Fixed64 totalDistance,
 433        out Fixed64 distance)
 434    {
 50435        ValidateTotalDistance(totalDistance);
 48436        if (sphericalExpansion < Fixed64.Zero)
 1437            throw new ArgumentOutOfRangeException(nameof(sphericalExpansion));
 438
 47439        return WideOrientedBox.TryGetSweptSphereIntersectionDistance(
 47440            box.Center,
 47441            box.Orientation,
 47442            box.HalfExtents,
 47443            this,
 47444            sphericalExpansion,
 47445            totalDistance,
 47446            out distance);
 447    }
 448
 449    /// <summary>
 450    /// Finds the physical-distance interval where this segment intersects the
 451    /// exact spherical dilation of a centered finite cylinder.
 452    /// </summary>
 453    /// <remarks>
 454    /// Unlike affine radial and axial expansion, spherical dilation preserves
 455    /// the cylinder's rounded cap rims. Final distances use round-half-to-even.
 456    /// </remarks>
 457    /// <param name="center">Cylinder center.</param>
 458    /// <param name="axisDirection">Normalized cylinder axis direction.</param>
 459    /// <param name="axisLength">Positive unexpanded cylinder axis length.</param>
 460    /// <param name="radius">Nonnegative unexpanded cylinder radius.</param>
 461    /// <param name="sphericalExpansion">Nonnegative spherical dilation radius.</param>
 462    /// <param name="totalDistance">Nonnegative physical length represented by this segment.</param>
 463    /// <param name="entryDistance">First intersection distance when an interval exists.</param>
 464    /// <param name="exitDistance">Last intersection distance when an interval exists.</param>
 465    /// <param name="startContained">Whether the segment start lies in the closed dilation.</param>
 466    /// <param name="endContainedStrict">Whether the segment end lies strictly inside the dilation.</param>
 467    /// <exception cref="ArgumentException">
 468    /// Thrown when <paramref name="axisDirection"/> is not normalized, or when
 469    /// <paramref name="totalDistance"/> is zero for a non-point segment.
 470    /// </exception>
 471    /// <exception cref="ArgumentOutOfRangeException">
 472    /// Thrown when the axis length is not positive, or when the radius,
 473    /// expansion, or total distance is negative.
 474    /// </exception>
 475    public readonly bool TryGetSweptSphereFiniteCylinderIntersectionDistanceInterval(
 476        Vector3d center,
 477        Vector3d axisDirection,
 478        Fixed64 axisLength,
 479        Fixed64 radius,
 480        Fixed64 sphericalExpansion,
 481        Fixed64 totalDistance,
 482        out Fixed64 entryDistance,
 483        out Fixed64 exitDistance,
 484        out bool startContained,
 485        out bool endContainedStrict)
 486    {
 39487        ValidateSphericallyExpandedFiniteCylinderArguments(
 39488            axisDirection,
 39489            axisLength,
 39490            radius,
 39491            sphericalExpansion,
 39492            totalDistance);
 493
 35494        return WideFiniteAxisIntersection.TryGetSphericallyExpandedFiniteCylinderDistanceInterval(
 35495            this,
 35496            center,
 35497            axisDirection,
 35498            axisLength,
 35499            radius,
 35500            sphericalExpansion,
 35501            totalDistance,
 35502            out entryDistance,
 35503            out exitDistance,
 35504            out startContained,
 35505            out endContainedStrict);
 506    }
 507
 508    private readonly void ValidateSphericallyExpandedFiniteCylinderArguments(
 509        Vector3d axisDirection,
 510        Fixed64 axisLength,
 511        Fixed64 radius,
 512        Fixed64 sphericalExpansion,
 513        Fixed64 totalDistance)
 514    {
 44515        ValidateTotalDistance(totalDistance);
 44516        ValidateCenteredAxis(axisDirection, axisLength);
 43517        if (axisLength <= Fixed64.Zero)
 1518            throw new ArgumentOutOfRangeException(nameof(axisLength));
 42519        if (radius < Fixed64.Zero)
 1520            throw new ArgumentOutOfRangeException(nameof(radius));
 41521        if (sphericalExpansion < Fixed64.Zero)
 1522            throw new ArgumentOutOfRangeException(nameof(sphericalExpansion));
 40523    }
 524
 525    /// <summary>
 526    /// Reconstructs the point at an authored physical distance along this
 527    /// segment using one exact chord interpolation per coordinate.
 528    /// </summary>
 529    /// <remarks>
 530    /// This method does not normalize <see cref="Delta"/>. It therefore retains
 531    /// representable chord components that would round away in a normalized
 532    /// direction. The final coordinates use round-half-to-even.
 533    /// </remarks>
 534    /// <exception cref="ArgumentOutOfRangeException">
 535    /// Thrown when <paramref name="totalDistance"/> is negative, or when
 536    /// <paramref name="distance"/> is outside [0, <paramref name="totalDistance"/>].
 537    /// </exception>
 538    /// <exception cref="ArgumentException">
 539    /// Thrown when <paramref name="totalDistance"/> is zero and this segment is
 540    /// not a point.
 541    /// </exception>
 542    public readonly Vector3d GetPointAtDistance(Fixed64 distance, Fixed64 totalDistance)
 543    {
 45544        ValidateDistance(distance, totalDistance);
 42545        if (distance == Fixed64.Zero)
 8546            return Start;
 34547        if (distance == totalDistance)
 2548            return End;
 549
 32550        Signed192 distanceRaw = Signed192.Signed(distance.m_rawValue);
 32551        Signed192 totalDistanceRaw = Signed192.Signed(totalDistance.m_rawValue);
 32552        return new Vector3d(
 32553            WideGeometry.InterpolateCoordinate(Start.X, End.X, distanceRaw, totalDistanceRaw),
 32554            WideGeometry.InterpolateCoordinate(Start.Y, End.Y, distanceRaw, totalDistanceRaw),
 32555            WideGeometry.InterpolateCoordinate(Start.Z, End.Z, distanceRaw, totalDistanceRaw));
 556    }
 557
 558    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 559    private readonly void ValidateDistance(Fixed64 distance, Fixed64 totalDistance)
 560    {
 45561        ValidateTotalDistance(totalDistance);
 44562        if (distance < Fixed64.Zero || distance > totalDistance)
 2563            throw new ArgumentOutOfRangeException(nameof(distance));
 42564    }
 565
 566    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 567    private readonly void ValidateTotalDistance(Fixed64 totalDistance)
 568    {
 638569        if (totalDistance < Fixed64.Zero)
 4570            throw new ArgumentOutOfRangeException(nameof(totalDistance));
 634571        if (totalDistance == Fixed64.Zero && Start != End)
 5572            throw new ArgumentException("Zero total distance requires a zero-length segment.", nameof(totalDistance));
 629573    }
 574
 575}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Primitives/Segments/FixedSegment.FiniteShapeQueries.cs

#LineLine coverage
 1//=======================================================================
 2// FixedSegment.FiniteShapeQueries.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024-present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System;
 9
 10namespace FixedMathSharp.Geometry;
 11
 12/// <content>
 13/// Contains methods for computing the oriented penetration of a centered 3D capsule, finite cylinder,
 14/// or finite cone and a centered planar capsule extruded through a world-Y slab.
 15/// </content>
 16public partial struct FixedSegment
 17{
 18    /// <summary>
 19    /// Attempts to return the oriented penetration of a centered 3D capsule
 20    /// and a centered planar capsule extruded through a world-Y slab.
 21    /// </summary>
 22    public static bool TryGetCenteredCapsuleCapsuleSlabAxisPenetration(
 23        Vector3d projectionAxis,
 24        Vector3d capsuleCenter,
 25        Vector3d capsuleAxisDirection,
 26        Fixed64 capsuleAxisLength,
 27        Fixed64 capsuleRadius,
 28        Vector3d slabCenter,
 29        Vector2d slabCapsuleAxisDirection,
 30        Fixed64 slabCapsuleAxisLength,
 31        Fixed64 slabCapsuleRadius,
 32        Fixed64 slabHalfThickness,
 33        out Vector3d orientedAxis,
 34        out Fixed64 depth,
 35        out bool depthIsClamped)
 36    {
 1237        ValidateCapsuleSlabProjection(
 1238            projectionAxis,
 1239            capsuleAxisDirection,
 1240            capsuleAxisLength,
 1241            capsuleRadius,
 1242            requirePositiveShapeLength: false,
 1243            slabCapsuleAxisDirection,
 1244            slabCapsuleAxisLength,
 1245            slabCapsuleRadius,
 1246            slabHalfThickness);
 447        return WideFiniteAxisProjection
 448            .TryGetCapsuleCapsuleSlabAxisPenetration(
 449                projectionAxis,
 450                capsuleCenter,
 451                capsuleAxisDirection,
 452                capsuleAxisLength,
 453                capsuleRadius,
 454                slabCenter,
 455                slabCapsuleAxisDirection,
 456                slabCapsuleAxisLength,
 457                slabCapsuleRadius,
 458                slabHalfThickness,
 459                out orientedAxis,
 460                out depth,
 461                out depthIsClamped);
 62    }
 63
 64    /// <summary>
 65    /// Attempts to return the oriented penetration of a centered finite
 66    /// cylinder and a centered planar capsule extruded through a world-Y slab.
 67    /// </summary>
 68    public static bool TryGetCenteredFiniteCylinderCapsuleSlabAxisPenetration(
 69        Vector3d projectionAxis,
 70        Vector3d cylinderCenter,
 71        Vector3d cylinderAxisDirection,
 72        Fixed64 cylinderAxisLength,
 73        Fixed64 cylinderRadius,
 74        Vector3d slabCenter,
 75        Vector2d slabCapsuleAxisDirection,
 76        Fixed64 slabCapsuleAxisLength,
 77        Fixed64 slabCapsuleRadius,
 78        Fixed64 slabHalfThickness,
 79        out Vector3d orientedAxis,
 80        out Fixed64 depth,
 81        out bool depthIsClamped)
 82    {
 483        ValidateCapsuleSlabProjection(
 484            projectionAxis,
 485            cylinderAxisDirection,
 486            cylinderAxisLength,
 487            cylinderRadius,
 488            requirePositiveShapeLength: true,
 489            slabCapsuleAxisDirection,
 490            slabCapsuleAxisLength,
 491            slabCapsuleRadius,
 492            slabHalfThickness);
 393        return WideFiniteAxisProjection
 394            .TryGetCylinderCapsuleSlabAxisPenetration(
 395                projectionAxis,
 396                cylinderCenter,
 397                cylinderAxisDirection,
 398                cylinderAxisLength,
 399                cylinderRadius,
 3100                slabCenter,
 3101                slabCapsuleAxisDirection,
 3102                slabCapsuleAxisLength,
 3103                slabCapsuleRadius,
 3104                slabHalfThickness,
 3105                out orientedAxis,
 3106                out depth,
 3107                out depthIsClamped);
 108    }
 109
 110    /// <summary>
 111    /// Attempts to return the oriented penetration of a centered finite cone
 112    /// and a centered planar capsule extruded through a world-Y slab.
 113    /// </summary>
 114    public static bool TryGetCenteredFiniteConeCapsuleSlabAxisPenetration(
 115        Vector3d projectionAxis,
 116        Vector3d coneCenter,
 117        Vector3d baseToApexDirection,
 118        Fixed64 coneHeight,
 119        Fixed64 coneRadius,
 120        Vector3d slabCenter,
 121        Vector2d slabCapsuleAxisDirection,
 122        Fixed64 slabCapsuleAxisLength,
 123        Fixed64 slabCapsuleRadius,
 124        Fixed64 slabHalfThickness,
 125        out Vector3d orientedAxis,
 126        out Fixed64 depth,
 127        out bool depthIsClamped)
 128    {
 10129        ValidateCapsuleSlabProjection(
 10130            projectionAxis,
 10131            baseToApexDirection,
 10132            coneHeight,
 10133            coneRadius,
 10134            requirePositiveShapeLength: true,
 10135            slabCapsuleAxisDirection,
 10136            slabCapsuleAxisLength,
 10137            slabCapsuleRadius,
 10138            slabHalfThickness);
 10139        return WideFiniteAxisProjection
 10140            .TryGetConeCapsuleSlabAxisPenetration(
 10141                projectionAxis,
 10142                coneCenter,
 10143                baseToApexDirection,
 10144                coneHeight,
 10145                coneRadius,
 10146                slabCenter,
 10147                slabCapsuleAxisDirection,
 10148                slabCapsuleAxisLength,
 10149                slabCapsuleRadius,
 10150                slabHalfThickness,
 10151                out orientedAxis,
 10152                out depth,
 10153                out depthIsClamped);
 154    }
 155
 156    private static void ValidateCapsuleSlabProjection(
 157        Vector3d projectionAxis,
 158        Vector3d shapeAxisDirection,
 159        Fixed64 shapeAxisLength,
 160        Fixed64 shapeRadius,
 161        bool requirePositiveShapeLength,
 162        Vector2d slabCapsuleAxisDirection,
 163        Fixed64 slabCapsuleAxisLength,
 164        Fixed64 slabCapsuleRadius,
 165        Fixed64 slabHalfThickness)
 166    {
 26167        if (!projectionAxis.IsNormalized())
 1168            throw new ArgumentException("Projection axis must be normalized.", nameof(projectionAxis));
 25169        if (!shapeAxisDirection.IsNormalized())
 1170            throw new ArgumentException("Shape axis direction must be normalized.", nameof(shapeAxisDirection));
 24171        if (requirePositiveShapeLength
 24172            ? shapeAxisLength <= Fixed64.Zero
 24173            : shapeAxisLength < Fixed64.Zero)
 174        {
 2175            throw new ArgumentOutOfRangeException(nameof(shapeAxisLength));
 176        }
 22177        if (shapeRadius < Fixed64.Zero)
 1178            throw new ArgumentOutOfRangeException(nameof(shapeRadius));
 21179        if (!slabCapsuleAxisDirection.IsNormalized())
 180        {
 1181            throw new ArgumentException(
 1182                "Slab capsule axis direction must be normalized.",
 1183                nameof(slabCapsuleAxisDirection));
 184        }
 20185        if (slabCapsuleAxisLength < Fixed64.Zero)
 1186            throw new ArgumentOutOfRangeException(nameof(slabCapsuleAxisLength));
 19187        if (slabCapsuleRadius < Fixed64.Zero)
 1188            throw new ArgumentOutOfRangeException(nameof(slabCapsuleRadius));
 18189        if (slabHalfThickness <= Fixed64.Zero)
 1190            throw new ArgumentOutOfRangeException(nameof(slabHalfThickness));
 17191    }
 192
 193    /// <summary>
 194    /// Finds the closed parameter interval where this segment intersects a
 195    /// finite cone authored from its apex toward the center of its flat base.
 196    /// </summary>
 197    /// <param name="apex">The cone apex.</param>
 198    /// <param name="apexToBaseDirection">The normalized direction from apex to base.</param>
 199    /// <param name="height">
 200    /// The positive parametric axis extent; the conceptual base center is
 201    /// <c>apex + apexToBaseDirection * height</c>.
 202    /// </param>
 203    /// <param name="baseRadius">The nonnegative base radius.</param>
 204    /// <param name="entryParameter">The first intersecting segment parameter in [0, 1].</param>
 205    /// <param name="exitParameter">The last intersecting segment parameter in [0, 1].</param>
 206    /// <exception cref="ArgumentException">
 207    /// <paramref name="apexToBaseDirection"/> is zero or not normalized.
 208    /// </exception>
 209    /// <exception cref="ArgumentOutOfRangeException">
 210    /// <paramref name="height"/> is not positive or <paramref name="baseRadius"/> is negative.
 211    /// </exception>
 212    public readonly bool TryGetFiniteConeIntersectionInterval(
 213        Vector3d apex,
 214        Vector3d apexToBaseDirection,
 215        Fixed64 height,
 216        Fixed64 baseRadius,
 217        out Fixed64 entryParameter,
 218        out Fixed64 exitParameter) =>
 46219        TryGetFiniteConeIntersectionInterval(
 46220            apex,
 46221            apexToBaseDirection,
 46222            height,
 46223            baseRadius,
 46224            out entryParameter,
 46225            out exitParameter,
 46226            out _,
 46227            out _);
 228
 229    /// <summary>
 230    /// Finds the closed parameter interval where this segment intersects a
 231    /// finite apex-authored cone and reports exact endpoint containment.
 232    /// </summary>
 233    /// <remarks>
 234    /// <paramref name="startContained"/> includes the side, apex, and flat base.
 235    /// <paramref name="endContainedStrict"/> excludes every boundary. The
 236    /// classifications and quadratic solve remain wide until the final
 237    /// deterministic parameter conversion.
 238    /// </remarks>
 239    public readonly bool TryGetFiniteConeIntersectionInterval(
 240        Vector3d apex,
 241        Vector3d apexToBaseDirection,
 242        Fixed64 height,
 243        Fixed64 baseRadius,
 244        out Fixed64 entryParameter,
 245        out Fixed64 exitParameter,
 246        out bool startContained,
 247        out bool endContainedStrict)
 248    {
 47249        ValidateFiniteCone(
 47250            apexToBaseDirection,
 47251            height,
 47252            baseRadius,
 47253            nameof(apexToBaseDirection),
 47254            nameof(height));
 43255        return WideFiniteConeIntersection.TryGetApexInterval(
 43256            this,
 43257            apex,
 43258            apexToBaseDirection,
 43259            height,
 43260            baseRadius,
 43261            out entryParameter,
 43262            out exitParameter,
 43263            out startContained,
 43264            out endContainedStrict);
 265    }
 266
 267    /// <summary>
 268    /// Finds the closed parameter interval where this segment intersects a
 269    /// centered finite cone.
 270    /// </summary>
 271    /// <param name="center">The midpoint between the apex and flat-base center.</param>
 272    /// <param name="baseToApexDirection">The normalized direction from base to apex.</param>
 273    /// <param name="height">
 274    /// The positive full parametric axis extent between base and apex.
 275    /// </param>
 276    /// <param name="baseRadius">The nonnegative base radius.</param>
 277    /// <param name="entryParameter">The first intersecting segment parameter in [0, 1].</param>
 278    /// <param name="exitParameter">The last intersecting segment parameter in [0, 1].</param>
 279    /// <exception cref="ArgumentException">
 280    /// <paramref name="baseToApexDirection"/> is zero or not normalized.
 281    /// </exception>
 282    /// <exception cref="ArgumentOutOfRangeException">
 283    /// <paramref name="height"/> is not positive or <paramref name="baseRadius"/> is negative.
 284    /// </exception>
 285    public readonly bool TryGetCenteredFiniteConeIntersectionInterval(
 286        Vector3d center,
 287        Vector3d baseToApexDirection,
 288        Fixed64 height,
 289        Fixed64 baseRadius,
 290        out Fixed64 entryParameter,
 291        out Fixed64 exitParameter) =>
 5292        TryGetCenteredFiniteConeIntersectionInterval(
 5293            center,
 5294            baseToApexDirection,
 5295            height,
 5296            baseRadius,
 5297            out entryParameter,
 5298            out exitParameter,
 5299            out _,
 5300            out _);
 301
 302    /// <summary>
 303    /// Finds the closed parameter interval where this segment intersects a
 304    /// centered finite cone and reports exact endpoint containment.
 305    /// </summary>
 306    public readonly bool TryGetCenteredFiniteConeIntersectionInterval(
 307        Vector3d center,
 308        Vector3d baseToApexDirection,
 309        Fixed64 height,
 310        Fixed64 baseRadius,
 311        out Fixed64 entryParameter,
 312        out Fixed64 exitParameter,
 313        out bool startContained,
 314        out bool endContainedStrict)
 315    {
 6316        ValidateFiniteCone(
 6317            baseToApexDirection,
 6318            height,
 6319            baseRadius,
 6320            nameof(baseToApexDirection),
 6321            nameof(height));
 3322        return WideFiniteConeIntersection.TryGetCenteredInterval(
 3323            this,
 3324            center,
 3325            baseToApexDirection,
 3326            height,
 3327            baseRadius,
 3328            out entryParameter,
 3329            out exitParameter,
 3330            out startContained,
 3331            out endContainedStrict);
 332    }
 333
 334    /// <summary>
 335    /// Finds the physical-distance interval where this segment intersects a
 336    /// finite cone authored from its apex toward its flat base.
 337    /// </summary>
 338    /// <remarks>
 339    /// Distances are solved directly from the wide polynomial; they are not
 340    /// reconstructed from rounded Q32.32 parameters.
 341    /// </remarks>
 342    public readonly bool TryGetFiniteConeIntersectionDistanceInterval(
 343        Vector3d apex,
 344        Vector3d apexToBaseDirection,
 345        Fixed64 height,
 346        Fixed64 baseRadius,
 347        Fixed64 totalDistance,
 348        out Fixed64 entryDistance,
 349        out Fixed64 exitDistance) =>
 4350        TryGetFiniteConeIntersectionDistanceInterval(
 4351            apex,
 4352            apexToBaseDirection,
 4353            height,
 4354            baseRadius,
 4355            totalDistance,
 4356            out entryDistance,
 4357            out exitDistance,
 4358            out _,
 4359            out _);
 360
 361    /// <summary>
 362    /// Finds the physical-distance interval where this segment intersects an
 363    /// apex-authored finite cone and reports exact endpoint containment.
 364    /// </summary>
 365    public readonly bool TryGetFiniteConeIntersectionDistanceInterval(
 366        Vector3d apex,
 367        Vector3d apexToBaseDirection,
 368        Fixed64 height,
 369        Fixed64 baseRadius,
 370        Fixed64 totalDistance,
 371        out Fixed64 entryDistance,
 372        out Fixed64 exitDistance,
 373        out bool startContained,
 374        out bool endContainedStrict)
 375    {
 5376        ValidateTotalDistance(totalDistance);
 4377        ValidateFiniteCone(
 4378            apexToBaseDirection,
 4379            height,
 4380            baseRadius,
 4381            nameof(apexToBaseDirection),
 4382            nameof(height));
 4383        return WideFiniteConeIntersection.TryGetApexDistanceInterval(
 4384            this,
 4385            apex,
 4386            apexToBaseDirection,
 4387            height,
 4388            baseRadius,
 4389            totalDistance,
 4390            out entryDistance,
 4391            out exitDistance,
 4392            out startContained,
 4393            out endContainedStrict);
 394    }
 395
 396    /// <summary>
 397    /// Finds the physical-distance interval where this segment intersects a
 398    /// centered finite cone.
 399    /// </summary>
 400    public readonly bool TryGetCenteredFiniteConeIntersectionDistanceInterval(
 401        Vector3d center,
 402        Vector3d baseToApexDirection,
 403        Fixed64 height,
 404        Fixed64 baseRadius,
 405        Fixed64 totalDistance,
 406        out Fixed64 entryDistance,
 407        out Fixed64 exitDistance) =>
 2408        TryGetCenteredFiniteConeIntersectionDistanceInterval(
 2409            center,
 2410            baseToApexDirection,
 2411            height,
 2412            baseRadius,
 2413            totalDistance,
 2414            out entryDistance,
 2415            out exitDistance,
 2416            out _,
 2417            out _);
 418
 419    /// <summary>
 420    /// Finds the physical-distance interval where this segment intersects a
 421    /// centered finite cone and reports exact endpoint containment.
 422    /// </summary>
 423    public readonly bool TryGetCenteredFiniteConeIntersectionDistanceInterval(
 424        Vector3d center,
 425        Vector3d baseToApexDirection,
 426        Fixed64 height,
 427        Fixed64 baseRadius,
 428        Fixed64 totalDistance,
 429        out Fixed64 entryDistance,
 430        out Fixed64 exitDistance,
 431        out bool startContained,
 432        out bool endContainedStrict)
 433    {
 8434        ValidateTotalDistance(totalDistance);
 7435        ValidateFiniteCone(
 7436            baseToApexDirection,
 7437            height,
 7438            baseRadius,
 7439            nameof(baseToApexDirection),
 7440            nameof(height));
 7441        return WideFiniteConeIntersection.TryGetCenteredDistanceInterval(
 7442            this,
 7443            center,
 7444            baseToApexDirection,
 7445            height,
 7446            baseRadius,
 7447            totalDistance,
 7448            out entryDistance,
 7449            out exitDistance,
 7450            out startContained,
 7451            out endContainedStrict);
 452    }
 453
 454    /// <summary>
 455    /// Finds deterministic lattice witnesses for the first and last points where
 456    /// this segment intersects an apex-authored finite cone.
 457    /// </summary>
 458    /// <remarks>
 459    /// The solver uses the largest positive Q32.32 interval scale before exact
 460    /// authored-chord interpolation, so long segments do not amplify ordinary
 461    /// Q32.32 parameter rounding into coarse spatial error.
 462    /// </remarks>
 463    public readonly bool TryGetFiniteConeIntersectionPointInterval(
 464        Vector3d apex,
 465        Vector3d apexToBaseDirection,
 466        Fixed64 height,
 467        Fixed64 baseRadius,
 468        out Vector3d entryPoint,
 469        out Vector3d exitPoint)
 470    {
 3471        ValidateFiniteCone(
 3472            apexToBaseDirection,
 3473            height,
 3474            baseRadius,
 3475            nameof(apexToBaseDirection),
 3476            nameof(height));
 3477        Fixed64 intervalScale = Start == End ? Fixed64.Zero : Fixed64.MaxValue;
 3478        if (!WideFiniteConeIntersection.TryGetApexDistanceInterval(
 3479                this,
 3480                apex,
 3481                apexToBaseDirection,
 3482                height,
 3483                baseRadius,
 3484                intervalScale,
 3485                out Fixed64 entry,
 3486                out Fixed64 exit,
 3487                out _,
 3488                out _))
 489        {
 1490            entryPoint = default;
 1491            exitPoint = default;
 1492            return false;
 493        }
 494
 2495        entryPoint = GetPointAtDistance(entry, intervalScale);
 2496        exitPoint = GetPointAtDistance(exit, intervalScale);
 2497        return true;
 498    }
 499
 500    /// <summary>
 501    /// Finds the intersecting lattice point with the smallest axial distance
 502    /// from an apex-authored cone's apex.
 503    /// </summary>
 504    /// <remarks>
 505    /// The exact segment-axis projection selects the appropriate end of the
 506    /// admitted interval before one high-resolution authored-chord interpolation.
 507    /// </remarks>
 508    public readonly bool TryGetFiniteConeIntersectionMinimumAxialPoint(
 509        Vector3d apex,
 510        Vector3d apexToBaseDirection,
 511        Fixed64 height,
 512        Fixed64 baseRadius,
 513        out Vector3d point)
 514    {
 92515        ValidateFiniteCone(
 92516            apexToBaseDirection,
 92517            height,
 92518            baseRadius,
 92519            nameof(apexToBaseDirection),
 92520            nameof(height));
 92521        Fixed64 intervalScale = Start == End ? Fixed64.Zero : Fixed64.MaxValue;
 92522        if (!WideFiniteConeIntersection.TryGetApexDistanceInterval(
 92523                this,
 92524                apex,
 92525                apexToBaseDirection,
 92526                height,
 92527                baseRadius,
 92528                intervalScale,
 92529                out Fixed64 entry,
 92530                out Fixed64 exit,
 92531                out _,
 92532                out _))
 533        {
 67534            point = default;
 67535            return false;
 536        }
 537
 25538        Signed192 axialVelocity = WideGeometry.GetDifferenceDotProduct3D(
 25539            End.X, Start.X, End.Y, Start.Y, End.Z, Start.Z,
 25540            apexToBaseDirection.X, Fixed64.Zero,
 25541            apexToBaseDirection.Y, Fixed64.Zero,
 25542            apexToBaseDirection.Z, Fixed64.Zero);
 25543        point = GetPointAtDistance(axialVelocity.Sign < 0 ? exit : entry, intervalScale);
 25544        return true;
 545    }
 546
 547    /// <summary>
 548    /// Finds deterministic lattice witnesses for the first and last points where
 549    /// this segment intersects a centered finite cone.
 550    /// </summary>
 551    public readonly bool TryGetCenteredFiniteConeIntersectionPointInterval(
 552        Vector3d center,
 553        Vector3d baseToApexDirection,
 554        Fixed64 height,
 555        Fixed64 baseRadius,
 556        out Vector3d entryPoint,
 557        out Vector3d exitPoint)
 558    {
 3559        ValidateFiniteCone(
 3560            baseToApexDirection,
 3561            height,
 3562            baseRadius,
 3563            nameof(baseToApexDirection),
 3564            nameof(height));
 3565        Fixed64 intervalScale = Start == End ? Fixed64.Zero : Fixed64.MaxValue;
 3566        if (!WideFiniteConeIntersection.TryGetCenteredDistanceInterval(
 3567                this,
 3568                center,
 3569                baseToApexDirection,
 3570                height,
 3571                baseRadius,
 3572                intervalScale,
 3573                out Fixed64 entry,
 3574                out Fixed64 exit,
 3575                out _,
 3576                out _))
 577        {
 1578            entryPoint = default;
 1579            exitPoint = default;
 1580            return false;
 581        }
 582
 2583        entryPoint = GetPointAtDistance(entry, intervalScale);
 2584        exitPoint = GetPointAtDistance(exit, intervalScale);
 2585        return true;
 586    }
 587
 588    /// <summary>
 589    /// Returns whether a point lies strictly inside or inclusively within a
 590    /// finite cone authored from its apex toward its flat base.
 591    /// </summary>
 592    public static bool ContainsPointInFiniteCone(
 593        Vector3d point,
 594        Vector3d apex,
 595        Vector3d apexToBaseDirection,
 596        Fixed64 height,
 597        Fixed64 baseRadius,
 598        bool strict = false)
 599    {
 9600        ValidateFiniteCone(
 9601            apexToBaseDirection,
 9602            height,
 9603            baseRadius,
 9604            nameof(apexToBaseDirection),
 9605            nameof(height));
 8606        return WideFiniteConeIntersection.ContainsPointInApexCone(
 8607            point,
 8608            apex,
 8609            apexToBaseDirection,
 8610            height,
 8611            baseRadius,
 8612            strict);
 613    }
 614
 615    /// <summary>
 616    /// Returns whether a point lies strictly inside or inclusively within a
 617    /// centered finite cone whose direction points from base to apex.
 618    /// </summary>
 619    public static bool ContainsPointInCenteredFiniteCone(
 620        Vector3d point,
 621        Vector3d center,
 622        Vector3d baseToApexDirection,
 623        Fixed64 height,
 624        Fixed64 baseRadius,
 625        bool strict = false)
 626    {
 7627        ValidateFiniteCone(
 7628            baseToApexDirection,
 7629            height,
 7630            baseRadius,
 7631            nameof(baseToApexDirection),
 7632            nameof(height));
 6633        return WideFiniteConeIntersection.ContainsPointInCenteredCone(
 6634            point,
 6635            center,
 6636            baseToApexDirection,
 6637            height,
 6638            baseRadius,
 6639            strict);
 640    }
 641
 642    private static void ValidateFiniteCone(
 643        Vector3d axisDirection,
 644        Fixed64 height,
 645        Fixed64 baseRadius,
 646        string axisParameterName,
 647        string heightParameterName)
 648    {
 178649        if (!axisDirection.IsNormalized())
 4650            throw new ArgumentException("Finite cone axis direction must be normalized.", axisParameterName);
 174651        if (height <= Fixed64.Zero)
 3652            throw new ArgumentOutOfRangeException(heightParameterName);
 171653        if (baseRadius < Fixed64.Zero)
 2654            throw new ArgumentOutOfRangeException(nameof(baseRadius));
 169655    }
 656}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Primitives/Segments/FixedSegment.RigidQueries.cs

#LineLine coverage
 1//=======================================================================
 2// FixedSegment.RigidQueries.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024–present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System;
 9
 10namespace FixedMathSharp.Geometry;
 11
 12/// <content>
 13/// Contains intersection and contact queries for rigidly oriented finite
 14/// capsules, cylinders, and cones.
 15/// </content>
 16public partial struct FixedSegment
 17{
 18    /// <summary>
 19    /// Finds the physical-distance interval where this segment intersects a
 20    /// centered capsule whose local positive Y axis is transformed by a rigid
 21    /// quaternion frame.
 22    /// </summary>
 23    public readonly bool TryGetCapsuleIntersectionDistanceInterval(
 24        Vector3d center,
 25        FixedQuaternion rotation,
 26        Fixed64 axisLength,
 27        Fixed64 radius,
 28        Fixed64 radiusExpansion,
 29        Fixed64 totalDistance,
 30        out Fixed64 entryDistance,
 31        out Fixed64 exitDistance,
 32        out bool startContained,
 33        out bool endContainedStrict)
 34    {
 14435        ValidateRigidFiniteAxisQuery(
 14436            rotation,
 14437            axisLength,
 14438            radius,
 14439            radiusExpansion,
 14440            totalDistance,
 14441            requirePositiveLength: false);
 14142        return WideOrientedBox.TryGetRigidCapsuleDistanceInterval(
 14143            this,
 14144            center,
 14145            rotation,
 14146            axisLength,
 14147            radius,
 14148            radiusExpansion,
 14149            totalDistance,
 14150            out entryDistance,
 14151            out exitDistance,
 14152            out startContained,
 14153            out endContainedStrict);
 54    }
 55
 56    /// <summary>
 57    /// Finds the physical-distance interval where this segment intersects a
 58    /// centered finite cylinder whose local positive Y axis is transformed by
 59    /// a rigid quaternion frame.
 60    /// </summary>
 61    public readonly bool TryGetFiniteCylinderIntersectionDistanceInterval(
 62        Vector3d center,
 63        FixedQuaternion rotation,
 64        Fixed64 axisLength,
 65        Fixed64 radius,
 66        Fixed64 radiusExpansion,
 67        Fixed64 axialExpansion,
 68        Fixed64 totalDistance,
 69        out Fixed64 entryDistance,
 70        out Fixed64 exitDistance,
 71        out bool startContained,
 72        out bool endContainedStrict)
 73    {
 13874        ValidateRigidFiniteAxisQuery(
 13875            rotation,
 13876            axisLength,
 13877            radius,
 13878            radiusExpansion,
 13879            totalDistance,
 13880            requirePositiveLength: true);
 13781        if (axialExpansion < Fixed64.Zero)
 182            throw new ArgumentOutOfRangeException(nameof(axialExpansion));
 83
 13684        return WideOrientedBox.TryGetRigidCylinderDistanceInterval(
 13685            this,
 13686            center,
 13687            rotation,
 13688            axisLength,
 13689            radius,
 13690            radiusExpansion,
 13691            axialExpansion,
 13692            totalDistance,
 13693            out entryDistance,
 13694            out exitDistance,
 13695            out startContained,
 13696            out endContainedStrict);
 97    }
 98
 99    /// <summary>
 100    /// Finds the physical-distance interval where this segment intersects a
 101    /// centered finite cone whose local positive Y axis runs from base to apex
 102    /// in a rigid quaternion frame.
 103    /// </summary>
 104    public readonly bool TryGetCenteredFiniteConeIntersectionDistanceInterval(
 105        Vector3d center,
 106        FixedQuaternion rotation,
 107        Fixed64 height,
 108        Fixed64 baseRadius,
 109        Fixed64 totalDistance,
 110        out Fixed64 entryDistance,
 111        out Fixed64 exitDistance,
 112        out bool startContained,
 113        out bool endContainedStrict)
 114    {
 142115        ValidateRigidFiniteAxisQuery(
 142116            rotation,
 142117            height,
 142118            baseRadius,
 142119            Fixed64.Zero,
 142120            totalDistance,
 142121            requirePositiveLength: true);
 141122        return WideOrientedBox.TryGetRigidConeDistanceInterval(
 141123            this,
 141124            center,
 141125            rotation,
 141126            height,
 141127            baseRadius,
 141128            totalDistance,
 141129            out entryDistance,
 141130            out exitDistance,
 141131            out startContained,
 141132            out endContainedStrict);
 133    }
 134
 135    private readonly void ValidateRigidFiniteAxisQuery(
 136        FixedQuaternion rotation,
 137        Fixed64 axisLength,
 138        Fixed64 radius,
 139        Fixed64 radiusExpansion,
 140        Fixed64 totalDistance,
 141        bool requirePositiveLength)
 142    {
 424143        ValidateTotalDistance(totalDistance);
 424144        if (!rotation.IsNormalized())
 145        {
 1146            throw new ArgumentException(
 1147                "Finite-axis rotation must be normalized.",
 1148                nameof(rotation));
 149        }
 423150        if (requirePositiveLength
 423151            ? axisLength <= Fixed64.Zero
 423152            : axisLength < Fixed64.Zero)
 153        {
 2154            throw new ArgumentOutOfRangeException(nameof(axisLength));
 155        }
 421156        if (radius < Fixed64.Zero)
 1157            throw new ArgumentOutOfRangeException(nameof(radius));
 420158        if (radiusExpansion < Fixed64.Zero)
 1159            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 419160    }
 161
 162    /// <summary>
 163    /// Attempts to construct the minimum-translation contact between two
 164    /// centered finite cylinders.
 165    /// </summary>
 166    /// <remarks>
 167    /// Both finite axes remain authoritative in their normalized rigid frames.
 168    /// The returned normal points from the first cylinder toward the second.
 169    /// </remarks>
 170    public static bool TryGetCenteredFiniteCylindersContact(
 171        Vector3d firstCenter,
 172        FixedQuaternion firstRotation,
 173        Vector3d firstLocalAxisDirection,
 174        Fixed64 firstAxisLength,
 175        Fixed64 firstRadius,
 176        Vector3d secondCenter,
 177        FixedQuaternion secondRotation,
 178        Vector3d secondLocalAxisDirection,
 179        Fixed64 secondAxisLength,
 180        Fixed64 secondRadius,
 181        out FixedContactAnchors contact)
 182    {
 119183        ValidateRigidFiniteShape(
 119184            firstRotation,
 119185            firstLocalAxisDirection,
 119186            firstAxisLength,
 119187            firstRadius,
 119188            requirePositiveLength: true,
 119189            nameof(firstRotation),
 119190            nameof(firstLocalAxisDirection),
 119191            nameof(firstAxisLength),
 119192            nameof(firstRadius));
 118193        ValidateRigidFiniteShape(
 118194            secondRotation,
 118195            secondLocalAxisDirection,
 118196            secondAxisLength,
 118197            secondRadius,
 118198            requirePositiveLength: true,
 118199            nameof(secondRotation),
 118200            nameof(secondLocalAxisDirection),
 118201            nameof(secondAxisLength),
 118202            nameof(secondRadius));
 117203        return WideConvexPrismRelations
 117204            .TryGetCenteredFiniteCylindersContact(
 117205                firstCenter,
 117206                firstRotation,
 117207                firstLocalAxisDirection,
 117208                firstAxisLength,
 117209                firstRadius,
 117210                secondCenter,
 117211                secondRotation,
 117212                secondLocalAxisDirection,
 117213                secondAxisLength,
 117214                secondRadius,
 117215                out contact);
 216    }
 217
 218    /// <summary>
 219    /// Attempts to construct the minimum-translation contact between a
 220    /// centered finite cylinder and a centered capsule.
 221    /// </summary>
 222    /// <remarks>
 223    /// Both finite axes remain authoritative in their normalized rigid frames.
 224    /// The returned normal points from the cylinder toward the capsule.
 225    /// </remarks>
 226    public static bool TryGetCenteredFiniteCylinderCapsuleContact(
 227        Vector3d cylinderCenter,
 228        FixedQuaternion cylinderRotation,
 229        Vector3d cylinderLocalAxisDirection,
 230        Fixed64 cylinderAxisLength,
 231        Fixed64 cylinderRadius,
 232        Vector3d capsuleCenter,
 233        FixedQuaternion capsuleRotation,
 234        Vector3d capsuleLocalAxisDirection,
 235        Fixed64 capsuleAxisLength,
 236        Fixed64 capsuleRadius,
 237        out FixedContactAnchors contact)
 238    {
 87239        ValidateRigidFiniteShape(
 87240            cylinderRotation,
 87241            cylinderLocalAxisDirection,
 87242            cylinderAxisLength,
 87243            cylinderRadius,
 87244            requirePositiveLength: true,
 87245            nameof(cylinderRotation),
 87246            nameof(cylinderLocalAxisDirection),
 87247            nameof(cylinderAxisLength),
 87248            nameof(cylinderRadius));
 83249        ValidateRigidFiniteShape(
 83250            capsuleRotation,
 83251            capsuleLocalAxisDirection,
 83252            capsuleAxisLength,
 83253            capsuleRadius,
 83254            requirePositiveLength: false,
 83255            nameof(capsuleRotation),
 83256            nameof(capsuleLocalAxisDirection),
 83257            nameof(capsuleAxisLength),
 83258            nameof(capsuleRadius));
 79259        return WideConvexPrismRelations
 79260            .TryGetCenteredFiniteCylinderCapsuleContact(
 79261                cylinderCenter,
 79262                cylinderRotation,
 79263                cylinderLocalAxisDirection,
 79264                cylinderAxisLength,
 79265                cylinderRadius,
 79266                capsuleCenter,
 79267                capsuleRotation,
 79268                capsuleLocalAxisDirection,
 79269                capsuleAxisLength,
 79270                capsuleRadius,
 79271                out contact);
 272    }
 273
 274    private static void ValidateRigidFiniteShape(
 275        FixedQuaternion rotation,
 276        Vector3d localAxisDirection,
 277        Fixed64 axisLength,
 278        Fixed64 radius,
 279        bool requirePositiveLength,
 280        string rotationParameterName,
 281        string axisParameterName,
 282        string lengthParameterName,
 283        string radiusParameterName)
 284    {
 407285        if (!rotation.IsNormalized())
 3286            throw new ArgumentException("The rigid rotation must be normalized.", rotationParameterName);
 404287        if (!localAxisDirection.IsNormalized())
 2288            throw new ArgumentException("The local axis direction must be normalized.", axisParameterName);
 402289        if (requirePositiveLength
 402290            ? axisLength <= Fixed64.Zero
 402291            : axisLength < Fixed64.Zero)
 292        {
 3293            throw new ArgumentOutOfRangeException(lengthParameterName);
 294        }
 399295        if (radius < Fixed64.Zero)
 2296            throw new ArgumentOutOfRangeException(radiusParameterName);
 397297    }
 298}

Methods/Properties

TryGetDistanceToCenteredAxis(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetDistanceBetweenCenteredAxes(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
DoCenteredCapsulesOverlap(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
TryGetCenteredAxisEndpoint(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,System.Boolean,FixedMathSharp.Vector3d&)
TryGetCenteredCapsuleSupport(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
TryGetCenteredCapsuleSupportOffset(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
GetCenteredCapsuleSupportAnchor(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d)
TryGetCenteredFiniteCylinderSupport(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
TryGetCenteredFiniteCylinderSupportOffset(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
GetCenteredFiniteCylinderSupportAnchor(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d)
TryGetCenteredFiniteConeSupport(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
TryGetCenteredFiniteConeSupportOffset(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
GetCenteredFiniteConeSupportAnchor(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d)
GetCenteredFiniteConeSupportAnchor(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d)
ContainsPointInCenteredFiniteCylinder(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
ContainsPointInCenteredFiniteCylinder(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
GetDistanceToCenteredCapsule(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
TryGetDistanceToCenteredCapsule(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
ContainsPointInCenteredCapsule(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
ContainsPointInCenteredCapsule(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
ContainsPointInCenteredCapsule(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
ContainsPointInCenteredCapsule(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
GetDirectionFromCenteredAxis(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
TryGetClosestPointsBetweenCenteredAxes(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&)
TryGetClosestOffsetsBetweenCenteredAxes(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&)
GetClosestDirectionBetweenCenteredAxes(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
TryGetCenteredCapsulesContact(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedContactAnchors&)
ValidateNormalizedRotation(FixedMathSharp.FixedQuaternion,System.String)
ValidateCenteredCapsulesContact(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d)
ValidateCenteredAxis(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
ValidateCenteredAxis(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,System.String,System.String)
DoCenteredFiniteCylinderAndCapsuleOverlapOnAxis(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
TryGetCenteredFiniteCylinderCapsuleAxisPenetration(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&)
TryGetCenteredFiniteCylinderCapsuleAxisPenetration(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&,System.Boolean&)
DoCenteredFiniteCylindersOverlapOnAxis(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
TryGetCenteredFiniteCylindersAxisPenetration(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&)
TryGetCenteredFiniteCylindersAxisPenetration(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&,System.Boolean&)
DoesCenteredFiniteCylinderOverlapSphere(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
TryGetClosestPointOnCenteredFiniteCylinderSurface(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&)
TryGetClosestCenteredFiniteCylinderSurfaceOffset(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&)
DoesCenteredFiniteConeOverlapSphere(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
TryGetClosestPointOnCenteredFiniteConeSurface(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&)
TryGetClosestCenteredFiniteConeSurfaceOffset(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&)
ValidateCenteredCone(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
ValidateCylinderCapsuleProjection(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
ValidateCylinderProjection(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.String,System.String,System.String)
ValidateCenteredSurface(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,System.String,System.String,System.String,System.String)
TryGetSurfacePointOnCenteredCapsule(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
TryGetSurfaceOffsetOnCenteredCapsule(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
GetSurfaceAnchorOnCenteredCapsule(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d)
GetSurfaceAnchorOnCenteredCapsule(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d)
ValidateCenteredCapsuleSurface(FixedMathSharp.Fixed64,FixedMathSharp.Vector3d)
TryGetClosestCenteredCapsuleSurfaceAnchor(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&)
TryGetClosestCenteredFiniteCylinderSurfaceAnchor(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&)
TryGetClosestCenteredFiniteConeSurfaceAnchor(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&)
ValidateCenteredSurfaceFrame(FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d)
.ctor(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
get_Delta()
get_Length()
get_LengthSquared()
get_Bounds()
ClosestPoint(FixedMathSharp.Vector3d)
DistanceSquared(FixedMathSharp.Vector3d)
TryGetCapsuleIntersectionInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCapsuleIntersectionInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCapsuleIntersectionInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCapsuleIntersectionInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCapsuleIntersectionInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCapsuleIntersectionInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetFiniteCylinderIntersectionInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetFiniteCylinderIntersectionInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetFiniteCylinderIntersectionInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetFiniteCylinderIntersectionInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetFiniteCylinderIntersectionInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
GetClosestPoints(FixedMathSharp.Geometry.FixedSegment)
SolveClosestParameters(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320)
ClampParameter(FixedMathSharp.Signed192,FixedMathSharp.Signed192)
GetDifferenceDot(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
PointOnSegment(FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Signed192)
Interpolate(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Fixed64)
Deconstruct(FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&)
op_Equality(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Geometry.FixedSegment)
op_Inequality(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Geometry.FixedSegment)
Equals(FixedMathSharp.Geometry.FixedSegment)
Equals(System.Object)
GetHashCode()
TryGetSphereIntersectionDistanceInterval(FixedMathSharp.Geometry.FixedBoundSphere,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetSphereIntersectionDistanceInterval(FixedMathSharp.Geometry.FixedBoundSphere,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCapsuleIntersectionDistanceInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCapsuleIntersectionDistanceInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCapsuleIntersectionDistanceInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCapsuleIntersectionDistanceInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetFiniteCylinderIntersectionDistanceInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetFiniteCylinderIntersectionDistanceInterval(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetFiniteCylinderIntersectionDistanceInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetSweptSphereFiniteCylinderIntersectionDistance(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetSweptSphereCenteredFiniteCylinderIntersectionDistanceFromHalfAxisLength(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetSweptSphereBoxIntersectionDistance(FixedMathSharp.Geometry.FixedBoundBox,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetSweptSphereOrientedBoxIntersectionDistance(FixedMathSharp.Geometry.FixedOrientedBox,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetSweptSphereFiniteCylinderIntersectionDistanceInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
ValidateSphericallyExpandedFiniteCylinderArguments(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
GetPointAtDistance(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
ValidateDistance(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
ValidateTotalDistance(FixedMathSharp.Fixed64)
TryGetCenteredCapsuleCapsuleSlabAxisPenetration(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&,System.Boolean&)
TryGetCenteredFiniteCylinderCapsuleSlabAxisPenetration(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&,System.Boolean&)
TryGetCenteredFiniteConeCapsuleSlabAxisPenetration(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d&,FixedMathSharp.Fixed64&,System.Boolean&)
ValidateCapsuleSlabProjection(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
TryGetFiniteConeIntersectionInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetFiniteConeIntersectionInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCenteredFiniteConeIntersectionInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCenteredFiniteConeIntersectionInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetFiniteConeIntersectionDistanceInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetFiniteConeIntersectionDistanceInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCenteredFiniteConeIntersectionDistanceInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCenteredFiniteConeIntersectionDistanceInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetFiniteConeIntersectionPointInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&)
TryGetFiniteConeIntersectionMinimumAxialPoint(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d&)
TryGetCenteredFiniteConeIntersectionPointInterval(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&)
ContainsPointInFiniteCone(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
ContainsPointInCenteredFiniteCone(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
ValidateFiniteCone(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.String,System.String)
TryGetCapsuleIntersectionDistanceInterval(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetFiniteCylinderIntersectionDistanceInterval(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCenteredFiniteConeIntersectionDistanceInterval(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
ValidateRigidFiniteAxisQuery(FixedMathSharp.FixedQuaternion,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
TryGetCenteredFiniteCylindersContact(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.FixedContactAnchors&)
TryGetCenteredFiniteCylinderCapsuleContact(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.FixedContactAnchors&)
ValidateRigidFiniteShape(FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean,System.String,System.String,System.String,System.String)