< Summary

Information
Class: FixedMathSharp.FixedConvexPrismRelations
Assembly: FixedMathSharp
File(s): /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Primitives/Relations/FixedConvexPrismRelations.cs
Line coverage
100%
Covered lines: 126
Uncovered lines: 0
Coverable lines: 126
Total lines: 335
Line coverage: 100%
Branch coverage
100%
Covered branches: 18
Total branches: 18
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
IntersectsSweptUprightCylinderStrict(...)100%22100%
TryGetTriangleContact(...)100%22100%
TryGetSphereContact(...)100%11100%
TryGetCenteredCapsuleContact(...)100%11100%
TryGetCenteredCylinderContact(...)100%11100%
TryGetCenteredConeContact(...)100%11100%
Validate(...)100%88100%
ValidatePrism(...)100%66100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Primitives/Relations/FixedConvexPrismRelations.cs

#LineLine coverage
 1//=======================================================================
 2// FixedConvexPrismRelations.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 FixedMathSharp.Geometry;
 10
 11namespace FixedMathSharp;
 12
 13/// <summary>
 14/// Provides exact owner-relative contacts between centered finite surfaces
 15/// and vertical convex prisms.
 16/// </summary>
 17public static class FixedConvexPrismRelations
 18{
 19    /// <summary>
 20    /// Determines whether an upright cylinder translated between two
 21    /// bottom-center points has strict positive-volume overlap with a rotated
 22    /// vertical convex prism at any shared continuous parameter in [0, 1].
 23    /// </summary>
 24    /// <remarks>
 25    /// Planar tangency, vertical tangency, and contact that exists only where
 26    /// the planar and vertical strict intervals meet at one boundary parameter
 27    /// return <see langword="false"/>. A zero radius requires the swept axis
 28    /// point to enter the strict prism footprint. The joint parameter relation
 29    /// is evaluated with exact wide intermediates and does not publish rounded
 30    /// interval endpoints.
 31    /// </remarks>
 32    /// <param name="bottomStart">The cylinder bottom center at parameter zero.</param>
 33    /// <param name="bottomEnd">The cylinder bottom center at parameter one.</param>
 34    /// <param name="radius">The nonnegative cylinder radius.</param>
 35    /// <param name="height">The positive full cylinder height.</param>
 36    /// <param name="prismOrigin">The center of the vertical convex prism.</param>
 37    /// <param name="prismRotation">The prism footprint rotation about world Y.</param>
 38    /// <param name="prismLocalOffsets">At least three ordered convex-footprint offsets.</param>
 39    /// <param name="prismHalfThickness">The positive prism half-thickness along world Y.</param>
 40    /// <exception cref="ArgumentOutOfRangeException">
 41    /// <paramref name="radius"/> is negative, <paramref name="height"/> is not
 42    /// positive, or <paramref name="prismHalfThickness"/> is not positive.
 43    /// </exception>
 44    /// <exception cref="ArgumentException">
 45    /// Fewer than three ordered prism offsets were supplied.
 46    /// </exception>
 47    public static bool IntersectsSweptUprightCylinderStrict(
 48        Vector3d bottomStart,
 49        Vector3d bottomEnd,
 50        Fixed64 radius,
 51        Fixed64 height,
 52        Vector3d prismOrigin,
 53        Fixed64 prismRotation,
 54        ReadOnlySpan<Vector2d> prismLocalOffsets,
 55        Fixed64 prismHalfThickness)
 56    {
 16457        if (height <= Fixed64.Zero)
 158            throw new ArgumentOutOfRangeException(nameof(height));
 16359        ValidatePrism(radius, prismLocalOffsets, prismHalfThickness);
 16060        return WideConvexPrismRelations
 16061            .IntersectsSweptUprightCylinderStrict(
 16062                bottomStart,
 16063                bottomEnd,
 16064                radius,
 16065                height,
 16066                prismOrigin,
 16067                prismRotation,
 16068                prismLocalOffsets,
 16069                prismHalfThickness);
 70    }
 71
 72    /// <summary>
 73    /// Attempts to construct canonical contact anchors between a rigidly
 74    /// transformed triangle and a rotated vertical convex prism.
 75    /// </summary>
 76    public static bool TryGetTriangleContact(
 77        Vector3d triangleOrigin,
 78        FixedQuaternion triangleRotation,
 79        FixedTriangle triangle,
 80        Vector3d prismOrigin,
 81        Fixed64 prismRotation,
 82        ReadOnlySpan<Vector2d> prismLocalOffsets,
 83        Fixed64 prismHalfThickness,
 84        out FixedContactAnchors contact)
 85    {
 7686        if (!triangleRotation.IsNormalized())
 187            throw new ArgumentException(
 188                "The triangle rotation must be normalized.",
 189                nameof(triangleRotation));
 7590        ValidatePrism(
 7591            Fixed64.Zero,
 7592            prismLocalOffsets,
 7593            prismHalfThickness);
 7594        return WideOrientedBox.TryGetTrianglePrismContact(
 7595            triangleOrigin,
 7596            triangleRotation,
 7597            triangle,
 7598            prismOrigin,
 7599            prismRotation,
 75100            prismLocalOffsets,
 75101            prismHalfThickness,
 75102            out contact);
 103    }
 104
 105    /// <summary>
 106    /// Attempts to construct canonical contact anchors between a sphere and a
 107    /// rotated vertical convex prism.
 108    /// </summary>
 109    public static bool TryGetSphereContact(
 110        Vector3d sphereCenter,
 111        Fixed64 sphereRadius,
 112        Vector3d prismOrigin,
 113        Fixed64 prismRotation,
 114        ReadOnlySpan<Vector2d> prismLocalOffsets,
 115        Fixed64 prismHalfThickness,
 116        out FixedContactAnchors contact)
 117    {
 64118        ValidatePrism(
 64119            sphereRadius,
 64120            prismLocalOffsets,
 64121            prismHalfThickness);
 64122        return WideConvexPrismRelations.TryGetCenteredCapsuleContact(
 64123            sphereCenter,
 64124            FixedQuaternion.Identity,
 64125            Vector3d.Up,
 64126            Fixed64.Zero,
 64127            sphereRadius,
 64128            prismOrigin,
 64129            prismRotation,
 64130            prismLocalOffsets,
 64131            prismHalfThickness,
 64132            out contact);
 133    }
 134
 135    /// <summary>
 136    /// Attempts to construct canonical contact anchors between a centered
 137    /// capsule and a rotated vertical convex prism.
 138    /// </summary>
 139    public static bool TryGetCenteredCapsuleContact(
 140        Vector3d capsuleCenter,
 141        FixedQuaternion capsuleRotation,
 142        Vector3d localCapsuleAxisDirection,
 143        Fixed64 capsuleAxisLength,
 144        Fixed64 capsuleRadius,
 145        Vector3d prismOrigin,
 146        Fixed64 prismRotation,
 147        ReadOnlySpan<Vector2d> prismLocalOffsets,
 148        Fixed64 prismHalfThickness,
 149        out FixedContactAnchors contact)
 150    {
 453151        Validate(
 453152            capsuleRotation,
 453153            localCapsuleAxisDirection,
 453154            capsuleAxisLength,
 453155            nameof(capsuleAxisLength),
 453156            capsuleRadius,
 453157            prismLocalOffsets,
 453158            prismHalfThickness,
 453159            requirePositiveLength: false);
 449160        return WideConvexPrismRelations.TryGetCenteredCapsuleContact(
 449161            capsuleCenter,
 449162            capsuleRotation,
 449163            localCapsuleAxisDirection,
 449164            capsuleAxisLength,
 449165            capsuleRadius,
 449166            prismOrigin,
 449167            prismRotation,
 449168            prismLocalOffsets,
 449169            prismHalfThickness,
 449170            out contact);
 171    }
 172
 173    /// <summary>
 174    /// Attempts to find the minimum-depth contact between a centered
 175    /// finite cylinder and a rotated vertical convex prism.
 176    /// </summary>
 177    /// <remarks>
 178    /// The complete support fan includes prism faces, real edges and vertices
 179    /// against both flat caps, the side and circular rims. Classification and
 180    /// minimum-depth ranking use the exact authored geometry. Touching is
 181    /// contact with zero depth; an overlap smaller than half a raw unit can
 182    /// also round to zero. A zero radius is the finite axis segment.
 183    /// <para>
 184    /// The normal points from the cylinder toward the prism. Depth and each
 185    /// unit-normal component round nearest-even after selection. Unclamped
 186    /// depth differs from the exact minimum by at most half a raw unit;
 187    /// translating along the rounded normal additionally introduces an error
 188    /// proportional to depth. <see cref="FixedContactAnchors.DepthIsClamped"/>
 189    /// identifies an exact minimum above <see cref="Fixed64.MaxValue"/>.
 190    /// </para>
 191    /// <para>
 192    /// Both finite support witnesses are matched before final coordinate
 193    /// rounding. The first anchor retains the cylinder center and the second
 194    /// the prism origin; both use the cylinder rotation as their local frame.
 195    /// The prism's scalar yaw remains authoritative. Use the anchor operations
 196    /// to compare or materialize points rather than interpreting the second
 197    /// anchor's local coordinates as prism footprint offsets.
 198    /// </para>
 199    /// </remarks>
 200    public static bool TryGetCenteredCylinderContact(
 201        Vector3d cylinderCenter,
 202        FixedQuaternion cylinderRotation,
 203        Vector3d localCylinderAxisDirection,
 204        Fixed64 cylinderAxisLength,
 205        Fixed64 cylinderRadius,
 206        Vector3d prismOrigin,
 207        Fixed64 prismRotation,
 208        ReadOnlySpan<Vector2d> prismLocalOffsets,
 209        Fixed64 prismHalfThickness,
 210        out FixedContactAnchors contact)
 211    {
 500212        Validate(
 500213            cylinderRotation,
 500214            localCylinderAxisDirection,
 500215            cylinderAxisLength,
 500216            nameof(cylinderAxisLength),
 500217            cylinderRadius,
 500218            prismLocalOffsets,
 500219            prismHalfThickness,
 500220            requirePositiveLength: true);
 498221        return WideConvexPrismRelations.TryGetCenteredCylinderContact(
 498222            cylinderCenter,
 498223            cylinderRotation,
 498224            localCylinderAxisDirection,
 498225            cylinderAxisLength,
 498226            cylinderRadius,
 498227            prismOrigin,
 498228            prismRotation,
 498229            prismLocalOffsets,
 498230            prismHalfThickness,
 498231            out contact);
 232    }
 233
 234    /// <summary>
 235    /// Attempts to find the minimum-depth contact between a centered
 236    /// finite cone and a rotated vertical convex prism.
 237    /// </summary>
 238    /// <remarks>
 239    /// The complete support fan includes prism faces, real edges and vertices
 240    /// against the base disk and rim, apex and lateral generators.
 241    /// Classification and minimum-depth ranking use the exact authored
 242    /// geometry. Touching is contact with zero depth; an overlap smaller than
 243    /// half a raw unit can also round to zero. A zero radius is the finite axis
 244    /// segment.
 245    /// <para>
 246    /// The normal points from the cone toward the prism. Depth and each
 247    /// unit-normal component round nearest-even after selection. Unclamped
 248    /// depth differs from the exact minimum by at most half a raw unit;
 249    /// translating along the rounded normal additionally introduces an error
 250    /// proportional to depth. <see cref="FixedContactAnchors.DepthIsClamped"/>
 251    /// identifies an exact minimum above <see cref="Fixed64.MaxValue"/>.
 252    /// </para>
 253    /// <para>
 254    /// Both finite support witnesses are matched before final coordinate
 255    /// rounding. The first anchor retains the cone center and the second the
 256    /// prism origin; both use the cone rotation as their local frame. The
 257    /// prism's scalar yaw remains authoritative. Use the anchor operations to
 258    /// compare or materialize points rather than interpreting the second
 259    /// anchor's local coordinates as prism footprint offsets.
 260    /// </para>
 261    /// </remarks>
 262    public static bool TryGetCenteredConeContact(
 263        Vector3d coneCenter,
 264        FixedQuaternion coneRotation,
 265        Vector3d localConeAxisDirection,
 266        Fixed64 coneHeight,
 267        Fixed64 coneRadius,
 268        Vector3d prismOrigin,
 269        Fixed64 prismRotation,
 270        ReadOnlySpan<Vector2d> prismLocalOffsets,
 271        Fixed64 prismHalfThickness,
 272        out FixedContactAnchors contact)
 273    {
 392274        Validate(
 392275            coneRotation,
 392276            localConeAxisDirection,
 392277            coneHeight,
 392278            nameof(coneHeight),
 392279            coneRadius,
 392280            prismLocalOffsets,
 392281            prismHalfThickness,
 392282            requirePositiveLength: true);
 390283        return WideConvexPrismRelations.TryGetCenteredConeContact(
 390284            coneCenter,
 390285            coneRotation,
 390286            localConeAxisDirection,
 390287            coneHeight,
 390288            coneRadius,
 390289            prismOrigin,
 390290            prismRotation,
 390291            prismLocalOffsets,
 390292            prismHalfThickness,
 390293            out contact);
 294    }
 295
 296    private static void Validate(
 297        FixedQuaternion rotation,
 298        Vector3d localAxisDirection,
 299        Fixed64 length,
 300        string lengthParameterName,
 301        Fixed64 radius,
 302        ReadOnlySpan<Vector2d> prismLocalOffsets,
 303        Fixed64 prismHalfThickness,
 304        bool requirePositiveLength)
 305    {
 1345306        if (!rotation.IsNormalized())
 1307            throw new ArgumentException(
 1308                "Shape rotation must be normalized.",
 1309                nameof(rotation));
 1344310        if (!localAxisDirection.IsNormalized())
 1311            throw new ArgumentException(
 1312                "Local shape axis direction must be normalized.",
 1313                nameof(localAxisDirection));
 1343314        if (requirePositiveLength ? length <= Fixed64.Zero : length < Fixed64.Zero)
 3315            throw new ArgumentOutOfRangeException(lengthParameterName);
 1340316        ValidatePrism(radius, prismLocalOffsets, prismHalfThickness);
 1337317    }
 318
 319    private static void ValidatePrism(
 320        Fixed64 radius,
 321        ReadOnlySpan<Vector2d> prismLocalOffsets,
 322        Fixed64 prismHalfThickness)
 323    {
 1642324        if (radius < Fixed64.Zero)
 2325            throw new ArgumentOutOfRangeException(nameof(radius));
 1640326        if (prismLocalOffsets.Length < 3)
 327        {
 2328            throw new ArgumentException(
 2329                "A convex prism requires at least three ordered boundary offsets.",
 2330                nameof(prismLocalOffsets));
 331        }
 1638332        if (prismHalfThickness <= Fixed64.Zero)
 2333            throw new ArgumentOutOfRangeException(nameof(prismHalfThickness));
 1636334    }
 335}

