< Summary

Line coverage
100%
Covered lines: 892
Uncovered lines: 0
Coverable lines: 892
Total lines: 2347
Line coverage: 100%
Branch coverage
100%
Covered branches: 188
Total branches: 188
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%11100%
File 1: TryGetDistanceToCenteredAxis(...)100%11100%
File 1: TryGetDistanceBetweenCenteredAxes(...)100%11100%
File 1: DoCenteredCapsulesOverlap(...)100%44100%
File 1: TryGetCenteredCapsulesContact(...)100%66100%
File 1: TryGetCenteredAxisEndpoint(...)100%11100%
File 1: TryGetCenteredCapsuleSupport(...)100%22100%
File 1: GetCenteredCapsuleSupportAnchor(...)100%22100%
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: TryGetSurfacePointOnCenteredCapsule(...)100%44100%
File 1: TryGetSurfaceOffsetOnCenteredCapsule(...)100%44100%
File 1: GetSurfaceAnchorOnCenteredCapsule(...)100%44100%
File 1: GetDirectionFromCenteredAxis(...)100%11100%
File 1: TryGetClosestPointsBetweenCenteredAxes(...)100%11100%
File 1: ValidateCenteredAxis(...)100%11100%
File 1: ValidateCenteredAxis(...)100%44100%
File 1: ContainsPointInCenteredCapsule(...)100%11100%
File 1: ContainsPointInCenteredCapsule(...)100%11100%
File 1: ContainsPointInCenteredCapsule(...)100%22100%
File 1: GetDirectionFromCenteredAxis(...)100%11100%
File 1: GetDistanceToCenteredCapsule(...)100%11100%
File 1: TryGetDistanceToCenteredCapsule(...)100%11100%
File 1: TryGetCenteredCapsuleSupport(...)100%11100%
File 1: TryGetSurfacePointOnCenteredCapsule(...)100%22100%
File 1: TryGetSurfaceOffsetOnCenteredCapsule(...)100%22100%
File 1: DoCenteredCapsulesOverlap(...)100%11100%
File 1: TryGetCenteredCapsulesContact(...)100%22100%
File 1: TryGetCenteredCapsuleConvexMinimumTranslation(...)100%22100%
File 1: TryGetSweptCenteredCapsuleSegmentFirstDistance(...)100%11100%
File 1: TryGetSweptCenteredCapsulesFirstDistance(...)100%11100%
File 1: TryGetCapsuleIntersectionDistanceInterval(...)100%22100%
File 1: GetRotatedPositiveYAxis(...)100%11100%
File 1: ValidateRotatedCapsule(...)100%22100%
File 2: DoesCenteredCapsulePenetrateConvex(...)100%11100%
File 2: DoesCenteredCapsulePenetrateConvex(...)100%44100%
File 2: TryGetCenteredCapsuleConvexMinimumTranslation(...)100%44100%
File 2: TryGetCenteredCapsuleConvexMinimumTranslation(...)100%44100%
File 2: TryGetCenteredCapsuleConvexContacts(...)100%88100%
File 2: TryGetSweptCenteredCapsuleSegmentFirstDistance(...)100%11100%
File 2: TryGetSweptCenteredCapsulesFirstDistance(...)100%11100%
File 2: ValidateSweep(...)100%88100%
File 3: .ctor(...)100%11100%
File 3: get_Delta()100%11100%
File 3: get_Length()100%11100%
File 3: get_LengthSquared()100%11100%
File 3: get_Bounds()100%11100%
File 3: ClosestPoint(...)100%11100%
File 3: DistanceSquared(...)100%11100%
File 3: IsDistanceAtLeast(...)100%66100%
File 3: TryGetCapsuleIntersectionInterval(...)100%11100%
File 3: TryGetCapsuleIntersectionParameterEnclosure(...)100%66100%
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: TryGetUniqueIntersection(...)100%11100%
File 3: TryGetUniqueIntersectionParameterEnclosure(...)100%66100%
File 3: GetClosestPoints(...)100%1010100%
File 3: TryGetUniqueIntersection(...)100%2020100%
File 3: Interpolate(...)100%11100%
File 3: PointOnSegment(...)100%88100%
File 3: ConsiderSharedEndpoint(...)100%88100%
File 3: ConsiderClosestCandidate(...)100%22100%
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 3: TryGetCircleIntersectionDistanceInterval(...)100%11100%
File 3: TryGetCircleIntersectionDistanceInterval(...)100%22100%
File 3: TryGetCapsuleIntersectionDistanceInterval(...)100%11100%
File 3: TryGetCapsuleIntersectionDistanceInterval(...)100%44100%
File 3: TryGetCapsuleIntersectionDistanceInterval(...)100%11100%
File 3: TryGetCapsuleIntersectionDistanceInterval(...)100%44100%
File 3: GetPointAtDistance(...)100%44100%
File 3: ValidateDistance(...)100%44100%
File 3: ValidateTotalDistance(...)100%66100%

File(s)

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

