< Summary

Line coverage
100%
Covered lines: 1869
Uncovered lines: 0
Coverable lines: 1869
Total lines: 4408
Line coverage: 100%
Branch coverage
100%
Covered branches: 388
Total branches: 388
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: DoCenteredCapsulesOverlapStrict(...)100%44100%
File 1: DoCenteredCapsulesOverlapStrict(...)100%44100%
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%66100%
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: Contains(...)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    /// Returns whether two centered capsules in normalized rigid frames have
 20    /// strictly positive radial overlap, excluding exact tangency.
 21    /// </summary>
 22    /// <remarks>
 23    /// Each axis is expressed in its capsule's local frame. The exact rational
 24    /// quaternion rotation remains authoritative; derived rounded world axes,
 25    /// endpoint coordinates, and contact depths do not affect classification.
 26    /// Zero-length axes are points; a zero radius sum has no strict overlap.
 27    /// </remarks>
 28    public static bool DoCenteredCapsulesOverlapStrict(
 29        Vector3d firstCenter,
 30        FixedQuaternion firstRotation,
 31        Vector3d firstLocalAxisDirection,
 32        Fixed64 firstAxisLength,
 33        Fixed64 firstRadius,
 34        Vector3d secondCenter,
 35        FixedQuaternion secondRotation,
 36        Vector3d secondLocalAxisDirection,
 37        Fixed64 secondAxisLength,
 38        Fixed64 secondRadius)
 39    {
 3340        ValidateNormalizedRotation(firstRotation, nameof(firstRotation));
 3341        ValidateNormalizedRotation(secondRotation, nameof(secondRotation));
 3342        ValidateCenteredAxis(firstLocalAxisDirection, firstAxisLength,
 3343            nameof(firstLocalAxisDirection), nameof(firstAxisLength));
 3344        if (firstRadius < Fixed64.Zero)
 145            throw new ArgumentOutOfRangeException(nameof(firstRadius));
 3246        ValidateCenteredAxis(secondLocalAxisDirection, secondAxisLength,
 3247            nameof(secondLocalAxisDirection), nameof(secondAxisLength));
 3248        if (secondRadius < Fixed64.Zero)
 149            throw new ArgumentOutOfRangeException(nameof(secondRadius));
 50
 3151        return WideOrientedBox.DoCenteredRigidCapsulesOverlap(
 3152            firstCenter, firstRotation, firstLocalAxisDirection, firstAxisLength, firstRadius,
 3153            secondCenter, secondRotation, secondLocalAxisDirection, secondAxisLength, secondRadius,
 3154            strict: true);
 55    }
 56
 57    /// <summary>
 58    /// Returns whether the exact distance between two centered capsule axes is
 59    /// strictly less than their radius sum. Exact tangency is excluded.
 60    /// </summary>
 61    /// <remarks>
 62    /// Classification precedes endpoint, distance, and contact-depth rounding.
 63    /// Zero-length axes are points; a zero radius sum has no strict overlap.
 64    /// </remarks>
 65    public static bool DoCenteredCapsulesOverlapStrict(
 66        Vector3d firstCenter,
 67        Vector3d firstAxisDirection,
 68        Fixed64 firstAxisLength,
 69        Fixed64 firstRadius,
 70        Vector3d secondCenter,
 71        Vector3d secondAxisDirection,
 72        Fixed64 secondAxisLength,
 73        Fixed64 secondRadius)
 74    {
 33275        ValidateCenteredAxis(firstAxisDirection, firstAxisLength,
 33276            nameof(firstAxisDirection), nameof(firstAxisLength));
 33277        if (firstRadius < Fixed64.Zero)
 278            throw new ArgumentOutOfRangeException(nameof(firstRadius));
 33079        ValidateCenteredAxis(secondAxisDirection, secondAxisLength,
 33080            nameof(secondAxisDirection), nameof(secondAxisLength));
 33081        if (secondRadius < Fixed64.Zero)
 182            throw new ArgumentOutOfRangeException(nameof(secondRadius));
 83
 32984        return WideFiniteAxisIntersection.DoCenteredCapsulesOverlap(
 32985            firstCenter, firstAxisDirection, firstAxisLength, firstRadius,
 32986            secondCenter, secondAxisDirection, secondAxisLength, secondRadius,
 32987            strict: true);
 88    }
 89
 90    /// <summary>
 91    /// Attempts to return the rounded distance from a point to a conceptual
 92    /// centered finite axis without materializing its endpoints.
 93    /// </summary>
 94    /// <returns>
 95    /// True when the final distance is representable; otherwise false and
 96    /// <paramref name="distance"/> is <see cref="Fixed64.MaxValue"/>.
 97    /// </returns>
 98    public static bool TryGetDistanceToCenteredAxis(
 99        Vector3d point,
 100        Vector3d center,
 101        Vector3d axisDirection,
 102        Fixed64 axisLength,
 103        out Fixed64 distance)
 104    {
 3105        ValidateCenteredAxis(axisDirection, axisLength);
 3106        return WideFiniteAxisIntersection.TryGetDistanceToCenteredAxis(
 3107            point,
 3108            center,
 3109            axisDirection,
 3110            axisLength,
 3111            out distance);
 112    }
 113
 114    /// <summary>
 115    /// Attempts to return the rounded distance between two conceptual
 116    /// centered finite axes without materializing either pair of endpoints.
 117    /// </summary>
 118    /// <returns>
 119    /// True when the final distance is representable; otherwise false and
 120    /// <paramref name="distance"/> is <see cref="Fixed64.MaxValue"/>.
 121    /// </returns>
 122    public static bool TryGetDistanceBetweenCenteredAxes(
 123        Vector3d firstCenter,
 124        Vector3d firstAxisDirection,
 125        Fixed64 firstAxisLength,
 126        Vector3d secondCenter,
 127        Vector3d secondAxisDirection,
 128        Fixed64 secondAxisLength,
 129        out Fixed64 distance)
 130    {
 263131        ValidateCenteredAxis(
 263132            firstAxisDirection,
 263133            firstAxisLength,
 263134            nameof(firstAxisDirection),
 263135            nameof(firstAxisLength));
 263136        ValidateCenteredAxis(
 263137            secondAxisDirection,
 263138            secondAxisLength,
 263139            nameof(secondAxisDirection),
 263140            nameof(secondAxisLength));
 263141        return WideFiniteAxisIntersection.TryGetDistanceBetweenCenteredAxes(
 263142            firstCenter,
 263143            firstAxisDirection,
 263144            firstAxisLength,
 263145            secondCenter,
 263146            secondAxisDirection,
 263147            secondAxisLength,
 263148            out distance);
 149    }
 150
 151    /// <summary>
 152    /// Returns whether two conceptual centered capsules overlap, including
 153    /// exact tangency, without narrowing their axis distance or radius sum.
 154    /// </summary>
 155    public static bool DoCenteredCapsulesOverlap(
 156        Vector3d firstCenter,
 157        Vector3d firstAxisDirection,
 158        Fixed64 firstAxisLength,
 159        Fixed64 firstRadius,
 160        Vector3d secondCenter,
 161        Vector3d secondAxisDirection,
 162        Fixed64 secondAxisLength,
 163        Fixed64 secondRadius)
 164    {
 262165        ValidateCenteredAxis(
 262166            firstAxisDirection,
 262167            firstAxisLength,
 262168            nameof(firstAxisDirection),
 262169            nameof(firstAxisLength));
 262170        if (firstRadius < Fixed64.Zero)
 1171            throw new ArgumentOutOfRangeException(nameof(firstRadius));
 261172        ValidateCenteredAxis(
 261173            secondAxisDirection,
 261174            secondAxisLength,
 261175            nameof(secondAxisDirection),
 261176            nameof(secondAxisLength));
 261177        if (secondRadius < Fixed64.Zero)
 1178            throw new ArgumentOutOfRangeException(nameof(secondRadius));
 179
 260180        return WideFiniteAxisIntersection.DoCenteredCapsulesOverlap(
 260181            firstCenter,
 260182            firstAxisDirection,
 260183            firstAxisLength,
 260184            firstRadius,
 260185            secondCenter,
 260186            secondAxisDirection,
 260187            secondAxisLength,
 260188            secondRadius);
 189    }
 190
 191    /// <summary>
 192    /// Attempts to materialize one endpoint of a conceptual centered finite
 193    /// axis from its normalized direction and full length.
 194    /// </summary>
 195    /// <remarks>
 196    /// The endpoint is rounded only after combining its center and half-length
 197    /// contribution. Failure is atomic.
 198    /// </remarks>
 199    public static bool TryGetCenteredAxisEndpoint(
 200        Vector3d center,
 201        Vector3d axisDirection,
 202        Fixed64 axisLength,
 203        bool positive,
 204        out Vector3d endpoint)
 205    {
 267206        ValidateCenteredAxis(axisDirection, axisLength);
 265207        return WideFiniteAxisIntersection.TryGetCenteredAxisEndpoint(
 265208            center,
 265209            axisDirection,
 265210            axisLength,
 265211            positive,
 265212            out endpoint);
 213    }
 214
 215    /// <summary>
 216    /// Attempts to materialize the support point of a conceptual centered
 217    /// capsule in a world-space direction.
 218    /// </summary>
 219    /// <remarks>
 220    /// The direction need not be normalized. A zero direction and an exact
 221    /// axial tie select the axis center.
 222    /// </remarks>
 223    public static bool TryGetCenteredCapsuleSupport(
 224        Vector3d center,
 225        Vector3d axisDirection,
 226        Fixed64 axisLength,
 227        Fixed64 radius,
 228        Vector3d direction,
 229        out Vector3d support)
 230    {
 268231        ValidateCenteredAxis(axisDirection, axisLength);
 268232        if (radius < Fixed64.Zero)
 1233            throw new ArgumentOutOfRangeException(nameof(radius));
 234
 267235        return WideFiniteAxisIntersection.TryGetCenteredCapsuleSupport(
 267236            center,
 267237            axisDirection,
 267238            axisLength,
 267239            radius,
 267240            direction,
 267241            out support);
 242    }
 243
 244    /// <summary>
 245    /// Attempts to return the support offset of a conceptual centered capsule
 246    /// relative to its center.
 247    /// </summary>
 248    /// <remarks>
 249    /// The direction need not be normalized. A zero direction and an exact
 250    /// axial tie select the axis center.
 251    /// </remarks>
 252    public static bool TryGetCenteredCapsuleSupportOffset(
 253        Vector3d axisDirection,
 254        Fixed64 axisLength,
 255        Fixed64 radius,
 256        Vector3d direction,
 257        out Vector3d supportOffset)
 258    {
 2259        ValidateCenteredAxis(axisDirection, axisLength);
 2260        if (radius < Fixed64.Zero)
 1261            throw new ArgumentOutOfRangeException(nameof(radius));
 262
 1263        return WideFiniteAxisIntersection.TryGetCenteredCapsuleSupport(
 1264            Vector3d.Zero,
 1265            axisDirection,
 1266            axisLength,
 1267            radius,
 1268            direction,
 1269            out supportOffset);
 270    }
 271
 272    /// <summary>
 273    /// Returns the support anchor of a centered capsule whose local positive Y
 274    /// axis is its conceptual center axis.
 275    /// </summary>
 276    /// <remarks>
 277    /// The rigid frame remains authoritative, so support construction does not
 278    /// feed the rounded derived world axis back into the geometry. The
 279    /// direction need not be normalized. A zero direction and an exact axial
 280    /// tie select the axis center.
 281    /// </remarks>
 282    public static FixedPointAnchor GetCenteredCapsuleSupportAnchor(
 283        Vector3d center,
 284        FixedQuaternion rotation,
 285        Fixed64 axisLength,
 286        Fixed64 radius,
 287        Vector3d direction)
 288    {
 9289        if (!rotation.IsNormalized())
 290        {
 1291            throw new ArgumentException(
 1292                "Capsule rotation must be normalized.",
 1293                nameof(rotation));
 294        }
 8295        if (axisLength < Fixed64.Zero)
 1296            throw new ArgumentOutOfRangeException(nameof(axisLength));
 7297        if (radius < Fixed64.Zero)
 1298            throw new ArgumentOutOfRangeException(nameof(radius));
 299
 6300        return WideGeometry.GetCenteredCapsuleSupportAnchor(
 6301            center,
 6302            rotation,
 6303            axisLength,
 6304            radius,
 6305            direction);
 306    }
 307
 308    /// <summary>
 309    /// Attempts to materialize the support point of a conceptual centered
 310    /// finite cylinder in a world-space direction.
 311    /// </summary>
 312    /// <remarks>
 313    /// The direction need not be normalized. A zero direction and an exact
 314    /// axial tie select the negative cap center. A direction parallel to the
 315    /// axis selects the cap center rather than an arbitrary rim point.
 316    /// </remarks>
 317    public static bool TryGetCenteredFiniteCylinderSupport(
 318        Vector3d center,
 319        Vector3d axisDirection,
 320        Fixed64 axisLength,
 321        Fixed64 radius,
 322        Vector3d direction,
 323        out Vector3d support)
 324    {
 266325        if (!axisDirection.IsNormalized())
 1326            throw new ArgumentException("Finite cylinder axis direction must be normalized.", nameof(axisDirection));
 265327        if (axisLength <= Fixed64.Zero)
 1328            throw new ArgumentOutOfRangeException(nameof(axisLength));
 264329        if (radius < Fixed64.Zero)
 1330            throw new ArgumentOutOfRangeException(nameof(radius));
 331
 263332        return WideFiniteAxisIntersection.TryGetCenteredFiniteCylinderSupport(
 263333            center,
 263334            axisDirection,
 263335            axisLength,
 263336            radius,
 263337            direction,
 263338            out support);
 339    }
 340
 341    /// <summary>
 342    /// Attempts to return the support offset of a conceptual centered finite
 343    /// cylinder relative to its center.
 344    /// </summary>
 345    public static bool TryGetCenteredFiniteCylinderSupportOffset(
 346        Vector3d axisDirection,
 347        Fixed64 axisLength,
 348        Fixed64 radius,
 349        Vector3d direction,
 350        out Vector3d supportOffset)
 351    {
 4352        if (!axisDirection.IsNormalized())
 1353            throw new ArgumentException("Finite cylinder axis direction must be normalized.", nameof(axisDirection));
 3354        if (axisLength <= Fixed64.Zero)
 1355            throw new ArgumentOutOfRangeException(nameof(axisLength));
 2356        if (radius < Fixed64.Zero)
 1357            throw new ArgumentOutOfRangeException(nameof(radius));
 358
 1359        return WideFiniteAxisIntersection.TryGetCenteredFiniteCylinderSupport(
 1360            Vector3d.Zero,
 1361            axisDirection,
 1362            axisLength,
 1363            radius,
 1364            direction,
 1365            out supportOffset);
 366    }
 367
 368    /// <summary>
 369    /// Returns the support anchor of a centered finite cylinder whose local
 370    /// positive Y axis is its conceptual center axis.
 371    /// </summary>
 372    /// <remarks>
 373    /// The rigid frame remains authoritative. Axial full-length/2 and radial
 374    /// direction-times-radius terms remain exact through final world-point or
 375    /// relative-offset materialization.
 376    /// </remarks>
 377    public static FixedPointAnchor GetCenteredFiniteCylinderSupportAnchor(
 378        Vector3d center,
 379        FixedQuaternion rotation,
 380        Fixed64 axisLength,
 381        Fixed64 radius,
 382        Vector3d direction)
 383    {
 10384        if (!rotation.IsNormalized())
 385        {
 1386            throw new ArgumentException(
 1387                "Finite cylinder rotation must be normalized.",
 1388                nameof(rotation));
 389        }
 9390        if (axisLength <= Fixed64.Zero)
 1391            throw new ArgumentOutOfRangeException(nameof(axisLength));
 8392        if (radius < Fixed64.Zero)
 1393            throw new ArgumentOutOfRangeException(nameof(radius));
 394
 7395        return WideGeometry.GetCenteredCylinderSupportAnchor(
 7396            center,
 7397            rotation,
 7398            axisLength,
 7399            radius,
 7400            direction);
 401    }
 402
 403    /// <summary>
 404    /// Attempts to materialize the support point of a conceptual centered
 405    /// finite cone in a world-space direction.
 406    /// </summary>
 407    /// <remarks>
 408    /// The axis points from the base toward the apex. The direction need not
 409    /// be normalized. Equal apex and base projections, including a zero
 410    /// direction, select the base.
 411    /// </remarks>
 412    public static bool TryGetCenteredFiniteConeSupport(
 413        Vector3d center,
 414        Vector3d axisDirection,
 415        Fixed64 height,
 416        Fixed64 radius,
 417        Vector3d direction,
 418        out Vector3d support)
 419    {
 265420        if (!axisDirection.IsNormalized())
 1421            throw new ArgumentException("Finite cone axis direction must be normalized.", nameof(axisDirection));
 264422        if (height <= Fixed64.Zero)
 1423            throw new ArgumentOutOfRangeException(nameof(height));
 263424        if (radius < Fixed64.Zero)
 1425            throw new ArgumentOutOfRangeException(nameof(radius));
 426
 262427        return WideFiniteAxisIntersection.TryGetCenteredFiniteConeSupport(
 262428            center,
 262429            axisDirection,
 262430            height,
 262431            radius,
 262432            direction,
 262433            out support);
 434    }
 435
 436    /// <summary>
 437    /// Attempts to return the support offset of a conceptual centered finite
 438    /// cone relative to its center.
 439    /// </summary>
 440    public static bool TryGetCenteredFiniteConeSupportOffset(
 441        Vector3d axisDirection,
 442        Fixed64 height,
 443        Fixed64 radius,
 444        Vector3d direction,
 445        out Vector3d supportOffset)
 446    {
 4447        if (!axisDirection.IsNormalized())
 1448            throw new ArgumentException("Finite cone axis direction must be normalized.", nameof(axisDirection));
 3449        if (height <= Fixed64.Zero)
 1450            throw new ArgumentOutOfRangeException(nameof(height));
 2451        if (radius < Fixed64.Zero)
 1452            throw new ArgumentOutOfRangeException(nameof(radius));
 453
 1454        return WideFiniteAxisIntersection.TryGetCenteredFiniteConeSupport(
 1455            Vector3d.Zero,
 1456            axisDirection,
 1457            height,
 1458            radius,
 1459            direction,
 1460            out supportOffset);
 461    }
 462
 463    /// <summary>
 464    /// Returns the support point of a centered finite cone as a local point in
 465    /// its rigid frame without materializing an absolute world coordinate.
 466    /// </summary>
 467    /// <remarks>
 468    /// The cone's local positive Y axis points from the base toward the apex.
 469    /// The direction need not be normalized. Equal apex and base projections,
 470    /// including a zero direction, select the base.
 471    /// </remarks>
 472    public static FixedPointAnchor GetCenteredFiniteConeSupportAnchor(
 473        Vector3d center,
 474        FixedQuaternion rotation,
 475        Fixed64 height,
 476        Fixed64 radius,
 477        Vector3d direction)
 478    {
 6479        if (!rotation.IsNormalized())
 480        {
 1481            throw new ArgumentException(
 1482                "Finite cone rotation must be normalized.",
 1483                nameof(rotation));
 484        }
 5485        if (height <= Fixed64.Zero)
 1486            throw new ArgumentOutOfRangeException(nameof(height));
 4487        if (radius < Fixed64.Zero)
 1488            throw new ArgumentOutOfRangeException(nameof(radius));
 489
 3490        return WideGeometry.GetCenteredConeSupportAnchor(
 3491            center,
 3492            rotation,
 3493            height,
 3494            radius,
 3495            direction);
 496    }
 497
 498    /// <summary>
 499    /// Returns the support point of a centered finite cone in a deterministic
 500    /// canonical axis frame without materializing an absolute world
 501    /// coordinate.
 502    /// </summary>
 503    public static FixedPointAnchor GetCenteredFiniteConeSupportAnchor(
 504        Vector3d center,
 505        Vector3d axisDirection,
 506        Fixed64 height,
 507        Fixed64 radius,
 508        Vector3d direction)
 509    {
 6510        if (!axisDirection.IsNormalized())
 511        {
 1512            throw new ArgumentException(
 1513                "Finite cone axis direction must be normalized.",
 1514                nameof(axisDirection));
 515        }
 5516        if (height <= Fixed64.Zero)
 1517            throw new ArgumentOutOfRangeException(nameof(height));
 4518        if (radius < Fixed64.Zero)
 1519            throw new ArgumentOutOfRangeException(nameof(radius));
 520
 3521        FixedQuaternion rotation =
 3522            WideGeometry.GetCanonicalAxisRotation(axisDirection);
 3523        return WideGeometry.GetCenteredConeSupportAnchor(
 3524            center,
 3525            rotation,
 3526            height,
 3527            radius,
 3528            direction);
 529    }
 530
 531    /// <summary>
 532    /// Returns whether a point lies in a centered finite cylinder whose flat
 533    /// caps are defined without constructing scalar coordinates.
 534    /// </summary>
 535    /// <param name="point">The point to classify.</param>
 536    /// <param name="center">The cylinder center.</param>
 537    /// <param name="axisDirection">The normalized cap-normal direction.</param>
 538    /// <param name="axisLength">The positive full physical axis length.</param>
 539    /// <param name="radius">The nonnegative radial extent.</param>
 540    /// <param name="strict">
 541    /// <see langword="true"/> to exclude the side and both flat caps;
 542    /// otherwise, boundaries are included.
 543    /// </param>
 544    /// <exception cref="ArgumentException">
 545    /// <paramref name="axisDirection"/> is zero or not normalized.
 546    /// </exception>
 547    /// <exception cref="ArgumentOutOfRangeException">
 548    /// <paramref name="axisLength"/> is not positive or
 549    /// <paramref name="radius"/> is negative.
 550    /// </exception>
 551    public static bool ContainsPointInCenteredFiniteCylinder(
 552        Vector3d point,
 553        Vector3d center,
 554        Vector3d axisDirection,
 555        Fixed64 axisLength,
 556        Fixed64 radius,
 557        bool strict = false)
 558    {
 13559        if (!axisDirection.IsNormalized())
 1560            throw new ArgumentException("Finite cylinder axis direction must be normalized.", nameof(axisDirection));
 12561        if (axisLength <= Fixed64.Zero)
 1562            throw new ArgumentOutOfRangeException(nameof(axisLength));
 11563        if (radius < Fixed64.Zero)
 1564            throw new ArgumentOutOfRangeException(nameof(radius));
 565
 10566        return WideFiniteAxisIntersection.ContainsPointInCenteredFiniteCylinder(
 10567            point,
 10568            center,
 10569            axisDirection,
 10570            axisLength,
 10571            radius,
 10572            strict);
 573    }
 574
 575    /// <summary>
 576    /// Returns whether a point lies in a centered finite cylinder after
 577    /// independently expanding its flat caps and radial side.
 578    /// </summary>
 579    /// <param name="point">The point to classify.</param>
 580    /// <param name="center">The cylinder center.</param>
 581    /// <param name="axisDirection">The normalized cylinder axis.</param>
 582    /// <param name="axisLength">The positive full cylinder length.</param>
 583    /// <param name="radius">The nonnegative cylinder radius.</param>
 584    /// <param name="axialTolerance">
 585    /// The nonnegative distance added beyond each flat cap.
 586    /// </param>
 587    /// <param name="radialTolerance">
 588    /// The nonnegative distance added to the radial extent.
 589    /// </param>
 590    /// <param name="strict">
 591    /// <see langword="true"/> to exclude every expanded boundary.
 592    /// </param>
 593    public static bool ContainsPointInCenteredFiniteCylinder(
 594        Vector3d point,
 595        Vector3d center,
 596        Vector3d axisDirection,
 597        Fixed64 axisLength,
 598        Fixed64 radius,
 599        Fixed64 axialTolerance,
 600        Fixed64 radialTolerance,
 601        bool strict = false)
 602    {
 8603        if (!axisDirection.IsNormalized())
 1604            throw new ArgumentException("Finite cylinder axis direction must be normalized.", nameof(axisDirection));
 7605        if (axisLength <= Fixed64.Zero)
 1606            throw new ArgumentOutOfRangeException(nameof(axisLength));
 6607        if (radius < Fixed64.Zero)
 1608            throw new ArgumentOutOfRangeException(nameof(radius));
 5609        if (axialTolerance < Fixed64.Zero)
 1610            throw new ArgumentOutOfRangeException(nameof(axialTolerance));
 4611        if (radialTolerance < Fixed64.Zero)
 1612            throw new ArgumentOutOfRangeException(nameof(radialTolerance));
 613
 3614        return WideFiniteAxisIntersection.ContainsPointInCenteredFiniteCylinder(
 3615            point,
 3616            center,
 3617            axisDirection,
 3618            axisLength,
 3619            radius,
 3620            axialTolerance,
 3621            radialTolerance,
 3622            strict);
 623    }
 624
 625    /// <summary>
 626    /// Returns the rounded nonnegative distance from a point to a conceptual
 627    /// centered capsule surface, saturating to <see cref="Fixed64.MaxValue"/>
 628    /// when the distance is not representable.
 629    /// </summary>
 630    /// <remarks>
 631    /// The final value uses round-half-to-even. Points inside or on the capsule
 632    /// return zero.
 633    /// </remarks>
 634    /// <exception cref="ArgumentException">
 635    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 636    /// </exception>
 637    /// <exception cref="ArgumentOutOfRangeException">
 638    /// Thrown when <paramref name="axisLength"/> or <paramref name="radius"/>
 639    /// is negative.
 640    /// </exception>
 641    public static Fixed64 GetDistanceToCenteredCapsule(
 642        Vector3d point,
 643        Vector3d center,
 644        Vector3d axisDirection,
 645        Fixed64 axisLength,
 646        Fixed64 radius)
 647    {
 2648        TryGetDistanceToCenteredCapsule(
 2649            point,
 2650            center,
 2651            axisDirection,
 2652            axisLength,
 2653            radius,
 2654            out Fixed64 distance);
 2655        return distance;
 656    }
 657
 658    /// <summary>
 659    /// Attempts to return the rounded nonnegative distance from a point to a
 660    /// conceptual centered capsule surface.
 661    /// </summary>
 662    /// <remarks>The final value uses round-half-to-even.</remarks>
 663    /// <returns>
 664    /// True when the final distance is representable; otherwise false and
 665    /// <paramref name="distance"/> is <see cref="Fixed64.MaxValue"/>.
 666    /// Points inside or on the capsule return zero.
 667    /// </returns>
 668    /// <exception cref="ArgumentException">
 669    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 670    /// </exception>
 671    /// <exception cref="ArgumentOutOfRangeException">
 672    /// Thrown when <paramref name="axisLength"/> or <paramref name="radius"/>
 673    /// is negative.
 674    /// </exception>
 675    public static bool TryGetDistanceToCenteredCapsule(
 676        Vector3d point,
 677        Vector3d center,
 678        Vector3d axisDirection,
 679        Fixed64 axisLength,
 680        Fixed64 radius,
 681        out Fixed64 distance)
 682    {
 5683        ValidateCenteredAxis(axisDirection, axisLength);
 5684        if (radius < Fixed64.Zero)
 1685            throw new ArgumentOutOfRangeException(nameof(radius));
 686
 4687        return WideFiniteAxisIntersection.TryGetDistanceToCenteredCapsule(
 4688            point,
 4689            center,
 4690            axisDirection,
 4691            axisLength,
 4692            radius,
 4693            out distance);
 694    }
 695
 696    /// <summary>
 697    /// Returns whether a point lies inside or on a conceptual centered capsule.
 698    /// </summary>
 699    /// <exception cref="ArgumentException">
 700    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 701    /// </exception>
 702    /// <exception cref="ArgumentOutOfRangeException">
 703    /// Thrown when <paramref name="axisLength"/> or <paramref name="radius"/>
 704    /// is negative.
 705    /// </exception>
 706    public static bool ContainsPointInCenteredCapsule(
 707        Vector3d point,
 708        Vector3d center,
 709        Vector3d axisDirection,
 710        Fixed64 axisLength,
 711        Fixed64 radius) =>
 5712        ContainsPointInCenteredCapsule(
 5713            point,
 5714            center,
 5715            axisDirection,
 5716            axisLength,
 5717            radius,
 5718            Fixed64.Zero,
 5719            strict: false);
 720
 721    /// <summary>
 722    /// Returns whether a point lies strictly inside or inclusively within a
 723    /// conceptual centered capsule.
 724    /// </summary>
 725    public static bool ContainsPointInCenteredCapsule(
 726        Vector3d point,
 727        Vector3d center,
 728        Vector3d axisDirection,
 729        Fixed64 axisLength,
 730        Fixed64 radius,
 731        bool strict) =>
 3732        ContainsPointInCenteredCapsule(
 3733            point,
 3734            center,
 3735            axisDirection,
 3736            axisLength,
 3737            radius,
 3738            Fixed64.Zero,
 3739            strict);
 740
 741    /// <summary>
 742    /// Returns whether a point lies inside or on a conceptual centered capsule,
 743    /// including a nonnegative radial expansion.
 744    /// </summary>
 745    /// <exception cref="ArgumentException">
 746    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 747    /// </exception>
 748    /// <exception cref="ArgumentOutOfRangeException">
 749    /// Thrown when <paramref name="axisLength"/>, <paramref name="radius"/>,
 750    /// or <paramref name="radiusExpansion"/> is negative.
 751    /// </exception>
 752    public static bool ContainsPointInCenteredCapsule(
 753        Vector3d point,
 754        Vector3d center,
 755        Vector3d axisDirection,
 756        Fixed64 axisLength,
 757        Fixed64 radius,
 758        Fixed64 radiusExpansion) =>
 2759        ContainsPointInCenteredCapsule(
 2760            point,
 2761            center,
 2762            axisDirection,
 2763            axisLength,
 2764            radius,
 2765            radiusExpansion,
 2766            strict: false);
 767
 768    /// <summary>
 769    /// Returns whether a point lies strictly inside or inclusively within a
 770    /// conceptual centered capsule with nonnegative radial expansion.
 771    /// </summary>
 772    public static bool ContainsPointInCenteredCapsule(
 773        Vector3d point,
 774        Vector3d center,
 775        Vector3d axisDirection,
 776        Fixed64 axisLength,
 777        Fixed64 radius,
 778        Fixed64 radiusExpansion,
 779        bool strict)
 780    {
 12781        ValidateCenteredAxis(axisDirection, axisLength);
 12782        if (radius < Fixed64.Zero)
 1783            throw new ArgumentOutOfRangeException(nameof(radius));
 11784        if (radiusExpansion < Fixed64.Zero)
 1785            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 786
 10787        return WideFiniteAxisIntersection.ContainsPointInCenteredCapsule(
 10788            point,
 10789            center,
 10790            axisDirection,
 10791            axisLength,
 10792            radius,
 10793            radiusExpansion,
 10794            strict);
 795    }
 796
 797    /// <summary>
 798    /// Returns the normalized direction from the closest point on a conceptual
 799    /// centered finite axis toward <paramref name="point"/>, or zero when the
 800    /// point lies on that axis.
 801    /// </summary>
 802    /// <remarks>
 803    /// The conceptual endpoints are
 804    /// <c>center +/- axisDirection * (axisLength / 2)</c>. They are never
 805    /// constructed or narrowed before the closest-feature decision.
 806    /// </remarks>
 807    /// <exception cref="ArgumentException">
 808    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 809    /// </exception>
 810    /// <exception cref="ArgumentOutOfRangeException">
 811    /// Thrown when <paramref name="axisLength"/> is negative.
 812    /// </exception>
 813    public static Vector3d GetDirectionFromCenteredAxis(
 814        Vector3d point,
 815        Vector3d center,
 816        Vector3d axisDirection,
 817        Fixed64 axisLength)
 818    {
 6819        ValidateCenteredAxis(axisDirection, axisLength);
 820
 4821        return WideFiniteAxisIntersection.GetDirectionFromCenteredAxis(
 4822            point,
 4823            center,
 4824            axisDirection,
 4825            axisLength);
 826    }
 827
 828    /// <summary>
 829    /// Attempts to return the closest points on two conceptual centered finite
 830    /// axes described by normalized directions and full lengths.
 831    /// </summary>
 832    /// <returns>
 833    /// <see langword="true"/> when both final world points are representable;
 834    /// otherwise <see langword="false"/> and both outputs are zero.
 835    /// </returns>
 836    public static bool TryGetClosestPointsBetweenCenteredAxes(
 837        Vector3d firstCenter,
 838        Vector3d firstAxisDirection,
 839        Fixed64 firstAxisLength,
 840        Vector3d secondCenter,
 841        Vector3d secondAxisDirection,
 842        Fixed64 secondAxisLength,
 843        out Vector3d firstPoint,
 844        out Vector3d secondPoint)
 845    {
 139846        ValidateCenteredAxis(
 139847            firstAxisDirection,
 139848            firstAxisLength,
 139849            nameof(firstAxisDirection),
 139850            nameof(firstAxisLength));
 138851        ValidateCenteredAxis(
 138852            secondAxisDirection,
 138853            secondAxisLength,
 138854            nameof(secondAxisDirection),
 138855            nameof(secondAxisLength));
 137856        return WideFiniteAxisIntersection.TryGetClosestPointsBetweenCenteredAxes(
 137857            firstCenter,
 137858            firstAxisDirection,
 137859            firstAxisLength,
 137860            secondCenter,
 137861            secondAxisDirection,
 137862            secondAxisLength,
 137863            out firstPoint,
 137864            out secondPoint);
 865    }
 866
 867    /// <summary>
 868    /// Attempts to return the closest offsets on two conceptual centered
 869    /// finite axes, each relative to its own center.
 870    /// </summary>
 871    /// <remarks>
 872    /// This relation remains usable when either absolute closest point would
 873    /// exceed the public scalar coordinate range.
 874    /// </remarks>
 875    public static bool TryGetClosestOffsetsBetweenCenteredAxes(
 876        Vector3d firstCenter,
 877        Vector3d firstAxisDirection,
 878        Fixed64 firstAxisLength,
 879        Vector3d secondCenter,
 880        Vector3d secondAxisDirection,
 881        Fixed64 secondAxisLength,
 882        out Vector3d firstCenterOffset,
 883        out Vector3d secondCenterOffset)
 884    {
 1885        ValidateCenteredAxis(
 1886            firstAxisDirection,
 1887            firstAxisLength,
 1888            nameof(firstAxisDirection),
 1889            nameof(firstAxisLength));
 1890        ValidateCenteredAxis(
 1891            secondAxisDirection,
 1892            secondAxisLength,
 1893            nameof(secondAxisDirection),
 1894            nameof(secondAxisLength));
 1895        return WideFiniteAxisIntersection.TryGetClosestOffsetsBetweenCenteredAxes(
 1896            firstCenter,
 1897            firstAxisDirection,
 1898            firstAxisLength,
 1899            secondCenter,
 1900            secondAxisDirection,
 1901            secondAxisLength,
 1902            out firstCenterOffset,
 1903            out secondCenterOffset);
 904    }
 905
 906    /// <summary>
 907    /// Returns the normalized direction from the closest point on the first
 908    /// conceptual centered axis to the closest point on the second.
 909    /// </summary>
 910    /// <remarks>
 911    /// Coincident closest points return zero. The direction is resolved from
 912    /// the exact wide relation without materializing either world point.
 913    /// </remarks>
 914    public static Vector3d GetClosestDirectionBetweenCenteredAxes(
 915        Vector3d firstCenter,
 916        Vector3d firstAxisDirection,
 917        Fixed64 firstAxisLength,
 918        Vector3d secondCenter,
 919        Vector3d secondAxisDirection,
 920        Fixed64 secondAxisLength)
 921    {
 1922        ValidateCenteredAxis(
 1923            firstAxisDirection,
 1924            firstAxisLength,
 1925            nameof(firstAxisDirection),
 1926            nameof(firstAxisLength));
 1927        ValidateCenteredAxis(
 1928            secondAxisDirection,
 1929            secondAxisLength,
 1930            nameof(secondAxisDirection),
 1931            nameof(secondAxisLength));
 1932        return WideFiniteAxisIntersection.GetClosestDirectionBetweenCenteredAxes(
 1933            firstCenter,
 1934            firstAxisDirection,
 1935            firstAxisLength,
 1936            secondCenter,
 1937            secondAxisDirection,
 1938            secondAxisLength);
 939    }
 940
 941    /// <summary>
 942    /// Attempts to build the exact contact relation between two conceptual
 943    /// centered capsules without narrowing either finite axis.
 944    /// </summary>
 945    /// <remarks>
 946    /// Each capsule axis is expressed in its normalized rigid frame. The
 947    /// returned normal points from the first capsule toward the second.
 948    /// <paramref name="fallbackNormal"/> is used only when the closest axis
 949    /// points coincide. Axial and radial terms remain separate in each anchor,
 950    /// so classification does not depend on materializing a combined world
 951    /// point or center-relative offset.
 952    /// </remarks>
 953    /// <returns>
 954    /// <see langword="true"/> when the capsules overlap; otherwise
 955    /// <see langword="false"/>.
 956    /// </returns>
 957    public static bool TryGetCenteredCapsulesContact(
 958        Vector3d firstCenter,
 959        FixedQuaternion firstRotation,
 960        Vector3d firstLocalAxisDirection,
 961        Fixed64 firstAxisLength,
 962        Fixed64 firstRadius,
 963        Vector3d secondCenter,
 964        FixedQuaternion secondRotation,
 965        Vector3d secondLocalAxisDirection,
 966        Fixed64 secondAxisLength,
 967        Fixed64 secondRadius,
 968        Vector3d fallbackNormal,
 969        out FixedContactAnchors contact)
 970    {
 62971        ValidateNormalizedRotation(firstRotation, nameof(firstRotation));
 61972        ValidateNormalizedRotation(secondRotation, nameof(secondRotation));
 61973        ValidateCenteredCapsulesContact(
 61974            firstLocalAxisDirection,
 61975            firstAxisLength,
 61976            firstRadius,
 61977            secondLocalAxisDirection,
 61978            secondAxisLength,
 61979            secondRadius,
 61980            fallbackNormal);
 58981        if (!WideOrientedBox.DoCenteredRigidCapsulesOverlap(
 58982                firstCenter,
 58983                firstRotation,
 58984                firstLocalAxisDirection,
 58985                firstAxisLength,
 58986                firstRadius,
 58987                secondCenter,
 58988                secondRotation,
 58989                secondLocalAxisDirection,
 58990                secondAxisLength,
 58991                secondRadius))
 992        {
 18993            contact = default;
 18994            return false;
 995        }
 40996        Vector3d firstAxisDirection = firstLocalAxisDirection;
 40997        Vector3d secondAxisDirection = secondLocalAxisDirection;
 998        // Zero-core axes are irrelevant to the candidate; rotations still own
 999        // the radial anchors. Keep the exact rigid classifier above for all pairs.
 401000        if (firstAxisLength != Fixed64.Zero || secondAxisLength != Fixed64.Zero)
 1001        {
 141002            _ = firstRotation.TryRotate(firstLocalAxisDirection, out firstAxisDirection);
 141003            _ = secondRotation.TryRotate(secondLocalAxisDirection, out secondAxisDirection);
 141004            firstAxisDirection = firstAxisDirection.Normalized;
 141005            secondAxisDirection = secondAxisDirection.Normalized;
 1006        }
 1007
 401008        return WideFiniteAxisIntersection.TryGetCenteredCapsulesContact(
 401009            firstCenter,
 401010            firstRotation,
 401011            firstLocalAxisDirection,
 401012            firstAxisDirection,
 401013            firstAxisLength,
 401014            firstRadius,
 401015            secondCenter,
 401016            secondRotation,
 401017            secondLocalAxisDirection,
 401018            secondAxisDirection,
 401019            secondAxisLength,
 401020            secondRadius,
 401021            fallbackNormal,
 401022            out contact);
 1023    }
 1024
 1025    private static void ValidateNormalizedRotation(
 1026        FixedQuaternion rotation,
 1027        string parameterName)
 1028    {
 1891029        if (!rotation.IsNormalized())
 1030        {
 11031            throw new ArgumentException(
 11032                "Capsule rotation must be normalized.",
 11033                parameterName);
 1034        }
 1881035    }
 1036
 1037    private static void ValidateCenteredCapsulesContact(
 1038        Vector3d firstAxisDirection,
 1039        Fixed64 firstAxisLength,
 1040        Fixed64 firstRadius,
 1041        Vector3d secondAxisDirection,
 1042        Fixed64 secondAxisLength,
 1043        Fixed64 secondRadius,
 1044        Vector3d fallbackNormal)
 1045    {
 611046        ValidateCenteredAxis(
 611047            firstAxisDirection,
 611048            firstAxisLength,
 611049            nameof(firstAxisDirection),
 611050            nameof(firstAxisLength));
 611051        ValidateCenteredAxis(
 611052            secondAxisDirection,
 611053            secondAxisLength,
 611054            nameof(secondAxisDirection),
 611055            nameof(secondAxisLength));
 611056        if (firstRadius < Fixed64.Zero)
 11057            throw new ArgumentOutOfRangeException(nameof(firstRadius));
 601058        if (secondRadius < Fixed64.Zero)
 11059            throw new ArgumentOutOfRangeException(nameof(secondRadius));
 591060        if (!fallbackNormal.IsNormalized())
 11061            throw new ArgumentException("Fallback normal must be normalized.", nameof(fallbackNormal));
 581062    }
 1063
 1064    private static void ValidateCenteredAxis(
 1065        Vector3d axisDirection,
 1066        Fixed64 axisLength) =>
 7971067        ValidateCenteredAxis(
 7971068            axisDirection,
 7971069            axisLength,
 7971070            nameof(axisDirection),
 7971071            nameof(axisLength));
 1072
 1073    private static void ValidateCenteredAxis(
 1074        Vector3d axisDirection,
 1075        Fixed64 axisLength,
 1076        string directionParameterName,
 1077        string lengthParameterName)
 1078    {
 29761079        if (!axisDirection.IsNormalized())
 51080            throw new ArgumentException("Axis direction must be normalized.", directionParameterName);
 29711081        if (axisLength < Fixed64.Zero)
 41082            throw new ArgumentOutOfRangeException(lengthParameterName);
 29671083    }
 1084}

