< Summary

Line coverage
100%
Covered lines: 1577
Uncovered lines: 0
Coverable lines: 1577
Total lines: 2536
Line coverage: 100%
Branch coverage
100%
Covered branches: 644
Total branches: 644
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: ContainsProjection(...)100%66100%
File 1: TryGetProjectionBarycentrics(...)100%22100%
File 1: TryGetProjectedSegmentInterval(...)100%2020100%
File 1: TryGetProjectedSegmentFaceAnchors(...)100%1616100%
File 1: TryGetProjectedCoreParameter(...)100%1212100%
File 1: TryGetProjectedSegmentCoreParameter(...)100%2020100%
File 1: GetClosestNonparallelLineNumerators(...)100%11100%
File 1: TryGetClosestNonparallelSegmentParameters(...)100%1010100%
File 1: MaterializeSegmentPoint(...)100%22100%
File 1: GetProjectedCoreDot(...)100%11100%
File 1: CompareCoreParameters(...)100%44100%
File 1: MaterializeCorePoint(...)100%11100%
File 1: GetClosestPointAnchor(...)100%11100%
File 1: GetClosestTriangleLocalPoint(...)100%3434100%
File 1: GetClosestTriangleEdgePoint(...)100%11100%
File 1: KeepCloserTriangleSegmentPoint(...)100%22100%
File 1: GetClosestTriangleSegmentPoint(...)100%66100%
File 1: GetTriangleSquaredDistanceNumerator(...)100%11100%
File 1: GetPointEdgeDotNumerator(...)100%11100%
File 1: GetTrianglePointDeltaNumerator(...)100%11100%
File 1: ScaleTriangleDot(...)100%11100%
File 1: GetTriangleUnitRatio(...)100%11100%
File 1: GetTriangleDifferenceDot(...)100%11100%
File 1: GetPointLocalNumerators(...)100%44100%
File 1: GetTriangleRotatedPointCoordinate(...)100%44100%
File 1: GetTriangleFrameCoordinateNumerator(...)100%11100%
File 2: TryGetContact(...)100%44100%
File 2: TryGetPenetration(...)100%1818100%
File 2: TryKeepPairAxis(...)100%2020100%
File 2: GetProjectionInterval(...)100%11100%
File 2: GetLocalEdge(...)100%44100%
File 3: TryGetEdgeCoverage(...)100%2828100%
File 3: GetCoveragePoint(...)100%11100%
File 3: CoverageDifference(...)100%11100%
File 3: CoverageCross(...)100%11100%
File 3: CoverageHalfPlane(...)100%22100%
File 4: LocateEdgePoint(...)100%3434100%
File 4: EdgePointValue(...)100%11100%
File 5: TryGetClosestNonparallelSegmentParameters(...)100%88100%
File 5: TryGetSegmentPointAnchor(...)100%11100%
File 5: TryGetSegmentPointAnchor(...)100%11100%
File 5: TryGetSegmentPointAnchor(...)100%44100%
File 5: LocateEdgePoint(...)100%11100%
File 5: LocateEdgePoint(...)100%11100%
File 5: LocateFrameEdgePoint(...)100%11100%
File 5: LocatePointOnFrameEdge(...)100%11100%
File 5: LocateFrameEdgePoint(...)100%5252100%
File 5: EvaluateScaledEdgePoint(...)100%11100%
File 5: TryGetEdgeCoverage(...)100%2424100%
File 5: TryGetContact(...)100%1414100%
File 5: ContainsProjection(...)100%11100%
File 5: ContainsProjection(...)100%66100%
File 5: TryGetProjectedPointAnchor(...)100%11100%
File 5: TryGetProjectedPointAnchor(...)100%11100%
File 5: TryGetProjectedPlanePointAnchor(...)100%11100%
File 5: TryGetProjectedPointAnchor(...)100%2020100%
File 5: TryGetProjectedSegmentInterval(...)100%11100%
File 5: TryGetProjectedSegmentInterval(...)100%66100%
File 5: TryGetProjectedRectangleInterval(...)100%11100%
File 5: TryGetProjectedRectangleInterval(...)100%2828100%
File 5: ClipProjectedRectangleWall(...)100%1616100%
File 5: TryGetProjectedSegmentFaceAnchors(...)100%11100%
File 5: TryGetProjectedFrameSegmentFaceAnchors(...)100%2424100%
File 5: TryGetProjectedRectangleFaceAnchors(...)100%11100%
File 5: TryGetProjectedSegmentFaceWitness(...)100%4646100%
File 5: ClipScaledHalfPlane(...)100%1616100%
File 5: GetScaledTriangleHalfPlanes(...)100%11100%
File 5: GetScaledTriangleHalfPlanes(...)100%44100%
File 5: GetScaledTriangleLocalNormal(...)100%22100%
File 5: GetScaledPointDifference(...)100%11100%
File 5: DotScaledDirections(...)100%11100%
File 6: GetScaledAreaAndNormal(...)100%11100%
File 6: TryGetProjectedSupportContact(...)100%88100%
File 6: TryGetSegmentIntersection(...)100%1616100%
File 6: TryGetClosestPointAnchor(...)100%11100%
File 6: TryGetClosestPointAnchor(...)100%11100%
File 6: TryGetClosestPointAnchor(...)100%3232100%
File 6: MaterializeScaledSegmentPoint(...)100%11100%
File 6: TryMaterializeScaledEdge(...)100%11100%
File 7: TryGetSweptSphereDistance(...)100%3030100%
File 7: TryGetScaledSphereFeatureRoot(...)100%3636100%
File 7: Difference(...)100%11100%
File 7: Multiply(...)100%11100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Triangles/WideTriangleRelations.ClosestPoint.cs