#LineLine coverage
 1//=======================================================================
 2// FixedSegment2d.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 centered-axis and rotated-capsule geometry that avoids
 14/// materializing potentially unrepresentable segment endpoints.
 15/// </content>
 16public partial struct FixedSegment2d
 17{
 18    /// <summary>
 19    /// Returns whether the exact distance between two centered capsule axes is
 20    /// strictly less than their radius sum. Exact tangency is excluded.
 21    /// </summary>
 22    /// <remarks>
 23    /// Classification precedes endpoint, distance, and contact-depth rounding.
 24    /// Zero-length axes are points; a zero radius sum has no strict overlap.
 25    /// </remarks>
 26    public static bool DoCenteredCapsulesOverlapStrict(
 27        Vector2d firstCenter,
 28        Vector2d firstAxisDirection,
 29        Fixed64 firstAxisLength,
 30        Fixed64 firstRadius,
 31        Vector2d secondCenter,
 32        Vector2d secondAxisDirection,
 33        Fixed64 secondAxisLength,
 34        Fixed64 secondRadius)
 35    {
 33236        ValidateCenteredAxis(firstAxisDirection, firstAxisLength,
 33237            nameof(firstAxisDirection), nameof(firstAxisLength));
 33138        if (firstRadius < Fixed64.Zero)
 139            throw new ArgumentOutOfRangeException(nameof(firstRadius));
 33040        ValidateCenteredAxis(secondAxisDirection, secondAxisLength,
 33041            nameof(secondAxisDirection), nameof(secondAxisLength));
 33042        if (secondRadius < Fixed64.Zero)
 143            throw new ArgumentOutOfRangeException(nameof(secondRadius));
 44
 32945        return WideFiniteAxisIntersection.DoCenteredCapsulesOverlap(
 32946            firstCenter, firstAxisDirection, firstAxisLength, firstRadius,
 32947            secondCenter, secondAxisDirection, secondAxisLength, secondRadius,
 32948            strict: true);
 49    }
 50
 51    /// <summary>
 52    /// Returns whether two centered capsules expressed by scalar rigid-frame
 53    /// rotations have strictly positive radial overlap, excluding exact tangency.
 54    /// </summary>
 55    public static bool DoCenteredCapsulesOverlapStrict(
 56        Vector2d firstCenter,
 57        Fixed64 firstRotation,
 58        Fixed64 firstAxisLength,
 59        Fixed64 firstRadius,
 60        Vector2d secondCenter,
 61        Fixed64 secondRotation,
 62        Fixed64 secondAxisLength,
 63        Fixed64 secondRadius)
 64    {
 365        ValidateRotatedCapsule(firstAxisLength, firstRadius);
 266        ValidateRotatedCapsule(secondAxisLength, secondRadius);
 267        return WideFiniteAxisIntersection.DoCenteredCapsulesOverlap(
 268            firstCenter, GetRotatedPositiveYAxis(firstRotation), firstAxisLength, firstRadius,
 269            secondCenter, GetRotatedPositiveYAxis(secondRotation), secondAxisLength, secondRadius,
 270            strict: true);
 71    }
 72
 73    /// <summary>
 74    /// Attempts to return the rounded distance from a point to a conceptual
 75    /// centered finite axis without materializing its endpoints.
 76    /// </summary>
 77    /// <returns>
 78    /// True when the final distance is representable; otherwise false and
 79    /// <paramref name="distance"/> is <see cref="Fixed64.MaxValue"/>.
 80    /// </returns>
 81    public static bool TryGetDistanceToCenteredAxis(
 82        Vector2d point,
 83        Vector2d center,
 84        Vector2d axisDirection,
 85        Fixed64 axisLength,
 86        out Fixed64 distance)
 87    {
 288        ValidateCenteredAxis(axisDirection, axisLength);
 289        return WideFiniteAxisIntersection.TryGetDistanceToCenteredAxis(
 290            point,
 291            center,
 292            axisDirection,
 293            axisLength,
 294            out distance);
 95    }
 96
 97    /// <summary>
 98    /// Attempts to return the rounded distance between two conceptual
 99    /// centered finite axes without materializing either pair of endpoints.
 100    /// </summary>
 101    /// <returns>
 102    /// True when the final distance is representable; otherwise false and
 103    /// <paramref name="distance"/> is <see cref="Fixed64.MaxValue"/>.
 104    /// </returns>
 105    public static bool TryGetDistanceBetweenCenteredAxes(
 106        Vector2d firstCenter,
 107        Vector2d firstAxisDirection,
 108        Fixed64 firstAxisLength,
 109        Vector2d secondCenter,
 110        Vector2d secondAxisDirection,
 111        Fixed64 secondAxisLength,
 112        out Fixed64 distance)
 113    {
 4612114        ValidateCenteredAxis(
 4612115            firstAxisDirection,
 4612116            firstAxisLength,
 4612117            nameof(firstAxisDirection),
 4612118            nameof(firstAxisLength));
 4611119        ValidateCenteredAxis(
 4611120            secondAxisDirection,
 4611121            secondAxisLength,
 4611122            nameof(secondAxisDirection),
 4611123            nameof(secondAxisLength));
 4610124        return WideFiniteAxisIntersection.TryGetDistanceBetweenCenteredAxes(
 4610125            firstCenter,
 4610126            firstAxisDirection,
 4610127            firstAxisLength,
 4610128            secondCenter,
 4610129            secondAxisDirection,
 4610130            secondAxisLength,
 4610131            out distance);
 132    }
 133
 134    /// <summary>
 135    /// Returns whether two conceptual centered capsules overlap, including
 136    /// exact tangency, without narrowing their axis distance or radius sum.
 137    /// </summary>
 138    public static bool DoCenteredCapsulesOverlap(
 139        Vector2d firstCenter,
 140        Vector2d firstAxisDirection,
 141        Fixed64 firstAxisLength,
 142        Fixed64 firstRadius,
 143        Vector2d secondCenter,
 144        Vector2d secondAxisDirection,
 145        Fixed64 secondAxisLength,
 146        Fixed64 secondRadius)
 147    {
 4616148        ValidateCenteredAxis(
 4616149            firstAxisDirection,
 4616150            firstAxisLength,
 4616151            nameof(firstAxisDirection),
 4616152            nameof(firstAxisLength));
 4616153        if (firstRadius < Fixed64.Zero)
 1154            throw new ArgumentOutOfRangeException(nameof(firstRadius));
 4615155        ValidateCenteredAxis(
 4615156            secondAxisDirection,
 4615157            secondAxisLength,
 4615158            nameof(secondAxisDirection),
 4615159            nameof(secondAxisLength));
 4615160        if (secondRadius < Fixed64.Zero)
 1161            throw new ArgumentOutOfRangeException(nameof(secondRadius));
 162
 4614163        return WideFiniteAxisIntersection.DoCenteredCapsulesOverlap(
 4614164            firstCenter,
 4614165            firstAxisDirection,
 4614166            firstAxisLength,
 4614167            firstRadius,
 4614168            secondCenter,
 4614169            secondAxisDirection,
 4614170            secondAxisLength,
 4614171            secondRadius);
 172    }
 173
 174    /// <summary>
 175    /// Attempts to build an exact contact between two conceptual centered
 176    /// capsules.
 177    /// </summary>
 178    /// <remarks>
 179    /// Each surface witness retains its axial and radial contributions
 180    /// separately. Classification is independent of absolute world-point
 181    /// materialization.
 182    /// </remarks>
 183    public static bool TryGetCenteredCapsulesContact(
 184        Vector2d firstCenter,
 185        Fixed64 firstAnchorRotation,
 186        Vector2d firstAxisDirection,
 187        Fixed64 firstAxisLength,
 188        Fixed64 firstRadius,
 189        Vector2d secondCenter,
 190        Fixed64 secondAnchorRotation,
 191        Vector2d secondAxisDirection,
 192        Fixed64 secondAxisLength,
 193        Fixed64 secondRadius,
 194        Vector2d fallbackNormal,
 195        out FixedContactAnchors2d contact)
 196    {
 31197        ValidateCenteredAxis(
 31198            firstAxisDirection,
 31199            firstAxisLength,
 31200            nameof(firstAxisDirection),
 31201            nameof(firstAxisLength));
 31202        if (firstRadius < Fixed64.Zero)
 1203            throw new ArgumentOutOfRangeException(nameof(firstRadius));
 30204        ValidateCenteredAxis(
 30205            secondAxisDirection,
 30206            secondAxisLength,
 30207            nameof(secondAxisDirection),
 30208            nameof(secondAxisLength));
 30209        if (secondRadius < Fixed64.Zero)
 1210            throw new ArgumentOutOfRangeException(nameof(secondRadius));
 29211        if (!fallbackNormal.IsNormalized())
 1212            throw new ArgumentException("Fallback normal must be normalized.", nameof(fallbackNormal));
 213
 28214        return WideFiniteAxisIntersection.TryGetCenteredCapsulesContact(
 28215            firstCenter,
 28216            firstAnchorRotation,
 28217            firstAxisDirection,
 28218            firstAxisLength,
 28219            firstRadius,
 28220            secondCenter,
 28221            secondAnchorRotation,
 28222            secondAxisDirection,
 28223            secondAxisLength,
 28224            secondRadius,
 28225            fallbackNormal,
 28226            out contact);
 227    }
 228
 229    /// <summary>
 230    /// Attempts to materialize one endpoint of a conceptual centered finite
 231    /// axis from its normalized direction and full length.
 232    /// </summary>
 233    /// <remarks>
 234    /// The endpoint is rounded only after combining its center and half-length
 235    /// contribution. Failure is atomic.
 236    /// </remarks>
 237    public static bool TryGetCenteredAxisEndpoint(
 238        Vector2d center,
 239        Vector2d axisDirection,
 240        Fixed64 axisLength,
 241        bool positive,
 242        out Vector2d endpoint)
 243    {
 3244        ValidateCenteredAxis(axisDirection, axisLength);
 2245        return WideFiniteAxisIntersection.TryGetCenteredAxisEndpoint(
 2246            center,
 2247            axisDirection,
 2248            axisLength,
 2249            positive,
 2250            out endpoint);
 251    }
 252
 253    /// <summary>
 254    /// Attempts to materialize the support point of a conceptual centered
 255    /// capsule in a world-space direction.
 256    /// </summary>
 257    /// <remarks>
 258    /// The direction need not be normalized. A zero direction and an exact
 259    /// axial tie select the capsule center along the tied axis.
 260    /// </remarks>
 261    public static bool TryGetCenteredCapsuleSupport(
 262        Vector2d center,
 263        Vector2d axisDirection,
 264        Fixed64 axisLength,
 265        Fixed64 radius,
 266        Vector2d direction,
 267        out Vector2d support)
 268    {
 4269        ValidateCenteredAxis(axisDirection, axisLength);
 4270        if (radius < Fixed64.Zero)
 1271            throw new ArgumentOutOfRangeException(nameof(radius));
 272
 3273        return WideFiniteAxisIntersection.TryGetCenteredCapsuleSupport(
 3274            center,
 3275            axisDirection,
 3276            axisLength,
 3277            radius,
 3278            direction,
 3279            out support);
 280    }
 281
 282    /// <summary>
 283    /// Returns the support anchor of a conceptual centered capsule without
 284    /// combining its axial and radial feature components.
 285    /// </summary>
 286    /// <remarks>
 287    /// The direction need not be normalized. A zero direction and an exact
 288    /// axial tie select the axis center.
 289    /// </remarks>
 290    public static FixedPointAnchor2d GetCenteredCapsuleSupportAnchor(
 291        Vector2d center,
 292        Fixed64 frameRotation,
 293        Vector2d localAxisDirection,
 294        Fixed64 axisLength,
 295        Fixed64 radius,
 296        Vector2d localDirection)
 297    {
 83298        ValidateCenteredAxis(localAxisDirection, axisLength);
 82299        if (radius < Fixed64.Zero)
 1300            throw new ArgumentOutOfRangeException(nameof(radius));
 301
 81302        return WideFiniteAxisIntersection.GetCenteredCapsuleSupportAnchor(
 81303            center,
 81304            frameRotation,
 81305            localAxisDirection,
 81306            axisLength,
 81307            radius,
 81308            localDirection);
 309    }
 310
 311    /// <summary>
 312    /// Returns the rounded nonnegative distance from a point to a conceptual
 313    /// centered capsule surface, saturating to <see cref="Fixed64.MaxValue"/>
 314    /// when the distance is not representable.
 315    /// </summary>
 316    /// <remarks>
 317    /// The final value uses round-half-to-even. Points inside or on the capsule
 318    /// return zero.
 319    /// </remarks>
 320    /// <exception cref="ArgumentException">
 321    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 322    /// </exception>
 323    /// <exception cref="ArgumentOutOfRangeException">
 324    /// Thrown when <paramref name="axisLength"/> or <paramref name="radius"/>
 325    /// is negative.
 326    /// </exception>
 327    public static Fixed64 GetDistanceToCenteredCapsule(
 328        Vector2d point,
 329        Vector2d center,
 330        Vector2d axisDirection,
 331        Fixed64 axisLength,
 332        Fixed64 radius)
 333    {
 2334        TryGetDistanceToCenteredCapsule(
 2335            point,
 2336            center,
 2337            axisDirection,
 2338            axisLength,
 2339            radius,
 2340            out Fixed64 distance);
 2341        return distance;
 342    }
 343
 344    /// <summary>
 345    /// Attempts to return the rounded nonnegative distance from a point to a
 346    /// conceptual centered capsule surface.
 347    /// </summary>
 348    /// <remarks>The final value uses round-half-to-even.</remarks>
 349    /// <returns>
 350    /// True when the final distance is representable; otherwise false and
 351    /// <paramref name="distance"/> is <see cref="Fixed64.MaxValue"/>.
 352    /// Points inside or on the capsule return zero.
 353    /// </returns>
 354    /// <exception cref="ArgumentException">
 355    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 356    /// </exception>
 357    /// <exception cref="ArgumentOutOfRangeException">
 358    /// Thrown when <paramref name="axisLength"/> or <paramref name="radius"/>
 359    /// is negative.
 360    /// </exception>
 361    public static bool TryGetDistanceToCenteredCapsule(
 362        Vector2d point,
 363        Vector2d center,
 364        Vector2d axisDirection,
 365        Fixed64 axisLength,
 366        Fixed64 radius,
 367        out Fixed64 distance)
 368    {
 8369        ValidateCenteredAxis(axisDirection, axisLength);
 8370        if (radius < Fixed64.Zero)
 1371            throw new ArgumentOutOfRangeException(nameof(radius));
 372
 7373        return WideFiniteAxisIntersection.TryGetDistanceToCenteredCapsule(
 7374            point,
 7375            center,
 7376            axisDirection,
 7377            axisLength,
 7378            radius,
 7379            out distance);
 380    }
 381
 382    /// <summary>
 383    /// Returns whether a point lies inside or on a conceptual centered capsule.
 384    /// </summary>
 385    /// <exception cref="ArgumentException">
 386    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 387    /// </exception>
 388    /// <exception cref="ArgumentOutOfRangeException">
 389    /// Thrown when <paramref name="axisLength"/> or <paramref name="radius"/>
 390    /// is negative.
 391    /// </exception>
 392    public static bool ContainsPointInCenteredCapsule(
 393        Vector2d point,
 394        Vector2d center,
 395        Vector2d axisDirection,
 396        Fixed64 axisLength,
 397        Fixed64 radius) =>
 7398        ContainsPointInCenteredCapsule(
 7399            point,
 7400            center,
 7401            axisDirection,
 7402            axisLength,
 7403            radius,
 7404            Fixed64.Zero,
 7405            strict: false);
 406
 407    /// <summary>
 408    /// Returns whether a point lies strictly inside or inclusively within a
 409    /// conceptual centered capsule.
 410    /// </summary>
 411    public static bool ContainsPointInCenteredCapsule(
 412        Vector2d point,
 413        Vector2d center,
 414        Vector2d axisDirection,
 415        Fixed64 axisLength,
 416        Fixed64 radius,
 417        bool strict) =>
 3418        ContainsPointInCenteredCapsule(
 3419            point,
 3420            center,
 3421            axisDirection,
 3422            axisLength,
 3423            radius,
 3424            Fixed64.Zero,
 3425            strict);
 426
 427    /// <summary>
 428    /// Returns whether a point lies inside or on a conceptual centered capsule,
 429    /// including a nonnegative radial expansion.
 430    /// </summary>
 431    /// <exception cref="ArgumentException">
 432    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 433    /// </exception>
 434    /// <exception cref="ArgumentOutOfRangeException">
 435    /// Thrown when <paramref name="axisLength"/>, <paramref name="radius"/>,
 436    /// or <paramref name="radiusExpansion"/> is negative.
 437    /// </exception>
 438    public static bool ContainsPointInCenteredCapsule(
 439        Vector2d point,
 440        Vector2d center,
 441        Vector2d axisDirection,
 442        Fixed64 axisLength,
 443        Fixed64 radius,
 444        Fixed64 radiusExpansion) =>
 5445        ContainsPointInCenteredCapsule(
 5446            point,
 5447            center,
 5448            axisDirection,
 5449            axisLength,
 5450            radius,
 5451            radiusExpansion,
 5452            strict: false);
 453
 454    /// <summary>
 455    /// Returns whether a point lies strictly inside or inclusively within a
 456    /// conceptual centered capsule with nonnegative radial expansion.
 457    /// </summary>
 458    public static bool ContainsPointInCenteredCapsule(
 459        Vector2d point,
 460        Vector2d center,
 461        Vector2d axisDirection,
 462        Fixed64 axisLength,
 463        Fixed64 radius,
 464        Fixed64 radiusExpansion,
 465        bool strict)
 466    {
 17467        ValidateCenteredAxis(axisDirection, axisLength);
 17468        if (radius < Fixed64.Zero)
 1469            throw new ArgumentOutOfRangeException(nameof(radius));
 16470        if (radiusExpansion < Fixed64.Zero)
 1471            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 472
 15473        return WideFiniteAxisIntersection.ContainsPointInCenteredCapsule(
 15474            point,
 15475            center,
 15476            axisDirection,
 15477            axisLength,
 15478            radius,
 15479            radiusExpansion,
 15480            strict);
 481    }
 482
 483    /// <summary>
 484    /// Attempts to return the selected point on a conceptual centered capsule
 485    /// surface without narrowing its axis point before applying the radial offset.
 486    /// </summary>
 487    /// <remarks>
 488    /// <paramref name="surfaceDirection"/> must be the nonzero result of
 489    /// <see cref="GetDirectionFromCenteredAxis(Vector2d, Vector2d, Vector2d, Fixed64)"/>,
 490    /// or a caller-selected normalized
 491    /// direction perpendicular to the axis when that method returns zero.
 492    /// </remarks>
 493    /// <returns>
 494    /// True when every final surface coordinate is representable; otherwise
 495    /// false and <paramref name="surfacePoint"/> is zero.
 496    /// </returns>
 497    /// <exception cref="ArgumentException">
 498    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized,
 499    /// or when <paramref name="surfaceDirection"/> is not normalized.
 500    /// </exception>
 501    /// <exception cref="ArgumentOutOfRangeException">
 502    /// Thrown when <paramref name="axisLength"/> or <paramref name="radius"/>
 503    /// is negative.
 504    /// </exception>
 505    public static bool TryGetSurfacePointOnCenteredCapsule(
 506        Vector2d point,
 507        Vector2d center,
 508        Vector2d axisDirection,
 509        Fixed64 axisLength,
 510        Fixed64 radius,
 511        Vector2d surfaceDirection,
 512        out Vector2d surfacePoint)
 513    {
 9514        ValidateCenteredAxis(axisDirection, axisLength);
 9515        if (radius < Fixed64.Zero)
 1516            throw new ArgumentOutOfRangeException(nameof(radius));
 8517        if (!surfaceDirection.IsNormalized())
 1518            throw new ArgumentException("Surface direction must be normalized.", nameof(surfaceDirection));
 519
 7520        return WideFiniteAxisIntersection.TryGetSurfacePointOnCenteredCapsule(
 7521            point,
 7522            center,
 7523            axisDirection,
 7524            axisLength,
 7525            radius,
 7526            surfaceDirection,
 7527            out surfacePoint);
 528    }
 529
 530    /// <summary>
 531    /// Attempts to return the center-relative surface offset on a conceptual
 532    /// centered capsule nearest to a world-space point in the supplied surface
 533    /// direction.
 534    /// </summary>
 535    public static bool TryGetSurfaceOffsetOnCenteredCapsule(
 536        Vector2d point,
 537        Vector2d center,
 538        Vector2d axisDirection,
 539        Fixed64 axisLength,
 540        Fixed64 radius,
 541        Vector2d surfaceDirection,
 542        out Vector2d surfaceOffset)
 543    {
 5544        ValidateCenteredAxis(axisDirection, axisLength);
 5545        if (radius < Fixed64.Zero)
 1546            throw new ArgumentOutOfRangeException(nameof(radius));
 4547        if (!surfaceDirection.IsNormalized())
 548        {
 1549            throw new ArgumentException(
 1550                "Surface direction must be normalized.",
 1551                nameof(surfaceDirection));
 552        }
 553
 3554        return WideFiniteAxisIntersection.TryGetSurfaceOffsetOnCenteredCapsule(
 3555            point,
 3556            center,
 3557            axisDirection,
 3558            axisLength,
 3559            radius,
 3560            surfaceDirection,
 3561            out surfaceOffset);
 562    }
 563
 564    /// <summary>
 565    /// Returns the centered-capsule surface anchor nearest to a world-space
 566    /// point in the supplied normalized surface direction.
 567    /// </summary>
 568    public static FixedPointAnchor2d GetSurfaceAnchorOnCenteredCapsule(
 569        Vector2d point,
 570        Vector2d center,
 571        Fixed64 frameRotation,
 572        Vector2d localAxisDirection,
 573        Fixed64 axisLength,
 574        Fixed64 radius,
 575        Vector2d localSurfaceDirection)
 576    {
 5577        ValidateCenteredAxis(localAxisDirection, axisLength);
 5578        if (radius < Fixed64.Zero)
 1579            throw new ArgumentOutOfRangeException(nameof(radius));
 4580        if (!localSurfaceDirection.IsNormalized())
 581        {
 1582            throw new ArgumentException(
 1583                "Surface direction must be normalized.",
 1584                nameof(localSurfaceDirection));
 585        }
 586
 3587        return WideFiniteAxisIntersection.GetSurfaceAnchorOnCenteredCapsule(
 3588            point,
 3589            center,
 3590            frameRotation,
 3591            localAxisDirection,
 3592            axisLength,
 3593            radius,
 3594            localSurfaceDirection);
 595    }
 596
 597    /// <summary>
 598    /// Returns the normalized direction from the closest point on a conceptual
 599    /// centered finite axis toward <paramref name="point"/>, or zero when the
 600    /// point lies on that axis.
 601    /// </summary>
 602    /// <remarks>
 603    /// The conceptual endpoints are
 604    /// <c>center +/- axisDirection * (axisLength / 2)</c>. They are never
 605    /// constructed or narrowed before the closest-feature decision.
 606    /// </remarks>
 607    /// <exception cref="ArgumentException">
 608    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 609    /// </exception>
 610    /// <exception cref="ArgumentOutOfRangeException">
 611    /// Thrown when <paramref name="axisLength"/> is negative.
 612    /// </exception>
 613    public static Vector2d GetDirectionFromCenteredAxis(
 614        Vector2d point,
 615        Vector2d center,
 616        Vector2d axisDirection,
 617        Fixed64 axisLength)
 618    {
 7619        ValidateCenteredAxis(axisDirection, axisLength);
 620
 5621        return WideFiniteAxisIntersection.GetDirectionFromCenteredAxis(
 5622            point,
 5623            center,
 5624            axisDirection,
 5625            axisLength);
 626    }
 627
 628    /// <summary>
 629    /// Attempts to return the closest points on two conceptual centered finite
 630    /// axes described by normalized directions and full lengths.
 631    /// </summary>
 632    /// <returns>
 633    /// <see langword="true"/> when both final world points are representable;
 634    /// otherwise <see langword="false"/> and both outputs are zero.
 635    /// </returns>
 636    public static bool TryGetClosestPointsBetweenCenteredAxes(
 637        Vector2d firstCenter,
 638        Vector2d firstAxisDirection,
 639        Fixed64 firstAxisLength,
 640        Vector2d secondCenter,
 641        Vector2d secondAxisDirection,
 642        Fixed64 secondAxisLength,
 643        out Vector2d firstPoint,
 644        out Vector2d secondPoint)
 645    {
 4646        ValidateCenteredAxis(
 4647            firstAxisDirection,
 4648            firstAxisLength,
 4649            nameof(firstAxisDirection),
 4650            nameof(firstAxisLength));
 4651        ValidateCenteredAxis(
 4652            secondAxisDirection,
 4653            secondAxisLength,
 4654            nameof(secondAxisDirection),
 4655            nameof(secondAxisLength));
 4656        return WideFiniteAxisIntersection.TryGetClosestPointsBetweenCenteredAxes(
 4657            firstCenter,
 4658            firstAxisDirection,
 4659            firstAxisLength,
 4660            secondCenter,
 4661            secondAxisDirection,
 4662            secondAxisLength,
 4663            out firstPoint,
 4664            out secondPoint);
 665    }
 666
 667    private static void ValidateCenteredAxis(Vector2d axisDirection, Fixed64 axisLength)
 2941668        => ValidateCenteredAxis(
 2941669            axisDirection,
 2941670            axisLength,
 2941671            nameof(axisDirection),
 2941672            nameof(axisLength));
 673
 674    private static void ValidateCenteredAxis(
 675        Vector2d axisDirection,
 676        Fixed64 axisLength,
 677        string directionParameterName,
 678        string lengthParameterName)
 679    {
 22136680        if (!axisDirection.IsNormalized())
 7681            throw new ArgumentException("Axis direction must be normalized.", directionParameterName);
 22129682        if (axisLength < Fixed64.Zero)
 4683            throw new ArgumentOutOfRangeException(lengthParameterName);
 22125684    }
 685
 686    /// <summary>
 687    /// Returns whether a point lies inside or on a centered rotated capsule.
 688    /// </summary>
 689    public static bool ContainsPointInCenteredCapsule(
 690        Vector2d point,
 691        Vector2d center,
 692        Fixed64 frameRotation,
 693        Fixed64 axisLength,
 694        Fixed64 radius) =>
 1695        ContainsPointInCenteredCapsule(
 1696            point,
 1697            center,
 1698            frameRotation,
 1699            axisLength,
 1700            radius,
 1701            Fixed64.Zero,
 1702            strict: false);
 703
 704    /// <summary>
 705    /// Returns whether a point lies inside or on a radially expanded centered
 706    /// rotated capsule.
 707    /// </summary>
 708    public static bool ContainsPointInCenteredCapsule(
 709        Vector2d point,
 710        Vector2d center,
 711        Fixed64 frameRotation,
 712        Fixed64 axisLength,
 713        Fixed64 radius,
 714        Fixed64 radiusExpansion) =>
 1715        ContainsPointInCenteredCapsule(
 1716            point,
 1717            center,
 1718            frameRotation,
 1719            axisLength,
 1720            radius,
 1721            radiusExpansion,
 1722            strict: false);
 723
 724    /// <summary>
 725    /// Returns whether a point lies within a centered capsule whose local
 726    /// positive Y axis is transformed by a scalar rigid-frame rotation.
 727    /// </summary>
 728    public static bool ContainsPointInCenteredCapsule(
 729        Vector2d point,
 730        Vector2d center,
 731        Fixed64 frameRotation,
 732        Fixed64 axisLength,
 733        Fixed64 radius,
 734        Fixed64 radiusExpansion,
 735        bool strict)
 736    {
 4737        ValidateRotatedCapsule(axisLength, radius);
 4738        if (radiusExpansion < Fixed64.Zero)
 1739            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 740
 3741        return WideFiniteAxisIntersection.ContainsPointInCenteredCapsule(
 3742            point,
 3743            center,
 3744            GetRotatedPositiveYAxis(frameRotation),
 3745            axisLength,
 3746            radius,
 3747            radiusExpansion,
 3748            strict);
 749    }
 750
 751    /// <summary>
 752    /// Returns the normalized direction from the closest point on a centered
 753    /// capsule axis expressed by a scalar rigid-frame rotation.
 754    /// </summary>
 755    public static Vector2d GetDirectionFromCenteredAxis(
 756        Vector2d point,
 757        Vector2d center,
 758        Fixed64 frameRotation,
 759        Fixed64 axisLength)
 760    {
 1761        ValidateCenteredAxis(Vector2d.Forward, axisLength);
 1762        return WideFiniteAxisIntersection.GetDirectionFromCenteredAxis(
 1763            point,
 1764            center,
 1765            GetRotatedPositiveYAxis(frameRotation),
 1766            axisLength);
 767    }
 768
 769    /// <summary>
 770    /// Returns the rounded distance from a point to a centered rotated capsule.
 771    /// </summary>
 772    public static Fixed64 GetDistanceToCenteredCapsule(
 773        Vector2d point,
 774        Vector2d center,
 775        Fixed64 frameRotation,
 776        Fixed64 axisLength,
 777        Fixed64 radius)
 778    {
 1779        _ = TryGetDistanceToCenteredCapsule(
 1780            point,
 1781            center,
 1782            frameRotation,
 1783            axisLength,
 1784            radius,
 1785            out Fixed64 distance);
 1786        return distance;
 787    }
 788
 789    /// <summary>
 790    /// Attempts to return the rounded distance from a point to a centered
 791    /// rotated capsule.
 792    /// </summary>
 793    public static bool TryGetDistanceToCenteredCapsule(
 794        Vector2d point,
 795        Vector2d center,
 796        Fixed64 frameRotation,
 797        Fixed64 axisLength,
 798        Fixed64 radius,
 799        out Fixed64 distance)
 800    {
 2801        ValidateRotatedCapsule(axisLength, radius);
 2802        return WideFiniteAxisIntersection.TryGetDistanceToCenteredCapsule(
 2803            point,
 2804            center,
 2805            GetRotatedPositiveYAxis(frameRotation),
 2806            axisLength,
 2807            radius,
 2808            out distance);
 809    }
 810
 811    /// <summary>
 812    /// Attempts to materialize support for a centered rotated capsule.
 813    /// </summary>
 814    public static bool TryGetCenteredCapsuleSupport(
 815        Vector2d center,
 816        Fixed64 frameRotation,
 817        Fixed64 axisLength,
 818        Fixed64 radius,
 819        Vector2d direction,
 820        out Vector2d support)
 821    {
 2822        ValidateRotatedCapsule(axisLength, radius);
 1823        return WideFiniteAxisIntersection.TryGetCenteredCapsuleSupport(
 1824            center,
 1825            GetRotatedPositiveYAxis(frameRotation),
 1826            axisLength,
 1827            radius,
 1828            direction,
 1829            out support);
 830    }
 831
 832    /// <summary>
 833    /// Attempts to materialize the selected surface point of a centered
 834    /// rotated capsule.
 835    /// </summary>
 836    public static bool TryGetSurfacePointOnCenteredCapsule(
 837        Vector2d point,
 838        Vector2d center,
 839        Fixed64 frameRotation,
 840        Fixed64 axisLength,
 841        Fixed64 radius,
 842        Vector2d surfaceDirection,
 843        out Vector2d surfacePoint)
 844    {
 2845        ValidateRotatedCapsule(axisLength, radius);
 2846        if (!surfaceDirection.IsNormalized())
 847        {
 1848            throw new ArgumentException(
 1849                "Surface direction must be normalized.",
 1850                nameof(surfaceDirection));
 851        }
 852
 1853        return WideFiniteAxisIntersection.TryGetSurfacePointOnCenteredCapsule(
 1854            point,
 1855            center,
 1856            GetRotatedPositiveYAxis(frameRotation),
 1857            axisLength,
 1858            radius,
 1859            surfaceDirection,
 1860            out surfacePoint);
 861    }
 862
 863    /// <summary>
 864    /// Attempts to materialize the center-relative selected surface offset of
 865    /// a centered rotated capsule.
 866    /// </summary>
 867    public static bool TryGetSurfaceOffsetOnCenteredCapsule(
 868        Vector2d point,
 869        Vector2d center,
 870        Fixed64 frameRotation,
 871        Fixed64 axisLength,
 872        Fixed64 radius,
 873        Vector2d surfaceDirection,
 874        out Vector2d surfaceOffset)
 875    {
 2876        ValidateRotatedCapsule(axisLength, radius);
 2877        if (!surfaceDirection.IsNormalized())
 878        {
 1879            throw new ArgumentException(
 1880                "Surface direction must be normalized.",
 1881                nameof(surfaceDirection));
 882        }
 883
 1884        return WideFiniteAxisIntersection.TryGetSurfaceOffsetOnCenteredCapsule(
 1885            point,
 1886            center,
 1887            GetRotatedPositiveYAxis(frameRotation),
 1888            axisLength,
 1889            radius,
 1890            surfaceDirection,
 1891            out surfaceOffset);
 892    }
 893
 894    /// <summary>
 895    /// Returns whether two centered capsules expressed by scalar rigid-frame
 896    /// rotations overlap, including exact tangency.
 897    /// </summary>
 898    public static bool DoCenteredCapsulesOverlap(
 899        Vector2d firstCenter,
 900        Fixed64 firstRotation,
 901        Fixed64 firstAxisLength,
 902        Fixed64 firstRadius,
 903        Vector2d secondCenter,
 904        Fixed64 secondRotation,
 905        Fixed64 secondAxisLength,
 906        Fixed64 secondRadius)
 907    {
 2908        ValidateRotatedCapsule(firstAxisLength, firstRadius);
 2909        ValidateRotatedCapsule(secondAxisLength, secondRadius);
 2910        return WideFiniteAxisIntersection.DoCenteredCapsulesOverlap(
 2911            firstCenter,
 2912            GetRotatedPositiveYAxis(firstRotation),
 2913            firstAxisLength,
 2914            firstRadius,
 2915            secondCenter,
 2916            GetRotatedPositiveYAxis(secondRotation),
 2917            secondAxisLength,
 2918            secondRadius);
 919    }
 920
 921    /// <summary>
 922    /// Attempts to build exact anchors between two centered capsules expressed
 923    /// by scalar rigid-frame rotations.
 924    /// </summary>
 925    public static bool TryGetCenteredCapsulesContact(
 926        Vector2d firstCenter,
 927        Fixed64 firstRotation,
 928        Fixed64 firstAxisLength,
 929        Fixed64 firstRadius,
 930        Vector2d secondCenter,
 931        Fixed64 secondRotation,
 932        Fixed64 secondAxisLength,
 933        Fixed64 secondRadius,
 934        Vector2d fallbackNormal,
 935        out FixedContactAnchors2d contact)
 936    {
 2937        ValidateRotatedCapsule(firstAxisLength, firstRadius);
 2938        ValidateRotatedCapsule(secondAxisLength, secondRadius);
 2939        if (!fallbackNormal.IsNormalized())
 940        {
 1941            throw new ArgumentException(
 1942                "Fallback normal must be normalized.",
 1943                nameof(fallbackNormal));
 944        }
 945
 1946        return WideFiniteAxisIntersection.TryGetCenteredCapsulesContact(
 1947            firstCenter,
 1948            firstRotation,
 1949            GetRotatedPositiveYAxis(firstRotation),
 1950            firstAxisLength,
 1951            firstRadius,
 1952            secondCenter,
 1953            secondRotation,
 1954            GetRotatedPositiveYAxis(secondRotation),
 1955            secondAxisLength,
 1956            secondRadius,
 1957            fallbackNormal,
 1958            out contact);
 959    }
 960
 961    /// <summary>
 962    /// Finds the minimum translation that separates a centered rotated capsule
 963    /// from a closed convex polygon represented by origin-relative offsets.
 964    /// </summary>
 965    public static bool TryGetCenteredCapsuleConvexMinimumTranslation(
 966        Vector2d center,
 967        Fixed64 rotation,
 968        Fixed64 axisLength,
 969        Fixed64 radius,
 970        Vector2d convexOrigin,
 971        ReadOnlySpan<Vector2d> convexVertexOffsets,
 972        out Vector2d normal,
 973        out Fixed64 depth)
 974    {
 5975        ValidateRotatedCapsule(axisLength, radius);
 5976        if (convexVertexOffsets.Length < 3)
 977        {
 1978            throw new ArgumentException(
 1979                "A convex polygon requires at least three vertex offsets.",
 1980                nameof(convexVertexOffsets));
 981        }
 982
 4983        return WideCenteredCapsule2dRelations.TryGetMinimumTranslation(
 4984            center,
 4985            GetRotatedPositiveYAxis(rotation),
 4986            axisLength,
 4987            radius,
 4988            convexOrigin,
 4989            convexVertexOffsets,
 4990            out normal,
 4991            out depth);
 992    }
 993
 994    /// <summary>
 995    /// Finds the first distance where a translated centered rotated capsule
 996    /// intersects an endpoint-authored capsule axis.
 997    /// </summary>
 998    public static bool TryGetSweptCenteredCapsuleSegmentFirstDistance(
 999        Vector2d center,
 1000        Fixed64 rotation,
 1001        Fixed64 axisLength,
 1002        Fixed64 radius,
 1003        Vector2d direction,
 1004        Fixed64 maximumDistance,
 1005        FixedSegment2d targetAxis,
 1006        Fixed64 targetRadius,
 1007        out Fixed64 distance,
 1008        out Vector2d normal)
 1009    {
 11010        ValidateSweep(
 11011            Vector2d.Forward,
 11012            axisLength,
 11013            radius,
 11014            direction,
 11015            maximumDistance,
 11016            targetRadius);
 11017        return WideFiniteAxisIntersection.TryGetSweptCenteredCapsuleSegmentFirstDistance(
 11018            center,
 11019            GetRotatedPositiveYAxis(rotation),
 11020            axisLength,
 11021            radius,
 11022            direction,
 11023            maximumDistance,
 11024            targetAxis,
 11025            targetRadius,
 11026            out distance,
 11027            out normal);
 1028    }
 1029
 1030    /// <summary>
 1031    /// Finds the first distance where a translated centered rotated capsule
 1032    /// intersects another centered rotated capsule.
 1033    /// </summary>
 1034    public static bool TryGetSweptCenteredCapsulesFirstDistance(
 1035        Vector2d center,
 1036        Fixed64 rotation,
 1037        Fixed64 axisLength,
 1038        Fixed64 radius,
 1039        Vector2d direction,
 1040        Fixed64 maximumDistance,
 1041        Vector2d targetCenter,
 1042        Fixed64 targetRotation,
 1043        Fixed64 targetAxisLength,
 1044        Fixed64 targetRadius,
 1045        out Fixed64 distance,
 1046        out Vector2d normal)
 1047    {
 11048        ValidateSweep(
 11049            Vector2d.Forward,
 11050            axisLength,
 11051            radius,
 11052            direction,
 11053            maximumDistance,
 11054            targetRadius);
 11055        ValidateCenteredAxis(Vector2d.Forward, targetAxisLength);
 11056        return WideFiniteAxisIntersection.TryGetSweptCenteredCapsulesFirstDistance(
 11057            center,
 11058            GetRotatedPositiveYAxis(rotation),
 11059            axisLength,
 11060            radius,
 11061            direction,
 11062            maximumDistance,
 11063            targetCenter,
 11064            GetRotatedPositiveYAxis(targetRotation),
 11065            targetAxisLength,
 11066            targetRadius,
 11067            out distance,
 11068            out normal);
 1069    }
 1070
 1071    /// <summary>
 1072    /// Finds the physical-distance interval where this segment intersects a
 1073    /// centered rotated capsule.
 1074    /// </summary>
 1075    public readonly bool TryGetCapsuleIntersectionDistanceInterval(
 1076        Vector2d center,
 1077        Fixed64 rotation,
 1078        Fixed64 axisLength,
 1079        Fixed64 radius,
 1080        Fixed64 radiusExpansion,
 1081        Fixed64 totalDistance,
 1082        out Fixed64 entryDistance,
 1083        out Fixed64 exitDistance,
 1084        out bool startContained,
 1085        out bool endContainedStrict)
 1086    {
 21087        ValidateTotalDistance(totalDistance);
 21088        ValidateRotatedCapsule(axisLength, radius);
 21089        if (radiusExpansion < Fixed64.Zero)
 11090            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 1091
 11092        return WideFiniteAxisIntersection.TryGetCapsuleDistanceInterval(
 11093            this,
 11094            center,
 11095            GetRotatedPositiveYAxis(rotation),
 11096            axisLength,
 11097            radius,
 11098            radiusExpansion,
 11099            totalDistance,
 11100            out entryDistance,
 11101            out exitDistance,
 11102            out startContained,
 11103            out endContainedStrict);
 1104    }
 1105
 1106    private static Vector2d GetRotatedPositiveYAxis(Fixed64 rotation) =>
 331107        new(-FixedMath.Sin(rotation), FixedMath.Cos(rotation));
 1108
 1109    private static void ValidateRotatedCapsule(
 1110        Fixed64 axisLength,
 1111        Fixed64 radius)
 1112    {
 321113        ValidateCenteredAxis(Vector2d.Forward, axisLength);
 311114        if (radius < Fixed64.Zero)
 11115            throw new ArgumentOutOfRangeException(nameof(radius));
 301116    }
 1117}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Primitives/Segments/FixedSegment2d.ConvexQueries.cs