Methods/Properties

IntersectsSweptUprightCylinderStrict(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,System.ReadOnlySpan`1<FixedMathSharp.Vector2d>,FixedMathSharp.Fixed64)
TryGetTriangleContact(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,System.ReadOnlySpan`1<FixedMathSharp.Vector2d>,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.FixedContactAnchors&)
TryGetSphereContact(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,System.ReadOnlySpan`1<FixedMathSharp.Vector2d>,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.FixedContactAnchors&)
TryGetCenteredCapsuleContact(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,System.ReadOnlySpan`1<FixedMathSharp.Vector2d>,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.FixedContactAnchors&)
TryGetCenteredCylinderContact(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,System.ReadOnlySpan`1<FixedMathSharp.Vector2d>,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.FixedContactAnchors&)
TryGetCenteredConeContact(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,System.ReadOnlySpan`1<FixedMathSharp.Vector2d>,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.FixedContactAnchors&)
Validate(FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,System.String,FixedMathSharp.Fixed64,System.ReadOnlySpan`1<FixedMathSharp.Vector2d>,FixedMathSharp.Fixed64,System.Boolean)
ValidatePrism(FixedMathSharp.Fixed64,System.ReadOnlySpan`1<FixedMathSharp.Vector2d>,FixedMathSharp.Fixed64)