#LineLine coverage
 1//=======================================================================
 2// WideTriangleRelations.ClosestPoint.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/// Provides the exact closest-point reducer for rigid triangle frames.
 14/// </content>
 15internal static partial class WideTriangleRelations
 16{
 17    // Tests the orthogonal projection inclusively, without materializing the
 18    // point or its barycentric coordinates. A degenerate face has no interior.
 19    internal static bool ContainsProjection(
 20        FixedTriangle triangle,
 21        Vector3d triangleOrigin,
 22        FixedQuaternion triangleRotation,
 23        in FixedPointAnchor point)
 24    {
 46425        return TryGetProjectionBarycentrics(triangle, triangleOrigin, triangleRotation, point,
 46426                out Signed576 va, out Signed576 vb, out Signed576 vc)
 46427            && va.Sign >= 0 && vb.Sign >= 0 && vc.Sign >= 0;
 28    }
 29
 30    private static bool TryGetProjectionBarycentrics(
 31        FixedTriangle triangle, Vector3d triangleOrigin, FixedQuaternion triangleRotation,
 32        in FixedPointAnchor point, out Signed576 va, out Signed576 vb, out Signed576 vc)
 33    {
 133734        Signed192 abAb = GetTriangleDifferenceDot(triangle.B, triangle.A, triangle.B, triangle.A);
 133735        Signed192 abAc = GetTriangleDifferenceDot(triangle.B, triangle.A, triangle.C, triangle.A);
 133736        Signed192 acAc = GetTriangleDifferenceDot(triangle.C, triangle.A, triangle.C, triangle.A);
 133737        Signed320 gram = WideArithmetic.MultiplySubtract(abAb, acAc, abAc, abAc);
 133738        if (gram.Sign <= 0)
 39        {
 18040            va = vb = vc = default;
 18041            return false;
 42        }
 43
 115744        GetPointLocalNumerators(point, triangleOrigin, triangleRotation,
 115745            out Signed576 pointX, out Signed576 pointY, out Signed576 pointZ,
 115746            out Signed320 pointDenominator);
 115747        Signed576 d1 = GetPointEdgeDotNumerator(pointX, pointY, pointZ,
 115748            pointDenominator, triangle.A, triangle.B);
 115749        Signed576 d2 = GetPointEdgeDotNumerator(pointX, pointY, pointZ,
 115750            pointDenominator, triangle.A, triangle.C);
 115751        vb = WideArithmetic.SubtractSigned576(
 115752            WideArithmetic.MultiplySigned576(d1, acAc),
 115753            WideArithmetic.MultiplySigned576(d2, abAc));
 115754        vc = WideArithmetic.SubtractSigned576(
 115755            WideArithmetic.MultiplySigned576(d2, abAb),
 115756            WideArithmetic.MultiplySigned576(d1, abAc));
 115757        va = WideArithmetic.SubtractSigned576(
 115758            WideArithmetic.SubtractSigned576(
 115759                WideArithmetic.MultiplySigned320(gram, pointDenominator), vb), vc);
 115760        return true;
 61    }
 62
 63    internal static bool TryGetProjectedSegmentInterval(
 64        FixedTriangle triangle, Vector3d origin, FixedQuaternion rotation,
 65        in FixedPointAnchor first, in FixedPointAnchor second,
 66        out Signed832 lowerN, out Signed832 lowerD, out Signed832 upperN, out Signed832 upperD)
 67    {
 34468        if (TryGetProjectionBarycentrics(triangle, origin, rotation, first,
 34469                out Signed576 firstA, out Signed576 firstB, out Signed576 firstC))
 70        {
 26171            _ = TryGetProjectionBarycentrics(triangle, origin, rotation, second,
 26172                out Signed576 secondA, out Signed576 secondB, out Signed576 secondC);
 26173            Span<Signed576> firstValues = stackalloc Signed576[3] { firstA, firstB, firstC };
 26174            Span<Signed576> secondValues = stackalloc Signed576[3] { secondA, secondB, secondC };
 52275            lowerN = default; lowerD = Signed832.ExtendValue(Signed192.Signed(1));
 52276            upperN = lowerD; upperD = lowerD;
 174877            for (int index = 0; index < 3; index++)
 78            {
 70679                if (firstValues[index].Sign < 0 && secondValues[index].Sign < 0)
 80                {
 9381                    lowerN = lowerD = upperN = upperD = default;
 9382                    return false;
 83                }
 61384                if (firstValues[index].Sign >= 0 && secondValues[index].Sign >= 0)
 85                    continue;
 27986                Signed576 difference = WideArithmetic.SubtractSigned576(secondValues[index], firstValues[index]);
 27987                Signed832 n = Signed832.ExtendValue(WideArithmetic.SubtractSigned576(default, firstValues[index]));
 27988                Signed832 d = Signed832.ExtendValue(difference);
 27989                if (d.Sign < 0)
 90                {
 14691                    n = WideArithmetic.SubtractSigned832(default, n);
 14692                    d = WideArithmetic.SubtractSigned832(default, d);
 14693                    if (WideArithmetic.CompareNonNegativeProducts(n, upperD, upperN, d) < 0)
 28894                    { upperN = n; upperD = d; }
 95                }
 13396                else if (WideArithmetic.CompareNonNegativeProducts(n, lowerD, lowerN, d) > 0)
 26497                { lowerN = n; lowerD = d; }
 98            }
 16899            if (WideArithmetic.CompareNonNegativeProducts(lowerN, upperD, upperN, lowerD) > 0)
 100            {
 17101                lowerN = lowerD = upperN = upperD = default;
 17102                return false;
 103            }
 151104            return true;
 105        }
 83106        lowerN = lowerD = upperN = upperD = default;
 83107        return false;
 108    }
 109
 110    internal static bool TryGetProjectedSegmentFaceAnchors(
 111        FixedTriangle triangle, Vector3d origin, FixedQuaternion rotation,
 112        in FixedPointAnchor first, in FixedPointAnchor second, Signed832 n, Signed832 d,
 113        int physicalBoundaryMask, out FixedPointAnchor source, out FixedPointAnchor target,
 114        bool requirePhysicalTargetBoundary = true, bool materialize = true)
 115    {
 87116        source = target = default;
 117        System.Diagnostics.Debug.Assert(first.Origin == second.Origin && first.Rotation == second.Rotation
 118            && first.ExactLocalTerm.IsZero && second.ExactLocalTerm.IsZero);
 87119        bool nondegenerate = TryGetProjectionBarycentrics(triangle, origin, rotation, first,
 87120            out Signed576 a0, out Signed576 b0, out Signed576 c0);
 121        System.Diagnostics.Debug.Assert(nondegenerate);
 87122        _ = TryGetProjectionBarycentrics(triangle, origin, rotation, second,
 87123            out Signed576 a1, out Signed576 b1, out Signed576 c1);
 87124        Span<Signed576> start = stackalloc Signed576[3] { a0, b0, c0 };
 87125        Span<Signed576> end = stackalloc Signed576[3] { a1, b1, c1 };
 87126        Span<ulong> magnitude = stackalloc ulong[13];
 174127        int coefficientWords = 1, parameterWords = 1;
 696128        for (int index = 0; index < 3; index++)
 129        {
 522130            magnitude.Clear(); WideArithmetic.GetMagnitude(start[index], magnitude);
 261131            coefficientWords = Math.Max(coefficientWords, WideArithmetic.GetActiveMagnitudeLength(magnitude));
 522132            magnitude.Clear(); WideArithmetic.GetMagnitude(end[index], magnitude);
 261133            coefficientWords = Math.Max(coefficientWords, WideArithmetic.GetActiveMagnitudeLength(magnitude));
 134        }
 87135        WideArithmetic.GetMagnitude(n, magnitude);
 87136        parameterWords = Math.Max(parameterWords, WideArithmetic.GetActiveMagnitudeLength(magnitude));
 87137        WideArithmetic.GetMagnitude(d, magnitude);
 87138        parameterWords = Math.Max(parameterWords, WideArithmetic.GetActiveMagnitudeLength(magnitude));
 139        // Products need both original coefficient widths, one raw-coordinate limb and sum carries.
 87140        int words = Math.Max(9, coefficientWords + parameterWords + 3);
 174141        Span<ulong> values = stackalloc ulong[20 * words]; Span<int> signs = stackalloc int[20];
 87142        ContactQuadratic parameter = ContactQuadratic.At(values, signs, 0, words),
 174143            divisor = ContactQuadratic.At(values, signs, 1, words), remaining = ContactQuadratic.At(values, signs, 2, wo
 174144            denominator = ContactQuadratic.At(values, signs, 6, words), numerator = ContactQuadratic.At(values, signs, 7
 174145            term = ContactQuadratic.At(values, signs, 8, words), coefficient = ContactQuadratic.At(values, signs, 9, wor
 348146        Import(n, parameter); Import(d, divisor); divisor.CopyTo(remaining); remaining.Add(parameter, -1);
 147        System.Diagnostics.Debug.Assert(n.Sign > 0 && remaining.Signs[0] > 0);
 87148        bool physical = false;
 87149        denominator.Clear();
 696150        for (int index = 0; index < 3; index++)
 151        {
 261152            ContactQuadratic barycentric = ContactQuadratic.At(values, signs, 3 + index, words);
 522153            coefficient.Set(start[index]); ContactQuadratic.Multiply(coefficient, remaining, ReadOnlySpan<ulong>.Empty, 
 522154            coefficient.Set(end[index]); ContactQuadratic.Multiply(coefficient, parameter, ReadOnlySpan<ulong>.Empty, te
 261155            barycentric.Add(term);
 156            System.Diagnostics.Debug.Assert(barycentric.Signs[0] >= 0);
 261157            physical |= barycentric.Signs[0] == 0 && (physicalBoundaryMask & (1 << index)) != 0;
 261158            denominator.Add(barycentric);
 159        }
 127160        if (requirePhysicalTargetBoundary && !physical) return false;
 48161        if (!materialize) return true;
 92162        Vector3d sourcePoint = default, targetPoint = default;
 46163        Span<Vector3d> corners = stackalloc Vector3d[3] { triangle.A, triangle.B, triangle.C };
 368164        for (int axis = 0; axis < 3; axis++)
 165        {
 138166            ContactQuadratic.Scale(remaining, Signed576.ExtendValue(Signed320.ExtendValue(Signed192.Raw(first.LocalPoint
 138167            ContactQuadratic.Scale(parameter, Signed576.ExtendValue(Signed320.ExtendValue(Signed192.Raw(second.LocalPoin
 276168            numerator.Add(term); sourcePoint[axis] = ContactQuadratic.RoundRatio(numerator, divisor, ReadOnlySpan<ulong>
 138169            numerator.Clear();
 1104170            for (int index = 0; index < 3; index++)
 171            {
 414172                ContactQuadratic.Scale(ContactQuadratic.At(values, signs, 3 + index, words),
 414173                    Signed576.ExtendValue(Signed320.ExtendValue(Signed192.Raw(corners[index][axis]))), term);
 414174                numerator.Add(term);
 175            }
 138176            targetPoint[axis] = ContactQuadratic.RoundRatio(numerator, denominator, ReadOnlySpan<ulong>.Empty);
 177        }
 46178        source = new FixedPointAnchor(first.Origin, first.Rotation, sourcePoint);
 46179        target = new FixedPointAnchor(origin, rotation, targetPoint);
 46180        return true;
 181
 182        static void Import(Signed832 value, ContactQuadratic destination)
 183        {
 184            Span<ulong> magnitude = stackalloc ulong[13]; WideArithmetic.GetMagnitude(value, magnitude);
 185            destination.Clear(); magnitude[..WideArithmetic.GetActiveMagnitudeLength(magnitude)].CopyTo(destination.Rati
 186            destination.Signs[0] = value.Sign;
 187        }
 188    }
 189
 190    // Clips the exact finite core projection before either witness is rounded.
 191    // Endpoint terms share a denominator, including odd raw half-length residues.
 192    internal static bool TryGetProjectedCoreParameter(
 193        FixedTriangle triangle, Vector3d origin, FixedQuaternion rotation,
 194        in FixedPointAnchor firstCoreEnd, in FixedPointAnchor secondCoreEnd,
 195        Vector3d coreCenter, FixedQuaternion coreRotation, Vector3d coreAxis,
 196        Fixed64 coreLength, out Signed832 numerator, out Signed832 denominator)
 197    {
 139198        if (TryGetProjectedSegmentInterval(triangle, origin, rotation, firstCoreEnd, secondCoreEnd,
 139199                out Signed832 lowerN, out Signed832 lowerD, out Signed832 upperN, out Signed832 upperD))
 200        {
 45201            Signed832 twiceLower = WideArithmetic.AddSigned832(lowerN, lowerN);
 45202            Signed832 twiceUpper = WideArithmetic.AddSigned832(upperN, upperN);
 45203            Signed832 one = Signed832.ExtendValue(Signed192.Signed(1));
 90204            Signed832 chosenN = default, chosenD = one;
 45205            if (WideArithmetic.CompareNonNegativeProducts(twiceLower, one, lowerD, one) > 0)
 34206            { chosenN = WideArithmetic.SubtractSigned832(twiceLower, lowerD); chosenD = lowerD; }
 28207            else if (WideArithmetic.CompareNonNegativeProducts(twiceUpper, one, upperD, one) < 0)
 54208            { chosenN = WideArithmetic.SubtractSigned832(twiceUpper, upperD); chosenD = upperD; }
 209            // Raw axial s = length * (2t - 1) / 2; fits 512 significant bits.
 45210            numerator = WideArithmetic.MultiplySigned832(chosenN, Signed192.Raw(coreLength));
 45211            denominator = WideArithmetic.AddSigned832(chosenD, chosenD);
 45212            return true;
 213        }
 214
 94215        if (TryGetProjectionBarycentrics(triangle, origin, rotation, firstCoreEnd, out _, out _, out _))
 216        {
 11217            numerator = denominator = default;
 11218            return false;
 219        }
 220        // A degenerate triangle owns its complete finite edge. Ranking its
 221        // duplicated vertices separately could replace a valid interior foot
 222        // with a closer-to-midpoint parameter that has tangential separation.
 166223        Vector3d start = triangle.A, end = triangle.B;
 83224        Signed192 longest = GetTriangleDifferenceDot(triangle.B, triangle.A, triangle.B, triangle.A);
 83225        Signed192 bc = GetTriangleDifferenceDot(triangle.C, triangle.B, triangle.C, triangle.B);
 83226        if (WideArithmetic.SubtractSigned192(bc, longest).Sign > 0)
 3227        { start = triangle.B; end = triangle.C; longest = bc; }
 83228        Signed192 ca = GetTriangleDifferenceDot(triangle.A, triangle.C, triangle.A, triangle.C);
 83229        if (WideArithmetic.SubtractSigned192(ca, longest).Sign > 0)
 2230        { start = triangle.C; end = triangle.A; }
 83231        return TryGetProjectedSegmentCoreParameter(
 83232            new FixedPointAnchor(origin, rotation, start),
 83233            new FixedPointAnchor(origin, rotation, end), coreCenter, coreRotation,
 83234            coreAxis, coreLength, out numerator, out denominator);
 235    }
 236
 237    private static bool TryGetProjectedSegmentCoreParameter(
 238        in FixedPointAnchor start, in FixedPointAnchor end, Vector3d center,
 239        FixedQuaternion rotation, Vector3d axis, Fixed64 length,
 240        out Signed832 numerator, out Signed832 denominator)
 241    {
 83242        GetPointLocalNumerators(start, center, rotation, out Signed576 px, out Signed576 py,
 83243            out Signed576 pz, out Signed320 pointD);
 83244        GetPointLocalNumerators(end, center, rotation, out Signed576 ex, out Signed576 ey,
 83245            out Signed576 ez, out _);
 83246        ex = WideArithmetic.SubtractSigned576(ex, px);
 83247        ey = WideArithmetic.SubtractSigned576(ey, py);
 83248        ez = WideArithmetic.SubtractSigned576(ez, pz);
 83249        Signed576 ux = Signed576.ExtendValue(Signed320.ExtendValue(Signed192.Raw(axis.X)));
 83250        Signed576 uy = Signed576.ExtendValue(Signed320.ExtendValue(Signed192.Raw(axis.Y)));
 83251        Signed576 uz = Signed576.ExtendValue(Signed320.ExtendValue(Signed192.Raw(axis.Z)));
 83252        Signed192 aa = Signed192.NarrowValue(WideArithmetic.GetDotProduct3D(
 83253            Signed192.Raw(axis.X), Signed192.Raw(axis.Y), Signed192.Raw(axis.Z),
 83254            Signed192.Raw(axis.X), Signed192.Raw(axis.Y), Signed192.Raw(axis.Z)));
 83255        Signed576 bb = GetProjectedCoreDot(ex, ey, ez, ex, ey, ez);
 83256        Signed320 ab = Signed320.NarrowValue(GetProjectedCoreDot(ex, ey, ez, ux, uy, uz));
 83257        Signed320 ao = Signed320.NarrowValue(GetProjectedCoreDot(px, py, pz, ux, uy, uz));
 83258        Signed576 bo = GetProjectedCoreDot(ex, ey, ez, px, py, pz);
 83259        Signed576 determinant = WideArithmetic.SubtractSigned576(
 83260            WideArithmetic.MultiplySigned576(bb, aa), WideArithmetic.MultiplySigned320(ab, ab));
 83261        if (determinant.IsZero)
 262        {
 24263            Signed320 second = WideArithmetic.AddSigned320(ao, ab);
 24264            Signed320 chosen = default;
 24265            if (ao.Sign > 0 && second.Sign > 0)
 10266                chosen = WideArithmetic.SubtractSigned320(ao, second).Sign <= 0 ? ao : second;
 14267            else if (ao.Sign < 0 && second.Sign < 0)
 5268                chosen = WideArithmetic.SubtractSigned320(ao, second).Sign >= 0 ? ao : second;
 24269            numerator = WideArithmetic.MultiplySigned832(Signed832.ExtendValue(Signed576.ExtendValue(chosen)), Signed192
 24270            denominator = Signed832.ExtendValue(WideArithmetic.MultiplySigned320(pointD, Signed320.ExtendValue(aa)));
 271        }
 272        else
 273        {
 59274            GetClosestNonparallelLineNumerators(aa, bb, ab, ao, bo, out Signed576 edgeN, out Signed704 coreN);
 59275            if (edgeN.Sign < 0 || WideArithmetic.SubtractSigned576(determinant, edgeN).Sign < 0)
 2276            { numerator = denominator = default; return false; }
 277            // Normalized bases have <=65-bit coefficients and denominators.
 278            // Raw-origin differences and transformed points fit 201 bits;
 279            // Gram products fit 476, axial ratios 680, and final coordinates
 280            // 744 signed bits. All products therefore fit their wide owners.
 58281            numerator = WideArithmetic.MultiplySigned704ToSigned832(coreN, Signed192.One);
 58282            denominator = Signed832.ExtendValue(WideArithmetic.MultiplySigned576ToSigned704(determinant, pointD));
 283        }
 82284        Signed832 magnitude = numerator.Sign < 0 ? WideArithmetic.SubtractSigned832(default, numerator) : numerator;
 82285        return WideArithmetic.SubtractSigned832(
 82286            WideArithmetic.MultiplySigned832(denominator, Signed192.Raw(length)),
 82287            WideArithmetic.AddSigned832(magnitude, magnitude)).Sign >= 0;
 288    }
 289
 290    private static void GetClosestNonparallelLineNumerators(Signed192 aa, Signed576 bb,
 291        Signed320 ab, Signed320 ao, Signed576 bo, out Signed576 edgeN, out Signed704 coreN)
 292    {
 143293        edgeN = WideArithmetic.SubtractSigned576(
 143294            WideArithmetic.MultiplySigned320(ab, ao), WideArithmetic.MultiplySigned576(bo, aa));
 143295        coreN = WideArithmetic.SubtractSigned704(WideArithmetic.MultiplySigned576ToSigned704(bb, ao),
 143296            WideArithmetic.MultiplySigned576ToSigned704(bo, ab));
 143297    }
 298
 299    /// <summary>Retains both closed finite line-foot parameters before witness rounding.</summary>
 300    internal static bool TryGetClosestNonparallelSegmentParameters(
 301        Vector3d firstOrigin, FixedQuaternion firstRotation, FixedSegment first,
 302        Vector3d secondOrigin, FixedQuaternion secondRotation, FixedSegment second,
 303        out Signed832 firstNumerator, out Signed832 firstDenominator,
 304        out Signed832 secondNumerator, out Signed832 secondDenominator)
 305    {
 159306        firstNumerator = firstDenominator = secondNumerator = secondDenominator = default;
 159307        GetPointLocalNumerators(new FixedPointAnchor(firstOrigin, firstRotation, first.Start), secondOrigin, secondRotat
 159308            out Signed576 px, out Signed576 py, out Signed576 pz, out Signed320 pointD);
 159309        GetPointLocalNumerators(new FixedPointAnchor(firstOrigin, firstRotation, first.End), secondOrigin, secondRotatio
 159310            out Signed576 ex, out Signed576 ey, out Signed576 ez, out _);
 318311        ex = WideArithmetic.SubtractSigned576(ex, px); ey = WideArithmetic.SubtractSigned576(ey, py);
 159312        ez = WideArithmetic.SubtractSigned576(ez, pz);
 159313        px = WideArithmetic.SubtractSigned576(px, WideArithmetic.MultiplySigned320(pointD, Signed192.Raw(second.Start.X)
 159314        py = WideArithmetic.SubtractSigned576(py, WideArithmetic.MultiplySigned320(pointD, Signed192.Raw(second.Start.Y)
 159315        pz = WideArithmetic.SubtractSigned576(pz, WideArithmetic.MultiplySigned320(pointD, Signed192.Raw(second.Start.Z)
 159316        Signed576 ux = Signed576.ExtendValue(Signed320.ExtendValue(WideArithmetic.Difference(second.End.X, second.Start.
 159317            uy = Signed576.ExtendValue(Signed320.ExtendValue(WideArithmetic.Difference(second.End.Y, second.Start.Y))),
 159318            uz = Signed576.ExtendValue(Signed320.ExtendValue(WideArithmetic.Difference(second.End.Z, second.Start.Z)));
 159319        Signed192 aa = Signed192.NarrowValue(GetProjectedCoreDot(ux, uy, uz, ux, uy, uz));
 318320        Signed576 bb = GetProjectedCoreDot(ex, ey, ez, ex, ey, ez), bo = GetProjectedCoreDot(ex, ey, ez, px, py, pz);
 159321        Signed320 ab = Signed320.NarrowValue(GetProjectedCoreDot(ex, ey, ez, ux, uy, uz)),
 159322            ao = Signed320.NarrowValue(GetProjectedCoreDot(px, py, pz, ux, uy, uz));
 159323        Signed576 determinant = WideArithmetic.SubtractSigned576(
 159324            WideArithmetic.MultiplySigned576(bb, aa), WideArithmetic.MultiplySigned320(ab, ab));
 234325        if (determinant.Sign <= 0) return false;
 84326        GetClosestNonparallelLineNumerators(aa, bb, ab, ao, bo, out Signed576 firstN, out Signed704 secondN);
 84327        Signed704 secondD = WideArithmetic.MultiplySigned576ToSigned704(determinant, pointD);
 84328        if (firstN.Sign < 0 || WideArithmetic.SubtractSigned576(determinant, firstN).Sign < 0
 136329            || secondN.Sign < 0 || WideArithmetic.SubtractSigned704(secondD, secondN).Sign < 0) return false;
 330        // Rigid numerators fit 202 bits; line minors fit 540/680, and final local coordinates fit 744/808.
 64331        firstNumerator = Signed832.ExtendValue(firstN); firstDenominator = Signed832.ExtendValue(determinant);
 64332        secondNumerator = Signed832.ExtendValue(secondN); secondDenominator = Signed832.ExtendValue(secondD);
 32333        return true;
 334    }
 335
 336    internal static Vector3d MaterializeSegmentPoint(FixedSegment segment, Signed832 n, Signed832 d)
 337    {
 6338        Vector3d point = default;
 6339        Signed832 remaining = WideArithmetic.SubtractSigned832(d, n);
 48340        for (int axis = 0; axis < 3; axis++)
 341        {
 18342            Signed832 coordinate = WideArithmetic.AddSigned832(
 18343                WideArithmetic.MultiplySigned832(remaining, Signed192.Raw(segment.Start[axis])),
 18344                WideArithmetic.MultiplySigned832(n, Signed192.Raw(segment.End[axis])));
 18345            bool represented = Fixed64.TryGetSignedRawRatio(coordinate, d, 0, out Fixed64 component);
 18346            System.Diagnostics.Debug.Assert(represented); point[axis] = component;
 347        }
 6348        return point;
 349    }
 350
 351    private static Signed576 GetProjectedCoreDot(
 352        Signed576 ax, Signed576 ay, Signed576 az, Signed576 bx, Signed576 by, Signed576 bz) =>
 1127353        WideArithmetic.AddSigned576(WideArithmetic.AddSigned576(
 1127354            WideArithmetic.MultiplySigned320(Signed320.NarrowValue(ax), Signed320.NarrowValue(bx)),
 1127355            WideArithmetic.MultiplySigned320(Signed320.NarrowValue(ay), Signed320.NarrowValue(by))),
 1127356            WideArithmetic.MultiplySigned320(Signed320.NarrowValue(az), Signed320.NarrowValue(bz)));
 357
 358    internal static int CompareCoreParameters(Signed832 firstN, Signed832 firstD, Signed832 secondN, Signed832 secondD) 
 17359        WideArithmetic.CompareNonNegativeProducts(
 17360            firstN.Sign < 0 ? WideArithmetic.SubtractSigned832(default, firstN) : firstN, secondD,
 17361            secondN.Sign < 0 ? WideArithmetic.SubtractSigned832(default, secondN) : secondN, firstD);
 362
 363    internal static Vector3d MaterializeCorePoint(Vector3d axis, Signed832 numerator, Signed832 denominator)
 364    {
 307365        Signed832 scaledD = WideArithmetic.MultiplySigned832(denominator, Signed192.One);
 307366        _ = Fixed64.TryGetSignedRawRatio(WideArithmetic.MultiplySigned832(numerator, Signed192.Raw(axis.X)), scaledD, 0,
 307367        _ = Fixed64.TryGetSignedRawRatio(WideArithmetic.MultiplySigned832(numerator, Signed192.Raw(axis.Y)), scaledD, 0,
 307368        _ = Fixed64.TryGetSignedRawRatio(WideArithmetic.MultiplySigned832(numerator, Signed192.Raw(axis.Z)), scaledD, 0,
 307369        return new Vector3d(x, y, z);
 370    }
 371
 372    internal static FixedPointAnchor GetClosestPointAnchor(
 373        FixedTriangle triangle,
 374        Vector3d triangleOrigin,
 375        FixedQuaternion triangleRotation,
 376        in FixedPointAnchor point,
 377        bool preserveExactFace = false)
 378    {
 414379        GetPointLocalNumerators(
 414380            point,
 414381            triangleOrigin,
 414382            triangleRotation,
 414383            out Signed576 pointX,
 414384            out Signed576 pointY,
 414385            out Signed576 pointZ,
 414386            out Signed320 pointDenominator);
 414387        Vector3d closest = GetClosestTriangleLocalPoint(
 414388            triangle,
 414389            pointX,
 414390            pointY,
 414391            pointZ,
 414392            pointDenominator,
 414393            preserveExactFace);
 414394        return FixedPointAnchor.FromValidatedFrame(
 414395            triangleOrigin,
 414396            triangleRotation,
 414397            closest);
 398    }
 399
 400    private static Vector3d GetClosestTriangleLocalPoint(
 401        FixedTriangle triangle,
 402        Signed576 pointX,
 403        Signed576 pointY,
 404        Signed576 pointZ,
 405        Signed320 pointDenominator,
 406        bool preserveExactFace)
 407    {
 414408        Signed192 abAb = GetTriangleDifferenceDot(
 414409            triangle.B,
 414410            triangle.A,
 414411            triangle.B,
 414412            triangle.A);
 414413        Signed192 abAc = GetTriangleDifferenceDot(
 414414            triangle.B,
 414415            triangle.A,
 414416            triangle.C,
 414417            triangle.A);
 414418        Signed192 acAc = GetTriangleDifferenceDot(
 414419            triangle.C,
 414420            triangle.A,
 414421            triangle.C,
 414422            triangle.A);
 414423        Signed320 gram = WideArithmetic.MultiplySubtract(
 414424            abAb,
 414425            acAc,
 414426            abAc,
 414427            abAc);
 428        // A certified support footprint must retain even a tiny exact face.
 414429        if (preserveExactFace ? gram.Sign <= 0 : WideGeometry.IsQ128MagnitudeAtMostEpsilon(gram))
 430        {
 73431            return GetClosestTriangleEdgePoint(
 73432                triangle,
 73433                pointX,
 73434                pointY,
 73435                pointZ,
 73436                pointDenominator);
 437        }
 438
 341439        Signed576 d1 = GetPointEdgeDotNumerator(
 341440            pointX,
 341441            pointY,
 341442            pointZ,
 341443            pointDenominator,
 341444            triangle.A,
 341445            triangle.B);
 341446        Signed576 d2 = GetPointEdgeDotNumerator(
 341447            pointX,
 341448            pointY,
 341449            pointZ,
 341450            pointDenominator,
 341451            triangle.A,
 341452            triangle.C);
 341453        if (d1.Sign <= 0 && d2.Sign <= 0)
 3454            return triangle.A;
 455
 338456        Signed576 abAbScaled = ScaleTriangleDot(abAb, pointDenominator);
 338457        Signed576 abAcScaled = ScaleTriangleDot(abAc, pointDenominator);
 338458        Signed576 acAcScaled = ScaleTriangleDot(acAc, pointDenominator);
 338459        Signed576 d3 = WideArithmetic.SubtractSigned576(d1, abAbScaled);
 338460        Signed576 d4 = WideArithmetic.SubtractSigned576(d2, abAcScaled);
 338461        if (d3.Sign >= 0
 338462            && WideArithmetic.SubtractSigned576(d4, d3).Sign <= 0)
 463        {
 2464            return triangle.B;
 465        }
 466
 336467        Signed576 vc = WideArithmetic.SubtractSigned576(
 336468            WideArithmetic.MultiplySigned576(d2, abAb),
 336469            WideArithmetic.MultiplySigned576(d1, abAc));
 336470        if (vc.Sign <= 0 && d1.Sign >= 0 && d3.Sign <= 0)
 471        {
 11472            Fixed64 parameter = GetTriangleUnitRatio(d1, abAbScaled);
 11473            return Vector3d.Lerp(triangle.A, triangle.B, parameter);
 474        }
 475
 325476        Signed576 d5 = WideArithmetic.SubtractSigned576(d1, abAcScaled);
 325477        Signed576 d6 = WideArithmetic.SubtractSigned576(d2, acAcScaled);
 325478        if (d6.Sign >= 0
 325479            && WideArithmetic.SubtractSigned576(d5, d6).Sign <= 0)
 480        {
 2481            return triangle.C;
 482        }
 483
 323484        Signed576 vb = WideArithmetic.SubtractSigned576(
 323485            WideArithmetic.MultiplySigned576(d1, acAc),
 323486            WideArithmetic.MultiplySigned576(d2, abAc));
 323487        if (vb.Sign <= 0 && d2.Sign >= 0 && d6.Sign <= 0)
 488        {
 118489            Fixed64 parameter = GetTriangleUnitRatio(d2, acAcScaled);
 118490            return Vector3d.Lerp(triangle.A, triangle.C, parameter);
 491        }
 492
 205493        Signed576 d4MinusD3 = WideArithmetic.SubtractSigned576(d4, d3);
 205494        Signed576 d5MinusD6 = WideArithmetic.SubtractSigned576(d5, d6);
 205495        Signed576 gramScaled = WideArithmetic.MultiplySigned320(
 205496            gram,
 205497            pointDenominator);
 205498        Signed576 va = WideArithmetic.SubtractSigned576(
 205499            WideArithmetic.SubtractSigned576(gramScaled, vb),
 205500            vc);
 205501        if (va.Sign <= 0
 205502            && d4MinusD3.Sign >= 0
 205503            && d5MinusD6.Sign >= 0)
 504        {
 83505            Fixed64 parameter = GetTriangleUnitRatio(
 83506                d4MinusD3,
 83507                WideArithmetic.AddSigned576(d4MinusD3, d5MinusD6));
 83508            return Vector3d.Lerp(triangle.B, triangle.C, parameter);
 509        }
 510
 122511        Fixed64 weightB = GetTriangleUnitRatio(vb, gramScaled);
 122512        Fixed64 weightC = GetTriangleUnitRatio(vc, gramScaled);
 122513        return triangle.GetPoint(weightB, weightC);
 514    }
 515
 516    private static Vector3d GetClosestTriangleEdgePoint(
 517        FixedTriangle triangle,
 518        Signed576 pointX,
 519        Signed576 pointY,
 520        Signed576 pointZ,
 521        Signed320 pointDenominator)
 522    {
 73523        Vector3d best = GetClosestTriangleSegmentPoint(
 73524            triangle.A,
 73525            triangle.B,
 73526            pointX,
 73527            pointY,
 73528            pointZ,
 73529            pointDenominator);
 73530        KeepCloserTriangleSegmentPoint(
 73531            triangle.B,
 73532            triangle.C,
 73533            pointX,
 73534            pointY,
 73535            pointZ,
 73536            pointDenominator,
 73537            ref best);
 73538        KeepCloserTriangleSegmentPoint(
 73539            triangle.C,
 73540            triangle.A,
 73541            pointX,
 73542            pointY,
 73543            pointZ,
 73544            pointDenominator,
 73545            ref best);
 73546        return best;
 547    }
 548
 549    private static void KeepCloserTriangleSegmentPoint(
 550        Vector3d start,
 551        Vector3d end,
 552        Signed576 pointX,
 553        Signed576 pointY,
 554        Signed576 pointZ,
 555        Signed320 pointDenominator,
 556        ref Vector3d best)
 557    {
 146558        Vector3d candidate = GetClosestTriangleSegmentPoint(
 146559            start,
 146560            end,
 146561            pointX,
 146562            pointY,
 146563            pointZ,
 146564            pointDenominator);
 146565        Signed832 candidateDistance = GetTriangleSquaredDistanceNumerator(
 146566            pointX,
 146567            pointY,
 146568            pointZ,
 146569            pointDenominator,
 146570            candidate);
 146571        Signed832 bestDistance = GetTriangleSquaredDistanceNumerator(
 146572            pointX,
 146573            pointY,
 146574            pointZ,
 146575            pointDenominator,
 146576            best);
 146577        if (WideArithmetic.SubtractSigned832(
 146578                candidateDistance,
 146579                bestDistance).Sign < 0)
 580        {
 1581            best = candidate;
 582        }
 146583    }
 584
 585    private static Vector3d GetClosestTriangleSegmentPoint(
 586        Vector3d start,
 587        Vector3d end,
 588        Signed576 pointX,
 589        Signed576 pointY,
 590        Signed576 pointZ,
 591        Signed320 pointDenominator)
 592    {
 219593        Signed192 lengthSquared = GetTriangleDifferenceDot(
 219594            end,
 219595            start,
 219596            end,
 219597            start);
 219598        if (lengthSquared.Sign <= 0)
 81599            return start;
 600
 138601        Signed576 projection = GetPointEdgeDotNumerator(
 138602            pointX,
 138603            pointY,
 138604            pointZ,
 138605            pointDenominator,
 138606            start,
 138607            end);
 138608        if (projection.Sign <= 0)
 4609            return start;
 610
 134611        Signed576 scaledLength =
 134612            ScaleTriangleDot(lengthSquared, pointDenominator);
 134613        if (WideArithmetic.SubtractSigned576(
 134614                projection,
 134615                scaledLength).Sign >= 0)
 616        {
 4617            return end;
 618        }
 619
 130620        return Vector3d.Lerp(
 130621            start,
 130622            end,
 130623            GetTriangleUnitRatio(projection, scaledLength));
 624    }
 625
 626    private static Signed832 GetTriangleSquaredDistanceNumerator(
 627        Signed576 pointX,
 628        Signed576 pointY,
 629        Signed576 pointZ,
 630        Signed320 pointDenominator,
 631        Vector3d candidate)
 632    {
 292633        Signed576 x = GetTrianglePointDeltaNumerator(
 292634            pointX,
 292635            candidate.X,
 292636            pointDenominator);
 292637        Signed576 y = GetTrianglePointDeltaNumerator(
 292638            pointY,
 292639            candidate.Y,
 292640            pointDenominator);
 292641        Signed576 z = GetTrianglePointDeltaNumerator(
 292642            pointZ,
 292643            candidate.Z,
 292644            pointDenominator);
 292645        return WideArithmetic.AddSigned832(
 292646            WideArithmetic.AddSigned832(
 292647                WideArithmetic.MultiplySigned576ToSigned832(x, x),
 292648                WideArithmetic.MultiplySigned576ToSigned832(y, y)),
 292649            WideArithmetic.MultiplySigned576ToSigned832(z, z));
 650    }
 651
 652    private static Signed576 GetPointEdgeDotNumerator(
 653        Signed576 pointX,
 654        Signed576 pointY,
 655        Signed576 pointZ,
 656        Signed320 pointDenominator,
 657        Vector3d edgeStart,
 658        Vector3d edgeEnd)
 659    {
 3134660        Signed576 deltaX = GetTrianglePointDeltaNumerator(
 3134661            pointX,
 3134662            edgeStart.X,
 3134663            pointDenominator);
 3134664        Signed576 deltaY = GetTrianglePointDeltaNumerator(
 3134665            pointY,
 3134666            edgeStart.Y,
 3134667            pointDenominator);
 3134668        Signed576 deltaZ = GetTrianglePointDeltaNumerator(
 3134669            pointZ,
 3134670            edgeStart.Z,
 3134671            pointDenominator);
 3134672        Signed192 edgeX = WideArithmetic.SubtractSigned192(
 3134673            Signed192.Raw(edgeEnd.X),
 3134674            Signed192.Raw(edgeStart.X));
 3134675        Signed192 edgeY = WideArithmetic.SubtractSigned192(
 3134676            Signed192.Raw(edgeEnd.Y),
 3134677            Signed192.Raw(edgeStart.Y));
 3134678        Signed192 edgeZ = WideArithmetic.SubtractSigned192(
 3134679            Signed192.Raw(edgeEnd.Z),
 3134680            Signed192.Raw(edgeStart.Z));
 3134681        return WideArithmetic.AddSigned576(
 3134682            WideArithmetic.AddSigned576(
 3134683                WideArithmetic.MultiplySigned576(deltaX, edgeX),
 3134684                WideArithmetic.MultiplySigned576(deltaY, edgeY)),
 3134685            WideArithmetic.MultiplySigned576(deltaZ, edgeZ));
 686    }
 687
 688    private static Signed576 GetTrianglePointDeltaNumerator(
 689        Signed576 pointCoordinate,
 690        Fixed64 triangleCoordinate,
 691        Signed320 pointDenominator) =>
 10278692        WideArithmetic.SubtractSigned576(
 10278693            pointCoordinate,
 10278694            WideArithmetic.MultiplySigned320(
 10278695                Signed320.ExtendValue(Signed192.Raw(triangleCoordinate)),
 10278696                pointDenominator));
 697
 698    private static Signed576 ScaleTriangleDot(
 699        Signed192 value,
 700        Signed320 scale) =>
 1148701        WideArithmetic.MultiplySigned320(
 1148702            Signed320.ExtendValue(value),
 1148703            scale);
 704
 705    private static Fixed64 GetTriangleUnitRatio(
 706        Signed576 numerator,
 707        Signed576 denominator)
 708    {
 586709        _ = Fixed64.TryGetSignedRawRatio(
 586710            WideArithmetic.MultiplySigned576ToSigned704(
 586711                numerator,
 586712                Signed320.ExtendValue(Signed192.One)),
 586713            Signed704.ExtendValue(denominator),
 586714            out Fixed64 ratio);
 586715        return ratio;
 716    }
 717
 718    private static Signed192 GetTriangleDifferenceDot(
 719        Vector3d leftEnd,
 720        Vector3d leftStart,
 721        Vector3d rightEnd,
 722        Vector3d rightStart) =>
 5721723        WideGeometry.GetDifferenceDotProduct3D(
 5721724            leftEnd.X,
 5721725            leftStart.X,
 5721726            leftEnd.Y,
 5721727            leftStart.Y,
 5721728            leftEnd.Z,
 5721729            leftStart.Z,
 5721730            rightEnd.X,
 5721731            rightStart.X,
 5721732            rightEnd.Y,
 5721733            rightStart.Y,
 5721734            rightEnd.Z,
 5721735            rightStart.Z);
 736
 737    internal static void GetPointLocalNumerators(
 738        in FixedPointAnchor point,
 739        Vector3d frameOrigin,
 740        FixedQuaternion frameRotation,
 741        out Signed576 x,
 742        out Signed576 y,
 743        out Signed576 z,
 744        out Signed320 denominator)
 745    {
 3141746        WideRationalBasis3d pointBasis = new(point.Rotation);
 3141747        Signed192 pointDenominator = point.ExactLocalTerm.IsZero
 3141748            ? pointBasis.Denominator
 3141749            : Signed192.NarrowValue(WideArithmetic.MultiplySigned192(
 3141750                pointBasis.Denominator, FixedPointAnchorTerm3d.Denominator));
 3141751        Signed192 originX = WideArithmetic.SubtractSigned192(
 3141752            Signed192.Raw(point.Origin.X),
 3141753            Signed192.Raw(frameOrigin.X));
 3141754        Signed192 originY = WideArithmetic.SubtractSigned192(
 3141755            Signed192.Raw(point.Origin.Y),
 3141756            Signed192.Raw(frameOrigin.Y));
 3141757        Signed192 originZ = WideArithmetic.SubtractSigned192(
 3141758            Signed192.Raw(point.Origin.Z),
 3141759            Signed192.Raw(frameOrigin.Z));
 3141760        Signed320 rotatedX = GetTriangleRotatedPointCoordinate(
 3141761            point,
 3141762            pointBasis.Xx,
 3141763            pointBasis.Yx,
 3141764            pointBasis.Zx);
 3141765        Signed320 rotatedY = GetTriangleRotatedPointCoordinate(
 3141766            point,
 3141767            pointBasis.Xy,
 3141768            pointBasis.Yy,
 3141769            pointBasis.Zy);
 3141770        Signed320 rotatedZ = GetTriangleRotatedPointCoordinate(
 3141771            point,
 3141772            pointBasis.Xz,
 3141773            pointBasis.Yz,
 3141774            pointBasis.Zz);
 3141775        if (frameRotation == FixedQuaternion.Identity)
 776        {
 777            // The identity frame needs no projection or additional basis scale.
 2831778            denominator = Signed320.ExtendValue(pointDenominator);
 2831779            x = Signed576.ExtendValue(WideArithmetic.AddSigned320(
 2831780                WideArithmetic.MultiplySigned192(originX, pointDenominator), rotatedX));
 2831781            y = Signed576.ExtendValue(WideArithmetic.AddSigned320(
 2831782                WideArithmetic.MultiplySigned192(originY, pointDenominator), rotatedY));
 2831783            z = Signed576.ExtendValue(WideArithmetic.AddSigned320(
 2831784                WideArithmetic.MultiplySigned192(originZ, pointDenominator), rotatedZ));
 2831785            return;
 786        }
 310787        WideRationalBasis3d frameBasis = new(frameRotation);
 310788        denominator = WideArithmetic.MultiplySigned192(pointDenominator, frameBasis.Denominator);
 310789        x = GetTriangleFrameCoordinateNumerator(
 310790            originX,
 310791            originY,
 310792            originZ,
 310793            rotatedX,
 310794            rotatedY,
 310795            rotatedZ,
 310796            pointDenominator,
 310797            frameBasis.Xx,
 310798            frameBasis.Xy,
 310799            frameBasis.Xz);
 310800        y = GetTriangleFrameCoordinateNumerator(
 310801            originX,
 310802            originY,
 310803            originZ,
 310804            rotatedX,
 310805            rotatedY,
 310806            rotatedZ,
 310807            pointDenominator,
 310808            frameBasis.Yx,
 310809            frameBasis.Yy,
 310810            frameBasis.Yz);
 310811        z = GetTriangleFrameCoordinateNumerator(
 310812            originX,
 310813            originY,
 310814            originZ,
 310815            rotatedX,
 310816            rotatedY,
 310817            rotatedZ,
 310818            pointDenominator,
 310819            frameBasis.Zx,
 310820            frameBasis.Zy,
 310821            frameBasis.Zz);
 310822    }
 823
 824    private static Signed320 GetTriangleRotatedPointCoordinate(
 825        in FixedPointAnchor point,
 826        Signed192 axisX,
 827        Signed192 axisY,
 828        Signed192 axisZ)
 829    {
 9423830        Signed320 rounded = WideArithmetic.AddSigned320(
 9423831            WideArithmetic.GetDotProduct3D(
 9423832                Signed192.Raw(point.LocalPoint.X),
 9423833                Signed192.Raw(point.LocalPoint.Y),
 9423834                Signed192.Raw(point.LocalPoint.Z),
 9423835                axisX,
 9423836                axisY,
 9423837                axisZ),
 9423838            WideArithmetic.GetDotProduct3D(
 9423839                Signed192.Raw(point.LocalDisplacement.X),
 9423840                Signed192.Raw(point.LocalDisplacement.Y),
 9423841                Signed192.Raw(point.LocalDisplacement.Z),
 9423842                axisX,
 9423843                axisY,
 9423844                axisZ));
 9423845        if (point.LocalTranslation != Vector3d.Zero)
 9846            rounded = WideArithmetic.AddSigned320(rounded,
 9847                WideArithmetic.GetDotProduct3D(
 9848                    Signed192.Raw(point.LocalTranslation.X),
 9849                    Signed192.Raw(point.LocalTranslation.Y),
 9850                    Signed192.Raw(point.LocalTranslation.Z), axisX, axisY, axisZ));
 9423851        if (point.ExactLocalTerm.IsZero)
 8853852            return rounded;
 853
 854        // Normalized rational bases, three scalar feature components and the
 855        // shared 33-bit residual denominator fit well within Signed320. The
 856        // frame transform and barycentric products remain within Signed576.
 570857        Signed576 scaled = WideArithmetic.MultiplySigned320(rounded,
 570858            Signed320.ExtendValue(FixedPointAnchorTerm3d.Denominator));
 570859        Signed320 residual = WideArithmetic.GetDotProduct3D(
 570860            Signed192.Signed(point.ExactLocalTerm.X),
 570861            Signed192.Signed(point.ExactLocalTerm.Y),
 570862            Signed192.Signed(point.ExactLocalTerm.Z), axisX, axisY, axisZ);
 570863        return WideArithmetic.AddSigned320(Signed320.NarrowValue(scaled), residual);
 864    }
 865
 866    private static Signed576 GetTriangleFrameCoordinateNumerator(
 867        Signed192 originX,
 868        Signed192 originY,
 869        Signed192 originZ,
 870        Signed320 rotatedX,
 871        Signed320 rotatedY,
 872        Signed320 rotatedZ,
 873        Signed192 pointDenominator,
 874        Signed192 frameAxisX,
 875        Signed192 frameAxisY,
 876        Signed192 frameAxisZ)
 877    {
 930878        Signed320 originProjection = WideArithmetic.GetDotProduct3D(
 930879            originX,
 930880            originY,
 930881            originZ,
 930882            frameAxisX,
 930883            frameAxisY,
 930884            frameAxisZ);
 930885        Signed576 rotatedProjection = WideArithmetic.AddSigned576(
 930886            WideArithmetic.AddSigned576(
 930887                WideArithmetic.MultiplySigned320(
 930888                    rotatedX,
 930889                    Signed320.ExtendValue(frameAxisX)),
 930890                WideArithmetic.MultiplySigned320(
 930891                    rotatedY,
 930892                    Signed320.ExtendValue(frameAxisY))),
 930893            WideArithmetic.MultiplySigned320(
 930894                rotatedZ,
 930895                Signed320.ExtendValue(frameAxisZ)));
 930896        return WideArithmetic.AddSigned576(
 930897            WideArithmetic.MultiplySigned320(
 930898                originProjection,
 930899                Signed320.ExtendValue(pointDenominator)),
 930900            rotatedProjection);
 901    }
 902}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Triangles/WideTriangleRelations.cs

#LineLine coverage
 1//=======================================================================
 2// WideTriangleRelations.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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <summary>
 11/// Owns exact full-domain relations for <see cref="FixedTriangle"/>.
 12/// </summary>
 13/// <content>Provides exact contact relations between rigid triangles.</content>
 14internal static partial class WideTriangleRelations
 15{
 16    internal static bool TryGetContact(
 17        FixedTriangle first,
 18        Vector3d firstOrigin,
 19        FixedQuaternion firstRotation,
 20        FixedTriangle second,
 21        Vector3d secondOrigin,
 22        FixedQuaternion secondRotation,
 23        out FixedContactAnchors contact)
 24    {
 8925        if (!TryGetPenetration(first, firstOrigin, firstRotation, second, secondOrigin, secondRotation,
 8926            out WidePointSpanPenetration best))
 27        {
 1228            contact = default;
 1229            return false;
 30        }
 7731        WideAxis3 orientedAxis = best.Negate ? -best.Axis : best.Axis;
 7732        Vector3d normal = WideNormalization.GetNormalized(
 7733            Signed576.ExtendValue(orientedAxis.X),
 7734            Signed576.ExtendValue(orientedAxis.Y),
 7735            Signed576.ExtendValue(orientedAxis.Z));
 7736        FixedPointAnchor secondCentroid = FixedPointAnchor.FromValidatedFrame(
 7737            secondOrigin,
 7738            secondRotation,
 7739            second.Centroid);
 7740        FixedPointAnchor firstAnchor = GetClosestPointAnchor(
 7741            first,
 7742            firstOrigin,
 7743            firstRotation,
 7744            secondCentroid);
 7745        FixedPointAnchor secondAnchor = GetClosestPointAnchor(
 7746            second,
 7747            secondOrigin,
 7748            secondRotation,
 7749            firstAnchor);
 7750        Fixed64 depth = best.GetRoundedDepth(out bool depthIsClamped);
 7751        contact = new FixedContactAnchors(
 7752            firstAnchor,
 7753            secondAnchor,
 7754            normal,
 7755            depth,
 7756            depthIsClamped);
 7757        return true;
 58    }
 59
 60    /// <summary>Returns geometric overlap independently of whether the signed response filter admits a candidate.</summ
 61    internal static bool TryGetPenetration(
 62        FixedTriangle first,
 63        Vector3d firstOrigin,
 64        FixedQuaternion firstRotation,
 65        FixedTriangle second,
 66        Vector3d secondOrigin,
 67        FixedQuaternion secondRotation,
 68        out WidePointSpanPenetration best, PointSpanPenetrationAdmission? admission = null)
 69    {
 10670        best = default;
 10671        first.GetExactNormal(
 10672            out Signed192 firstNormalX,
 10673            out Signed192 firstNormalY,
 10674            out Signed192 firstNormalZ,
 10675            out Signed320 firstNormalSquared);
 10676        second.GetExactNormal(
 10677            out Signed192 secondNormalX,
 10678            out Signed192 secondNormalY,
 10679            out Signed192 secondNormalZ,
 10680            out Signed320 secondNormalSquared);
 10681        if (firstNormalSquared.IsZero || secondNormalSquared.IsZero)
 82        {
 283            return false;
 84        }
 85
 10486        WideRationalBasis3d firstBasis = new(firstRotation);
 10487        WideRationalBasis3d secondBasis = new(secondRotation);
 10488        WideAxis3 firstNormal = WideRigidProjection.TransformLocalAxis(
 10489            firstBasis,
 10490            firstNormalX,
 10491            firstNormalY,
 10492            firstNormalZ);
 10493        WideAxis3 secondNormal = WideRigidProjection.TransformLocalAxis(
 10494            secondBasis,
 10495            secondNormalX,
 10496            secondNormalY,
 10497            secondNormalZ);
 10498        if (!TryKeepPairAxis(
 10499                firstNormal,
 104100                first,
 104101                firstOrigin,
 104102                firstBasis,
 104103                second,
 104104                secondOrigin,
 104105                secondBasis,
 104106                ref best, admission)
 104107            || !TryKeepPairAxis(
 104108                secondNormal,
 104109                first,
 104110                firstOrigin,
 104111                firstBasis,
 104112                second,
 104113                secondOrigin,
 104114                secondBasis,
 104115                ref best, admission))
 116        {
 5117            return false;
 118        }
 119
 99120        for (int firstEdgeIndex = 0;
 359121            firstEdgeIndex < FixedTriangle.EdgeCount;
 260122            firstEdgeIndex++)
 123        {
 275124            GetLocalEdge(
 275125                first,
 275126                firstEdgeIndex,
 275127                out Signed192 firstEdgeX,
 275128                out Signed192 firstEdgeY,
 275129                out Signed192 firstEdgeZ);
 275130            WideAxis3 firstEdge = WideRigidProjection.TransformLocalAxis(
 275131                firstBasis,
 275132                firstEdgeX,
 275133                firstEdgeY,
 275134                firstEdgeZ);
 275135            if (!TryKeepPairAxis(
 275136                    WideRigidProjection.TransformLocalNormalCrossEdge(
 275137                        firstBasis,
 275138                        firstNormalX,
 275139                        firstNormalY,
 275140                        firstNormalZ,
 275141                        firstEdgeX,
 275142                        firstEdgeY,
 275143                        firstEdgeZ),
 275144                    first,
 275145                    firstOrigin,
 275146                    firstBasis,
 275147                    second,
 275148                    secondOrigin,
 275149                    secondBasis,
 275150                    ref best, admission))
 151            {
 10152                return false;
 153            }
 154
 265155            GetLocalEdge(
 265156                second,
 265157                firstEdgeIndex,
 265158                out Signed192 secondOwnEdgeX,
 265159                out Signed192 secondOwnEdgeY,
 265160                out Signed192 secondOwnEdgeZ);
 265161            if (!TryKeepPairAxis(
 265162                    WideRigidProjection.TransformLocalNormalCrossEdge(
 265163                        secondBasis,
 265164                        secondNormalX,
 265165                        secondNormalY,
 265166                        secondNormalZ,
 265167                        secondOwnEdgeX,
 265168                        secondOwnEdgeY,
 265169                        secondOwnEdgeZ),
 265170                    first,
 265171                    firstOrigin,
 265172                    firstBasis,
 265173                    second,
 265174                    secondOrigin,
 265175                    secondBasis,
 265176                    ref best, admission))
 177            {
 3178                return false;
 179            }
 180
 262181            for (int secondEdgeIndex = 0;
 1044182                secondEdgeIndex < FixedTriangle.EdgeCount;
 782183                secondEdgeIndex++)
 184            {
 784185                GetLocalEdge(
 784186                    second,
 784187                    secondEdgeIndex,
 784188                    out Signed192 secondEdgeX,
 784189                    out Signed192 secondEdgeY,
 784190                    out Signed192 secondEdgeZ);
 784191                WideAxis3 secondEdge = WideRigidProjection.TransformLocalAxis(
 784192                    secondBasis,
 784193                    secondEdgeX,
 784194                    secondEdgeY,
 784195                    secondEdgeZ);
 784196                if (!TryKeepPairAxis(
 784197                        WideAxis3.Cross(firstEdge, secondEdge),
 784198                        first,
 784199                        firstOrigin,
 784200                        firstBasis,
 784201                        second,
 784202                        secondOrigin,
 784203                        secondBasis,
 784204                        ref best, admission))
 205                {
 2206                    return false;
 207                }
 208            }
 209        }
 210
 84211        return true;
 212    }
 213
 214    private static bool TryKeepPairAxis(
 215        in WideAxis3 axis,
 216        in FixedTriangle first,
 217        Vector3d firstOrigin,
 218        in WideRationalBasis3d firstBasis,
 219        in FixedTriangle second,
 220        Vector3d secondOrigin,
 221        in WideRationalBasis3d secondBasis,
 222        ref WidePointSpanPenetration best, PointSpanPenetrationAdmission? admission)
 223    {
 1530224        if (axis.IsZero)
 103225            return true;
 226
 1427227        GetProjectionInterval(
 1427228            first,
 1427229            firstBasis,
 1427230            axis,
 1427231            secondBasis.Denominator,
 1427232            out Signed576 firstMinimum,
 1427233            out Signed576 firstMaximum,
 1427234            out Signed576 firstSum);
 1427235        GetProjectionInterval(
 1427236            second,
 1427237            secondBasis,
 1427238            axis,
 1427239            firstBasis.Denominator,
 1427240            out Signed576 secondMinimum,
 1427241            out Signed576 secondMaximum,
 1427242            out Signed576 secondSum);
 1427243        Signed576 originCommon = WideArithmetic.MultiplySigned576(
 1427244            WideArithmetic.MultiplySigned576(
 1427245                WideRigidProjection.GetWorldOriginDifferenceProjection(
 1427246                    secondOrigin,
 1427247                    firstOrigin,
 1427248                    axis),
 1427249                firstBasis.Denominator),
 1427250            secondBasis.Denominator);
 1427251        secondMinimum = WideArithmetic.AddSigned576(
 1427252            secondMinimum,
 1427253            originCommon);
 1427254        secondMaximum = WideArithmetic.AddSigned576(
 1427255            secondMaximum,
 1427256            originCommon);
 257
 1427258        Signed576 pushNegative = WideArithmetic.SubtractSigned576(
 1427259            firstMaximum,
 1427260            secondMinimum);
 1427261        Signed576 pushPositive = WideArithmetic.SubtractSigned576(
 1427262            secondMaximum,
 1427263            firstMinimum);
 1427264        if (pushNegative.Sign < 0 || pushPositive.Sign < 0)
 20265            return false;
 266
 1407267        Signed576 overlap = WideArithmetic.SubtractSigned576(
 1407268                pushPositive,
 1407269                pushNegative).Sign < 0
 1407270            ? pushPositive
 1407271            : pushNegative;
 1407272        Signed320 commonDenominator = WideArithmetic.MultiplySigned192(
 1407273            firstBasis.Denominator,
 1407274            secondBasis.Denominator);
 1407275        Signed576 squaredAxisLength = axis.SquaredLength;
 1407276        if (admission != null)
 277        {
 278            // Both signed exits retain the original projection intervals.
 279            // Filtering a seam response never removes its separating-axis test.
 142280            var negative = new WidePointSpanPenetration(axis, false, pushNegative, squaredAxisLength, commonDenominator)
 144281            if (best.ShouldReplace(pushNegative, squaredAxisLength, commonDenominator) && admission(negative)) best = ne
 142282            var positive = new WidePointSpanPenetration(axis, true, pushPositive, squaredAxisLength, commonDenominator);
 144283            if (best.ShouldReplace(pushPositive, squaredAxisLength, commonDenominator) && admission(positive)) best = po
 142284            return true;
 285        }
 1265286        if (!best.ShouldReplace(
 1265287                overlap,
 1265288                squaredAxisLength,
 1265289                commonDenominator))
 290        {
 1175291            return true;
 292        }
 293
 90294        Signed576 secondCentroidProjection = WideArithmetic.AddSigned576(
 90295            secondSum,
 90296            WideArithmetic.AddSigned576(
 90297                WideArithmetic.AddSigned576(originCommon, originCommon),
 90298                originCommon));
 90299        bool negate = WideArithmetic.SubtractSigned576(
 90300            secondCentroidProjection,
 90301            firstSum).Sign < 0;
 90302        best = new WidePointSpanPenetration(
 90303            axis,
 90304            negate,
 90305            overlap,
 90306            squaredAxisLength,
 90307            commonDenominator);
 90308        return true;
 309    }
 310
 311    private static void GetProjectionInterval(
 312        in FixedTriangle triangle,
 313        in WideRationalBasis3d basis,
 314        in WideAxis3 axis,
 315        Signed192 otherDenominator,
 316        out Signed576 minimum,
 317        out Signed576 maximum,
 318        out Signed576 sum)
 319    {
 2854320        WideRigidProjection.GetLocalAxisProjections(
 2854321            axis,
 2854322            basis,
 2854323            out Signed576 localAxisX,
 2854324            out Signed576 localAxisY,
 2854325            out Signed576 localAxisZ);
 2854326        Signed576 first = WideArithmetic.MultiplySigned576(
 2854327            WideRigidProjection.GetLocalOffsetProjection(
 2854328                triangle.A,
 2854329                localAxisX,
 2854330                localAxisY,
 2854331                localAxisZ),
 2854332            otherDenominator);
 2854333        minimum = first;
 2854334        maximum = first;
 2854335        Signed576 second = WideArithmetic.MultiplySigned576(
 2854336            WideRigidProjection.GetLocalOffsetProjection(
 2854337                triangle.B,
 2854338                localAxisX,
 2854339                localAxisY,
 2854340                localAxisZ),
 2854341            otherDenominator);
 2854342        Signed576 third = WideArithmetic.MultiplySigned576(
 2854343            WideRigidProjection.GetLocalOffsetProjection(
 2854344                triangle.C,
 2854345                localAxisX,
 2854346                localAxisY,
 2854347                localAxisZ),
 2854348            otherDenominator);
 2854349        WideRigidProjection.IncludeProjection(
 2854350            second,
 2854351            ref minimum,
 2854352            ref maximum);
 2854353        WideRigidProjection.IncludeProjection(
 2854354            third,
 2854355            ref minimum,
 2854356            ref maximum);
 2854357        sum = WideArithmetic.AddSigned576(
 2854358            WideArithmetic.AddSigned576(first, second),
 2854359            third);
 2854360    }
 361
 362    private static void GetLocalEdge(
 363        FixedTriangle triangle,
 364        int index,
 365        out Signed192 x,
 366        out Signed192 y,
 367        out Signed192 z)
 368    {
 369        Vector3d start;
 370        Vector3d end;
 1324371        if (index == 0)
 372        {
 456373            start = triangle.A;
 456374            end = triangle.B;
 375        }
 868376        else if (index == 1)
 377        {
 437378            start = triangle.B;
 437379            end = triangle.C;
 380        }
 381        else
 382        {
 431383            start = triangle.C;
 431384            end = triangle.A;
 385        }
 386
 1324387        x = WideArithmetic.SubtractSigned192(
 1324388            Signed192.Raw(end.X),
 1324389            Signed192.Raw(start.X));
 1324390        y = WideArithmetic.SubtractSigned192(
 1324391            Signed192.Raw(end.Y),
 1324392            Signed192.Raw(start.Y));
 1324393        z = WideArithmetic.SubtractSigned192(
 1324394            Signed192.Raw(end.Z),
 1324395            Signed192.Raw(start.Z));
 1324396    }
 397}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Triangles/WideTriangleRelations.EdgeCoverage.cs

#LineLine coverage
 1//=======================================================================
 2// WideTriangleRelations.EdgeCoverage.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>Exact coplanar triangle coverage of an independently framed edge.</content>
 13internal static partial class WideTriangleRelations
 14{
 15    /// <summary>
 16    /// Clips source A/B against target, preserving the original unit parameter.
 17    /// Bits 1/2 denote coplanar target fill on source C's/opposite side;
 18    /// bit 4 denotes a folded target incident along the source edge.
 19    /// Requires normalized rigid rotations and raw authored triangle vertices.
 20    /// Degenerate, off-plane and disjoint edges return false; singleton
 21    /// intersections remain closed and do not imply positive-length coverage.
 22    /// </summary>
 23    internal static bool TryGetEdgeCoverage(in FixedTriangle source, Vector3d sourceOrigin,
 24        FixedQuaternion sourceRotation, in FixedTriangle target, Vector3d targetOrigin,
 25        FixedQuaternion targetRotation, out RationalSegmentInterval interval, out int sides)
 26    {
 50827        interval = default; sides = 0;
 25428        source.GetExactNormal(out _, out _, out _, out Signed320 sourceNormalSquared);
 25429        target.GetExactNormal(out Signed192 nx, out Signed192 ny, out Signed192 nz, out Signed320 targetNormalSquared);
 26230        if (sourceNormalSquared.IsZero || targetNormalSquared.IsZero) return false;
 24631        int axis = !nx.IsZero ? 0 : !ny.IsZero ? 1 : 2;
 49232        int u = (axis + 1) % 3, v = (axis + 2) % 3;
 24633        Span<Vector3d> vertices = stackalloc Vector3d[3] { target.A, target.B, target.C };
 24634        Span<Signed320> points = stackalloc Signed320[9];
 24635        GetCoveragePoint(source.A, sourceOrigin, sourceRotation, targetOrigin, targetRotation, points, out Signed320 d);
 24636        GetCoveragePoint(source.B, sourceOrigin, sourceRotation, targetOrigin, targetRotation, points.Slice(3), out _);
 24637        GetCoveragePoint(source.C, sourceOrigin, sourceRotation, targetOrigin, targetRotation, points.Slice(6), out _);
 38        // A/B must lie in the target plane. C distinguishes a coplanar fill
 39        // from a folded incident sheet, which must not disappear at a seam.
 195240        for (int point = 0; point < 3; point++)
 41        {
 73342            Signed576 plane = WideArithmetic.AddSigned576(WideArithmetic.AddSigned576(
 73343                WideArithmetic.MultiplySigned576(Signed576.ExtendValue(CoverageDifference(points[3 * point], target.A.X,
 73344                WideArithmetic.MultiplySigned576(Signed576.ExtendValue(CoverageDifference(points[3 * point + 1], target.
 73345                WideArithmetic.MultiplySigned576(Signed576.ExtendValue(CoverageDifference(points[3 * point + 2], target.
 73346            if (plane.IsZero) continue;
 1247            if (point != 2) return false;
 648            sides = 4;
 49        }
 24350        Signed320 dx = WideArithmetic.SubtractSigned320(points[3 + u], points[u]);
 24351        Signed320 dy = WideArithmetic.SubtractSigned320(points[3 + v], points[v]);
 24352        int inward = CoverageCross(dx, dy, WideArithmetic.SubtractSigned320(points[6 + u], points[u]),
 24353            WideArithmetic.SubtractSigned320(points[6 + v], points[v])).Sign;
 24354        int orientation = (axis == 0 ? nx : axis == 1 ? ny : nz).Sign;
 97255        Signed320 lowerN = default, lowerD = Signed320.One, upperN = Signed320.One, upperD = Signed320.One;
 183456        for (int edge = 0; edge < 3; edge++)
 57        {
 139858            Vector3d a = vertices[edge], b = vertices[(edge + 1) % 3];
 69959            Signed320 f0 = CoverageHalfPlane(a, b, points[u], points[v], d, u, v, orientation);
 69960            Signed320 f1 = CoverageHalfPlane(a, b, points[3 + u], points[3 + v], d, u, v, orientation);
 72461            if (!RationalSegmentInterval.TryClipHalfPlane(f0, f1, ref lowerN, ref lowerD, ref upperN, ref upperD)) retur
 67462            if (sides == 4) continue;
 65663            int side = inward * CoverageCross(dx, dy,
 65664                CoverageDifference(points[u], a[u], d), CoverageDifference(points[v], a[v], d)).Sign;
 65            // The differences above point FROM the vertex to source A.
 69966            if (side < 0) sides |= 1;
 86967            if (side > 0) sides |= 2;
 68        }
 21869        interval = new RationalSegmentInterval(lowerN, lowerD, upperN, upperD);
 21870        return true;
 71    }
 72
 73    private static void GetCoveragePoint(Vector3d point, Vector3d origin, FixedQuaternion rotation,
 74        Vector3d targetOrigin, FixedQuaternion targetRotation, Span<Signed320> coordinates, out Signed320 d)
 75    {
 79676        GetPointLocalNumerators(new FixedPointAnchor(origin, rotation, point), targetOrigin, targetRotation,
 79677            out Signed576 x, out Signed576 y, out Signed576 z, out d);
 78        // Normalized raw-point frames: D < 132 bits, coordinates < 200 bits.
 79679        coordinates[0] = Signed320.NarrowValue(x);
 79680        coordinates[1] = Signed320.NarrowValue(y);
 79681        coordinates[2] = Signed320.NarrowValue(z);
 79682    }
 83
 84    private static Signed320 CoverageDifference(Signed320 mapped, Fixed64 raw, Signed320 d) =>
 652785        WideArithmetic.SubtractSigned320(mapped, Signed320.NarrowValue(
 652786            WideArithmetic.MultiplySigned320(d, Signed320.ExtendValue(Signed192.Raw(raw)))));
 87
 88    private static Signed576 CoverageCross(Signed320 dx, Signed320 dy, Signed320 x, Signed320 y) =>
 106389        WideArithmetic.SubtractSigned576(WideArithmetic.MultiplySigned320(dx, y), WideArithmetic.MultiplySigned320(dy, x
 90
 91    private static Signed320 CoverageHalfPlane(Vector3d a, Vector3d b, Signed320 x, Signed320 y,
 92        Signed320 d, int u, int v, int orientation)
 93    {
 139894        Signed192 dx = WideArithmetic.SubtractSigned192(Signed192.Raw(b[u]), Signed192.Raw(a[u]));
 139895        Signed192 dy = WideArithmetic.SubtractSigned192(Signed192.Raw(b[v]), Signed192.Raw(a[v]));
 139896        Signed576 value = WideArithmetic.SubtractSigned576(
 139897            WideArithmetic.MultiplySigned576(Signed576.ExtendValue(CoverageDifference(y, a[v], d)), dx),
 139898            WideArithmetic.MultiplySigned576(Signed576.ExtendValue(CoverageDifference(x, a[u], d)), dy));
 99        // Raw edges < 65 bits and mapped differences < 201: F and root N/D
 100        // stay below 268 bits. Side crosses stay below 403 bits (Signed576).
 1398101        return Signed320.NarrowValue(orientation < 0 ? WideArithmetic.SubtractSigned576(default, value) : value);
 102    }
 103
 104}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Triangles/WideTriangleRelations.EdgePointLocation.cs

#LineLine coverage
 1//=======================================================================
 2// WideTriangleRelations.EdgePointLocation.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>Bounded incidence of exact rational edge points across independent rigid frames.</content>
 13internal static partial class WideTriangleRelations
 14{
 15    /// <summary>
 16    /// Locates A + (B-A)*n/d on a target edge: -1 outside, 0 start,
 17    /// 1 strict interior, 2 end. A degenerate target has only a start.
 18    /// Requires normalized rigid rotations and a nonnegative unit parameter.
 19    /// </summary>
 20    internal static int LocateEdgePoint(FixedSegment source, Vector3d sourceOrigin, FixedQuaternion sourceRotation,
 21        Signed320 n, Signed320 d, FixedSegment target, Vector3d targetOrigin, FixedQuaternion targetRotation,
 22        in RationalSegmentInterval targetInterval = default)
 23    {
 2924        Span<Signed320> points = stackalloc Signed320[6];
 2925        GetCoveragePoint(source.Start, sourceOrigin, sourceRotation, targetOrigin, targetRotation, points, out Signed320
 2926        GetCoveragePoint(source.End, sourceOrigin, sourceRotation, targetOrigin, targetRotation, points[3..], out _);
 8727        Span<Signed320> delta = stackalloc Signed320[3], first = stackalloc Signed320[3], second = stackalloc Signed320[
 2928        int axis = -1;
 23229        for (int coordinate = 0; coordinate < 3; coordinate++)
 30        {
 8731            delta[coordinate] = WideArithmetic.SubtractSigned320(Signed320.ExtendValue(Signed192.Raw(target.End[coordina
 8732                Signed320.ExtendValue(Signed192.Raw(target.Start[coordinate])));
 11433            if (!delta[coordinate].IsZero) axis = coordinate;
 8734            first[coordinate] = CoverageDifference(points[coordinate], target.Start[coordinate], frameD);
 8735            second[coordinate] = CoverageDifference(points[3 + coordinate], target.Start[coordinate], frameD);
 36        }
 21437        for (int coordinate = 0; coordinate < 3; coordinate++)
 38        {
 8239            int other = (coordinate + 1) % 3;
 8240            Signed576 a = CoverageCross(delta[coordinate], delta[other], first[coordinate], first[other]);
 8241            Signed576 b = CoverageCross(delta[coordinate], delta[other], second[coordinate], second[other]);
 8642            if (EdgePointValue(a, b, n, d).Sign != 0) return -1;
 43        }
 2544        if (axis < 0)
 45        {
 1046            for (int coordinate = 0; coordinate < 3; coordinate++)
 547                if (EdgePointValue(Signed576.ExtendValue(first[coordinate]), Signed576.ExtendValue(second[coordinate]), 
 148            return 0;
 49        }
 2350        Signed832 startValue = EdgePointValue(Signed576.ExtendValue(first[axis]), Signed576.ExtendValue(second[axis]), n
 2351        Signed832 endValue = EdgePointValue(Signed576.ExtendValue(CoverageDifference(points[axis], target.End[axis], fra
 2352            Signed576.ExtendValue(CoverageDifference(points[3 + axis], target.End[axis], frameD)), n, d);
 6953        int start = startValue.Sign, end = endValue.Sign, direction = delta[axis].Sign;
 2754        if (start != 0 && end != 0 && (start != direction || end != -direction)) return -1;
 1955        if (targetInterval.IsClipped)
 56        {
 1157            Signed832 edgeD = WideArithmetic.MultiplySigned576ToSigned832(
 1158                WideArithmetic.MultiplySigned320(delta[axis], frameD), Signed576.ExtendValue(d));
 1159            Signed832 edgeN = startValue;
 1160            if (direction < 0)
 1061            { edgeN = WideArithmetic.SubtractSigned832(default, edgeN); edgeD = WideArithmetic.SubtractSigned832(default
 62            // Cross-products are compared at full width; two independent
 63            // 319-bit bounds must never be narrowed into the incidence bank.
 1164            if (WideArithmetic.CompareNonNegativeProducts(edgeN,
 1165                    Signed832.ExtendValue(Signed576.ExtendValue(targetInterval.LowerDenominator)),
 1166                    Signed832.ExtendValue(Signed576.ExtendValue(targetInterval.LowerNumerator)), edgeD) < 0
 1167                || WideArithmetic.CompareNonNegativeProducts(edgeN,
 1168                    Signed832.ExtendValue(Signed576.ExtendValue(targetInterval.UpperDenominator)),
 1569                    Signed832.ExtendValue(Signed576.ExtendValue(targetInterval.UpperNumerator)), edgeD) > 0) return -1;
 70        }
 1571        return start == 0 ? 0 : end == 0 ? 2 : 1;
 72    }
 73
 74    private static Signed832 EdgePointValue(Signed576 first, Signed576 second, Signed320 n, Signed320 d)
 75    {
 76        // Unclipped mapped offsets need <201 bits and edge crosses <268.
 77        // A full 319-bit unit bound therefore keeps interpolation <589 bits.
 13278        Signed832 a = WideArithmetic.MultiplySigned576ToSigned832(first,
 13279            Signed576.ExtendValue(WideArithmetic.SubtractSigned320(d, n)));
 13280        Signed832 b = WideArithmetic.MultiplySigned576ToSigned832(second, Signed576.ExtendValue(n));
 13281        return WideArithmetic.AddSigned832(a, b);
 82    }
 83}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Triangles/WideTriangleRelations.ScaledFrame.cs

#LineLine coverage
 1//=======================================================================
 2// WideTriangleRelations.ScaledFrame.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>Finite triangle predicates and final witnesses over exact authored scaled frames.</content>
 13internal static partial class WideTriangleRelations
 14{
 15    internal static bool TryGetClosestNonparallelSegmentParameters(in RationalPoint3d firstStart,
 16        in RationalPoint3d firstEnd, in RationalPoint3d secondStart, in RationalPoint3d secondEnd,
 17        ContactQuadratic firstN, ContactQuadratic firstD, ContactQuadratic secondN, ContactQuadratic secondD)
 18    {
 30919        Signed192 firstRotationD = WideArithmetic.TruncateSigned320By64(firstStart.Denominator),
 30920            secondRotationD = WideArithmetic.TruncateSigned320By64(secondStart.Denominator);
 61821        WideDirection3d a = Common(firstStart, secondRotationD), b = Common(firstEnd, secondRotationD),
 61822            c = Common(secondStart, firstRotationD), d = Common(secondEnd, firstRotationD);
 92723        WideDirection3d e = Difference(b, a), f = Difference(d, c), r = Difference(a, c);
 24        // All points share Q^2*R1*R2. The line Gram minors need at most
 25        // twice a full 832-bit coefficient; keep them borrowed until selection.
 26        const int words = 27;
 61827        Span<ulong> values = stackalloc ulong[14 * words]; Span<int> signs = stackalloc int[14];
 30928        var aa = ContactQuadratic.At(values, signs, 0, words);
 30929        var ab = ContactQuadratic.At(values, signs, 1, words);
 30930        var bb = ContactQuadratic.At(values, signs, 2, words);
 30931        var ar = ContactQuadratic.At(values, signs, 3, words);
 30932        var br = ContactQuadratic.At(values, signs, 4, words);
 30933        var one = ContactQuadratic.At(values, signs, 5, words);
 30934        var two = ContactQuadratic.At(values, signs, 6, words);
 92735        aa.Set(WideDirection3d.Dot(e, e)); ab.Set(WideDirection3d.Dot(e, f)); bb.Set(WideDirection3d.Dot(f, f));
 61836        ar.Set(WideDirection3d.Dot(e, r)); br.Set(WideDirection3d.Dot(f, r));
 30937        ContactQuadratic.Multiply(aa, bb, ReadOnlySpan<ulong>.Empty, one);
 61838        ContactQuadratic.Multiply(ab, ab, ReadOnlySpan<ulong>.Empty, two); one.Add(two, -1);
 49139        if (one.Signs[0] <= 0) return false;
 25440        one.CopyTo(firstD); one.CopyTo(secondD);
 12741        ContactQuadratic.Multiply(ab, br, ReadOnlySpan<ulong>.Empty, one);
 25442        ContactQuadratic.Multiply(bb, ar, ReadOnlySpan<ulong>.Empty, two); one.Add(two, -1);
 15843        if (one.Signs[0] < 0) return false;
 28844        one.CopyTo(firstN); firstD.CopyTo(two); two.Add(firstN, -1);
 12745        if (two.Signs[0] < 0) return false;
 6546        ContactQuadratic.Multiply(aa, br, ReadOnlySpan<ulong>.Empty, one);
 13047        ContactQuadratic.Multiply(ab, ar, ReadOnlySpan<ulong>.Empty, two); one.Add(two, -1);
 8248        if (one.Signs[0] < 0) return false;
 14449        one.CopyTo(secondN); secondD.CopyTo(two); two.Add(secondN, -1);
 4850        return two.Signs[0] >= 0;
 51
 52        static WideDirection3d Common(in RationalPoint3d point, Signed192 otherD) => new(
 53            WideArithmetic.MultiplySigned320(point.X, otherD), WideArithmetic.MultiplySigned320(point.Y, otherD),
 54            WideArithmetic.MultiplySigned320(point.Z, otherD));
 55        static WideDirection3d Difference(in WideDirection3d end, in WideDirection3d start) => new(
 56            WideArithmetic.SubtractSigned576(end.X, start.X), WideArithmetic.SubtractSigned576(end.Y, start.Y),
 57            WideArithmetic.SubtractSigned576(end.Z, start.Z));
 58    }
 59
 60    internal static bool TryGetSegmentPointAnchor(in ScaledRigidFrame3d frame, in FixedSegment segment,
 61        scoped ContactQuadratic n, scoped ContactQuadratic d, Vector3d origin, out FixedPointAnchor anchor) =>
 2962        TryGetSegmentPointAnchor<ScaledRigidFrame3d>(frame, segment, n, d, origin, out anchor);
 63
 64    internal static bool TryGetSegmentPointAnchor<TFrame>(in TFrame frame, in FixedSegment segment,
 65        scoped ContactQuadratic n, scoped ContactQuadratic d, Vector3d origin, out FixedPointAnchor anchor)
 66        where TFrame : struct, IForwardHullFrame3d =>
 3467        TryGetSegmentPointAnchor(frame.GetPoint(segment.Start), frame.GetPoint(segment.End), n, d, origin, out anchor);
 68
 69    private static bool TryGetSegmentPointAnchor(in RationalPoint3d a, in RationalPoint3d b,
 70        scoped ContactQuadratic n, scoped ContactQuadratic d, Vector3d origin, out FixedPointAnchor anchor)
 71    {
 5772        anchor = default;
 73        System.Diagnostics.Debug.Assert(a.Denominator.Equals(b.Denominator));
 5774        a.GetLocalPointNumerators(origin, FixedQuaternion.Identity, out Signed576 ax, out Signed576 ay, out Signed576 az
 5775        b.GetLocalPointNumerators(origin, FixedQuaternion.Identity, out Signed576 bx, out Signed576 by, out Signed576 bz
 5776        int words = Math.Max(ContactQuadratic.ActiveWords(n), ContactQuadratic.ActiveWords(d)) + 7;
 11477        Span<ulong> values = stackalloc ulong[8 * words]; Span<int> signs = stackalloc int[8];
 5778        var remaining = ContactQuadratic.At(values, signs, 0, words);
 5779        var numerator = ContactQuadratic.At(values, signs, 1, words);
 5780        var term = ContactQuadratic.At(values, signs, 2, words);
 5781        var denominator = ContactQuadratic.At(values, signs, 3, words);
 11482        d.CopyTo(remaining); remaining.Add(n, -1);
 5783        ContactQuadratic.Scale(d, Signed576.ExtendValue(a.Denominator), denominator);
 11484        Span<Signed576> first = stackalloc Signed576[3] { ax, ay, az }, second = stackalloc Signed576[3] { bx, by, bz };
 5785        Vector3d local = default;
 41486        for (int coordinate = 0; coordinate < 3; coordinate++)
 87        {
 15788            EvaluateScaledEdgePoint(first[coordinate], second[coordinate], remaining, n, numerator, term);
 15789            if (!Fixed64.TryGetSignedRawRatio(numerator.Rational, denominator.Rational,
 16490                    numerator.Signs[0] < 0, out Fixed64 scalar)) return false;
 15091            local[coordinate] = scalar;
 92        }
 5093        anchor = new FixedPointAnchor(origin, FixedQuaternion.Identity, local);
 5094        return true;
 95    }
 96
 97    internal static int LocateEdgePoint(in FixedSegment source, in ScaledRigidFrame3d sourceFrame,
 98        Signed832 n, Signed832 d, in FixedSegment target, in ScaledRigidFrame3d targetFrame,
 99        in RationalSegmentInterval targetInterval = default)
 100    {
 120101        Span<ulong> values = stackalloc ulong[52]; Span<int> signs = stackalloc int[4];
 60102        var numerator = ContactQuadratic.At(values, signs, 0, 13);
 60103        var denominator = ContactQuadratic.At(values, signs, 1, 13);
 120104        numerator.Set(n); denominator.Set(d);
 60105        return LocateEdgePoint(source, sourceFrame, numerator, denominator, target, targetFrame, targetInterval);
 106    }
 107
 108    /// <summary>Locates a retained rational edge parameter without narrowing its transient numerator or denominator.</s
 109    internal static int LocateEdgePoint(in FixedSegment source, in ScaledRigidFrame3d sourceFrame,
 110        scoped ContactQuadratic n, scoped ContactQuadratic d, in FixedSegment target, in ScaledRigidFrame3d targetFrame,
 111        in RationalSegmentInterval targetInterval = default) =>
 60112        LocateFrameEdgePoint(source, sourceFrame, n, d, target, targetFrame, targetInterval);
 113
 114    /// <summary>Locates an exact retained point across forward-only scalar and authored charts.</summary>
 115    internal static int LocateFrameEdgePoint<TSource, TTarget>(in FixedSegment source, in TSource sourceFrame,
 116        scoped ContactQuadratic n, scoped ContactQuadratic d, in FixedSegment target, in TTarget targetFrame,
 117        in RationalSegmentInterval targetInterval = default)
 118        where TSource : struct, IForwardHullFrame3d
 119        where TTarget : struct, IForwardHullFrame3d
 120    {
 470121        RationalPoint3d a = sourceFrame.GetPoint(source.Start), b = sourceFrame.GetPoint(source.End);
 235122        return LocateFrameEdgePoint(a, b, n, d, target, targetFrame, targetInterval);
 123    }
 124
 125    /// <summary>Locates an exact anchored point without rounding its retained feature term.</summary>
 126    internal static int LocatePointOnFrameEdge<TFrame>(in RationalPoint3d point,
 127        in FixedSegment target, in TFrame frame, in RationalSegmentInterval interval = default)
 128        where TFrame : struct, IForwardHullFrame3d
 129    {
 32130        Span<ulong> values = stackalloc ulong[52]; Span<int> signs = stackalloc int[4];
 32131        var n = ContactQuadratic.At(values, signs, 0, 13); var d = ContactQuadratic.At(values, signs, 1, 13);
 32132        n.Clear(); d.Set(Signed832.ExtendValue(Signed192.Signed(1)));
 16133        return LocateFrameEdgePoint(point, point, n, d, target, frame, interval);
 134    }
 135
 136    private static int LocateFrameEdgePoint<TTarget>(in RationalPoint3d a, in RationalPoint3d b,
 137        scoped ContactQuadratic n, scoped ContactQuadratic d, in FixedSegment target, in TTarget targetFrame,
 138        in RationalSegmentInterval targetInterval) where TTarget : struct, IForwardHullFrame3d
 139    {
 502140        RationalPoint3d targetA = targetFrame.GetPoint(target.Start), targetB = targetFrame.GetPoint(target.End);
 251141        WideDirection3d first = GetScaledPointDifference(a, targetA, targetFrame.RotationDenominator),
 251142            second = GetScaledPointDifference(b, targetA, targetFrame.RotationDenominator);
 251143        WideDirection3d edge = targetFrame.GetEdgeDirection(target.Start, target.End);
 251144        int words = Math.Max(ContactQuadratic.ActiveWords(n), ContactQuadratic.ActiveWords(d)) + 11;
 502145        Span<ulong> values = stackalloc ulong[12 * words]; Span<int> signs = stackalloc int[12];
 251146        var remaining = ContactQuadratic.At(values, signs, 0, words);
 251147        var value = ContactQuadratic.At(values, signs, 1, words);
 251148        var term = ContactQuadratic.At(values, signs, 2, words);
 251149        var start = ContactQuadratic.At(values, signs, 3, words);
 251150        var end = ContactQuadratic.At(values, signs, 4, words);
 251151        var edgeD = ContactQuadratic.At(values, signs, 5, words);
 502152        d.CopyTo(remaining); remaining.Add(n, -1);
 502153        WideDirection3d firstCross = WideDirection3d.Cross(edge, first), secondCross = WideDirection3d.Cross(edge, secon
 251154        Span<Signed576> crossA = stackalloc Signed576[3] { firstCross.X, firstCross.Y, firstCross.Z };
 251155        Span<Signed576> crossB = stackalloc Signed576[3] { secondCross.X, secondCross.Y, secondCross.Z };
 1984156        for (int coordinate = 0; coordinate < 3; coordinate++)
 157        {
 749158            EvaluateScaledEdgePoint(crossA[coordinate], crossB[coordinate], remaining, n, value, term);
 757159            if (value.Signs[0] != 0) return -1;
 160        }
 243161        if (edge.IsZero)
 162        {
 12163            Span<Signed576> firstCoordinates = stackalloc Signed576[3] { first.X, first.Y, first.Z };
 12164            Span<Signed576> secondCoordinates = stackalloc Signed576[3] { second.X, second.Y, second.Z };
 72165            for (int coordinate = 0; coordinate < 3; coordinate++)
 166            {
 30167                EvaluateScaledEdgePoint(firstCoordinates[coordinate], secondCoordinates[coordinate], remaining, n, value
 36168                if (value.Signs[0] != 0) return -1;
 169            }
 6170            return 0;
 171        }
 231172        int axis = !edge.X.IsZero ? 0 : !edge.Y.IsZero ? 1 : 2;
 231173        Signed576 firstValue = axis == 0 ? first.X : axis == 1 ? first.Y : first.Z;
 231174        Signed576 secondValue = axis == 0 ? second.X : axis == 1 ? second.Y : second.Z;
 231175        EvaluateScaledEdgePoint(firstValue, secondValue, remaining, n, start, term);
 231176        first = GetScaledPointDifference(a, targetB, targetFrame.RotationDenominator);
 231177        second = GetScaledPointDifference(b, targetB, targetFrame.RotationDenominator);
 231178        firstValue = axis == 0 ? first.X : axis == 1 ? first.Y : first.Z;
 231179        secondValue = axis == 0 ? second.X : axis == 1 ? second.Y : second.Z;
 231180        EvaluateScaledEdgePoint(firstValue, secondValue, remaining, n, end, term);
 231181        int direction = (axis == 0 ? edge.X : axis == 1 ? edge.Y : edge.Z).Sign;
 462182        int startSign = start.Signs[0], endSign = end.Signs[0];
 298183        if (startSign != 0 && endSign != 0 && (startSign != direction || endSign != -direction)) return -1;
 164184        if (targetInterval.IsClipped)
 185        {
 130186            start.CopyTo(edgeD); edgeD.Add(end, -1);
 117187            if (direction < 0) { start.MultiplySign(-1); edgeD.MultiplySign(-1); }
 98188            if (!targetInterval.Contains(start, edgeD, ReadOnlySpan<ulong>.Empty)) return -1;
 189        }
 131190        return startSign == 0 ? 0 : endSign == 0 ? 2 : 1;
 191    }
 192
 193    private static void EvaluateScaledEdgePoint(Signed576 first, Signed576 second,
 194        ContactQuadratic remaining, ContactQuadratic n, ContactQuadratic value, ContactQuadratic term)
 195    {
 4194196        ContactQuadratic.Scale(remaining, first, value); ContactQuadratic.Scale(n, second, term); value.Add(term);
 1398197    }
 198
 199    /// <summary>
 200    /// Clips an authored edge against an independently scaled finite triangle.
 201    /// The side bits and closed unit interval match the rigid coverage contract.
 202    /// </summary>
 203    internal static bool TryGetEdgeCoverage(in FixedTriangle source, in ScaledRigidFrame3d sourceFrame,
 204        in FixedTriangle target, in ScaledRigidFrame3d targetFrame, out Signed832 lowerN,
 205        out Signed832 lowerD, out Signed832 upperN, out Signed832 upperD, out int sides)
 206    {
 39207        lowerN = default; lowerD = upperN = upperD = Signed832.ExtendValue(Signed192.One); sides = 0;
 13208        if (sourceFrame.HasSameMapping(targetFrame))
 209        {
 210            // An invertible affine map preserves incidence, filled sides and
 211            // the original edge parameter. Remove it before clipping at all.
 4212            if (!TryGetEdgeCoverage(source, Vector3d.Zero, FixedQuaternion.Identity, target,
 6213                    Vector3d.Zero, FixedQuaternion.Identity, out RationalSegmentInterval interval, out sides)) return fa
 2214            if (interval.IsClipped)
 215            {
 1216                lowerN = Signed832.ExtendValue(Signed576.ExtendValue(interval.LowerNumerator));
 1217                lowerD = Signed832.ExtendValue(Signed576.ExtendValue(interval.LowerDenominator));
 1218                upperN = Signed832.ExtendValue(Signed576.ExtendValue(interval.UpperNumerator));
 1219                upperD = Signed832.ExtendValue(Signed576.ExtendValue(interval.UpperDenominator));
 220            }
 2221            return true;
 222        }
 9223        WideDirection3d sourceLocalNormal = GetScaledTriangleLocalNormal(source, sourceFrame);
 9224        WideDirection3d targetLocalNormal = GetScaledTriangleLocalNormal(target, targetFrame);
 12225        if (sourceLocalNormal.IsZero || targetLocalNormal.IsZero) return false;
 6226        WideDirection3d targetNormal = targetLocalNormal.Transform(targetFrame.GeometryBasis);
 12227        RationalPoint3d a = sourceFrame.GetPoint(source.A), b = sourceFrame.GetPoint(source.B),
 12228            c = sourceFrame.GetPoint(source.C), targetOrigin = targetFrame.GetPoint(target.A);
 6229        if (!DotScaledDirections(targetNormal, GetScaledPointDifference(a, targetOrigin, targetFrame.RotationDenominator
 6230            || !DotScaledDirections(targetNormal, GetScaledPointDifference(b, targetOrigin, targetFrame.RotationDenomina
 2231            return false;
 4232        bool folded = !DotScaledDirections(targetNormal,
 4233            GetScaledPointDifference(c, targetOrigin, targetFrame.RotationDenominator)).IsZero;
 4234        if (!TryGetProjectedSegmentInterval(target, targetFrame, a, b, out lowerN, out lowerD, out upperN, out upperD))
 1235            return false;
 5236        if (folded) { sides = 4; return true; }
 2237        WideDirection3d inward = WideDirection3d.Cross(sourceLocalNormal,
 2238            WideDirection3d.GetLocalEdge(sourceFrame, source.A, source.B)).Transform(sourceFrame.GeometryBasis);
 2239        Span<Vector3d> vertices = stackalloc Vector3d[3] { target.A, target.B, target.C };
 16240        foreach (Vector3d vertex in vertices)
 241        {
 6242            int side = DotScaledDirections(inward, GetScaledPointDifference(targetFrame.GetPoint(vertex), a,
 6243                sourceFrame.RotationDenominator)).Sign;
 7244            if (side > 0) sides |= 1;
 7245            if (side < 0) sides |= 2;
 246        }
 2247        return true;
 248    }
 249
 250    /// <summary>Preserves the triangle pair's SAT and successive finite closest-witness contract.</summary>
 251    internal static bool TryGetContact(in FixedTriangle first, in ScaledRigidFrame3d firstFrame, Vector3d firstOrigin,
 252        in FixedTriangle second, in ScaledRigidFrame3d secondFrame, Vector3d secondOrigin, out FixedContactAnchors conta
 253    {
 8254        if (firstFrame.IsRigid && secondFrame.IsRigid)
 1255            return TryGetContact(first,firstFrame.RigidOrigin,firstFrame.Rotation,
 1256                second,secondFrame.RigidOrigin,secondFrame.Rotation,out contact);
 7257        contact=default;
 7258        if (GetScaledTriangleLocalNormal(first,firstFrame).IsZero
 10259            || GetScaledTriangleLocalNormal(second,secondFrame).IsZero) return false;
 4260        Span<Vector3d> firstPoints=stackalloc Vector3d[3]{first.A,first.B,first.C};
 4261        Span<Vector3d> secondPoints=stackalloc Vector3d[3]{second.A,second.B,second.C};
 8262        ReadOnlySpan<int> faces=stackalloc int[3]{0,1,2},edges=stackalloc int[6]{0,1,1,2,2,0};
 4263        if(!WideOrientedBox.TryGetConvexHullPenetration(firstFrame,firstPoints,faces,edges,
 4264                secondFrame,secondPoints,faces,edges,out WideScaledHullPenetration penetration,planarPair:true)
 4265            ||!TryGetClosestPointAnchor(first,firstFrame,secondFrame.GetPoint(second.Centroid),firstOrigin,out FixedPoin
 7266            ||!TryGetClosestPointAnchor(second,secondFrame,RationalPoint3d.FromAnchor(a),secondOrigin,out FixedPointAnch
 1267        Fixed64 depth=penetration.GetRoundedDepth(out bool clamped);
 2268        contact=new FixedContactAnchors(a,b,penetration.GetNormal(),depth,clamped);return true;
 269    }
 270
 271    /// <summary>Tests the finite orthogonal projection before rounding any vertex or witness.</summary>
 272    internal static bool ContainsProjection(in FixedTriangle triangle, in ScaledRigidFrame3d frame,
 273        in RationalPoint3d point) =>
 7274        ContainsProjection<ScaledRigidFrame3d>(triangle, frame, point);
 275
 276    internal static bool ContainsProjection<TFrame>(in FixedTriangle triangle, in TFrame frame,
 277        in RationalPoint3d point)
 278        where TFrame : struct, IForwardHullFrame3d
 279    {
 258280        Span<Signed832> values = stackalloc Signed832[3];
 258281        return GetScaledTriangleHalfPlanes(triangle, frame, point, values)
 258282            && values[0].Sign >= 0 && values[1].Sign >= 0 && values[2].Sign >= 0;
 283    }
 284
 285    /// <summary>
 286    /// Projects onto a finite exact face and rounds only the final witness in a
 287    /// caller-selected translated chart. Returns false outside the finite face
 288    /// or when the translated witness cannot fit a scalar coordinate.
 289    /// </summary>
 290    internal static bool TryGetProjectedPointAnchor(in FixedTriangle triangle, in ScaledRigidFrame3d frame,
 291        in RationalPoint3d point, Vector3d materializationOrigin, out FixedPointAnchor anchor) =>
 22292        TryGetProjectedPointAnchor<ScaledRigidFrame3d>(triangle, frame, point, materializationOrigin, out anchor);
 293
 294    internal static bool TryGetProjectedPointAnchor<TFrame>(in FixedTriangle triangle, in TFrame frame,
 295        in RationalPoint3d point, Vector3d materializationOrigin, out FixedPointAnchor anchor)
 296        where TFrame : struct, IForwardHullFrame3d =>
 42297        TryGetProjectedPointAnchor(triangle, frame, point, materializationOrigin, default, default, out anchor);
 298
 299    internal static bool TryGetProjectedPlanePointAnchor<TFrame>(in FixedTriangle plane, in TFrame frame,
 300        in RationalPoint3d point, Vector3d materializationOrigin, out FixedPointAnchor anchor)
 301        where TFrame : struct, IForwardHullFrame3d =>
 37302        TryGetProjectedPointAnchor(plane, frame, point, materializationOrigin, default, default, out anchor, finite: fal
 303
 304    private static bool TryGetProjectedPointAnchor<TFrame>(in FixedTriangle triangle, in TFrame frame,
 305        in RationalPoint3d point, Vector3d materializationOrigin,
 306        scoped ContactQuadratic squaredDistanceNumerator, scoped ContactQuadratic squaredDistanceDenominator,
 307        out FixedPointAnchor anchor, bool finite = true)
 308        where TFrame : struct, IForwardHullFrame3d
 309    {
 101310        anchor = default;
 124311        if (finite && !ContainsProjection(triangle, frame, point)) return false;
 78312        WideDirection3d normal = frame.GetFaceNormal(triangle);
 79313        if (normal.IsZero) return false;
 77314        WideDirection3d delta = GetScaledPointDifference(point, frame.GetPoint(triangle.A), frame.RotationDenominator);
 154315        Signed832 plane = DotScaledDirections(normal, delta), squared = normal.SquaredLength;
 77316        Signed576 commonD = WideArithmetic.MultiplySigned320(point.Denominator, frame.RotationDenominator);
 317        // A projected witness needs <962 numerator bits and <897 denominator
 318        // bits. Keep those products transient; no wider persistent integer is needed.
 319        const int words = 16;
 154320        Span<ulong> storage = stackalloc ulong[12 * words]; Span<int> signs = stackalloc int[12];
 77321        ContactQuadratic metric = ContactQuadratic.At(storage, signs, 0, words),
 77322            divisor = ContactQuadratic.At(storage, signs, 1, words),
 77323            denominator = ContactQuadratic.At(storage, signs, 2, words),
 77324            numerator = ContactQuadratic.At(storage, signs, 3, words),
 77325            planeValue = ContactQuadratic.At(storage, signs, 4, words),
 77326            term = ContactQuadratic.At(storage, signs, 5, words);
 231327        metric.Set(squared); divisor.Set(commonD); planeValue.Set(plane);
 77328        if (!squaredDistanceNumerator.Values.IsEmpty)
 329        {
 3330            ContactQuadratic.Multiply(planeValue, planeValue, ReadOnlySpan<ulong>.Empty, squaredDistanceNumerator);
 3331            ContactQuadratic.Multiply(divisor, divisor, ReadOnlySpan<ulong>.Empty, term);
 3332            ContactQuadratic.Multiply(metric, term, ReadOnlySpan<ulong>.Empty, squaredDistanceDenominator);
 333        }
 77334        ContactQuadratic.Multiply(metric, divisor, ReadOnlySpan<ulong>.Empty, denominator);
 77335        Vector3d local = default;
 580336        for (int coordinate = 0; coordinate < 3; coordinate++)
 337        {
 219338            Signed320 raw = coordinate == 0 ? point.X : coordinate == 1 ? point.Y : point.Z;
 219339            Signed576 relative = WideArithmetic.SubtractSigned576(
 219340                WideArithmetic.MultiplySigned320(raw, frame.RotationDenominator),
 219341                WideArithmetic.MultiplySigned576(commonD, Signed192.Raw(materializationOrigin[coordinate])));
 219342            Signed576 component = coordinate == 0 ? normal.X : coordinate == 1 ? normal.Y : normal.Z;
 219343            ContactQuadratic.Scale(metric, relative, numerator);
 438344            ContactQuadratic.Scale(planeValue, component, term); numerator.Add(term, -1);
 219345            if (!Fixed64.TryGetSignedRawRatio(numerator.Rational, denominator.Rational,
 225346                    numerator.Signs[0] < 0, out Fixed64 value)) return false;
 213347            local[coordinate] = value;
 348        }
 71349        anchor = new FixedPointAnchor(materializationOrigin, FixedQuaternion.Identity, local);
 71350        return true;
 351    }
 352
 353    /// <summary>Clips a same-frame rational segment's projection to the exact finite triangle.</summary>
 354    internal static bool TryGetProjectedSegmentInterval(in FixedTriangle triangle, in ScaledRigidFrame3d frame,
 355        in RationalPoint3d first, in RationalPoint3d second,
 356        out Signed832 lowerN, out Signed832 lowerD, out Signed832 upperN, out Signed832 upperD) =>
 87357        TryGetProjectedSegmentInterval<ScaledRigidFrame3d>(triangle, frame, first, second, out lowerN, out lowerD, out u
 358
 359    internal static bool TryGetProjectedSegmentInterval<TFrame>(in FixedTriangle triangle, in TFrame frame,
 360        in RationalPoint3d first, in RationalPoint3d second,
 361        out Signed832 lowerN, out Signed832 lowerD, out Signed832 upperN, out Signed832 upperD)
 362        where TFrame : struct, IForwardHullFrame3d
 363    {
 364        System.Diagnostics.Debug.Assert(first.Denominator.Equals(second.Denominator));
 1340365        Span<Signed832> start = stackalloc Signed832[3], end = stackalloc Signed832[3];
 1340366        lowerN = default; lowerD = upperN = upperD = Signed832.ExtendValue(Signed192.One);
 708367        if (!GetScaledTriangleHalfPlanes(triangle, frame, first, start)) return false;
 368        // Both points share the same nondegenerate face; only their values differ.
 632369        GetScaledTriangleHalfPlanes(triangle, frame, second, end);
 4130370        for (int edge = 0; edge < 3; edge++)
 1931371            if (!ClipScaledHalfPlane(start[edge], end[edge], ref lowerN, ref lowerD, ref upperN, ref upperD)) return fal
 383372        return true;
 373    }
 374
 375    /// <summary>Clips a segment's orthogonal projection to A+u(B-A)+v(C-A), with retained u and v in [0,1].</summary>
 376    /// <remarks>
 377    /// Both source points must share a positive denominator. The four disjoint output
 378    /// banks require 32 words each: full 832-bit cuts times exact face half-planes
 379    /// need fewer than 1,667 bits, even when the resulting interval cannot fit
 380    /// Signed832. Fractions remain borrowed; no endpoint is materialized.
 381    /// </remarks>
 382    internal static bool TryGetProjectedRectangleInterval(in FixedTriangle rectangleBasis, in ScaledRigidFrame3d frame,
 383        in RationalPoint3d first, in RationalPoint3d second, in RationalSegmentInterval tangentClip,
 384        scoped ContactQuadratic lowerN, scoped ContactQuadratic lowerD,
 385        scoped ContactQuadratic upperN, scoped ContactQuadratic upperD) =>
 57386        TryGetProjectedRectangleInterval<ScaledRigidFrame3d>(rectangleBasis, frame, first, second, tangentClip, lowerN, 
 387
 388    internal static bool TryGetProjectedRectangleInterval<TFrame>(in FixedTriangle rectangleBasis, in TFrame frame,
 389        in RationalPoint3d first, in RationalPoint3d second, in RationalSegmentInterval tangentClip,
 390        scoped ContactQuadratic lowerN, scoped ContactQuadratic lowerD,
 391        scoped ContactQuadratic upperN, scoped ContactQuadratic upperD)
 392        where TFrame : struct, IForwardHullFrame3d
 393    {
 394        System.Diagnostics.Debug.Assert(first.Denominator.Equals(second.Denominator));
 979395        Signed832 one = Signed832.ExtendValue(Signed192.One);
 3916396        Signed832 cutLowerN = default, cutLowerD = one, cutUpperN = one, cutUpperD = one;
 979397        if (tangentClip.IsClipped)
 398        {
 1186399            cutLowerN = tangentClip.WideLowerNumerator; cutLowerD = tangentClip.WideLowerDenominator;
 1186400            cutUpperN = tangentClip.WideUpperNumerator; cutUpperD = tangentClip.WideUpperDenominator;
 401        }
 3916402        lowerN.Clear(); lowerD.Set(one); upperN.Set(one); upperD.Set(one);
 1958403        Span<Signed832> start = stackalloc Signed832[3], end = stackalloc Signed832[3];
 983404        if (!GetScaledTriangleHalfPlanes(rectangleBasis, frame, first, start)) return false;
 975405        GetScaledTriangleHalfPlanes(rectangleBasis, frame, second, end);
 406        const int words = 32;
 1950407        Span<ulong> values = stackalloc ulong[12 * words]; Span<int> signs = stackalloc int[12];
 975408        var firstSum = ContactQuadratic.At(values, signs, 0, words);
 975409        var secondSum = ContactQuadratic.At(values, signs, 1, words);
 975410        var firstWall = ContactQuadratic.At(values, signs, 2, words);
 975411        var secondWall = ContactQuadratic.At(values, signs, 3, words);
 975412        var coefficient = ContactQuadratic.At(values, signs, 4, words);
 975413        var term = ContactQuadratic.At(values, signs, 5, words);
 1950414        firstSum.Set(start[0]); secondSum.Set(end[0]);
 5850415        for (int index = 1; index < 3; index++)
 416        {
 3900417            coefficient.Set(start[index]); firstSum.Add(coefficient);
 3900418            coefficient.Set(end[index]); secondSum.Add(coefficient);
 419        }
 420        // Half-planes opposite B and C are u and v times their common metric;
 421        // the rectangle has no triangular u+v<=1 restriction.
 4910422        for (int wall = 0; wall < 4; wall++)
 423        {
 13884424            for (int side = 0; side < 2; side++)
 425            {
 4628426                var sum = side == 0 ? firstSum : secondSum;
 4628427                var output = side == 0 ? firstWall : secondWall;
 4628428                ReadOnlySpan<Signed832> point = side == 0 ? start : end;
 4628429                if (wall < 2)
 430                {
 3224431                    Signed832 numerator = wall == 0 ? cutLowerN : cutUpperN;
 3224432                    Signed832 denominator = wall == 0 ? cutLowerD : cutUpperD;
 6448433                    coefficient.Set(point[2]); ContactQuadratic.Scale(coefficient, denominator, output);
 6448434                    ContactQuadratic.Scale(sum, numerator, term); output.Add(term, -1);
 4498435                    if (wall != 0) output.MultiplySign(-1);
 436                }
 2258437                else if (wall == 2) output.Set(point[0]);
 1650438                else { sum.CopyTo(output); coefficient.Set(point[0]); output.Add(coefficient, -1); }
 439            }
 3148440            if (!ClipProjectedRectangleWall(firstWall, secondWall, lowerN, lowerD, upperN, upperD)) return false;
 441        }
 141442        return true;
 443    }
 444
 445    private static bool ClipProjectedRectangleWall(scoped ContactQuadratic first, scoped ContactQuadratic second,
 446        scoped ContactQuadratic lowerN, scoped ContactQuadratic lowerD,
 447        scoped ContactQuadratic upperN, scoped ContactQuadratic upperD)
 448    {
 4628449        int firstSign = first.Signs[0], secondSign = second.Signs[0];
 3357450        if (firstSign >= 0 && secondSign >= 0) return true;
 2101451        if (firstSign < 0 && secondSign < 0) return false;
 452        const int words = 32;
 882453        Span<ulong> values = stackalloc ulong[4 * words]; Span<int> signs = stackalloc int[4];
 441454        var numerator = ContactQuadratic.At(values, signs, 0, words);
 441455        var denominator = ContactQuadratic.At(values, signs, 1, words);
 1323456        first.CopyTo(numerator); first.CopyTo(denominator); denominator.Add(second, -1);
 883457        if (denominator.Signs[0] < 0) { numerator.MultiplySign(-1); denominator.MultiplySign(-1); }
 441458        if (firstSign < 0)
 459        {
 221460            if (ContactQuadratic.CompareRatios(numerator, denominator, ReadOnlySpan<ulong>.Empty,
 221461                    lowerN, lowerD, ReadOnlySpan<ulong>.Empty) > 0)
 430462            { numerator.CopyTo(lowerN); denominator.CopyTo(lowerD); }
 463        }
 220464        else if (ContactQuadratic.CompareRatios(numerator, denominator, ReadOnlySpan<ulong>.Empty,
 220465                upperN, upperD, ReadOnlySpan<ulong>.Empty) < 0)
 436466        { numerator.CopyTo(upperN); denominator.CopyTo(upperD); }
 441467        return ContactQuadratic.CompareRatios(lowerN, lowerD, ReadOnlySpan<ulong>.Empty,
 441468            upperN, upperD, ReadOnlySpan<ulong>.Empty) <= 0;
 469    }
 470
 471    internal static bool TryGetProjectedSegmentFaceAnchors(in FixedTriangle triangle, in ScaledRigidFrame3d frame,
 472        in RationalPoint3d first, in RationalPoint3d second, Signed832 n, Signed832 d,
 473        Vector3d sourceOrigin, Vector3d targetOrigin, int physicalBoundaryMask,
 474        out FixedPointAnchor source, out FixedPointAnchor target,
 475        bool requirePhysicalTargetBoundary = true, bool materialize = true) =>
 8476        TryGetProjectedFrameSegmentFaceAnchors<ScaledRigidFrame3d>(triangle, frame, first, second, n, d, sourceOrigin, t
 477
 478    internal static bool TryGetProjectedFrameSegmentFaceAnchors<TFrame>(in FixedTriangle triangle, in TFrame frame,
 479        in RationalPoint3d first, in RationalPoint3d second, Signed832 n, Signed832 d,
 480        Vector3d sourceOrigin, Vector3d targetOrigin, int physicalBoundaryMask,
 481        out FixedPointAnchor source, out FixedPointAnchor target,
 482        bool requirePhysicalTargetBoundary = true, bool materialize = true,
 483        scoped ContactQuadratic wideN = default, scoped ContactQuadratic wideD = default, bool rectangle = false)
 484        where TFrame : struct, IForwardHullFrame3d
 485    {
 534486        source = target = default;
 534487        int words = rectangle ? 48 : 32;
 1068488        Span<ulong> values = stackalloc ulong[20 * words]; Span<int> signs = stackalloc int[20];
 534489        var sx = ContactQuadratic.At(values, signs, 0, words);
 534490        var sy = ContactQuadratic.At(values, signs, 1, words);
 534491        var sz = ContactQuadratic.At(values, signs, 2, words);
 534492        var sd = ContactQuadratic.At(values, signs, 3, words);
 534493        var tx = ContactQuadratic.At(values, signs, 4, words);
 534494        var ty = ContactQuadratic.At(values, signs, 5, words);
 534495        var tz = ContactQuadratic.At(values, signs, 6, words);
 534496        var td = ContactQuadratic.At(values, signs, 7, words);
 534497        if (!TryGetProjectedSegmentFaceWitness(triangle, frame, first, second, n, d,
 534498                sx, sy, sz, sd, tx, ty, tz, td, out int edgeMask, wideN, wideD, rectangle)
 661499            || requirePhysicalTargetBoundary && (edgeMask & physicalBoundaryMask) == 0) return false;
 409500        if (!materialize) return true;
 405501        var relative = ContactQuadratic.At(values, signs, 8, words);
 405502        var term = ContactQuadratic.At(values, signs, 9, words);
 810503        Vector3d sourcePoint = default, targetPoint = default;
 3036504        for (int coordinate = 0; coordinate < 3; coordinate++)
 505        {
 1147506            var sourceCoordinate = coordinate == 0 ? sx : coordinate == 1 ? sy : sz;
 1147507            var targetCoordinate = coordinate == 0 ? tx : coordinate == 1 ? ty : tz;
 1147508            sourceCoordinate.CopyTo(relative);
 2294509            ContactQuadratic.Scale(sd, Signed576.ExtendValue(Signed192.Raw(sourceOrigin[coordinate])), term); relative.A
 1147510            if (!Fixed64.TryGetSignedRawRatio(relative.Rational, sd.Rational,
 1164511                    relative.Signs[0] < 0, out Fixed64 scalar)) return false;
 1130512            sourcePoint[coordinate] = scalar;
 1130513            targetCoordinate.CopyTo(relative);
 2260514            ContactQuadratic.Scale(td, Signed576.ExtendValue(Signed192.Raw(targetOrigin[coordinate])), term); relative.A
 1130515            if (!Fixed64.TryGetSignedRawRatio(relative.Rational, td.Rational,
 1147516                    relative.Signs[0] < 0, out scalar)) return false;
 1113517            targetPoint[coordinate] = scalar;
 518        }
 371519        source = new FixedPointAnchor(sourceOrigin, FixedQuaternion.Identity, sourcePoint);
 371520        target = new FixedPointAnchor(targetOrigin, FixedQuaternion.Identity, targetPoint);
 371521        return true;
 522    }
 523
 524    /// <summary>Materializes a rectangle projection from an already clipped borrowed unit parameter.</summary>
 525    internal static bool TryGetProjectedRectangleFaceAnchors<TFrame>(in FixedTriangle rectangleBasis, in TFrame frame,
 526        in RationalPoint3d first, in RationalPoint3d second, scoped ContactQuadratic n, scoped ContactQuadratic d,
 527        Vector3d sourceOrigin, Vector3d targetOrigin, out FixedPointAnchor source, out FixedPointAnchor target)
 528        where TFrame : struct, IForwardHullFrame3d =>
 61529        TryGetProjectedFrameSegmentFaceAnchors(rectangleBasis, frame, first, second, default, default,
 61530            sourceOrigin, targetOrigin, 0, out source, out target, requirePhysicalTargetBoundary: false,
 61531            wideN: n, wideD: d, rectangle: true);
 532
 533    /// <summary>
 534    /// Retains the exact source point and its finite face projection as borrowed
 535    /// world-coordinate ratios. The zero barycentric weights identify opposite
 536    /// triangle edges; no coordinate or separation has been rounded.
 537    /// </summary>
 538    private static bool TryGetProjectedSegmentFaceWitness<TFrame>(in FixedTriangle triangle, in TFrame frame,
 539        in RationalPoint3d first, in RationalPoint3d second, Signed832 n, Signed832 d,
 540        scoped ContactQuadratic sourceX, scoped ContactQuadratic sourceY, scoped ContactQuadratic sourceZ,
 541        scoped ContactQuadratic sourceD, scoped ContactQuadratic targetX, scoped ContactQuadratic targetY,
 542        scoped ContactQuadratic targetZ, scoped ContactQuadratic targetD, out int edgeMask,
 543        scoped ContactQuadratic wideN = default, scoped ContactQuadratic wideD = default, bool rectangle = false)
 544        where TFrame : struct, IForwardHullFrame3d
 545    {
 534546        edgeMask = 0;
 1068547        Span<Signed832> start = stackalloc Signed832[3], end = stackalloc Signed832[3];
 535548        if (!GetScaledTriangleHalfPlanes(triangle, frame, first, start)) return false;
 533549        GetScaledTriangleHalfPlanes(triangle, frame, second, end);
 550        // Compact triangle parameters retain the original 2048-bit banks.
 551        // Full rectangle cuts need <1667 parameter bits; adding an 832-bit
 552        // half-plane and 320-bit coordinate remains below 3072 bits.
 533553        int words = rectangle ? 48 : 32;
 1066554        Span<ulong> values = stackalloc ulong[20 * words]; Span<int> signs = stackalloc int[20];
 533555        var parameter = ContactQuadratic.At(values, signs, 0, words);
 533556        var divisor = ContactQuadratic.At(values, signs, 1, words);
 533557        var remaining = ContactQuadratic.At(values, signs, 2, words);
 533558        var sum = ContactQuadratic.At(values, signs, 6, words);
 533559        var term = ContactQuadratic.At(values, signs, 7, words);
 533560        var coefficient = ContactQuadratic.At(values, signs, 8, words);
 655561        if (!wideD.Values.IsEmpty) { wideN.CopyTo(parameter); wideD.CopyTo(divisor); }
 944562        else { parameter.Set(n); divisor.Set(d); }
 1599563        divisor.CopyTo(remaining); remaining.Add(parameter, -1); sum.Clear();
 4254564        for (int corner = 0; corner < 3; corner++)
 565        {
 1597566            int edge = (corner + 1) % 3;
 1597567            var barycentric = ContactQuadratic.At(values, signs, 3 + corner, words);
 3194568            coefficient.Set(start[edge]); ContactQuadratic.Multiply(coefficient, remaining, ReadOnlySpan<ulong>.Empty, b
 3194569            coefficient.Set(end[edge]); ContactQuadratic.Multiply(coefficient, parameter, ReadOnlySpan<ulong>.Empty, ter
 1597570            barycentric.Add(term);
 1600571            if (barycentric.Signs[0] < 0 && (!rectangle || corner != 0)) return false;
 1848572            if (barycentric.Signs[0] == 0) edgeMask |= 1 << corner;
 1594573            sum.Add(barycentric);
 574        }
 575        // The three barycentric numerators sum to the nonzero face metric
 576        // times the positive input parameter denominator.
 577        System.Diagnostics.Debug.Assert(sum.Signs[0] > 0);
 530578        if (rectangle)
 348579            for (int corner = 1; corner < 3; corner++)
 580            {
 117581                ContactQuadratic.At(values, signs, 3 + corner, words).CopyTo(term);
 117582                term.Add(sum, -1);
 119583                if (term.Signs[0] > 0) return false;
 584            }
 528585        coefficient.Set(Signed576.ExtendValue(first.Denominator));
 528586        ContactQuadratic.Multiply(divisor, coefficient, ReadOnlySpan<ulong>.Empty, sourceD);
 528587        coefficient.Set(Signed576.ExtendValue(frame.Denominator));
 528588        ContactQuadratic.Multiply(sum, coefficient, ReadOnlySpan<ulong>.Empty, targetD);
 528589        Span<RationalPoint3d> corners = stackalloc RationalPoint3d[3]
 528590            { frame.GetPoint(triangle.A), frame.GetPoint(triangle.B), frame.GetPoint(triangle.C) };
 4224591        for (int coordinate = 0; coordinate < 3; coordinate++)
 592        {
 1584593            var source = coordinate == 0 ? sourceX : coordinate == 1 ? sourceY : sourceZ;
 1584594            var target = coordinate == 0 ? targetX : coordinate == 1 ? targetY : targetZ;
 1584595            Signed320 a = coordinate == 0 ? first.X : coordinate == 1 ? first.Y : first.Z;
 1584596            Signed320 b = coordinate == 0 ? second.X : coordinate == 1 ? second.Y : second.Z;
 1584597            ContactQuadratic.Scale(remaining, Signed576.ExtendValue(a), source);
 3168598            ContactQuadratic.Scale(parameter, Signed576.ExtendValue(b), term); source.Add(term);
 1584599            target.Clear();
 12672600            for (int corner = 0; corner < 3; corner++)
 601            {
 4752602                RationalPoint3d point = corners[corner];
 4752603                Signed320 raw = coordinate == 0 ? point.X : coordinate == 1 ? point.Y : point.Z;
 4752604                ContactQuadratic.Scale(ContactQuadratic.At(values, signs, 3 + corner, words), Signed576.ExtendValue(raw)
 4752605                target.Add(term);
 606            }
 607        }
 528608        return true;
 609    }
 610
 611    internal static bool ClipScaledHalfPlane(Signed832 first, Signed832 second,
 612        ref Signed832 lowerN, ref Signed832 lowerD, ref Signed832 upperN, ref Signed832 upperD)
 613    {
 62311614        if (first.Sign >= 0 && second.Sign >= 0) return true;
 19395615        if (first.Sign < 0 && second.Sign < 0) return false;
 1774616        Signed832 n = first, d = WideArithmetic.SubtractSigned832(first, second);
 1753617        if (d.Sign < 0) { n = WideArithmetic.SubtractSigned832(default, n); d = WideArithmetic.SubtractSigned832(default
 887618        if (first.Sign < 0)
 619        {
 1279620            if (WideArithmetic.CompareNonNegativeProducts(n, lowerD, lowerN, d) > 0) { lowerN = n; lowerD = d; }
 621        }
 1340622        else if (WideArithmetic.CompareNonNegativeProducts(n, upperD, upperN, d) < 0) { upperN = n; upperD = d; }
 887623        return WideArithmetic.CompareNonNegativeProducts(lowerN, upperD, upperN, lowerD) <= 0;
 624    }
 625
 626    internal static bool GetScaledTriangleHalfPlanes<TFrame>(in FixedTriangle triangle, in TFrame frame,
 627        in RationalPoint3d point, Span<Signed832> values) where TFrame : struct, IForwardHullFrame3d =>
 4581628        frame.TryGetTriangleHalfPlanes(triangle, point, values);
 629
 630    internal static bool GetScaledTriangleHalfPlanes(in FixedTriangle triangle, in ScaledRigidFrame3d frame,
 631        in RationalPoint3d point, Span<Signed832> values)
 632    {
 2864633        WideDirection3d localNormal = GetScaledTriangleLocalNormal(triangle, frame);
 2911634        if (localNormal.IsZero) return false;
 2817635        Span<Vector3d> vertices = stackalloc Vector3d[3] { triangle.A, triangle.B, triangle.C };
 22536636        for (int edge = 0; edge < 3; edge++)
 637        {
 16902638            Vector3d a = vertices[edge], b = vertices[(edge + 1) % 3];
 8451639            WideDirection3d inward = WideDirection3d.Cross(localNormal, WideDirection3d.GetLocalEdge(frame, a, b))
 8451640                .Transform(frame.GeometryBasis);
 8451641            WideDirection3d delta = GetScaledPointDifference(point, frame.GetPoint(a), frame.RotationDenominator);
 8451642            values[edge] = DotScaledDirections(inward, delta);
 643        }
 2817644        return true;
 645    }
 646
 647    internal static WideDirection3d GetScaledTriangleLocalNormal(in FixedTriangle triangle, in ScaledRigidFrame3d frame)
 648    {
 649        // Rigid geometry already uses physical local vertices. Retain the
 650        // original normal instead of injecting Q^4 through two unit-scale
 651        // edge numerators; that redundant factor also inflates fan minors.
 6479652        if (frame.IsRigid)
 653        {
 3532654            triangle.GetExactNormal(out Signed192 x, out Signed192 y, out Signed192 z, out _);
 3532655            return new WideDirection3d(Signed576.ExtendValue(x), Signed576.ExtendValue(y), Signed576.ExtendValue(z));
 656        }
 2947657        return WideDirection3d.Cross(WideDirection3d.GetLocalEdge(frame, triangle.A, triangle.B),
 2947658            WideDirection3d.GetLocalEdge(frame, triangle.A, triangle.C));
 659    }
 660
 661    internal static WideDirection3d GetScaledPointDifference(in RationalPoint3d point,
 662        in RationalPoint3d reference, Signed192 referenceRotationDenominator)
 663    {
 16609664        Signed192 pointRotationD = WideArithmetic.TruncateSigned320By64(point.Denominator);
 16609665        return new WideDirection3d(Difference(point.X, reference.X, referenceRotationDenominator, pointRotationD),
 16609666            Difference(point.Y, reference.Y, referenceRotationDenominator, pointRotationD),
 16609667            Difference(point.Z, reference.Z, referenceRotationDenominator, pointRotationD));
 668        static Signed576 Difference(Signed320 point, Signed320 reference, Signed192 referenceD, Signed192 pointD) =>
 669            WideArithmetic.SubtractSigned576(WideArithmetic.MultiplySigned320(point, referenceD),
 670                WideArithmetic.MultiplySigned320(reference, pointD));
 671    }
 672
 673    internal static Signed832 DotScaledDirections(in WideDirection3d first, in WideDirection3d second) =>
 9473674        WideArithmetic.AddSigned832(WideArithmetic.AddSigned832(WideArithmetic.MultiplySigned576ToSigned832(first.X, sec
 9473675            WideArithmetic.MultiplySigned576ToSigned832(first.Y, second.Y)), WideArithmetic.MultiplySigned576ToSigned832
 676}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Triangles/WideTriangleRelations.ScaledQueries.cs

#LineLine coverage
 1//=======================================================================
 2// WideTriangleRelations.ScaledQueries.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>Finite segment and closest-point queries over exact scaled source triangles.</content>
 13internal static partial class WideTriangleRelations
 14{
 15    /// <summary>Rounds scaled triangle area once and normalizes its exact local normal.</summary>
 16    /// <remarks>Source-frame centered reach is at most 4096 units; the squared normal fits Signed832.</remarks>
 17    internal static void GetScaledAreaAndNormal(in FixedTriangle triangle, in ScaledRigidFrame3d frame,
 18        out Fixed64 area, out Vector3d normal)
 19    {
 20        // Area needs the metric Q^4 cross factor even when the direction-only
 21        // rigid normal can cancel it.
 322        WideDirection3d exactNormal = WideDirection3d.Cross(
 323            WideDirection3d.GetLocalEdge(frame, triangle.A, triangle.B),
 324            WideDirection3d.GetLocalEdge(frame, triangle.A, triangle.C));
 325        normal = exactNormal.GetNormal(false);
 26        const int words = 13;
 627        Span<ulong> values = stackalloc ulong[4 * words]; Span<int> signs = stackalloc int[4];
 328        var numerator = ContactQuadratic.At(values, signs, 0, words);
 329        var denominator = ContactQuadratic.At(values, signs, 1, words);
 330        numerator.Set(exactNormal.SquaredLength);
 31        // Each edge carries Q^2 beyond its raw coordinate. Area's raw value
 32        // is |cross|/(2*Q^5), so the squared divisor is 4*Q^10.
 333        denominator.Set(new Signed576(0, 0, 0, 4, 0, 0, 0, 0, 0));
 334        bool represented = ContactQuadratic.TryRoundSquareRootRatio(numerator, denominator, ReadOnlySpan<ulong>.Empty, o
 35        System.Diagnostics.Debug.Assert(represented);
 336    }
 37
 38    internal static bool TryGetProjectedSupportContact(in FixedTriangle triangle, in ScaledRigidFrame3d frame,
 39        in FixedPointAnchor support, Vector3d worldNormal, Vector3d materializationOrigin, out FixedContactAnchors conta
 40    {
 841        contact = default;
 842        RationalPoint3d point = RationalPoint3d.FromAnchor(support);
 843        WideDirection3d normal = GetScaledTriangleLocalNormal(triangle, frame).Transform(frame.GeometryBasis);
 844        WideDirection3d offset = GetScaledPointDifference(point, frame.GetPoint(triangle.A), frame.RotationDenominator);
 845        Signed832 signedGap = WideDirection3d.Dot(normal, offset);
 846        var direction = new WideAxis3(Signed320.ExtendValue(Signed192.Raw(worldNormal.X)),
 847            Signed320.ExtendValue(Signed192.Raw(worldNormal.Y)), Signed320.ExtendValue(Signed192.Raw(worldNormal.Z)));
 848        int orientation = WideDirection3d.Dot(normal, direction).Sign;
 849        if (orientation == 0 || orientation * signedGap.Sign > 0
 1450            || !TryGetProjectedPointAnchor(triangle, frame, point, materializationOrigin, out FixedPointAnchor meshAncho
 251        Signed832 overlap = signedGap.Sign < 0 ? WideArithmetic.SubtractSigned832(default, signedGap) : signedGap;
 252        Signed576 denominator = WideArithmetic.MultiplySigned320(point.Denominator, frame.RotationDenominator);
 253        Fixed64 depth = WideArithmetic.GetRoundedNonNegativeNormalizedDepth(overlap, normal.SquaredLength, denominator, 
 254        contact = new FixedContactAnchors(meshAnchor, support, worldNormal, depth, clamped);
 255        return true;
 56    }
 57
 58    internal static bool TryGetSegmentIntersection(in FixedTriangle triangle, in ScaledRigidFrame3d frame,
 59        in FixedSegment segment, out Vector3d entry, out Vector3d exit)
 60    {
 2161        entry = exit = default;
 2162        RationalPoint3d first = RationalPoint3d.FromScalarPoint(segment.Start);
 2163        RationalPoint3d second = RationalPoint3d.FromScalarPoint(segment.End);
 2164        WideDirection3d normal = GetScaledTriangleLocalNormal(triangle, frame).Transform(frame.GeometryBasis);
 2465        if (normal.IsZero) return false;
 1866        RationalPoint3d origin = frame.GetPoint(triangle.A);
 1867        Signed832 planeFirst = DotScaledDirections(normal, GetScaledPointDifference(first, origin, frame.RotationDenomin
 1868        Signed832 planeSecond = DotScaledDirections(normal, GetScaledPointDifference(second, origin, frame.RotationDenom
 1869        if (planeFirst.IsZero && planeSecond.IsZero)
 70        {
 571            if (!TryGetProjectedSegmentInterval(triangle, frame, first, second,
 772                out Signed832 lowerN, out Signed832 lowerD, out Signed832 upperN, out Signed832 upperD)) return false;
 373            entry = MaterializeScaledSegmentPoint(segment, lowerN, lowerD);
 374            exit = MaterializeScaledSegmentPoint(segment, upperN, upperD);
 375            return true;
 76        }
 1877        if (planeFirst.Sign == planeSecond.Sign) return false;
 1678        Signed832 numerator = planeFirst, denominator = WideArithmetic.SubtractSigned832(planeFirst, planeSecond);
 879        if (denominator.Sign < 0)
 80        {
 381            numerator = WideArithmetic.SubtractSigned832(default, numerator);
 382            denominator = WideArithmetic.SubtractSigned832(default, denominator);
 83        }
 1684        Span<Signed832> a = stackalloc Signed832[3], b = stackalloc Signed832[3];
 85        // The nonzero normal above proves both finite half-plane loaders exist.
 886        GetScaledTriangleHalfPlanes(triangle, frame, first, a);
 887        GetScaledTriangleHalfPlanes(triangle, frame, second, b);
 88        const int words = 24;
 1689        Span<ulong> values = stackalloc ulong[8 * words]; Span<int> signs = stackalloc int[8];
 890        var left = ContactQuadratic.At(values, signs, 0, words);
 891        var right = ContactQuadratic.At(values, signs, 1, words);
 892        var term = ContactQuadratic.At(values, signs, 2, words);
 893        var sum = ContactQuadratic.At(values, signs, 3, words);
 894        Signed832 remaining = WideArithmetic.SubtractSigned832(denominator, numerator);
 95        // Half-plane values (<786 bits) times plane parameters (<610 bits)
 96        // fit the 1536-bit borrowed bank; no input or parameter is rounded.
 5697        for (int edge = 0; edge < 3; edge++)
 98        {
 4499            left.Set(a[edge]); right.Set(b[edge]);
 22100            ContactQuadratic.Scale(left, remaining, sum);
 44101            ContactQuadratic.Scale(right, numerator, term); sum.Add(term);
 24102            if (sum.Signs[0] < 0) return false;
 103        }
 6104        entry = MaterializeScaledSegmentPoint(segment, numerator, denominator);
 6105        exit = entry;
 6106        return true;
 107    }
 108
 109    internal static bool TryGetClosestPointAnchor(in FixedTriangle triangle, in ScaledRigidFrame3d frame,
 110        Vector3d queryPoint, Vector3d materializationOrigin, out FixedPointAnchor anchor) =>
 11111        TryGetClosestPointAnchor(triangle, frame, RationalPoint3d.FromScalarPoint(queryPoint), materializationOrigin, ou
 112
 113    internal static bool TryGetClosestPointAnchor(in FixedTriangle triangle, in ScaledRigidFrame3d frame,
 114        in RationalPoint3d query, Vector3d materializationOrigin, out FixedPointAnchor anchor) =>
 17115        TryGetClosestPointAnchor(triangle, frame, query, materializationOrigin, default, default, out anchor);
 116
 117    /// <summary>Also retains the exact squared raw-coordinate distance for cross-triangle selection.</summary>
 118    /// <remarks>
 119    /// Both borrowed output banks require 36 words. With admitted 4096-unit geometry,
 120    /// two source rotation denominators and a full-domain rational anchor query,
 121    /// the common denominator is below 294 bits, offsets below 360 and edges below
 122    /// 339. Edge squared lengths are below 680 bits; squared residual sums below
 123    /// 2090 and their squared denominators below 1950. Face ratios are smaller.
 124    /// Ratio comparison retains its complete transient cross products separately.
 125    /// </remarks>
 126    internal static bool TryGetClosestPointAnchor(in FixedTriangle triangle, in ScaledRigidFrame3d frame,
 127        in RationalPoint3d query, Vector3d materializationOrigin,
 128        scoped ContactQuadratic squaredDistanceNumerator, scoped ContactQuadratic squaredDistanceDenominator,
 129        out FixedPointAnchor anchor)
 130    {
 22131        if (TryGetProjectedPointAnchor(triangle, frame, query, materializationOrigin,
 30132                squaredDistanceNumerator, squaredDistanceDenominator, out anchor)) return true;
 14133        Span<Vector3d> vertices = stackalloc Vector3d[3] { triangle.A, triangle.B, triangle.C };
 134        // A rational query can carry another rigid denominator. The exact
 135        // residual square needs fewer than 2300 bits in the admitted domain.
 136        const int words = 36;
 28137        Span<ulong> values = stackalloc ulong[20 * words]; Span<int> signs = stackalloc int[20];
 14138        var bestNumerator = ContactQuadratic.At(values, signs, 0, words);
 14139        var bestDenominator = ContactQuadratic.At(values, signs, 1, words);
 14140        var distance = ContactQuadratic.At(values, signs, 2, words);
 14141        var distanceDenominator = ContactQuadratic.At(values, signs, 3, words);
 14142        var delta = ContactQuadratic.At(values, signs, 4, words);
 14143        var edgeValue = ContactQuadratic.At(values, signs, 5, words);
 14144        var term = ContactQuadratic.At(values, signs, 6, words);
 14145        var residual = ContactQuadratic.At(values, signs, 7, words);
 14146        var square = ContactQuadratic.At(values, signs, 8, words);
 14147        var divisor = ContactQuadratic.At(values, signs, 9, words);
 14148        Signed192 queryFactor = WideArithmetic.TruncateSigned320By64(query.Denominator);
 14149        Signed576 commonDenominator = WideArithmetic.MultiplySigned320(frame.Denominator, queryFactor);
 14150        int selected = -1;
 28151        Signed832 selectedN = default, selectedD = default;
 112152        for (int edge = 0; edge < 3; edge++)
 153        {
 84154            RationalPoint3d a = frame.GetPoint(vertices[edge]), b = frame.GetPoint(vertices[(edge + 1) % 3]);
 42155            var direction = new WideDirection3d(
 42156                WideArithmetic.MultiplySigned320(WideArithmetic.SubtractSigned320(b.X, a.X), queryFactor),
 42157                WideArithmetic.MultiplySigned320(WideArithmetic.SubtractSigned320(b.Y, a.Y), queryFactor),
 42158                WideArithmetic.MultiplySigned320(WideArithmetic.SubtractSigned320(b.Z, a.Z), queryFactor));
 42159            WideDirection3d offset = GetScaledPointDifference(query, a, frame.RotationDenominator);
 84160            Signed832 numerator = WideDirection3d.Dot(direction, offset), denominator = direction.SquaredLength;
 42161            if (denominator.IsZero) continue;
 39162            if (numerator.Sign < 0) numerator = default;
 35163            else if (WideArithmetic.SubtractSigned832(numerator, denominator).Sign > 0) numerator = denominator;
 33164            distance.Clear();
 264165            for (int axis = 0; axis < 3; axis++)
 166            {
 99167                delta.Set(axis == 0 ? offset.X : axis == 1 ? offset.Y : offset.Z);
 99168                edgeValue.Set(axis == 0 ? direction.X : axis == 1 ? direction.Y : direction.Z);
 99169                ContactQuadratic.Scale(delta, denominator, residual);
 198170                ContactQuadratic.Scale(edgeValue, numerator, term); residual.Add(term, -1);
 99171                ContactQuadratic.Multiply(residual, residual, ReadOnlySpan<ulong>.Empty, square);
 99172                distance.Add(square);
 173            }
 33174            divisor.Set(commonDenominator);
 33175            ContactQuadratic.Scale(divisor, denominator, term);
 33176            ContactQuadratic.Multiply(term, term, ReadOnlySpan<ulong>.Empty, distanceDenominator);
 177            // Squared residuals fit 2304 bits. Ratio comparison retains its
 178            // complete transient cross products before choosing the feature.
 33179            if (selected >= 0 && ContactQuadratic.CompareRatios(distance, distanceDenominator, ReadOnlySpan<ulong>.Empty
 33180                bestNumerator, bestDenominator, ReadOnlySpan<ulong>.Empty) >= 0) continue;
 32181            distance.CopyTo(bestNumerator); distanceDenominator.CopyTo(bestDenominator);
 48182            selected = edge; selectedN = numerator; selectedD = denominator;
 183        }
 14184        if (selected < 0)
 185        {
 3186            if (!squaredDistanceNumerator.Values.IsEmpty)
 187            {
 1188                WideDirection3d offset = GetScaledPointDifference(query, frame.GetPoint(triangle.A), frame.RotationDenom
 1189                squaredDistanceNumerator.Set(offset.SquaredLength);
 1190                divisor.Set(commonDenominator);
 1191                ContactQuadratic.Multiply(divisor, divisor, ReadOnlySpan<ulong>.Empty, squaredDistanceDenominator);
 192            }
 3193            bool represented = frame.GetPoint(triangle.A).TryGetLocalPointIn(materializationOrigin,
 3194                FixedQuaternion.Identity, out Vector3d local);
 3195            anchor = represented ? new FixedPointAnchor(materializationOrigin, FixedQuaternion.Identity, local) : defaul
 3196            return represented;
 197        }
 11198        if (!squaredDistanceNumerator.Values.IsEmpty)
 199        {
 1200            bestNumerator.CopyTo(squaredDistanceNumerator);
 1201            bestDenominator.CopyTo(squaredDistanceDenominator);
 202        }
 11203        return TryMaterializeScaledEdge(frame.GetPoint(vertices[selected]), frame.GetPoint(vertices[(selected + 1) % 3])
 11204            selectedN, selectedD, materializationOrigin, out anchor);
 205    }
 206
 207    private static Vector3d MaterializeScaledSegmentPoint(in FixedSegment segment, Signed832 n, Signed832 d)
 208    {
 12209        bool represented = TryMaterializeScaledEdge(RationalPoint3d.FromScalarPoint(segment.Start),
 12210            RationalPoint3d.FromScalarPoint(segment.End), n, d, Vector3d.Zero, out FixedPointAnchor anchor);
 211        // A retained closed unit parameter is a convex combination of two
 212        // scalar endpoints, so zero-origin final materialization cannot overflow.
 213        System.Diagnostics.Debug.Assert(represented);
 12214        return anchor.LocalPoint;
 215    }
 216
 217    private static bool TryMaterializeScaledEdge(in RationalPoint3d a, in RationalPoint3d b,
 218        Signed832 n, Signed832 d, Vector3d samplingOrigin, out FixedPointAnchor anchor)
 219    {
 220        const int words = 13;
 46221        Span<ulong> values = stackalloc ulong[4 * words]; Span<int> signs = stackalloc int[4];
 23222        var numerator = ContactQuadratic.At(values, signs, 0, words);
 23223        var denominator = ContactQuadratic.At(values, signs, 1, words);
 46224        numerator.Set(n); denominator.Set(d);
 23225        return TryGetSegmentPointAnchor(a, b, numerator, denominator, samplingOrigin, out anchor);
 226    }
 227}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Triangles/WideTriangleRelations.ScaledSphereSweep.cs

#LineLine coverage
 1//=======================================================================
 2// WideTriangleRelations.ScaledSphereSweep.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>Retains finite face, edge and vertex roots for a sphere swept against an authored affine triangle.</content
 13internal static partial class WideTriangleRelations
 14{
 15    internal static bool TryGetSweptSphereDistance(in FixedTriangle triangle, in ScaledRigidFrame3d frame,
 16        in FixedSegment query, Fixed64 length, Fixed64 radius, out Fixed64 distance)
 17    {
 2018        distance = Fixed64.MaxValue;
 2019        Span<WideDirection3d> points = stackalloc WideDirection3d[3];
 2020        Signed320 denominator = frame.Denominator;
 16021        for (int i = 0; i < 3; i++)
 22        {
 6023            frame.GetPoint(i == 0 ? triangle.A : i == 1 ? triangle.B : triangle.C)
 6024                .GetLocalPointNumerators(query.Start, FixedQuaternion.Identity,
 6025                    out Signed576 x, out Signed576 y, out Signed576 z, out denominator);
 6026            points[i] = new WideDirection3d(x, y, z);
 27        }
 28        // The caller has already admitted this chord's scalar length; every
 29        // component difference is bounded by that same representable magnitude.
 2030        bool represented = Vector3d.TrySubtract(query.End, query.Start, out Vector3d delta);
 31        System.Diagnostics.Debug.Assert(represented);
 2032        var velocity = new WideDirection3d(
 2033            WideArithmetic.MultiplySigned320(denominator, Signed192.Raw(delta.X)),
 2034            WideArithmetic.MultiplySigned320(denominator, Signed192.Raw(delta.Y)),
 2035            WideArithmetic.MultiplySigned320(denominator, Signed192.Raw(delta.Z)));
 2036        Signed576 expandedRadius = WideArithmetic.MultiplySigned320(denominator, Signed192.Raw(radius));
 2037        Signed832 radiusSquare = WideArithmetic.MultiplySigned576ToSigned832(expandedRadius, expandedRadius);
 2038        WideDirection3d normal = GetScaledTriangleLocalNormal(triangle, frame).Transform(frame.GeometryBasis);
 2039        bool found = false;
 32040        for (int feature = 0; feature < 7; feature++)
 41        {
 14042            int vertex = feature < 3 ? feature : feature < 6 ? feature - 3 : 0;
 14043            WideDirection3d point = points[vertex];
 14044            WideDirection3d edge = feature is >= 3 and < 6 ? Difference(points[(vertex + 1) % 3], point) : default;
 14045            if (feature == 6 && normal.IsZero || feature is >= 3 and < 6 && edge.IsZero) continue;
 9646            if (TryGetScaledSphereFeatureRoot(triangle, frame, points, velocity, normal, point, edge,
 9647                radiusSquare, feature, length, out Fixed64 candidate) && candidate < distance)
 2648            { distance = candidate; found = true; }
 49        }
 2050        return found;
 51    }
 52
 53    private static bool TryGetScaledSphereFeatureRoot(in FixedTriangle triangle, in ScaledRigidFrame3d frame,
 54        ReadOnlySpan<WideDirection3d> points, in WideDirection3d velocity, in WideDirection3d normal,
 55        in WideDirection3d point, in WideDirection3d edge, Signed832 radiusSquare, int feature,
 56        Fixed64 length, out Fixed64 distance)
 57    {
 58        // Source-frame numerators are <320 bits and normals <351 bits.
 59        // The largest coefficients are <1346 bits, discriminants <2694 bits;
 60        // root admission and output scaling stay below this 3072-bit bank.
 61        const int words = 48;
 19262        Span<ulong> storage = stackalloc ulong[20 * words]; Span<int> signs = stackalloc int[20];
 9663        var a = ContactQuadratic.At(storage, signs, 0, words);
 9664        var b = ContactQuadratic.At(storage, signs, 1, words);
 9665        var c = ContactQuadratic.At(storage, signs, 2, words);
 9666        var work = ContactQuadratic.At(storage, signs, 3, words);
 9667        var term = ContactQuadratic.At(storage, signs, 4, words);
 9668        var first = ContactQuadratic.At(storage, signs, 5, words);
 9669        var second = ContactQuadratic.At(storage, signs, 6, words);
 9670        var numerator = ContactQuadratic.At(storage, signs, 7, words);
 9671        var divisor = ContactQuadratic.At(storage, signs, 8, words);
 9672        var parameterWork = ContactQuadratic.At(storage, signs, 9, words);
 19273        Signed832 vv = WideDirection3d.Dot(velocity, velocity), vp = WideDirection3d.Dot(velocity, point);
 9674        Signed832 pp = WideDirection3d.Dot(point, point);
 28875        Signed832 ee = default, ev = default, ep = default;
 9676        if (feature < 3)
 77        {
 18078            a.Set(vv); b.Set(vp); b.MultiplySign(-1);
 6079            c.Set(WideArithmetic.SubtractSigned832(pp, radiusSquare));
 80        }
 3681        else if (feature < 6)
 82        {
 6083            ee = WideDirection3d.Dot(edge, edge); ev = WideDirection3d.Dot(edge, velocity);
 3084            ep = WideDirection3d.Dot(edge, point);
 9085            Multiply(ee, vv, first, second, a); Multiply(ev, ev, first, second, term); a.Add(term, -1);
 9086            Multiply(ev, ep, first, second, b); Multiply(ee, vp, first, second, term); b.Add(term, -1);
 3087            Multiply(ee, WideArithmetic.SubtractSigned832(pp, radiusSquare), first, second, c);
 6088            Multiply(ep, ep, first, second, term); c.Add(term, -1);
 89        }
 90        else
 91        {
 1292            Signed832 nv = WideDirection3d.Dot(normal, velocity), np = WideDirection3d.Dot(normal, point);
 1893            Multiply(nv, nv, first, second, a); Multiply(nv, np, first, second, b); b.MultiplySign(-1);
 694            Multiply(np, np, first, second, c);
 1295            Multiply(normal.SquaredLength, radiusSquare, first, second, term); c.Add(term, -1);
 96        }
 19297        distance = Fixed64.MaxValue; bool found = false;
 9698        Span<ulong> root = stackalloc ulong[2 * words];
 76899        for (int branch = 0; branch < 3; branch++)
 100        {
 288101            if (branch == 0)
 102            {
 96103                if (c.Signs[0] > 0) continue;
 42104                numerator.Clear(); divisor.Set(Signed576.ExtendValue(Signed192.Signed(1))); root.Clear();
 105            }
 192106            else if (!ContactQuadratic.TryGetParameter(a, b, c, branch == 1 ? -1 : 1, root, numerator, divisor)) continu
 90107            if (numerator.Sign(root) < 0) continue;
 228108            divisor.CopyTo(work); work.Add(numerator, -1); if (work.Sign(root) < 0) continue;
 67109            if (feature is >= 3 and < 6)
 110            {
 84111                ContactQuadratic.Scale(numerator, ev, work); ContactQuadratic.Scale(divisor, ep, term); work.Add(term, -
 28112                if (work.Sign(root) < 0) continue;
 76113                ContactQuadratic.Scale(divisor, ee, term); term.Add(work, -1); if (term.Sign(root) < 0) continue;
 114            }
 39115            else if (feature == 6)
 116            {
 12117                bool admitted = true;
 12118                WideDirection3d localNormal = GetScaledTriangleLocalNormal(triangle, frame);
 80119                for (int edgeIndex = 0; edgeIndex < 3; edgeIndex++)
 120                {
 32121                    FixedSegment authoredEdge = triangle.GetEdge(edgeIndex);
 32122                    WideDirection3d inward = WideDirection3d.Cross(localNormal,
 32123                        WideDirection3d.GetLocalEdge(frame, authoredEdge.Start, authoredEdge.End)).Transform(frame.Geome
 32124                    ContactQuadratic.Scale(numerator, WideDirection3d.Dot(inward, velocity), work);
 32125                    ContactQuadratic.Scale(divisor, WideDirection3d.Dot(inward, points[edgeIndex]), term);
 72126                    work.Add(term, -1); if (work.Sign(root) < 0) { admitted = false; break; }
 127                }
 12128                if (!admitted) continue;
 129            }
 55130            ContactQuadratic.Scale(numerator, Signed576.ExtendValue(Signed192.Raw(length)), parameterWork);
 55131            Fixed64 candidate = ContactQuadratic.RoundRatio(parameterWork, divisor, root, 0, length.m_rawValue);
 113132            if (candidate < distance) { distance = candidate; found = true; }
 133        }
 96134        return found;
 135    }
 136
 137    private static WideDirection3d Difference(in WideDirection3d first, in WideDirection3d second) =>
 60138        new(WideArithmetic.SubtractSigned576(first.X, second.X), WideArithmetic.SubtractSigned576(first.Y, second.Y),
 60139            WideArithmetic.SubtractSigned576(first.Z, second.Z));
 140
 141    private static void Multiply(Signed832 firstValue, Signed832 secondValue,
 142        scoped ContactQuadratic first, scoped ContactQuadratic second, scoped ContactQuadratic result)
 143    {
 408144        first.Set(firstValue); second.Set(secondValue);
 204145        ContactQuadratic.Multiply(first, second, ReadOnlySpan<ulong>.Empty, result);
 204146    }
 147}

Methods/Properties

ContainsProjection(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Geometry.FixedPointAnchor&)
TryGetProjectionBarycentrics(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&)
TryGetProjectedSegmentInterval(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&)
TryGetProjectedSegmentFaceAnchors(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Signed832,FixedMathSharp.Signed832,System.Int32,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Geometry.FixedPointAnchor&,System.Boolean,System.Boolean)
TryGetProjectedCoreParameter(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&)
TryGetProjectedSegmentCoreParameter(FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&)
GetClosestNonparallelLineNumerators(FixedMathSharp.Signed192,FixedMathSharp.Signed576,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed576,FixedMathSharp.Signed576&,FixedMathSharp.Signed704&)
TryGetClosestNonparallelSegmentParameters(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&)
MaterializeSegmentPoint(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Signed832,FixedMathSharp.Signed832)
GetProjectedCoreDot(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576)
CompareCoreParameters(FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed832)
MaterializeCorePoint(FixedMathSharp.Vector3d,FixedMathSharp.Signed832,FixedMathSharp.Signed832)
GetClosestPointAnchor(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Geometry.FixedPointAnchor&,System.Boolean)
GetClosestTriangleLocalPoint(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed320,System.Boolean)
GetClosestTriangleEdgePoint(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed320)
KeepCloserTriangleSegmentPoint(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed320,FixedMathSharp.Vector3d&)
GetClosestTriangleSegmentPoint(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed320)
GetTriangleSquaredDistanceNumerator(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed320,FixedMathSharp.Vector3d)
GetPointEdgeDotNumerator(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed320,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
GetTrianglePointDeltaNumerator(FixedMathSharp.Signed576,FixedMathSharp.Fixed64,FixedMathSharp.Signed320)
ScaleTriangleDot(FixedMathSharp.Signed192,FixedMathSharp.Signed320)
GetTriangleUnitRatio(FixedMathSharp.Signed576,FixedMathSharp.Signed576)
GetTriangleDifferenceDot(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
GetPointLocalNumerators(FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed320&)
GetTriangleRotatedPointCoordinate(FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
GetTriangleFrameCoordinateNumerator(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
TryGetContact(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Geometry.FixedContactAnchors&)
TryGetPenetration(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Geometry.WidePointSpanPenetration&,FixedMathSharp.Geometry.PointSpanPenetrationAdmission)
TryKeepPairAxis(FixedMathSharp.Geometry.WideAxis3&,FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.WideRationalBasis3d&,FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.WideRationalBasis3d&,FixedMathSharp.Geometry.WidePointSpanPenetration&,FixedMathSharp.Geometry.PointSpanPenetrationAdmission)
GetProjectionInterval(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.WideRationalBasis3d&,FixedMathSharp.Geometry.WideAxis3&,FixedMathSharp.Signed192,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&)
GetLocalEdge(FixedMathSharp.Geometry.FixedTriangle,System.Int32,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&)
TryGetEdgeCoverage(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Geometry.RationalSegmentInterval&,System.Int32&)
GetCoveragePoint(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,System.Span`1<FixedMathSharp.Signed320>,FixedMathSharp.Signed320&)
CoverageDifference(FixedMathSharp.Signed320,FixedMathSharp.Fixed64,FixedMathSharp.Signed320)
CoverageCross(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320)
CoverageHalfPlane(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,System.Int32,System.Int32,System.Int32)
LocateEdgePoint(FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Geometry.FixedSegment,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Geometry.RationalSegmentInterval&)
EdgePointValue(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed320,FixedMathSharp.Signed320)
TryGetClosestNonparallelSegmentParameters(FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic)
TryGetSegmentPointAnchor(FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Geometry.FixedSegment&,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedPointAnchor&)
TryGetSegmentPointAnchor(TFrame&,FixedMathSharp.Geometry.FixedSegment&,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedPointAnchor&)
TryGetSegmentPointAnchor(FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedPointAnchor&)
LocateEdgePoint(FixedMathSharp.Geometry.FixedSegment&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Geometry.FixedSegment&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Geometry.RationalSegmentInterval&)
LocateEdgePoint(FixedMathSharp.Geometry.FixedSegment&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.FixedSegment&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Geometry.RationalSegmentInterval&)
LocateFrameEdgePoint(FixedMathSharp.Geometry.FixedSegment&,TSource&,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.FixedSegment&,TTarget&,FixedMathSharp.Geometry.RationalSegmentInterval&)
LocatePointOnFrameEdge(FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.FixedSegment&,TFrame&,FixedMathSharp.Geometry.RationalSegmentInterval&)
LocateFrameEdgePoint(FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.FixedSegment&,TTarget&,FixedMathSharp.Geometry.RationalSegmentInterval&)
EvaluateScaledEdgePoint(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic)
TryGetEdgeCoverage(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&,System.Int32&)
TryGetContact(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedContactAnchors&)
ContainsProjection(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Geometry.RationalPoint3d&)
ContainsProjection(FixedMathSharp.Geometry.FixedTriangle&,TFrame&,FixedMathSharp.Geometry.RationalPoint3d&)
TryGetProjectedPointAnchor(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedPointAnchor&)
TryGetProjectedPointAnchor(FixedMathSharp.Geometry.FixedTriangle&,TFrame&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedPointAnchor&)
TryGetProjectedPlanePointAnchor(FixedMathSharp.Geometry.FixedTriangle&,TFrame&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedPointAnchor&)
TryGetProjectedPointAnchor(FixedMathSharp.Geometry.FixedTriangle&,TFrame&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.FixedPointAnchor&,System.Boolean)
TryGetProjectedSegmentInterval(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&)
TryGetProjectedSegmentInterval(FixedMathSharp.Geometry.FixedTriangle&,TFrame&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&)
TryGetProjectedRectangleInterval(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.RationalSegmentInterval&,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic)
TryGetProjectedRectangleInterval(FixedMathSharp.Geometry.FixedTriangle&,TFrame&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.RationalSegmentInterval&,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic)
ClipProjectedRectangleWall(FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic)
TryGetProjectedSegmentFaceAnchors(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Int32,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Geometry.FixedPointAnchor&,System.Boolean,System.Boolean)
TryGetProjectedFrameSegmentFaceAnchors(FixedMathSharp.Geometry.FixedTriangle&,TFrame&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Int32,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Geometry.FixedPointAnchor&,System.Boolean,System.Boolean,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,System.Boolean)
TryGetProjectedRectangleFaceAnchors(FixedMathSharp.Geometry.FixedTriangle&,TFrame&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Geometry.FixedPointAnchor&)
TryGetProjectedSegmentFaceWitness(FixedMathSharp.Geometry.FixedTriangle&,TFrame&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,System.Int32&,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,System.Boolean)
ClipScaledHalfPlane(FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&)
GetScaledTriangleHalfPlanes(FixedMathSharp.Geometry.FixedTriangle&,TFrame&,FixedMathSharp.Geometry.RationalPoint3d&,System.Span`1<FixedMathSharp.Signed832>)
GetScaledTriangleHalfPlanes(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Geometry.RationalPoint3d&,System.Span`1<FixedMathSharp.Signed832>)
GetScaledTriangleLocalNormal(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&)
GetScaledPointDifference(FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Signed192)
DotScaledDirections(FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Geometry.WideDirection3d&)
GetScaledAreaAndNormal(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Fixed64&,FixedMathSharp.Vector3d&)
TryGetProjectedSupportContact(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Geometry.FixedPointAnchor&,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedContactAnchors&)
TryGetSegmentIntersection(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Geometry.FixedSegment&,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&)
TryGetClosestPointAnchor(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedPointAnchor&)
TryGetClosestPointAnchor(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedPointAnchor&)
TryGetClosestPointAnchor(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.FixedPointAnchor&)
MaterializeScaledSegmentPoint(FixedMathSharp.Geometry.FixedSegment&,FixedMathSharp.Signed832,FixedMathSharp.Signed832)
TryMaterializeScaledEdge(FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Geometry.RationalPoint3d&,FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.FixedPointAnchor&)
TryGetSweptSphereDistance(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Geometry.FixedSegment&,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetScaledSphereFeatureRoot(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,System.ReadOnlySpan`1<FixedMathSharp.Geometry.WideDirection3d>,FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Signed832,System.Int32,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
Difference(FixedMathSharp.Geometry.WideDirection3d&,FixedMathSharp.Geometry.WideDirection3d&)
Multiply(FixedMathSharp.Signed832,FixedMathSharp.Signed832,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic,FixedMathSharp.Geometry.ContactQuadratic)