#LineLine coverage
 1//=======================================================================
 2// FixedSegment2d.ConvexQueries.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 centered-capsule versus convex-polygon contact and sweep queries.
 14/// </content>
 15public partial struct FixedSegment2d
 16{
 17    /// <summary>
 18    /// Returns whether a centered capsule expressed by a scalar rigid-frame
 19    /// rotation strictly penetrates a rotated convex polygon.
 20    /// </summary>
 21    /// <remarks>
 22    /// The capsule's local positive Y axis uses the authored sine and cosine
 23    /// coefficients without renormalizing the derived world axis. Exact touch
 24    /// is excluded; positive penetration survives contact-depth rounding to zero.
 25    /// </remarks>
 26    public static bool DoesCenteredCapsulePenetrateConvex(
 27        Vector2d center,
 28        Fixed64 rotation,
 29        Fixed64 axisLength,
 30        Fixed64 radius,
 31        Vector2d convexOrigin,
 32        Fixed64 convexRotation,
 33        ReadOnlySpan<Vector2d> convexVertexOffsets) =>
 634        DoesCenteredCapsulePenetrateConvex(
 635            center, GetRotatedPositiveYAxis(rotation), axisLength, radius,
 636            convexOrigin, convexRotation, convexVertexOffsets);
 37
 38    /// <summary>
 39    /// Returns whether a conceptual centered capsule has strictly positive
 40    /// penetration into a rotated convex polygon, excluding exact tangency.
 41    /// </summary>
 42    /// <remarks>
 43    /// Offsets must describe a convex polygon in boundary order. The world-space
 44    /// capsule axis and rotated polygon vertices retain their exact authored
 45    /// components through classification; no normal or contact depth is rounded.
 46    /// Repeated vertices retain the finite closed hull: collinear offsets form
 47    /// a segment, and coincident offsets form a point. A point target strictly
 48    /// penetrates only when its minimum separating translation is positive.
 49    /// For a nondegenerate polygon, a zero-radius point or finite axis must enter
 50    /// its interior. A noncollapsed collinear boundary instead uses positive
 51    /// minimum separating translation: a transverse axis crossing can penetrate,
 52    /// while a point on the line or an axis running along it cannot.
 53    /// </remarks>
 54    public static bool DoesCenteredCapsulePenetrateConvex(
 55        Vector2d center,
 56        Vector2d axisDirection,
 57        Fixed64 axisLength,
 58        Fixed64 radius,
 59        Vector2d convexOrigin,
 60        Fixed64 convexRotation,
 61        ReadOnlySpan<Vector2d> convexVertexOffsets)
 62    {
 130963        ValidateCenteredAxis(axisDirection, axisLength);
 130964        if (radius < Fixed64.Zero)
 165            throw new ArgumentOutOfRangeException(nameof(radius));
 130866        if (convexVertexOffsets.Length < 3)
 67        {
 168            throw new ArgumentException(
 169                "A convex polygon requires at least three vertex offsets.",
 170                nameof(convexVertexOffsets));
 71        }
 72
 130773        return WideCenteredCapsule2dRelations.DoesCapsuleOverlapConvex(
 130774            center, axisDirection, axisLength, radius,
 130775            convexOrigin, convexRotation, convexVertexOffsets);
 76    }
 77
 78    /// <summary>
 79    /// Finds the minimum translation that separates a conceptual centered
 80    /// capsule from a closed convex polygon represented by an origin and
 81    /// origin-relative vertex offsets.
 82    /// </summary>
 83    /// <remarks>
 84    /// Offsets must be supplied in boundary order. Exact depth ties retain the
 85    /// first authored edge axis, and exact direction ties retain the first
 86    /// authored vertex. Neither shape's conceptual world vertices need to be
 87    /// representable. Classification and depth ordering retain unnormalized
 88    /// axes and exact radial extents. The selected normal is then normalized
 89    /// to representable components, and depth rounds once to nearest-even.
 90    /// Depths outside the scalar domain saturate to <see cref="Fixed64.MaxValue"/>.
 91    /// </remarks>
 92    /// <returns>
 93    /// <see langword="true"/> when the shapes overlap, including tangency;
 94    /// otherwise <see langword="false"/> and both outputs are zero.
 95    /// </returns>
 96    public static bool TryGetCenteredCapsuleConvexMinimumTranslation(
 97        Vector2d center,
 98        Vector2d axisDirection,
 99        Fixed64 axisLength,
 100        Fixed64 radius,
 101        Vector2d convexOrigin,
 102        ReadOnlySpan<Vector2d> convexVertexOffsets,
 103        out Vector2d normal,
 104        out Fixed64 depth)
 105    {
 23106        ValidateCenteredAxis(axisDirection, axisLength);
 22107        if (radius < Fixed64.Zero)
 1108            throw new ArgumentOutOfRangeException(nameof(radius));
 21109        if (convexVertexOffsets.Length < 3)
 1110            throw new ArgumentException(
 1111                "A convex polygon requires at least three vertex offsets.",
 1112                nameof(convexVertexOffsets));
 113
 20114        return WideCenteredCapsule2dRelations.TryGetMinimumTranslation(
 20115            center,
 20116            axisDirection,
 20117            axisLength,
 20118            radius,
 20119            convexOrigin,
 20120            convexVertexOffsets,
 20121            out normal,
 20122            out depth);
 123    }
 124
 125    /// <summary>
 126    /// Finds the minimum translation that separates a conceptual centered
 127    /// capsule from a rotated closed convex polygon.
 128    /// </summary>
 129    public static bool TryGetCenteredCapsuleConvexMinimumTranslation(
 130        Vector2d center,
 131        Vector2d axisDirection,
 132        Fixed64 axisLength,
 133        Fixed64 radius,
 134        Vector2d convexOrigin,
 135        Fixed64 convexRotation,
 136        ReadOnlySpan<Vector2d> convexVertexOffsets,
 137        out Vector2d normal,
 138        out Fixed64 depth)
 139    {
 1292140        ValidateCenteredAxis(axisDirection, axisLength);
 1292141        if (radius < Fixed64.Zero)
 1142            throw new ArgumentOutOfRangeException(nameof(radius));
 1291143        if (convexVertexOffsets.Length < 3)
 144        {
 1145            throw new ArgumentException(
 1146                "A convex polygon requires at least three vertex offsets.",
 1147                nameof(convexVertexOffsets));
 148        }
 149
 1290150        return WideCenteredCapsule2dRelations.TryGetMinimumTranslation(
 1290151            center,
 1290152            axisDirection,
 1290153            axisLength,
 1290154            radius,
 1290155            convexOrigin,
 1290156            convexRotation,
 1290157            convexVertexOffsets,
 1290158            out normal,
 1290159            out depth);
 160    }
 161
 162    /// <summary>
 163    /// Attempts to build contact anchors between a conceptual centered capsule
 164    /// and a rotated closed convex polygon.
 165    /// </summary>
 166    /// <remarks>
 167    /// <paramref name="localCapsuleAxisDirection"/> is expressed in the
 168    /// capsule frame. Returned capsule anchors retain their axial and radial
 169    /// feature terms separately. Closed-contact classification precedes normal
 170    /// and depth rounding, so exact tangency returns true with zero depth.
 171    /// A single side contact projects the opposing polygon feature onto the
 172    /// capsule's finite side before rounding its axial parameter.
 173    /// </remarks>
 174    public static bool TryGetCenteredCapsuleConvexContacts(
 175        Vector2d capsuleCenter,
 176        Fixed64 capsuleRotation,
 177        Vector2d localCapsuleAxisDirection,
 178        Fixed64 capsuleAxisLength,
 179        Fixed64 capsuleRadius,
 180        Vector2d convexOrigin,
 181        Fixed64 convexRotation,
 182        ReadOnlySpan<Vector2d> convexVertexOffsets,
 183        Span<FixedPointAnchor2d> capsuleContacts,
 184        Span<FixedPointAnchor2d> convexContacts,
 185        out int contactCount,
 186        out Vector2d normal,
 187        out Fixed64 depth,
 188        out bool depthIsClamped)
 189    {
 111190        ValidateCenteredAxis(localCapsuleAxisDirection, capsuleAxisLength);
 111191        if (capsuleRadius < Fixed64.Zero)
 1192            throw new ArgumentOutOfRangeException(nameof(capsuleRadius));
 110193        if (convexVertexOffsets.Length < 3)
 194        {
 1195            throw new ArgumentException(
 1196                "A convex polygon requires at least three vertex offsets.",
 1197                nameof(convexVertexOffsets));
 198        }
 109199        if (capsuleContacts.Length < 2)
 200        {
 1201            throw new ArgumentException(
 1202                "Contact output requires capacity for two anchors.",
 1203                nameof(capsuleContacts));
 204        }
 108205        if (convexContacts.Length < 2)
 206        {
 1207            throw new ArgumentException(
 1208                "Contact output requires capacity for two anchors.",
 1209                nameof(convexContacts));
 210        }
 211
 107212        return WideCenteredCapsule2dRelations.TryGetContacts(
 107213            capsuleCenter,
 107214            capsuleRotation,
 107215            localCapsuleAxisDirection,
 107216            capsuleAxisLength,
 107217            capsuleRadius,
 107218            convexOrigin,
 107219            convexRotation,
 107220            convexVertexOffsets,
 107221            capsuleContacts,
 107222            convexContacts,
 107223            out contactCount,
 107224            out normal,
 107225            out depth,
 107226            out depthIsClamped);
 227    }
 228
 229    /// <summary>
 230    /// Finds the first distance where a translated conceptual centered
 231    /// capsule intersects an endpoint-authored capsule axis.
 232    /// </summary>
 233    public static bool TryGetSweptCenteredCapsuleSegmentFirstDistance(
 234        Vector2d center,
 235        Vector2d axisDirection,
 236        Fixed64 axisLength,
 237        Fixed64 radius,
 238        Vector2d direction,
 239        Fixed64 maximumDistance,
 240        FixedSegment2d targetAxis,
 241        Fixed64 targetRadius,
 242        out Fixed64 distance,
 243        out Vector2d normal)
 244    {
 8245        ValidateSweep(
 8246            axisDirection,
 8247            axisLength,
 8248            radius,
 8249            direction,
 8250            maximumDistance,
 8251            targetRadius);
 5252        return WideFiniteAxisIntersection.TryGetSweptCenteredCapsuleSegmentFirstDistance(
 5253            center,
 5254            axisDirection,
 5255            axisLength,
 5256            radius,
 5257            direction,
 5258            maximumDistance,
 5259            targetAxis,
 5260            targetRadius,
 5261            out distance,
 5262            out normal);
 263    }
 264
 265    /// <summary>
 266    /// Finds the first distance where a translated conceptual centered
 267    /// capsule intersects another conceptual centered capsule.
 268    /// </summary>
 269    public static bool TryGetSweptCenteredCapsulesFirstDistance(
 270        Vector2d center,
 271        Vector2d axisDirection,
 272        Fixed64 axisLength,
 273        Fixed64 radius,
 274        Vector2d direction,
 275        Fixed64 maximumDistance,
 276        Vector2d targetCenter,
 277        Vector2d targetAxisDirection,
 278        Fixed64 targetAxisLength,
 279        Fixed64 targetRadius,
 280        out Fixed64 distance,
 281        out Vector2d normal)
 282    {
 11283        ValidateSweep(
 11284            axisDirection,
 11285            axisLength,
 11286            radius,
 11287            direction,
 11288            maximumDistance,
 11289            targetRadius);
 10290        ValidateCenteredAxis(
 10291            targetAxisDirection,
 10292            targetAxisLength,
 10293            nameof(targetAxisDirection),
 10294            nameof(targetAxisLength));
 10295        return WideFiniteAxisIntersection.TryGetSweptCenteredCapsulesFirstDistance(
 10296            center,
 10297            axisDirection,
 10298            axisLength,
 10299            radius,
 10300            direction,
 10301            maximumDistance,
 10302            targetCenter,
 10303            targetAxisDirection,
 10304            targetAxisLength,
 10305            targetRadius,
 10306            out distance,
 10307            out normal);
 308    }
 309
 310    private static void ValidateSweep(
 311        Vector2d axisDirection,
 312        Fixed64 axisLength,
 313        Fixed64 radius,
 314        Vector2d direction,
 315        Fixed64 maximumDistance,
 316        Fixed64 targetRadius)
 317    {
 21318        ValidateCenteredAxis(axisDirection, axisLength);
 21319        if (radius < Fixed64.Zero)
 1320            throw new ArgumentOutOfRangeException(nameof(radius));
 20321        if (!direction.IsNormalized())
 1322            throw new ArgumentException("Sweep direction must be normalized.", nameof(direction));
 19323        if (maximumDistance < Fixed64.Zero)
 1324            throw new ArgumentOutOfRangeException(nameof(maximumDistance));
 18325        if (targetRadius < Fixed64.Zero)
 1326            throw new ArgumentOutOfRangeException(nameof(targetRadius));
 17327    }
 328}

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