/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    {
 153694        if (!frameRotation.IsNormalized())
 695        {
 1696            throw new ArgumentException(
 1697                "Frame rotation must be normalized.",
 1698                nameof(frameRotation));
 699        }
 152700        ValidateCenteredAxis(localAxisDirection, axisLength);
 152701        ValidateCenteredCapsuleSurface(radius, localSurfaceDirection);
 151702        return WideFiniteAxisIntersection.GetSurfaceAnchorOnCenteredCapsule(
 151703            point,
 151704            center,
 151705            frameRotation,
 151706            localAxisDirection,
 151707            axisLength,
 151708            radius,
 151709            localSurfaceDirection);
 710    }
 711
 712    private static void ValidateCenteredCapsuleSurface(
 713        Fixed64 radius,
 714        Vector3d surfaceDirection)
 715    {
 172716        if (radius < Fixed64.Zero)
 2717            throw new ArgumentOutOfRangeException(nameof(radius));
 170718        if (!surfaceDirection.IsNormalized())
 719        {
 3720            throw new ArgumentException(
 3721                "Surface direction must be normalized.",
 3722                nameof(surfaceDirection));
 723        }
 167724    }
 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    {
 3215249        Start = start;
 3215250        End = end;
 3215251    }
 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    /// Determines whether the supplied point lies exactly on this finite segment.
 126    /// </summary>
 127    /// <remarks>
 128    /// Collinearity and finite bounds use the complete fixed-point raw domain and
 129    /// do not compare a rounded closest-point projection.
 130    /// </remarks>
 131    public readonly bool Contains(Vector3d point)
 132    {
 264133        Signed192 lengthSquared = GetDifferenceDot(End, Start, End, Start);
 264134        return PointOnSegment(point, this, lengthSquared);
 135    }
 136
 137    /// <summary>
 138    /// Computes the squared distance from the supplied point to this finite segment.
 139    /// </summary>
 140    /// <remarks>
 141    /// Component differences and their exact squared sum are evaluated across the
 142    /// complete raw domain before one final round-half-to-even conversion. Results
 143    /// outside the positive <see cref="Fixed64"/> range saturate to
 144    /// <see cref="Fixed64.MaxValue"/>.
 145    /// </remarks>
 146    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 147    public Fixed64 DistanceSquared(Vector3d point)
 148    {
 15149        Vector3d closest = ClosestPoint(point);
 15150        return Fixed64.RoundSquaredDistance(GetDifferenceDot(point, closest, point, closest));
 151    }
 152
 153    /// <summary>
 154    /// Finds the closed parameter interval where this segment intersects a capsule.
 155    /// </summary>
 156    /// <remarks>
 157    /// The capsule is described by its finite center-line segment and radius.
 158    /// Returned parameters are clamped to [0, 1]. A zero-length capsule axis is
 159    /// treated as a sphere.
 160    /// </remarks>
 161    /// <exception cref="ArgumentOutOfRangeException">
 162    /// Thrown when <paramref name="radius"/> is negative.
 163    /// </exception>
 164    public readonly bool TryGetCapsuleIntersectionInterval(
 165        FixedSegment capsuleAxis,
 166        Fixed64 radius,
 167        out Fixed64 entryParameter,
 168        out Fixed64 exitParameter) =>
 2169        TryGetCapsuleIntersectionInterval(
 2170            capsuleAxis,
 2171            radius,
 2172            Fixed64.Zero,
 2173            out entryParameter,
 2174            out exitParameter);
 175
 176    /// <summary>
 177    /// Finds the closed parameter interval where this segment intersects a radially
 178    /// expanded capsule.
 179    /// </summary>
 180    /// <remarks>
 181    /// The authored radius and sweep expansion remain separate until the exact
 182    /// finite-axis solve. Returned parameters are clamped to [0, 1]. A zero-length
 183    /// capsule axis is treated as a sphere.
 184    /// </remarks>
 185    /// <exception cref="ArgumentOutOfRangeException">
 186    /// Thrown when <paramref name="radius"/> or <paramref name="radiusExpansion"/>
 187    /// is negative.
 188    /// </exception>
 189    public readonly bool TryGetCapsuleIntersectionInterval(
 190        FixedSegment capsuleAxis,
 191        Fixed64 radius,
 192        Fixed64 radiusExpansion,
 193        out Fixed64 entryParameter,
 194        out Fixed64 exitParameter) =>
 4195        TryGetCapsuleIntersectionInterval(
 4196            capsuleAxis,
 4197            radius,
 4198            radiusExpansion,
 4199            out entryParameter,
 4200            out exitParameter,
 4201            out _,
 4202            out _);
 203
 204    /// <summary>
 205    /// Finds the closed parameter interval where this segment intersects a capsule
 206    /// and reports exact endpoint containment.
 207    /// </summary>
 208    /// <remarks>
 209    /// <paramref name="startContained"/> is inclusive of the capsule boundary.
 210    /// <paramref name="endContainedStrict"/> is true only for the mathematical
 211    /// interior. Both classifications use the wide solve inputs rather than rounded
 212    /// parameters or reconstructed points. A zero-length capsule axis is treated as
 213    /// a sphere.
 214    /// </remarks>
 215    /// <exception cref="ArgumentOutOfRangeException">
 216    /// Thrown when <paramref name="radius"/> or <paramref name="radiusExpansion"/>
 217    /// is negative.
 218    /// </exception>
 219    public readonly bool TryGetCapsuleIntersectionInterval(
 220        FixedSegment capsuleAxis,
 221        Fixed64 radius,
 222        Fixed64 radiusExpansion,
 223        out Fixed64 entryParameter,
 224        out Fixed64 exitParameter,
 225        out bool startContained,
 226        out bool endContainedStrict)
 227    {
 11228        if (radius < Fixed64.Zero)
 1229            throw new ArgumentOutOfRangeException(nameof(radius));
 10230        if (radiusExpansion < Fixed64.Zero)
 1231            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 232
 9233        return WideFiniteAxisIntersection.TryGetCapsuleInterval(
 9234            this,
 9235            capsuleAxis,
 9236            radius,
 9237            radiusExpansion,
 9238            out entryParameter,
 9239            out exitParameter,
 9240            out startContained,
 9241            out endContainedStrict);
 242    }
 243
 244    /// <summary>
 245    /// Finds the closed parameter interval where this segment intersects a
 246    /// centered capsule.
 247    /// </summary>
 248    /// <remarks>
 249    /// The normalized axis defines the conceptual center-line endpoints as
 250    /// <c>center +/- axisDirection * (axisLength / 2)</c> without constructing or
 251    /// narrowing either endpoint.
 252    /// </remarks>
 253    /// <exception cref="ArgumentException">
 254    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 255    /// </exception>
 256    /// <exception cref="ArgumentOutOfRangeException">
 257    /// Thrown when <paramref name="axisLength"/> or
 258    /// <paramref name="radius"/> is negative.
 259    /// </exception>
 260    public readonly bool TryGetCapsuleIntersectionInterval(
 261        Vector3d center,
 262        Vector3d axisDirection,
 263        Fixed64 axisLength,
 264        Fixed64 radius,
 265        out Fixed64 entryParameter,
 266        out Fixed64 exitParameter) =>
 7267        TryGetCapsuleIntersectionInterval(
 7268            center,
 7269            axisDirection,
 7270            axisLength,
 7271            radius,
 7272            Fixed64.Zero,
 7273            out entryParameter,
 7274            out exitParameter);
 275
 276    /// <summary>
 277    /// Finds the closed parameter interval where this segment intersects a
 278    /// centered, radially expanded capsule.
 279    /// </summary>
 280    /// <exception cref="ArgumentException">
 281    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 282    /// </exception>
 283    /// <exception cref="ArgumentOutOfRangeException">
 284    /// Thrown when <paramref name="axisLength"/>,
 285    /// <paramref name="radius"/> or <paramref name="radiusExpansion"/> is
 286    /// negative.
 287    /// </exception>
 288    public readonly bool TryGetCapsuleIntersectionInterval(
 289        Vector3d center,
 290        Vector3d axisDirection,
 291        Fixed64 axisLength,
 292        Fixed64 radius,
 293        Fixed64 radiusExpansion,
 294        out Fixed64 entryParameter,
 295        out Fixed64 exitParameter) =>
 8296        TryGetCapsuleIntersectionInterval(
 8297            center,
 8298            axisDirection,
 8299            axisLength,
 8300            radius,
 8301            radiusExpansion,
 8302            out entryParameter,
 8303            out exitParameter,
 8304            out _,
 8305            out _);
 306
 307    /// <summary>
 308    /// Finds the closed parameter interval where this segment intersects a
 309    /// centered, radially expanded capsule and reports exact endpoint
 310    /// containment.
 311    /// </summary>
 312    /// <remarks>
 313    /// <paramref name="startContained"/> includes the capsule boundary;
 314    /// <paramref name="endContainedStrict"/> excludes it. The side projection,
 315    /// conceptual spherical caps, and containment classifications remain wide
 316    /// until the final deterministic parameter conversion.
 317    /// </remarks>
 318    /// <exception cref="ArgumentException">
 319    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 320    /// </exception>
 321    /// <exception cref="ArgumentOutOfRangeException">
 322    /// Thrown when <paramref name="axisLength"/>,
 323    /// <paramref name="radius"/> or <paramref name="radiusExpansion"/> is
 324    /// negative.
 325    /// </exception>
 326    public readonly bool TryGetCapsuleIntersectionInterval(
 327        Vector3d center,
 328        Vector3d axisDirection,
 329        Fixed64 axisLength,
 330        Fixed64 radius,
 331        Fixed64 radiusExpansion,
 332        out Fixed64 entryParameter,
 333        out Fixed64 exitParameter,
 334        out bool startContained,
 335        out bool endContainedStrict)
 336    {
 11337        if (!axisDirection.IsNormalized())
 2338            throw new ArgumentException("Capsule axis direction must be normalized.", nameof(axisDirection));
 9339        if (axisLength < Fixed64.Zero)
 1340            throw new ArgumentOutOfRangeException(nameof(axisLength));
 8341        if (radius < Fixed64.Zero)
 1342            throw new ArgumentOutOfRangeException(nameof(radius));
 7343        if (radiusExpansion < Fixed64.Zero)
 1344            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 345
 6346        return WideFiniteAxisIntersection.TryGetCapsuleInterval(
 6347            this,
 6348            center,
 6349            axisDirection,
 6350            axisLength,
 6351            radius,
 6352            radiusExpansion,
 6353            out entryParameter,
 6354            out exitParameter,
 6355            out startContained,
 6356            out endContainedStrict);
 357    }
 358
 359    /// <summary>
 360    /// Finds the closed parameter interval where this segment intersects a finite cylinder.
 361    /// </summary>
 362    /// <remarks>
 363    /// The cylinder is described by the centers of its flat end caps and its
 364    /// radius. Returned parameters are clamped to [0, 1].
 365    /// </remarks>
 366    /// <exception cref="ArgumentException">
 367    /// Thrown when <paramref name="cylinderAxis"/> has zero length because the
 368    /// segment alone cannot retain a flat-cap normal.
 369    /// </exception>
 370    /// <exception cref="ArgumentOutOfRangeException">
 371    /// Thrown when <paramref name="radius"/> is negative.
 372    /// </exception>
 373    public readonly bool TryGetFiniteCylinderIntersectionInterval(
 374        FixedSegment cylinderAxis,
 375        Fixed64 radius,
 376        out Fixed64 entryParameter,
 377        out Fixed64 exitParameter) =>
 5378        TryGetFiniteCylinderIntersectionInterval(
 5379            cylinderAxis,
 5380            radius,
 5381            Fixed64.Zero,
 5382            out entryParameter,
 5383            out exitParameter);
 384
 385    /// <summary>
 386    /// Finds the closed parameter interval where this segment intersects a radially
 387    /// expanded finite cylinder.
 388    /// </summary>
 389    /// <remarks>
 390    /// The authored radius and radial expansion remain separate until the exact
 391    /// finite-axis solve. Returned parameters are clamped to [0, 1].
 392    /// </remarks>
 393    /// <exception cref="ArgumentException">
 394    /// Thrown when <paramref name="cylinderAxis"/> has zero length.
 395    /// </exception>
 396    /// <exception cref="ArgumentOutOfRangeException">
 397    /// Thrown when <paramref name="radius"/> or <paramref name="radiusExpansion"/>
 398    /// is negative.
 399    /// </exception>
 400    public readonly bool TryGetFiniteCylinderIntersectionInterval(
 401        FixedSegment cylinderAxis,
 402        Fixed64 radius,
 403        Fixed64 radiusExpansion,
 404        out Fixed64 entryParameter,
 405        out Fixed64 exitParameter) =>
 55406        TryGetFiniteCylinderIntersectionInterval(
 55407            cylinderAxis,
 55408            radius,
 55409            radiusExpansion,
 55410            out entryParameter,
 55411            out exitParameter,
 55412            out _,
 55413            out _);
 414
 415    /// <summary>
 416    /// Finds the closed parameter interval where this segment intersects a finite
 417    /// cylinder and reports exact endpoint containment.
 418    /// </summary>
 419    /// <remarks>
 420    /// The cylinder is described by its flat-cap centers and radius.
 421    /// <paramref name="startContained"/> includes side and cap boundaries, while
 422    /// <paramref name="endContainedStrict"/> excludes every boundary. Both flags
 423    /// are evaluated from the wide axial projection and radial polynomial constant,
 424    /// independently of rounded interval parameters.
 425    /// </remarks>
 426    /// <exception cref="ArgumentException">
 427    /// Thrown when <paramref name="cylinderAxis"/> has zero length.
 428    /// </exception>
 429    /// <exception cref="ArgumentOutOfRangeException">
 430    /// Thrown when <paramref name="radius"/> or <paramref name="radiusExpansion"/>
 431    /// is negative.
 432    /// </exception>
 433    public readonly bool TryGetFiniteCylinderIntersectionInterval(
 434        FixedSegment cylinderAxis,
 435        Fixed64 radius,
 436        Fixed64 radiusExpansion,
 437        out Fixed64 entryParameter,
 438        out Fixed64 exitParameter,
 439        out bool startContained,
 440        out bool endContainedStrict)
 441    {
 58442        if (cylinderAxis.Start == cylinderAxis.End)
 1443            throw new ArgumentException("A finite cylinder axis must have nonzero length.", nameof(cylinderAxis));
 57444        if (radius < Fixed64.Zero)
 1445            throw new ArgumentOutOfRangeException(nameof(radius));
 56446        if (radiusExpansion < Fixed64.Zero)
 1447            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 448
 55449        return WideFiniteAxisIntersection.TryGetFiniteCylinderInterval(
 55450            this,
 55451            cylinderAxis,
 55452            radius,
 55453            radiusExpansion,
 55454            out entryParameter,
 55455            out exitParameter,
 55456            out startContained,
 55457            out endContainedStrict);
 458    }
 459
 460    /// <summary>
 461    /// Finds the closed parameter interval where this segment intersects a
 462    /// centered, affinely expanded finite cylinder.
 463    /// </summary>
 464    /// <remarks>
 465    /// <paramref name="axisDirection"/> must be normalized. The authored flat
 466    /// caps are defined parametrically by
 467    /// <c>center +/- axisDirection * (axisLength / 2)</c>; neither cap is
 468    /// constructed or narrowed. <paramref name="axialExpansion"/> extends each
 469    /// cap outward, while <paramref name="radiusExpansion"/> expands only the
 470    /// radial surface. Returned parameters use deterministic
 471    /// round-half-to-even conversion and are clamped to [0, 1].
 472    /// </remarks>
 473    /// <exception cref="ArgumentException">
 474    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 475    /// </exception>
 476    /// <exception cref="ArgumentOutOfRangeException">
 477    /// Thrown when <paramref name="axisLength"/> is not positive, or when
 478    /// <paramref name="radius"/>, <paramref name="radiusExpansion"/>, or
 479    /// <paramref name="axialExpansion"/> is negative.
 480    /// </exception>
 481    public readonly bool TryGetFiniteCylinderIntersectionInterval(
 482        Vector3d center,
 483        Vector3d axisDirection,
 484        Fixed64 axisLength,
 485        Fixed64 radius,
 486        Fixed64 radiusExpansion,
 487        Fixed64 axialExpansion,
 488        out Fixed64 entryParameter,
 489        out Fixed64 exitParameter) =>
 29490        TryGetFiniteCylinderIntersectionInterval(
 29491            center,
 29492            axisDirection,
 29493            axisLength,
 29494            radius,
 29495            radiusExpansion,
 29496            axialExpansion,
 29497            out entryParameter,
 29498            out exitParameter,
 29499            out _,
 29500            out _);
 501
 502    /// <summary>
 503    /// Finds the closed parameter interval where this segment intersects a
 504    /// centered, affinely expanded finite cylinder and reports exact endpoint
 505    /// containment.
 506    /// </summary>
 507    /// <remarks>
 508    /// <paramref name="startContained"/> includes side and cap boundaries;
 509    /// <paramref name="endContainedStrict"/> excludes every boundary. The
 510    /// normalized axis defines authored caps parametrically as
 511    /// <c>center +/- axisDirection * (axisLength / 2)</c> without constructing
 512    /// either endpoint. Interval and containment calculations remain wide until
 513    /// the final deterministic parameter conversion.
 514    /// </remarks>
 515    /// <exception cref="ArgumentException">
 516    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 517    /// </exception>
 518    /// <exception cref="ArgumentOutOfRangeException">
 519    /// Thrown when <paramref name="axisLength"/> is not positive, or when
 520    /// <paramref name="radius"/>, <paramref name="radiusExpansion"/>, or
 521    /// <paramref name="axialExpansion"/> is negative.
 522    /// </exception>
 523    public readonly bool TryGetFiniteCylinderIntersectionInterval(
 524        Vector3d center,
 525        Vector3d axisDirection,
 526        Fixed64 axisLength,
 527        Fixed64 radius,
 528        Fixed64 radiusExpansion,
 529        Fixed64 axialExpansion,
 530        out Fixed64 entryParameter,
 531        out Fixed64 exitParameter,
 532        out bool startContained,
 533        out bool endContainedStrict)
 534    {
 30535        if (!axisDirection.IsNormalized())
 2536            throw new ArgumentException("Finite cylinder axis direction must be normalized.", nameof(axisDirection));
 28537        if (axisLength <= Fixed64.Zero)
 1538            throw new ArgumentOutOfRangeException(nameof(axisLength));
 27539        if (radius < Fixed64.Zero)
 1540            throw new ArgumentOutOfRangeException(nameof(radius));
 26541        if (radiusExpansion < Fixed64.Zero)
 1542            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 25543        if (axialExpansion < Fixed64.Zero)
 1544            throw new ArgumentOutOfRangeException(nameof(axialExpansion));
 545
 24546        return WideFiniteAxisIntersection.TryGetFiniteCylinderInterval(
 24547            this,
 24548            center,
 24549            axisDirection,
 24550            axisLength,
 24551            radius,
 24552            radiusExpansion,
 24553            axialExpansion,
 24554            out entryParameter,
 24555            out exitParameter,
 24556            out startContained,
 24557            out endContainedStrict);
 558    }
 559
 560    /// <summary>
 561    /// Returns the closest finite points on this segment and another segment.
 562    /// </summary>
 563    /// <remarks>
 564    /// Endpoint differences, dot products, determinants, and parameter numerators
 565    /// are evaluated across the complete raw domain. A direction whose exact
 566    /// Q64.64 squared-length total is at most 2^31 raw units rounds to zero in
 567    /// Q32.32 and is treated as a point at its start. The established
 568    /// near-parallel policy compares the exact determinant magnitude with
 569    /// <see cref="Fixed64.Epsilon"/> before division. Parameters are rounded
 570    /// half-to-even and deterministically clamped to the closed interval [0, 1].
 571    /// When the mathematical zero-separation contact is an existing endpoint,
 572    /// both returned points preserve that endpoint bit-for-bit.
 573    /// </remarks>
 574    public readonly (Vector3d ThisPoint, Vector3d OtherPoint) GetClosestPoints(FixedSegment other)
 575    {
 71576        Signed192 firstLengthSquared = GetDifferenceDot(End, Start, End, Start);
 71577        Signed192 secondLengthSquared = GetDifferenceDot(
 71578            other.End,
 71579            other.Start,
 71580            other.End,
 71581            other.Start);
 582
 71583        if (WideGeometry.IsSquaredLengthDegenerate(firstLengthSquared))
 584        {
 9585            if (WideGeometry.IsSquaredLengthDegenerate(secondLengthSquared))
 2586                return (Start, other.Start);
 7587            if (PointOnSegment(Start, other, secondLengthSquared))
 3588                return (Start, Start);
 4589            return (Start, other.ClosestPoint(Start));
 590        }
 591
 62592        if (WideGeometry.IsSquaredLengthDegenerate(secondLengthSquared))
 593        {
 5594            if (PointOnSegment(other.Start, this, firstLengthSquared))
 2595                return (other.Start, other.Start);
 3596            return (Vector3d.ClosestPointOnLineSegment(other.Start, Start, End), other.Start);
 597        }
 598
 57599        Signed192 directionsDot = GetDifferenceDot(End, Start, other.End, other.Start);
 57600        Signed192 firstDirectionDotDifference = GetDifferenceDot(End, Start, Start, other.Start);
 57601        Signed192 secondDirectionDotDifference = GetDifferenceDot(
 57602            other.End,
 57603            other.Start,
 57604            Start,
 57605            other.Start);
 57606        Signed320 determinant = WideArithmetic.MultiplySubtract(
 57607            firstLengthSquared,
 57608            secondLengthSquared,
 57609            directionsDot,
 57610            directionsDot);
 611
 57612        (Fixed64 firstParameter, Fixed64 secondParameter, byte endpointCandidates) = SolveClosestParameters(
 57613            firstLengthSquared,
 57614            directionsDot,
 57615            secondLengthSquared,
 57616            firstDirectionDotDifference,
 57617            secondDirectionDotDifference,
 57618            determinant);
 619
 57620        if ((endpointCandidates & 1) != 0 && PointOnSegment(Start, other, secondLengthSquared))
 3621            return (Start, Start);
 54622        if ((endpointCandidates & 2) != 0 && PointOnSegment(End, other, secondLengthSquared))
 2623            return (End, End);
 52624        if ((endpointCandidates & 4) != 0 && PointOnSegment(other.Start, this, firstLengthSquared))
 2625            return (other.Start, other.Start);
 50626        if ((endpointCandidates & 8) != 0 && PointOnSegment(other.End, this, firstLengthSquared))
 2627            return (other.End, other.End);
 628
 48629        return (
 48630            Interpolate(this, firstParameter),
 48631            Interpolate(other, secondParameter));
 632    }
 633
 634    private static (Fixed64 First, Fixed64 Second, byte EndpointCandidates) SolveClosestParameters(
 635        Signed192 firstLengthSquared,
 636        Signed192 directionsDot,
 637        Signed192 secondLengthSquared,
 638        Signed192 firstDirectionDotDifference,
 639        Signed192 secondDirectionDotDifference,
 640        Signed320 determinant)
 641    {
 642        Fixed64 firstParameter;
 643        bool firstParameterIsClamped;
 57644        Signed320 firstNumerator = default;
 57645        Signed320 secondNumerator = default;
 57646        Signed320 secondDenominator = default;
 57647        Signed192 narrowSecondNumerator = default;
 57648        Signed192 narrowSecondDenominator = default;
 649        bool secondRatioIsWide;
 57650        byte endpointCandidates = 0;
 57651        bool isNearParallel = WideGeometry.IsSegmentDeterminantNearParallel(determinant);
 652
 57653        if (isNearParallel)
 654        {
 18655            firstParameter = Fixed64.Zero;
 18656            firstParameterIsClamped = true;
 18657            endpointCandidates = 1;
 18658            bool useDirectionsDot = directionsDot.Sign > 0
 18659                && WideArithmetic.CompareMagnitude(directionsDot, secondLengthSquared) > 0;
 18660            narrowSecondNumerator = useDirectionsDot
 18661                ? firstDirectionDotDifference
 18662                : secondDirectionDotDifference;
 18663            narrowSecondDenominator = useDirectionsDot ? directionsDot : secondLengthSquared;
 18664            secondRatioIsWide = false;
 665        }
 666        else
 667        {
 39668            firstNumerator = WideArithmetic.MultiplySubtract(
 39669                directionsDot,
 39670                secondDirectionDotDifference,
 39671                secondLengthSquared,
 39672                firstDirectionDotDifference);
 39673            int firstNumeratorComparison = firstNumerator.Sign < 0
 39674                ? -1
 39675                : WideArithmetic.CompareMagnitude(firstNumerator, determinant);
 676
 39677            if (firstNumerator.Sign < 0)
 678            {
 5679                firstParameter = Fixed64.Zero;
 5680                firstParameterIsClamped = true;
 5681                endpointCandidates = 0;
 5682                narrowSecondNumerator = secondDirectionDotDifference;
 5683                narrowSecondDenominator = secondLengthSquared;
 5684                secondRatioIsWide = false;
 685            }
 34686            else if (firstNumeratorComparison > 0)
 687            {
 7688                firstParameter = Fixed64.One;
 7689                firstParameterIsClamped = true;
 7690                endpointCandidates = 0;
 7691                narrowSecondNumerator = WideArithmetic.AddSigned192(
 7692                    secondDirectionDotDifference,
 7693                    directionsDot);
 7694                narrowSecondDenominator = secondLengthSquared;
 7695                secondRatioIsWide = false;
 696            }
 697            else
 698            {
 27699                firstParameter = default;
 27700                firstParameterIsClamped = false;
 27701                secondNumerator = WideArithmetic.MultiplySubtract(
 27702                    firstLengthSquared,
 27703                    secondDirectionDotDifference,
 27704                    directionsDot,
 27705                    firstDirectionDotDifference);
 27706                secondDenominator = determinant;
 27707                secondRatioIsWide = true;
 708
 27709                int secondNumeratorComparison = secondNumerator.Sign < 0
 27710                    ? -1
 27711                    : WideArithmetic.CompareMagnitude(secondNumerator, determinant);
 27712                if (secondNumerator.Sign >= 0 && secondNumeratorComparison <= 0)
 713                {
 22714                    if (firstNumerator.IsZero)
 3715                        endpointCandidates |= 1;
 19716                    else if (firstNumeratorComparison == 0)
 3717                        endpointCandidates |= 2;
 22718                    if (secondNumerator.IsZero)
 2719                        endpointCandidates |= 4;
 20720                    else if (secondNumeratorComparison == 0)
 3721                        endpointCandidates |= 8;
 722                }
 723            }
 724        }
 725
 57726        int secondNumeratorSign = secondRatioIsWide
 57727            ? secondNumerator.Sign
 57728            : narrowSecondNumerator.Sign;
 57729        if (secondNumeratorSign < 0)
 11730            return (
 11731                ClampParameter(
 11732                    WideArithmetic.SubtractSigned192(default, firstDirectionDotDifference),
 11733                    firstLengthSquared),
 11734                Fixed64.Zero,
 11735                isNearParallel ? (byte)4 : (byte)0);
 736
 46737        int secondRatioComparison = secondRatioIsWide
 46738            ? WideArithmetic.CompareMagnitude(secondNumerator, secondDenominator)
 46739            : WideArithmetic.CompareMagnitude(narrowSecondNumerator, narrowSecondDenominator);
 46740        if (secondRatioComparison > 0)
 6741            return (
 6742                ClampParameter(
 6743                    WideArithmetic.SubtractSigned192(directionsDot, firstDirectionDotDifference),
 6744                    firstLengthSquared),
 6745                Fixed64.One,
 6746                isNearParallel ? (byte)8 : (byte)0);
 747
 748        Fixed64 secondParameter;
 40749        if (secondRatioIsWide)
 750        {
 22751            _ = Fixed64.TryGetUnitIntervalRatio(
 22752                secondNumerator,
 22753                secondDenominator,
 22754                out secondParameter);
 755        }
 756        else
 757        {
 18758            _ = Fixed64.TryGetUnitIntervalRatio(
 18759                narrowSecondNumerator,
 18760                narrowSecondDenominator,
 18761                out secondParameter);
 762        }
 40763        if (!firstParameterIsClamped)
 22764            _ = Fixed64.TryGetUnitIntervalRatio(firstNumerator, determinant, out firstParameter);
 765
 40766        return (firstParameter, secondParameter, endpointCandidates);
 767    }
 768
 769    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 770    private static Fixed64 ClampParameter(Signed192 numerator, Signed192 denominator)
 771    {
 17772        if (numerator.Sign <= 0)
 5773            return Fixed64.Zero;
 12774        if (WideArithmetic.CompareMagnitude(numerator, denominator) >= 0)
 7775            return Fixed64.One;
 5776        _ = Fixed64.TryGetUnitIntervalRatio(numerator, denominator, out Fixed64 parameter);
 5777        return parameter;
 778    }
 779
 780    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 781    private static Signed192 GetDifferenceDot(
 782        Vector3d leftEnd,
 783        Vector3d leftStart,
 784        Vector3d rightEnd,
 785        Vector3d rightStart)
 786    {
 1146787        return WideGeometry.GetDifferenceDotProduct3D(
 1146788            leftEnd.X, leftStart.X, leftEnd.Y, leftStart.Y, leftEnd.Z, leftStart.Z,
 1146789            rightEnd.X, rightStart.X, rightEnd.Y, rightStart.Y, rightEnd.Z, rightStart.Z);
 790    }
 791
 792    private static bool PointOnSegment(
 793        Vector3d point,
 794        FixedSegment segment,
 795        Signed192 lengthSquared)
 796    {
 305797        long pointX = point.X.m_rawValue;
 305798        long pointY = point.Y.m_rawValue;
 305799        long pointZ = point.Z.m_rawValue;
 305800        if (pointX < Math.Min(segment.Start.X.m_rawValue, segment.End.X.m_rawValue)
 305801            || pointX > Math.Max(segment.Start.X.m_rawValue, segment.End.X.m_rawValue)
 305802            || pointY < Math.Min(segment.Start.Y.m_rawValue, segment.End.Y.m_rawValue)
 305803            || pointY > Math.Max(segment.Start.Y.m_rawValue, segment.End.Y.m_rawValue)
 305804            || pointZ < Math.Min(segment.Start.Z.m_rawValue, segment.End.Z.m_rawValue)
 305805            || pointZ > Math.Max(segment.Start.Z.m_rawValue, segment.End.Z.m_rawValue))
 806        {
 28807            return false;
 808        }
 809
 277810        Signed192 projection = GetDifferenceDot(
 277811            point,
 277812            segment.Start,
 277813            segment.End,
 277814            segment.Start);
 277815        Signed192 pointDistanceSquared = GetDifferenceDot(
 277816            point,
 277817            segment.Start,
 277818            point,
 277819            segment.Start);
 277820        return WideArithmetic.MultiplySubtract(
 277821            lengthSquared,
 277822            pointDistanceSquared,
 277823            projection,
 277824            projection).IsZero;
 825    }
 826
 827    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 828    private static Vector3d Interpolate(FixedSegment segment, Fixed64 parameter)
 829    {
 96830        return new Vector3d(
 96831            FixedMath.Lerp(segment.Start.X, segment.End.X, parameter),
 96832            FixedMath.Lerp(segment.Start.Y, segment.End.Y, parameter),
 96833            FixedMath.Lerp(segment.Start.Z, segment.End.Z, parameter));
 834    }
 835
 836    #endregion
 837
 838    #region Deconstruction
 839
 840    /// <summary>
 841    /// Deconstructs the segment into start and end points.
 842    /// </summary>
 843    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 844    public void Deconstruct(out Vector3d start, out Vector3d end)
 845    {
 1846        start = Start;
 1847        end = End;
 1848    }
 849
 850    #endregion
 851
 852    #region Operators
 853
 854    /// <summary>
 855    /// Determines whether two segments have the same ordered endpoints.
 856    /// </summary>
 857    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 2858    public static bool operator ==(FixedSegment left, FixedSegment right) => left.Equals(right);
 859
 860    /// <summary>
 861    /// Determines whether two segments have different ordered endpoints.
 862    /// </summary>
 863    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 2864    public static bool operator !=(FixedSegment left, FixedSegment right) => !left.Equals(right);
 865
 866    #endregion
 867
 868    #region Equality
 869
 870    /// <inheritdoc />
 871    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 872    public bool Equals(FixedSegment other)
 873    {
 11874        return Start == other.Start && End == other.End;
 875    }
 876
 877    /// <inheritdoc />
 878    public override bool Equals(object? obj)
 879    {
 2880        return obj is FixedSegment other && Equals(other);
 881    }
 882
 883    /// <inheritdoc />
 884    public override int GetHashCode()
 885    {
 886        unchecked
 887        {
 2888            int hash = 17;
 2889            hash = (hash * 31) + Start.StateHash;
 2890            hash = (hash * 31) + End.StateHash;
 2891            return hash;
 892        }
 893    }
 894
 895    #endregion
 896}