#LineLine coverage
 1//=======================================================================
 2// FixedSegment2d.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 two-dimensional fixed-point space.
 17/// </summary>
 18[Serializable]
 19[MemoryPackable]
 20public partial struct FixedSegment2d : IEquatable<FixedSegment2d>
 21{
 22    #region Fields
 23
 24    /// <summary>
 25    /// The start point of the segment.
 26    /// </summary>
 27    [JsonInclude]
 28    [MemoryPackOrder(0)]
 29    public Vector2d Start;
 30
 31    /// <summary>
 32    /// The end point of the segment.
 33    /// </summary>
 34    [JsonInclude]
 35    [MemoryPackOrder(1)]
 36    public Vector2d 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 FixedSegment2d(Vector2d start, Vector2d end)
 48    {
 855449        Start = start;
 855450        End = end;
 855451    }
 52
 53    #endregion
 54
 55    #region Properties
 56
 57    /// <summary>
 58    /// The vector from <see cref="Start"/> to <see cref="End"/>.
 59    /// </summary>
 60    [JsonIgnore]
 61    [MemoryPackIgnore]
 62    public Vector2d Delta
 63    {
 64        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1065        get => End - Start;
 66    }
 67
 68    /// <summary>
 69    /// The segment length.
 70    /// </summary>
 71    [JsonIgnore]
 72    [MemoryPackIgnore]
 73    public Fixed64 Length
 74    {
 75        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 276        get => Delta.Magnitude;
 77    }
 78
 79    /// <summary>
 80    /// The squared segment length.
 81    /// </summary>
 82    [JsonIgnore]
 83    [MemoryPackIgnore]
 84    public Fixed64 LengthSquared
 85    {
 86        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 287        get => Delta.MagnitudeSquared;
 88    }
 89
 90    /// <summary>
 91    /// The normalized axis-aligned area that contains this segment.
 92    /// </summary>
 93    [JsonIgnore]
 94    [MemoryPackIgnore]
 95    public FixedBoundArea Bounds
 96    {
 97        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 398        get => FixedBoundArea.FromMinMax(Start, End);
 99    }
 100
 101    #endregion
 102
 103    #region Spatial Queries
 104
 105    /// <summary>
 106    /// Finds the closest point on this finite segment to the supplied point.
 107    /// </summary>
 108    /// <remarks>
 109    /// Zero-length segments deterministically return <see cref="Start"/>.
 110    /// </remarks>
 111    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 86112    public Vector2d ClosestPoint(Vector2d point) => Vector2d.ClosestPointOnLineSegment(point, Start, End);
 113
 114    /// <summary>
 115    /// Computes the squared distance from the supplied point to this finite segment.
 116    /// </summary>
 117    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 118    public Fixed64 DistanceSquared(Vector2d point)
 119    {
 30120        return Vector2d.DistanceSquared(point, ClosestPoint(point));
 121    }
 122
 123    /// <summary>
 124    /// Determines whether the exact minimum distance to another finite segment
 125    /// is at least the supplied threshold.
 126    /// </summary>
 127    /// <remarks>
 128    /// The comparison uses wide rational distances and does not materialize a
 129    /// rounded closest point or square root. Equality is accepted.
 130    /// </remarks>
 131    /// <exception cref="ArgumentOutOfRangeException">
 132    /// Thrown when <paramref name="minimumDistance"/> is negative.
 133    /// </exception>
 134    public readonly bool IsDistanceAtLeast(
 135        FixedSegment2d other,
 136        Fixed64 minimumDistance)
 137    {
 571138        if (minimumDistance < Fixed64.Zero)
 1139            throw new ArgumentOutOfRangeException(nameof(minimumDistance));
 570140        if (minimumDistance == Fixed64.Zero)
 1141            return true;
 569142        if (TryGetUniqueIntersection(other, out _, out _))
 2143            return false;
 144
 567145        return WideFiniteAxisIntersection.AreSegmentEndpointDistancesAtLeast(
 567146            this,
 567147            other,
 567148            minimumDistance);
 149    }
 150
 151    /// <summary>
 152    /// Finds the closed parameter interval where this segment intersects a capsule.
 153    /// </summary>
 154    /// <remarks>
 155    /// The capsule is described by its finite center-line segment and radius.
 156    /// Returned parameters are clamped to [0, 1]. A zero-length capsule axis is
 157    /// treated as a circle.
 158    /// </remarks>
 159    /// <exception cref="ArgumentOutOfRangeException">
 160    /// Thrown when <paramref name="radius"/> is negative.
 161    /// </exception>
 162    public readonly bool TryGetCapsuleIntersectionInterval(
 163        FixedSegment2d capsuleAxis,
 164        Fixed64 radius,
 165        out Fixed64 entryParameter,
 166        out Fixed64 exitParameter) =>
 519167        TryGetCapsuleIntersectionInterval(
 519168            capsuleAxis,
 519169            radius,
 519170            Fixed64.Zero,
 519171            out entryParameter,
 519172            out exitParameter);
 173
 174    /// <summary>
 175    /// Finds a conservative parameter enclosure for the closed interval where
 176    /// this segment intersects an endpoint-authored capsule.
 177    /// </summary>
 178    /// <remarks>
 179    /// The exact finite-axis solve rounds its representable interval bounds to
 180    /// nearest. This method expands each returned bound outward by one raw
 181    /// quantum, clamped to [0, 1], so the mathematical interval is enclosed.
 182    /// A zero-length capsule axis is treated as a circle.
 183    /// </remarks>
 184    /// <exception cref="ArgumentOutOfRangeException">
 185    /// Thrown when <paramref name="radius"/> is negative.
 186    /// </exception>
 187    public readonly bool TryGetCapsuleIntersectionParameterEnclosure(
 188        FixedSegment2d capsuleAxis,
 189        Fixed64 radius,
 190        out Fixed64 entryParameter,
 191        out Fixed64 exitParameter)
 192    {
 516193        if (!TryGetCapsuleIntersectionInterval(
 516194                capsuleAxis,
 516195                radius,
 516196                out entryParameter,
 516197                out exitParameter))
 198        {
 1199            return false;
 200        }
 201
 514202        if (entryParameter > Fixed64.Zero)
 513203            entryParameter = Fixed64.FromRaw(entryParameter.m_rawValue - 1L);
 514204        if (exitParameter < Fixed64.One)
 513205            exitParameter = Fixed64.FromRaw(exitParameter.m_rawValue + 1L);
 514206        return true;
 207    }
 208
 209    /// <summary>
 210    /// Finds the closed parameter interval where this segment intersects a radially
 211    /// expanded capsule.
 212    /// </summary>
 213    /// <remarks>
 214    /// The authored radius and sweep expansion remain separate until the exact
 215    /// finite-axis solve. Returned parameters are clamped to [0, 1]. A zero-length
 216    /// capsule axis is treated as a circle.
 217    /// </remarks>
 218    /// <exception cref="ArgumentOutOfRangeException">
 219    /// Thrown when <paramref name="radius"/> or <paramref name="radiusExpansion"/>
 220    /// is negative.
 221    /// </exception>
 222    public readonly bool TryGetCapsuleIntersectionInterval(
 223        FixedSegment2d capsuleAxis,
 224        Fixed64 radius,
 225        Fixed64 radiusExpansion,
 226        out Fixed64 entryParameter,
 227        out Fixed64 exitParameter) =>
 521228        TryGetCapsuleIntersectionInterval(
 521229            capsuleAxis,
 521230            radius,
 521231            radiusExpansion,
 521232            out entryParameter,
 521233            out exitParameter,
 521234            out _,
 521235            out _);
 236
 237    /// <summary>
 238    /// Finds the closed parameter interval where this segment intersects a capsule
 239    /// and reports exact endpoint containment.
 240    /// </summary>
 241    /// <remarks>
 242    /// <paramref name="startContained"/> is inclusive of the capsule boundary.
 243    /// <paramref name="endContainedStrict"/> is true only for the mathematical
 244    /// interior. Both classifications use the wide solve inputs rather than rounded
 245    /// parameters or reconstructed points. A zero-length capsule axis is treated as
 246    /// a circle.
 247    /// </remarks>
 248    /// <exception cref="ArgumentOutOfRangeException">
 249    /// Thrown when <paramref name="radius"/> or <paramref name="radiusExpansion"/>
 250    /// is negative.
 251    /// </exception>
 252    public readonly bool TryGetCapsuleIntersectionInterval(
 253        FixedSegment2d capsuleAxis,
 254        Fixed64 radius,
 255        Fixed64 radiusExpansion,
 256        out Fixed64 entryParameter,
 257        out Fixed64 exitParameter,
 258        out bool startContained,
 259        out bool endContainedStrict)
 260    {
 533261        if (radius < Fixed64.Zero)
 2262            throw new ArgumentOutOfRangeException(nameof(radius));
 531263        if (radiusExpansion < Fixed64.Zero)
 1264            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 265
 530266        return WideFiniteAxisIntersection.TryGetCapsuleInterval(
 530267            this,
 530268            capsuleAxis,
 530269            radius,
 530270            radiusExpansion,
 530271            out entryParameter,
 530272            out exitParameter,
 530273            out startContained,
 530274            out endContainedStrict);
 275    }
 276
 277    /// <summary>
 278    /// Finds the closed parameter interval where this segment intersects a
 279    /// centered capsule.
 280    /// </summary>
 281    /// <exception cref="ArgumentException">
 282    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 283    /// </exception>
 284    /// <exception cref="ArgumentOutOfRangeException">
 285    /// Thrown when <paramref name="axisLength"/> or
 286    /// <paramref name="radius"/> is negative.
 287    /// </exception>
 288    public readonly bool TryGetCapsuleIntersectionInterval(
 289        Vector2d center,
 290        Vector2d axisDirection,
 291        Fixed64 axisLength,
 292        Fixed64 radius,
 293        out Fixed64 entryParameter,
 294        out Fixed64 exitParameter) =>
 142295        TryGetCapsuleIntersectionInterval(
 142296            center,
 142297            axisDirection,
 142298            axisLength,
 142299            radius,
 142300            Fixed64.Zero,
 142301            out entryParameter,
 142302            out exitParameter);
 303
 304    /// <summary>
 305    /// Finds the closed parameter interval where this segment intersects a
 306    /// centered, radially expanded capsule.
 307    /// </summary>
 308    /// <exception cref="ArgumentException">
 309    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 310    /// </exception>
 311    /// <exception cref="ArgumentOutOfRangeException">
 312    /// Thrown when <paramref name="axisLength"/>,
 313    /// <paramref name="radius"/> or <paramref name="radiusExpansion"/> is
 314    /// negative.
 315    /// </exception>
 316    public readonly bool TryGetCapsuleIntersectionInterval(
 317        Vector2d center,
 318        Vector2d axisDirection,
 319        Fixed64 axisLength,
 320        Fixed64 radius,
 321        Fixed64 radiusExpansion,
 322        out Fixed64 entryParameter,
 323        out Fixed64 exitParameter) =>
 144324        TryGetCapsuleIntersectionInterval(
 144325            center,
 144326            axisDirection,
 144327            axisLength,
 144328            radius,
 144329            radiusExpansion,
 144330            out entryParameter,
 144331            out exitParameter,
 144332            out _,
 144333            out _);
 334
 335    /// <summary>
 336    /// Finds the closed parameter interval where this segment intersects a
 337    /// centered, radially expanded capsule and reports exact endpoint
 338    /// containment.
 339    /// </summary>
 340    /// <remarks>
 341    /// The normalized axis defines the conceptual center-line endpoints as
 342    /// <c>center +/- axisDirection * (axisLength / 2)</c> without constructing or
 343    /// narrowing either endpoint. <paramref name="startContained"/> includes the
 344    /// boundary; <paramref name="endContainedStrict"/> excludes it.
 345    /// </remarks>
 346    /// <exception cref="ArgumentException">
 347    /// Thrown when <paramref name="axisDirection"/> is zero or not normalized.
 348    /// </exception>
 349    /// <exception cref="ArgumentOutOfRangeException">
 350    /// Thrown when <paramref name="axisLength"/>,
 351    /// <paramref name="radius"/> or <paramref name="radiusExpansion"/> is
 352    /// negative.
 353    /// </exception>
 354    public readonly bool TryGetCapsuleIntersectionInterval(
 355        Vector2d center,
 356        Vector2d axisDirection,
 357        Fixed64 axisLength,
 358        Fixed64 radius,
 359        Fixed64 radiusExpansion,
 360        out Fixed64 entryParameter,
 361        out Fixed64 exitParameter,
 362        out bool startContained,
 363        out bool endContainedStrict)
 364    {
 147365        if (!axisDirection.IsNormalized())
 1366            throw new ArgumentException("Capsule axis direction must be normalized.", nameof(axisDirection));
 146367        if (axisLength < Fixed64.Zero)
 1368            throw new ArgumentOutOfRangeException(nameof(axisLength));
 145369        if (radius < Fixed64.Zero)
 1370            throw new ArgumentOutOfRangeException(nameof(radius));
 144371        if (radiusExpansion < Fixed64.Zero)
 1372            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 373
 143374        return WideFiniteAxisIntersection.TryGetCapsuleInterval(
 143375            this,
 143376            center,
 143377            axisDirection,
 143378            axisLength,
 143379            radius,
 143380            radiusExpansion,
 143381            out entryParameter,
 143382            out exitParameter,
 143383            out startContained,
 143384            out endContainedStrict);
 385    }
 386
 387    /// <summary>
 388    /// Attempts to find the unique intersection point shared by this segment and another segment.
 389    /// </summary>
 390    /// <remarks>
 391    /// Closed endpoint touches and coincident point segments have one unique intersection.
 392    /// Collinear segments with a positive-length overlap do not.
 393    /// </remarks>
 394    public readonly bool TryGetUniqueIntersection(
 395        FixedSegment2d other,
 396        out Fixed64 thisParameter)
 397    {
 281398        return TryGetUniqueIntersection(other, out thisParameter, out _);
 399    }
 400
 401    /// <summary>
 402    /// Attempts to enclose the unique intersection parameter on this segment.
 403    /// </summary>
 404    /// <remarks>
 405    /// The exact rational intersection is enclosed by expanding the nearest
 406    /// representable parameter by one raw unit and clamping to [0, 1]. Collinear
 407    /// positive-length overlaps retain the unique-intersection failure behavior.
 408    /// </remarks>
 409    public readonly bool TryGetUniqueIntersectionParameterEnclosure(
 410        FixedSegment2d other,
 411        out Fixed64 nearestParameter,
 412        out Fixed64 lowerParameter,
 413        out Fixed64 upperParameter)
 414    {
 260415        if (!TryGetUniqueIntersection(other, out nearestParameter))
 416        {
 1417            nearestParameter = default;
 1418            lowerParameter = default;
 1419            upperParameter = default;
 1420            return false;
 421        }
 422
 259423        lowerParameter = nearestParameter > Fixed64.Zero
 259424            ? Fixed64.FromRaw(nearestParameter.m_rawValue - 1L)
 259425            : Fixed64.Zero;
 259426        upperParameter = nearestParameter < Fixed64.One
 259427            ? Fixed64.FromRaw(nearestParameter.m_rawValue + 1L)
 259428            : Fixed64.One;
 259429        return true;
 430    }
 431
 432    /// <summary>
 433    /// Returns the closest finite points on this segment and another segment.
 434    /// </summary>
 435    /// <remarks>
 436    /// Exact shared endpoints are returned in this-start, this-end, other-start,
 437    /// other-end order before parameterized interior intersections. Remaining endpoint
 438    /// projections use the same order, and exact distance ties keep the first candidate.
 439    /// </remarks>
 440    public readonly (Vector2d ThisPoint, Vector2d OtherPoint) GetClosestPoints(FixedSegment2d other)
 441    {
 15442        if (PointOnSegment(Start, other))
 2443            return (Start, Start);
 13444        if (PointOnSegment(End, other))
 2445            return (End, End);
 11446        if (PointOnSegment(other.Start, this))
 1447            return (other.Start, other.Start);
 10448        if (PointOnSegment(other.End, this))
 1449            return (other.End, other.End);
 450
 9451        if (TryGetUniqueIntersection(other, out Fixed64 thisParameter, out Fixed64 otherParameter))
 452        {
 1453            return (Interpolate(this, thisParameter), Interpolate(other, otherParameter));
 454        }
 455
 8456        Vector2d thisPoint = Start;
 8457        Vector2d otherPoint = other.ClosestPoint(Start);
 458
 8459        ConsiderClosestCandidate(End, other.ClosestPoint(End), ref thisPoint, ref otherPoint);
 8460        ConsiderClosestCandidate(
 8461            Vector2d.ClosestPointOnLineSegment(other.Start, Start, End),
 8462            other.Start,
 8463            ref thisPoint,
 8464            ref otherPoint);
 8465        ConsiderClosestCandidate(
 8466            Vector2d.ClosestPointOnLineSegment(other.End, Start, End),
 8467            other.End,
 8468            ref thisPoint,
 8469            ref otherPoint);
 470
 8471        return (thisPoint, otherPoint);
 472    }
 473
 474    private readonly bool TryGetUniqueIntersection(
 475        FixedSegment2d other,
 476        out Fixed64 thisParameter,
 477        out Fixed64 otherParameter)
 478    {
 859479        bool thisIsPoint = Start == End;
 859480        bool otherIsPoint = other.Start == other.End;
 481
 859482        if (thisIsPoint)
 483        {
 24484            thisParameter = Fixed64.Zero;
 24485            if (!PointOnSegment(Start, other))
 486            {
 22487                otherParameter = default;
 22488                return false;
 489            }
 490
 2491            otherParameter = otherIsPoint
 2492                ? Fixed64.Zero
 2493                : Vector2d.GetClosestPointOnLineSegmentParameter(Start, other.Start, other.End);
 2494            return true;
 495        }
 496
 835497        if (otherIsPoint)
 498        {
 14499            otherParameter = Fixed64.Zero;
 14500            if (!PointOnSegment(other.Start, this))
 501            {
 13502                thisParameter = default;
 13503                return false;
 504            }
 505
 1506            thisParameter = Vector2d.GetClosestPointOnLineSegmentParameter(other.Start, Start, End);
 1507            return true;
 508        }
 509
 821510        Signed192 determinant = WideGeometry.GetDifferenceCrossProduct2D(
 821511            End.X, Start.X, End.Y, Start.Y,
 821512            other.End.X, other.Start.X, other.End.Y, other.Start.Y);
 821513        if (!determinant.IsZero)
 514        {
 293515            Signed192 thisNumerator = WideGeometry.GetDifferenceCrossProduct2D(
 293516                other.Start.X, Start.X, other.Start.Y, Start.Y,
 293517                other.End.X, other.Start.X, other.End.Y, other.Start.Y);
 293518            Signed192 otherNumerator = WideGeometry.GetDifferenceCrossProduct2D(
 293519                other.Start.X, Start.X, other.Start.Y, Start.Y,
 293520                End.X, Start.X, End.Y, Start.Y);
 521
 293522            if (Fixed64.TryGetUnitIntervalRatio(thisNumerator, determinant, out thisParameter)
 293523                && Fixed64.TryGetUnitIntervalRatio(otherNumerator, determinant, out otherParameter))
 524            {
 272525                return true;
 526            }
 527
 21528            thisParameter = default;
 21529            otherParameter = default;
 21530            return false;
 531        }
 532
 528533        Signed192 collinearity = WideGeometry.GetDifferenceCrossProduct2D(
 528534            other.Start.X, Start.X, other.Start.Y, Start.Y,
 528535            End.X, Start.X, End.Y, Start.Y);
 528536        if (!collinearity.IsZero)
 537        {
 523538            thisParameter = default;
 523539            otherParameter = default;
 523540            return false;
 541        }
 542
 5543        int sharedPointCount = 0;
 5544        Vector2d sharedPoint = default;
 5545        ConsiderSharedEndpoint(Start, this, other, ref sharedPointCount, ref sharedPoint);
 5546        ConsiderSharedEndpoint(End, this, other, ref sharedPointCount, ref sharedPoint);
 5547        ConsiderSharedEndpoint(other.Start, this, other, ref sharedPointCount, ref sharedPoint);
 5548        ConsiderSharedEndpoint(other.End, this, other, ref sharedPointCount, ref sharedPoint);
 549
 5550        if (sharedPointCount == 1)
 551        {
 1552            thisParameter = Vector2d.GetClosestPointOnLineSegmentParameter(sharedPoint, Start, End);
 1553            otherParameter = Vector2d.GetClosestPointOnLineSegmentParameter(sharedPoint, other.Start, other.End);
 1554            return true;
 555        }
 556
 4557        thisParameter = default;
 4558        otherParameter = default;
 4559        return false;
 560    }
 561
 562    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 563    private static Vector2d Interpolate(FixedSegment2d segment, Fixed64 parameter)
 564    {
 2565        return new Vector2d(
 2566            FixedMath.Lerp(segment.Start.X, segment.End.X, parameter),
 2567            FixedMath.Lerp(segment.Start.Y, segment.End.Y, parameter));
 568    }
 569
 570    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 571    private static bool PointOnSegment(Vector2d point, FixedSegment2d segment)
 572    {
 122573        Signed192 cross = WideGeometry.GetDifferenceCrossProduct2D(
 122574            point.X, segment.Start.X, point.Y, segment.Start.Y,
 122575            segment.End.X, segment.Start.X, segment.End.Y, segment.Start.Y);
 122576        if (!cross.IsZero)
 60577            return false;
 578
 62579        long pointX = point.X.m_rawValue;
 62580        long pointY = point.Y.m_rawValue;
 62581        long startX = segment.Start.X.m_rawValue;
 62582        long startY = segment.Start.Y.m_rawValue;
 62583        long endX = segment.End.X.m_rawValue;
 62584        long endY = segment.End.Y.m_rawValue;
 62585        return pointX >= Math.Min(startX, endX)
 62586            && pointX <= Math.Max(startX, endX)
 62587            && pointY >= Math.Min(startY, endY)
 62588            && pointY <= Math.Max(startY, endY);
 589    }
 590
 591    private static void ConsiderSharedEndpoint(
 592        Vector2d candidate,
 593        FixedSegment2d first,
 594        FixedSegment2d second,
 595        ref int sharedPointCount,
 596        ref Vector2d sharedPoint)
 597    {
 20598        if (!PointOnSegment(candidate, first)
 20599            || !PointOnSegment(candidate, second)
 20600            || (sharedPointCount != 0 && candidate == sharedPoint))
 601        {
 11602            return;
 603        }
 604
 9605        sharedPoint = candidate;
 9606        sharedPointCount++;
 9607    }
 608
 609    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 610    private static void ConsiderClosestCandidate(
 611        Vector2d candidateThisPoint,
 612        Vector2d candidateOtherPoint,
 613        ref Vector2d thisPoint,
 614        ref Vector2d otherPoint)
 615    {
 24616        if (Vector2d.CompareDistanceSquared(
 24617            candidateThisPoint,
 24618            candidateOtherPoint,
 24619            thisPoint,
 24620            otherPoint) < 0)
 621        {
 3622            thisPoint = candidateThisPoint;
 3623            otherPoint = candidateOtherPoint;
 624        }
 24625    }
 626
 627    #endregion
 628
 629    #region Deconstruction
 630
 631    /// <summary>
 632    /// Deconstructs the segment into start and end points.
 633    /// </summary>
 634    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 635    public void Deconstruct(out Vector2d start, out Vector2d end)
 636    {
 1637        start = Start;
 1638        end = End;
 1639    }
 640
 641    #endregion
 642
 643    #region Operators
 644
 645    /// <summary>
 646    /// Determines whether two segments have the same ordered endpoints.
 647    /// </summary>
 648    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 2649    public static bool operator ==(FixedSegment2d left, FixedSegment2d right) => left.Equals(right);
 650
 651    /// <summary>
 652    /// Determines whether two segments have different ordered endpoints.
 653    /// </summary>
 654    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 2655    public static bool operator !=(FixedSegment2d left, FixedSegment2d right) => !left.Equals(right);
 656
 657    #endregion
 658
 659    #region Equality
 660
 661    /// <inheritdoc />
 662    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 663    public bool Equals(FixedSegment2d other)
 664    {
 11665        return Start == other.Start && End == other.End;
 666    }
 667
 668    /// <inheritdoc />
 669    public override bool Equals(object? obj)
 670    {
 2671        return obj is FixedSegment2d other && Equals(other);
 672    }
 673
 674    /// <inheritdoc />
 675    public override int GetHashCode()
 676    {
 677        unchecked
 678        {
 2679            int hash = 17;
 2680            hash = (hash * 31) + Start.StateHash;
 2681            hash = (hash * 31) + End.StateHash;
 2682            return hash;
 683        }
 684    }
 685
 686    #endregion
 687
 688    /// <summary>
 689    /// Finds the physical-distance interval where this segment intersects a
 690    /// circle, mapped to the caller-supplied total distance.
 691    /// </summary>
 692    public readonly bool TryGetCircleIntersectionDistanceInterval(
 693        FixedBoundCircle circle,
 694        Fixed64 totalDistance,
 695        out Fixed64 entryDistance,
 696        out Fixed64 exitDistance) =>
 4697        TryGetCircleIntersectionDistanceInterval(
 4698            circle,
 4699            Fixed64.Zero,
 4700            totalDistance,
 4701            out entryDistance,
 4702            out exitDistance,
 4703            out _,
 4704            out _);
 705
 706    /// <summary>
 707    /// Finds the physical-distance interval where this segment intersects a
 708    /// radially expanded circle and reports exact endpoint containment.
 709    /// </summary>
 710    /// <remarks>
 711    /// The exact segment interval maps to <c>[0, totalDistance]</c> with one
 712    /// final round-half-to-even conversion. Start containment is inclusive;
 713    /// end containment is strict and is classified before distance rounding.
 714    /// </remarks>
 715    public readonly bool TryGetCircleIntersectionDistanceInterval(
 716        FixedBoundCircle circle,
 717        Fixed64 radiusExpansion,
 718        Fixed64 totalDistance,
 719        out Fixed64 entryDistance,
 720        out Fixed64 exitDistance,
 721        out bool startContained,
 722        out bool endContainedStrict)
 723    {
 21724        ValidateTotalDistance(totalDistance);
 20725        if (radiusExpansion < Fixed64.Zero)
 1726            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 727
 19728        return WideFiniteAxisIntersection.TryGetCircleDistanceInterval(
 19729            this,
 19730            circle,
 19731            radiusExpansion,
 19732            totalDistance,
 19733            out entryDistance,
 19734            out exitDistance,
 19735            out startContained,
 19736            out endContainedStrict);
 737    }
 738
 739    /// <summary>
 740    /// Finds the physical-distance interval where this segment intersects an
 741    /// endpoint-authored capsule.
 742    /// </summary>
 743    public readonly bool TryGetCapsuleIntersectionDistanceInterval(
 744        FixedSegment2d capsuleAxis,
 745        Fixed64 radius,
 746        Fixed64 totalDistance,
 747        out Fixed64 entryDistance,
 748        out Fixed64 exitDistance) =>
 19764749        TryGetCapsuleIntersectionDistanceInterval(
 19764750            capsuleAxis,
 19764751            radius,
 19764752            Fixed64.Zero,
 19764753            totalDistance,
 19764754            out entryDistance,
 19764755            out exitDistance,
 19764756            out _,
 19764757            out _);
 758
 759    /// <summary>
 760    /// Finds the physical-distance interval where this segment intersects an
 761    /// endpoint-authored, radially expanded capsule and reports exact endpoint
 762    /// containment.
 763    /// </summary>
 764    public readonly bool TryGetCapsuleIntersectionDistanceInterval(
 765        FixedSegment2d capsuleAxis,
 766        Fixed64 radius,
 767        Fixed64 radiusExpansion,
 768        Fixed64 totalDistance,
 769        out Fixed64 entryDistance,
 770        out Fixed64 exitDistance,
 771        out bool startContained,
 772        out bool endContainedStrict)
 773    {
 19768774        ValidateTotalDistance(totalDistance);
 19767775        if (radius < Fixed64.Zero)
 1776            throw new ArgumentOutOfRangeException(nameof(radius));
 19766777        if (radiusExpansion < Fixed64.Zero)
 1778            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 779
 19765780        return WideFiniteAxisIntersection.TryGetCapsuleDistanceInterval(
 19765781            this,
 19765782            capsuleAxis,
 19765783            radius,
 19765784            radiusExpansion,
 19765785            totalDistance,
 19765786            out entryDistance,
 19765787            out exitDistance,
 19765788            out startContained,
 19765789            out endContainedStrict);
 790    }
 791
 792    /// <summary>
 793    /// Finds the physical-distance interval where this segment intersects a
 794    /// centered capsule.
 795    /// </summary>
 796    public readonly bool TryGetCapsuleIntersectionDistanceInterval(
 797        Vector2d center,
 798        Vector2d axisDirection,
 799        Fixed64 axisLength,
 800        Fixed64 radius,
 801        Fixed64 totalDistance,
 802        out Fixed64 entryDistance,
 803        out Fixed64 exitDistance) =>
 1804        TryGetCapsuleIntersectionDistanceInterval(
 1805            center,
 1806            axisDirection,
 1807            axisLength,
 1808            radius,
 1809            Fixed64.Zero,
 1810            totalDistance,
 1811            out entryDistance,
 1812            out exitDistance,
 1813            out _,
 1814            out _);
 815
 816    /// <summary>
 817    /// Finds the physical-distance interval where this segment intersects a
 818    /// centered, radially expanded capsule and reports exact endpoint
 819    /// containment.
 820    /// </summary>
 821    public readonly bool TryGetCapsuleIntersectionDistanceInterval(
 822        Vector2d center,
 823        Vector2d axisDirection,
 824        Fixed64 axisLength,
 825        Fixed64 radius,
 826        Fixed64 radiusExpansion,
 827        Fixed64 totalDistance,
 828        out Fixed64 entryDistance,
 829        out Fixed64 exitDistance,
 830        out bool startContained,
 831        out bool endContainedStrict)
 832    {
 8833        ValidateTotalDistance(totalDistance);
 8834        ValidateCenteredAxis(axisDirection, axisLength);
 6835        if (radius < Fixed64.Zero)
 1836            throw new ArgumentOutOfRangeException(nameof(radius));
 5837        if (radiusExpansion < Fixed64.Zero)
 1838            throw new ArgumentOutOfRangeException(nameof(radiusExpansion));
 839
 4840        return WideFiniteAxisIntersection.TryGetCapsuleDistanceInterval(
 4841            this,
 4842            center,
 4843            axisDirection,
 4844            axisLength,
 4845            radius,
 4846            radiusExpansion,
 4847            totalDistance,
 4848            out entryDistance,
 4849            out exitDistance,
 4850            out startContained,
 4851            out endContainedStrict);
 852    }
 853
 854    /// <summary>
 855    /// Reconstructs the point at an authored physical distance along this
 856    /// segment using one exact chord interpolation per coordinate.
 857    /// </summary>
 858    /// <remarks>
 859    /// This method does not normalize <see cref="Delta"/>. It therefore retains
 860    /// representable chord components that would round away in a normalized
 861    /// direction. The final coordinates use round-half-to-even.
 862    /// </remarks>
 863    /// <exception cref="ArgumentOutOfRangeException">
 864    /// Thrown when <paramref name="totalDistance"/> is negative, or when
 865    /// <paramref name="distance"/> is outside [0, <paramref name="totalDistance"/>].
 866    /// </exception>
 867    /// <exception cref="ArgumentException">
 868    /// Thrown when <paramref name="totalDistance"/> is zero and this segment is
 869    /// not a point.
 870    /// </exception>
 871    public readonly Vector2d GetPointAtDistance(Fixed64 distance, Fixed64 totalDistance)
 872    {
 277873        ValidateDistance(distance, totalDistance);
 271874        if (distance == Fixed64.Zero)
 254875            return Start;
 17876        if (distance == totalDistance)
 1877            return End;
 878
 16879        Signed192 distanceRaw = Signed192.Signed(distance.m_rawValue);
 16880        Signed192 totalDistanceRaw = Signed192.Signed(totalDistance.m_rawValue);
 16881        return new Vector2d(
 16882            WideGeometry.InterpolateCoordinate(Start.X, End.X, distanceRaw, totalDistanceRaw),
 16883            WideGeometry.InterpolateCoordinate(Start.Y, End.Y, distanceRaw, totalDistanceRaw));
 884    }
 885
 886    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 887    private readonly void ValidateDistance(Fixed64 distance, Fixed64 totalDistance)
 888    {
 277889        ValidateTotalDistance(totalDistance);
 272890        if (distance < Fixed64.Zero || distance > totalDistance)
 1891            throw new ArgumentOutOfRangeException(nameof(distance));
 271892    }
 893
 894    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 895    private readonly void ValidateTotalDistance(Fixed64 totalDistance)
 896    {
 20076897        if (totalDistance < Fixed64.Zero)
 4898            throw new ArgumentOutOfRangeException(nameof(totalDistance));
 20072899        if (totalDistance == Fixed64.Zero && Start != End)
 3900            throw new ArgumentException("Zero total distance requires a zero-length segment.", nameof(totalDistance));
 20069901    }
 902}