/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    {
 2155        ValidateTotalDistance(totalDistance);
 2056        if (radiusExpansion < Fixed64.Zero)
 157            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 58
 1959        return WideFiniteAxisIntersection.TryGetSphereDistanceInterval(
 1960            this,
 1961            sphere,
 1962            radiusExpansion,
 1963            totalDistance,
 1964            out entryDistance,
 1965            out exitDistance,
 1966            out startContained,
 1967            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    {
 129544        ValidateDistance(distance, totalDistance);
 126545        if (distance == Fixed64.Zero)
 13546            return Start;
 113547        if (distance == totalDistance)
 5548            return End;
 549
 108550        Signed192 distanceRaw = Signed192.Signed(distance.m_rawValue);
 108551        Signed192 totalDistanceRaw = Signed192.Signed(totalDistance.m_rawValue);
 108552        return new Vector3d(
 108553            WideGeometry.InterpolateCoordinate(Start.X, End.X, distanceRaw, totalDistanceRaw),
 108554            WideGeometry.InterpolateCoordinate(Start.Y, End.Y, distanceRaw, totalDistanceRaw),
 108555            WideGeometry.InterpolateCoordinate(Start.Z, End.Z, distanceRaw, totalDistanceRaw));
 556    }
 557
 558    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 559    private readonly void ValidateDistance(Fixed64 distance, Fixed64 totalDistance)
 560    {
 129561        ValidateTotalDistance(totalDistance);
 128562        if (distance < Fixed64.Zero || distance > totalDistance)
 2563            throw new ArgumentOutOfRangeException(nameof(distance));
 126564    }
 565
 566    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 567    private readonly void ValidateTotalDistance(Fixed64 totalDistance)
 568    {
 735569        if (totalDistance < Fixed64.Zero)
 4570            throw new ArgumentOutOfRangeException(nameof(totalDistance));
 731571        if (totalDistance == Fixed64.Zero && Start != End)
 5572            throw new ArgumentException("Zero total distance requires a zero-length segment.", nameof(totalDistance));
 726573    }
 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    {
 356515        ValidateFiniteCone(
 356516            apexToBaseDirection,
 356517            height,
 356518            baseRadius,
 356519            nameof(apexToBaseDirection),
 356520            nameof(height));
 356521        Fixed64 intervalScale = Start == End ? Fixed64.Zero : Fixed64.MaxValue;
 356522        if (!WideFiniteConeIntersection.TryGetApexDistanceInterval(
 356523                this,
 356524                apex,
 356525                apexToBaseDirection,
 356526                height,
 356527                baseRadius,
 356528                intervalScale,
 356529                out Fixed64 entry,
 356530                out Fixed64 exit,
 356531                out _,
 356532                out _))
 533        {
 260534            point = default;
 260535            return false;
 536        }
 537
 96538        Signed192 axialVelocity = WideGeometry.GetDifferenceDotProduct3D(
 96539            End.X, Start.X, End.Y, Start.Y, End.Z, Start.Z,
 96540            apexToBaseDirection.X, Fixed64.Zero,
 96541            apexToBaseDirection.Y, Fixed64.Zero,
 96542            apexToBaseDirection.Z, Fixed64.Zero);
 96543        point = GetPointAtDistance(axialVelocity.Sign < 0 ? exit : entry, intervalScale);
 96544        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    {
 442649        if (!axisDirection.IsNormalized())
 4650            throw new ArgumentException("Finite cone axis direction must be normalized.", axisParameterName);
 438651        if (height <= Fixed64.Zero)
 3652            throw new ArgumentOutOfRangeException(heightParameterName);
 435653        if (baseRadius < Fixed64.Zero)
 2654            throw new ArgumentOutOfRangeException(nameof(baseRadius));
 433655    }
 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    /// Zero-radius cylinders are finite segments. Oblique contacts, including
 170    /// positive-radius cylinder pairs, can require hundreds of KiB of bounded
 171    /// stack scratch without managed allocation. Allow at least a 1 MiB thread
 172    /// stack with adequate caller headroom; avoid deliberately small-stack workers.
 173    /// </remarks>
 174    public static bool TryGetCenteredFiniteCylindersContact(
 175        Vector3d firstCenter,
 176        FixedQuaternion firstRotation,
 177        Vector3d firstLocalAxisDirection,
 178        Fixed64 firstAxisLength,
 179        Fixed64 firstRadius,
 180        Vector3d secondCenter,
 181        FixedQuaternion secondRotation,
 182        Vector3d secondLocalAxisDirection,
 183        Fixed64 secondAxisLength,
 184        Fixed64 secondRadius,
 185        out FixedContactAnchors contact)
 186    {
 345187        ValidateRigidFiniteShape(
 345188            firstRotation,
 345189            firstLocalAxisDirection,
 345190            firstAxisLength,
 345191            firstRadius,
 345192            requirePositiveLength: true,
 345193            nameof(firstRotation),
 345194            nameof(firstLocalAxisDirection),
 345195            nameof(firstAxisLength),
 345196            nameof(firstRadius));
 344197        ValidateRigidFiniteShape(
 344198            secondRotation,
 344199            secondLocalAxisDirection,
 344200            secondAxisLength,
 344201            secondRadius,
 344202            requirePositiveLength: true,
 344203            nameof(secondRotation),
 344204            nameof(secondLocalAxisDirection),
 344205            nameof(secondAxisLength),
 344206            nameof(secondRadius));
 343207        return WideConvexPrismRelations
 343208            .TryGetCenteredFiniteCylindersContact(
 343209                firstCenter,
 343210                firstRotation,
 343211                firstLocalAxisDirection,
 343212                firstAxisLength,
 343213                firstRadius,
 343214                secondCenter,
 343215                secondRotation,
 343216                secondLocalAxisDirection,
 343217                secondAxisLength,
 343218                secondRadius,
 343219                out contact);
 220    }
 221
 222    /// <summary>
 223    /// Attempts to construct the minimum-translation contact between a
 224    /// centered finite cylinder and a centered capsule.
 225    /// </summary>
 226    /// <remarks>
 227    /// Both finite axes remain authoritative in their normalized rigid frames.
 228    /// The returned normal points from the cylinder toward the capsule.
 229    /// Separation, exact tangency, and minimum depth are decided before output
 230    /// rounding, including rim features and intersecting capsule cores. Depth
 231    /// rounds once to nearest-even; DepthIsClamped describes conceptual overflow.
 232    /// Exact ties retain stable feature order. Each anchor is an independent
 233    /// support point for the rounded normal, not a paired algebraic closest point.
 234    /// The exact curved-feature fallback uses bounded stack scratch storage;
 235    /// avoid deliberately small-stack worker threads for these queries.
 236    /// </remarks>
 237    public static bool TryGetCenteredFiniteCylinderCapsuleContact(
 238        Vector3d cylinderCenter,
 239        FixedQuaternion cylinderRotation,
 240        Vector3d cylinderLocalAxisDirection,
 241        Fixed64 cylinderAxisLength,
 242        Fixed64 cylinderRadius,
 243        Vector3d capsuleCenter,
 244        FixedQuaternion capsuleRotation,
 245        Vector3d capsuleLocalAxisDirection,
 246        Fixed64 capsuleAxisLength,
 247        Fixed64 capsuleRadius,
 248        out FixedContactAnchors contact)
 249    {
 704250        ValidateRigidFiniteShape(
 704251            cylinderRotation,
 704252            cylinderLocalAxisDirection,
 704253            cylinderAxisLength,
 704254            cylinderRadius,
 704255            requirePositiveLength: true,
 704256            nameof(cylinderRotation),
 704257            nameof(cylinderLocalAxisDirection),
 704258            nameof(cylinderAxisLength),
 704259            nameof(cylinderRadius));
 700260        ValidateRigidFiniteShape(
 700261            capsuleRotation,
 700262            capsuleLocalAxisDirection,
 700263            capsuleAxisLength,
 700264            capsuleRadius,
 700265            requirePositiveLength: false,
 700266            nameof(capsuleRotation),
 700267            nameof(capsuleLocalAxisDirection),
 700268            nameof(capsuleAxisLength),
 700269            nameof(capsuleRadius));
 696270        return WideConvexPrismRelations
 696271            .TryGetCenteredFiniteCylinderCapsuleContact(
 696272                cylinderCenter,
 696273                cylinderRotation,
 696274                cylinderLocalAxisDirection,
 696275                cylinderAxisLength,
 696276                cylinderRadius,
 696277                capsuleCenter,
 696278                capsuleRotation,
 696279                capsuleLocalAxisDirection,
 696280                capsuleAxisLength,
 696281                capsuleRadius,
 696282                out contact);
 283    }
 284
 285    private static void ValidateRigidFiniteShape(
 286        FixedQuaternion rotation,
 287        Vector3d localAxisDirection,
 288        Fixed64 axisLength,
 289        Fixed64 radius,
 290        bool requirePositiveLength,
 291        string rotationParameterName,
 292        string axisParameterName,
 293        string lengthParameterName,
 294        string radiusParameterName)
 295    {
 2093296        if (!rotation.IsNormalized())
 3297            throw new ArgumentException("The rigid rotation must be normalized.", rotationParameterName);
 2090298        if (!localAxisDirection.IsNormalized())
 2299            throw new ArgumentException("The local axis direction must be normalized.", axisParameterName);
 2088300        if (requirePositiveLength
 2088301            ? axisLength <= Fixed64.Zero
 2088302            : axisLength < Fixed64.Zero)
 303        {
 3304            throw new ArgumentOutOfRangeException(lengthParameterName);
 305        }
 2085306        if (radius < Fixed64.Zero)
 2307            throw new ArgumentOutOfRangeException(radiusParameterName);
 2083308    }
 309}

Methods/Properties

DoCenteredCapsulesOverlapStrict(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
DoCenteredCapsulesOverlapStrict(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
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)
Contains(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)