Methods/Properties

DoCenteredCapsulesOverlapStrict(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
DoCenteredCapsulesOverlapStrict(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
TryGetDistanceToCenteredAxis(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetDistanceBetweenCenteredAxes(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
DoCenteredCapsulesOverlap(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
TryGetCenteredCapsulesContact(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Geometry.FixedContactAnchors2d&)
TryGetCenteredAxisEndpoint(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,System.Boolean,FixedMathSharp.Vector2d&)
TryGetCenteredCapsuleSupport(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d&)
GetCenteredCapsuleSupportAnchor(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d)
GetDistanceToCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
TryGetDistanceToCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
ContainsPointInCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
ContainsPointInCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
ContainsPointInCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
ContainsPointInCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
TryGetSurfacePointOnCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d&)
TryGetSurfaceOffsetOnCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d&)
GetSurfaceAnchorOnCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d)
GetDirectionFromCenteredAxis(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64)
TryGetClosestPointsBetweenCenteredAxes(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d&,FixedMathSharp.Vector2d&)
ValidateCenteredAxis(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64)
ValidateCenteredAxis(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,System.String,System.String)
ContainsPointInCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
ContainsPointInCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
ContainsPointInCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
GetDirectionFromCenteredAxis(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
GetDistanceToCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
TryGetDistanceToCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetCenteredCapsuleSupport(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d&)
TryGetSurfacePointOnCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d&)
TryGetSurfaceOffsetOnCenteredCapsule(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d&)
DoCenteredCapsulesOverlap(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
TryGetCenteredCapsulesContact(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Geometry.FixedContactAnchors2d&)
TryGetCenteredCapsuleConvexMinimumTranslation(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,System.ReadOnlySpan`1<FixedMathSharp.Vector2d>,FixedMathSharp.Vector2d&,FixedMathSharp.Fixed64&)
TryGetSweptCenteredCapsuleSegmentFirstDistance(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Vector2d&)
TryGetSweptCenteredCapsulesFirstDistance(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Vector2d&)
TryGetCapsuleIntersectionDistanceInterval(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
GetRotatedPositiveYAxis(FixedMathSharp.Fixed64)
ValidateRotatedCapsule(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
DoesCenteredCapsulePenetrateConvex(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,System.ReadOnlySpan`1<FixedMathSharp.Vector2d>)
DoesCenteredCapsulePenetrateConvex(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,System.ReadOnlySpan`1<FixedMathSharp.Vector2d>)
TryGetCenteredCapsuleConvexMinimumTranslation(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,System.ReadOnlySpan`1<FixedMathSharp.Vector2d>,FixedMathSharp.Vector2d&,FixedMathSharp.Fixed64&)
TryGetCenteredCapsuleConvexMinimumTranslation(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,System.ReadOnlySpan`1<FixedMathSharp.Vector2d>,FixedMathSharp.Vector2d&,FixedMathSharp.Fixed64&)
TryGetCenteredCapsuleConvexContacts(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,System.ReadOnlySpan`1<FixedMathSharp.Vector2d>,System.Span`1<FixedMathSharp.Geometry.FixedPointAnchor2d>,System.Span`1<FixedMathSharp.Geometry.FixedPointAnchor2d>,System.Int32&,FixedMathSharp.Vector2d&,FixedMathSharp.Fixed64&,System.Boolean&)
TryGetSweptCenteredCapsuleSegmentFirstDistance(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Vector2d&)
TryGetSweptCenteredCapsulesFirstDistance(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Vector2d&)
ValidateSweep(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
.ctor(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d)
get_Delta()
get_Length()
get_LengthSquared()
get_Bounds()
ClosestPoint(FixedMathSharp.Vector2d)
DistanceSquared(FixedMathSharp.Vector2d)
IsDistanceAtLeast(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Fixed64)
TryGetCapsuleIntersectionInterval(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCapsuleIntersectionParameterEnclosure(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCapsuleIntersectionInterval(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCapsuleIntersectionInterval(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCapsuleIntersectionInterval(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCapsuleIntersectionInterval(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCapsuleIntersectionInterval(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetUniqueIntersection(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Fixed64&)
TryGetUniqueIntersectionParameterEnclosure(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
GetClosestPoints(FixedMathSharp.Geometry.FixedSegment2d)
TryGetUniqueIntersection(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
Interpolate(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Fixed64)
PointOnSegment(FixedMathSharp.Vector2d,FixedMathSharp.Geometry.FixedSegment2d)
ConsiderSharedEndpoint(FixedMathSharp.Vector2d,FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Geometry.FixedSegment2d,System.Int32&,FixedMathSharp.Vector2d&)
ConsiderClosestCandidate(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d&,FixedMathSharp.Vector2d&)
Deconstruct(FixedMathSharp.Vector2d&,FixedMathSharp.Vector2d&)
op_Equality(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Geometry.FixedSegment2d)
op_Inequality(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Geometry.FixedSegment2d)
Equals(FixedMathSharp.Geometry.FixedSegment2d)
Equals(System.Object)
GetHashCode()
TryGetCircleIntersectionDistanceInterval(FixedMathSharp.Geometry.FixedBoundCircle,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCircleIntersectionDistanceInterval(FixedMathSharp.Geometry.FixedBoundCircle,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCapsuleIntersectionDistanceInterval(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCapsuleIntersectionDistanceInterval(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
TryGetCapsuleIntersectionDistanceInterval(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCapsuleIntersectionDistanceInterval(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,System.Boolean&,System.Boolean&)
GetPointAtDistance(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
ValidateDistance(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
ValidateTotalDistance(FixedMathSharp.Fixed64)