< Summary

Line coverage
100%
Covered lines: 649
Uncovered lines: 0
Coverable lines: 649
Total lines: 904
Line coverage: 100%
Branch coverage
100%
Covered branches: 74
Total branches: 74
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

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
 8namespace FixedMathSharp.Geometry;
 9
 10/// <content>
 11/// Provides the exact closest-point reducer for rigid triangle frames.
 12/// </content>
 13internal static partial class WideTriangleRelations
 14{
 15    internal static FixedPointAnchor GetClosestPointAnchor(
 16        FixedTriangle triangle,
 17        Vector3d triangleOrigin,
 18        FixedQuaternion triangleRotation,
 19        in FixedPointAnchor point)
 20    {
 45021        GetPointLocalNumerators(
 45022            point,
 45023            triangleOrigin,
 45024            triangleRotation,
 45025            out Signed576 pointX,
 45026            out Signed576 pointY,
 45027            out Signed576 pointZ,
 45028            out Signed320 pointDenominator);
 45029        Vector3d closest = GetClosestTriangleLocalPoint(
 45030            triangle,
 45031            pointX,
 45032            pointY,
 45033            pointZ,
 45034            pointDenominator);
 45035        return FixedPointAnchor.FromValidatedFrame(
 45036            triangleOrigin,
 45037            triangleRotation,
 45038            closest);
 39    }
 40
 41    private static Vector3d GetClosestTriangleLocalPoint(
 42        FixedTriangle triangle,
 43        Signed576 pointX,
 44        Signed576 pointY,
 45        Signed576 pointZ,
 46        Signed320 pointDenominator)
 47    {
 45048        Signed192 abAb = GetTriangleDifferenceDot(
 45049            triangle.B,
 45050            triangle.A,
 45051            triangle.B,
 45052            triangle.A);
 45053        Signed192 abAc = GetTriangleDifferenceDot(
 45054            triangle.B,
 45055            triangle.A,
 45056            triangle.C,
 45057            triangle.A);
 45058        Signed192 acAc = GetTriangleDifferenceDot(
 45059            triangle.C,
 45060            triangle.A,
 45061            triangle.C,
 45062            triangle.A);
 45063        Signed320 gram = WideArithmetic.MultiplySubtract(
 45064            abAb,
 45065            acAc,
 45066            abAc,
 45067            abAc);
 45068        if (WideGeometry.IsQ128MagnitudeAtMostEpsilon(gram))
 69        {
 10270            return GetClosestTriangleEdgePoint(
 10271                triangle,
 10272                pointX,
 10273                pointY,
 10274                pointZ,
 10275                pointDenominator);
 76        }
 77
 34878        Signed576 d1 = GetPointEdgeDotNumerator(
 34879            pointX,
 34880            pointY,
 34881            pointZ,
 34882            pointDenominator,
 34883            triangle.A,
 34884            triangle.B);
 34885        Signed576 d2 = GetPointEdgeDotNumerator(
 34886            pointX,
 34887            pointY,
 34888            pointZ,
 34889            pointDenominator,
 34890            triangle.A,
 34891            triangle.C);
 34892        if (d1.Sign <= 0 && d2.Sign <= 0)
 293            return triangle.A;
 94
 34695        Signed576 abAbScaled = ScaleTriangleDot(abAb, pointDenominator);
 34696        Signed576 abAcScaled = ScaleTriangleDot(abAc, pointDenominator);
 34697        Signed576 acAcScaled = ScaleTriangleDot(acAc, pointDenominator);
 34698        Signed576 d3 = WideArithmetic.SubtractSigned576(d1, abAbScaled);
 34699        Signed576 d4 = WideArithmetic.SubtractSigned576(d2, abAcScaled);
 346100        if (d3.Sign >= 0
 346101            && WideArithmetic.SubtractSigned576(d4, d3).Sign <= 0)
 102        {
 2103            return triangle.B;
 104        }
 105
 344106        Signed576 vc = WideArithmetic.SubtractSigned576(
 344107            WideArithmetic.MultiplySigned576(d2, abAb),
 344108            WideArithmetic.MultiplySigned576(d1, abAc));
 344109        if (vc.Sign <= 0 && d1.Sign >= 0 && d3.Sign <= 0)
 110        {
 28111            Fixed64 parameter = GetTriangleUnitRatio(d1, abAbScaled);
 28112            return Vector3d.Lerp(triangle.A, triangle.B, parameter);
 113        }
 114
 316115        Signed576 d5 = WideArithmetic.SubtractSigned576(d1, abAcScaled);
 316116        Signed576 d6 = WideArithmetic.SubtractSigned576(d2, acAcScaled);
 316117        if (d6.Sign >= 0
 316118            && WideArithmetic.SubtractSigned576(d5, d6).Sign <= 0)
 119        {
 1120            return triangle.C;
 121        }
 122
 315123        Signed576 vb = WideArithmetic.SubtractSigned576(
 315124            WideArithmetic.MultiplySigned576(d1, acAc),
 315125            WideArithmetic.MultiplySigned576(d2, abAc));
 315126        if (vb.Sign <= 0 && d2.Sign >= 0 && d6.Sign <= 0)
 127        {
 163128            Fixed64 parameter = GetTriangleUnitRatio(d2, acAcScaled);
 163129            return Vector3d.Lerp(triangle.A, triangle.C, parameter);
 130        }
 131
 152132        Signed576 d4MinusD3 = WideArithmetic.SubtractSigned576(d4, d3);
 152133        Signed576 d5MinusD6 = WideArithmetic.SubtractSigned576(d5, d6);
 152134        Signed576 gramScaled = WideArithmetic.MultiplySigned320(
 152135            gram,
 152136            pointDenominator);
 152137        Signed576 va = WideArithmetic.SubtractSigned576(
 152138            WideArithmetic.SubtractSigned576(gramScaled, vb),
 152139            vc);
 152140        if (va.Sign <= 0
 152141            && d4MinusD3.Sign >= 0
 152142            && d5MinusD6.Sign >= 0)
 143        {
 66144            Fixed64 parameter = GetTriangleUnitRatio(
 66145                d4MinusD3,
 66146                WideArithmetic.AddSigned576(d4MinusD3, d5MinusD6));
 66147            return Vector3d.Lerp(triangle.B, triangle.C, parameter);
 148        }
 149
 86150        Fixed64 weightB = GetTriangleUnitRatio(vb, gramScaled);
 86151        Fixed64 weightC = GetTriangleUnitRatio(vc, gramScaled);
 86152        return triangle.GetPoint(weightB, weightC);
 153    }
 154
 155    private static Vector3d GetClosestTriangleEdgePoint(
 156        FixedTriangle triangle,
 157        Signed576 pointX,
 158        Signed576 pointY,
 159        Signed576 pointZ,
 160        Signed320 pointDenominator)
 161    {
 102162        Vector3d best = GetClosestTriangleSegmentPoint(
 102163            triangle.A,
 102164            triangle.B,
 102165            pointX,
 102166            pointY,
 102167            pointZ,
 102168            pointDenominator);
 102169        KeepCloserTriangleSegmentPoint(
 102170            triangle.B,
 102171            triangle.C,
 102172            pointX,
 102173            pointY,
 102174            pointZ,
 102175            pointDenominator,
 102176            ref best);
 102177        KeepCloserTriangleSegmentPoint(
 102178            triangle.C,
 102179            triangle.A,
 102180            pointX,
 102181            pointY,
 102182            pointZ,
 102183            pointDenominator,
 102184            ref best);
 102185        return best;
 186    }
 187
 188    private static void KeepCloserTriangleSegmentPoint(
 189        Vector3d start,
 190        Vector3d end,
 191        Signed576 pointX,
 192        Signed576 pointY,
 193        Signed576 pointZ,
 194        Signed320 pointDenominator,
 195        ref Vector3d best)
 196    {
 204197        Vector3d candidate = GetClosestTriangleSegmentPoint(
 204198            start,
 204199            end,
 204200            pointX,
 204201            pointY,
 204202            pointZ,
 204203            pointDenominator);
 204204        Signed832 candidateDistance = GetTriangleSquaredDistanceNumerator(
 204205            pointX,
 204206            pointY,
 204207            pointZ,
 204208            pointDenominator,
 204209            candidate);
 204210        Signed832 bestDistance = GetTriangleSquaredDistanceNumerator(
 204211            pointX,
 204212            pointY,
 204213            pointZ,
 204214            pointDenominator,
 204215            best);
 204216        if (WideArithmetic.SubtractSigned832(
 204217                candidateDistance,
 204218                bestDistance).Sign < 0)
 219        {
 1220            best = candidate;
 221        }
 204222    }
 223
 224    private static Vector3d GetClosestTriangleSegmentPoint(
 225        Vector3d start,
 226        Vector3d end,
 227        Signed576 pointX,
 228        Signed576 pointY,
 229        Signed576 pointZ,
 230        Signed320 pointDenominator)
 231    {
 306232        Signed192 lengthSquared = GetTriangleDifferenceDot(
 306233            end,
 306234            start,
 306235            end,
 306236            start);
 306237        if (lengthSquared.Sign <= 0)
 102238            return start;
 239
 204240        Signed576 projection = GetPointEdgeDotNumerator(
 204241            pointX,
 204242            pointY,
 204243            pointZ,
 204244            pointDenominator,
 204245            start,
 204246            end);
 204247        if (projection.Sign <= 0)
 2248            return start;
 249
 202250        Signed576 scaledLength =
 202251            ScaleTriangleDot(lengthSquared, pointDenominator);
 202252        if (WideArithmetic.SubtractSigned576(
 202253                projection,
 202254                scaledLength).Sign >= 0)
 255        {
 2256            return end;
 257        }
 258
 200259        return Vector3d.Lerp(
 200260            start,
 200261            end,
 200262            GetTriangleUnitRatio(projection, scaledLength));
 263    }
 264
 265    private static Signed832 GetTriangleSquaredDistanceNumerator(
 266        Signed576 pointX,
 267        Signed576 pointY,
 268        Signed576 pointZ,
 269        Signed320 pointDenominator,
 270        Vector3d candidate)
 271    {
 408272        Signed576 x = GetTrianglePointDeltaNumerator(
 408273            pointX,
 408274            candidate.X,
 408275            pointDenominator);
 408276        Signed576 y = GetTrianglePointDeltaNumerator(
 408277            pointY,
 408278            candidate.Y,
 408279            pointDenominator);
 408280        Signed576 z = GetTrianglePointDeltaNumerator(
 408281            pointZ,
 408282            candidate.Z,
 408283            pointDenominator);
 408284        return WideArithmetic.AddSigned832(
 408285            WideArithmetic.AddSigned832(
 408286                WideArithmetic.MultiplySigned576ToSigned832(x, x),
 408287                WideArithmetic.MultiplySigned576ToSigned832(y, y)),
 408288            WideArithmetic.MultiplySigned576ToSigned832(z, z));
 289    }
 290
 291    private static Signed576 GetPointEdgeDotNumerator(
 292        Signed576 pointX,
 293        Signed576 pointY,
 294        Signed576 pointZ,
 295        Signed320 pointDenominator,
 296        Vector3d edgeStart,
 297        Vector3d edgeEnd)
 298    {
 900299        Signed576 deltaX = GetTrianglePointDeltaNumerator(
 900300            pointX,
 900301            edgeStart.X,
 900302            pointDenominator);
 900303        Signed576 deltaY = GetTrianglePointDeltaNumerator(
 900304            pointY,
 900305            edgeStart.Y,
 900306            pointDenominator);
 900307        Signed576 deltaZ = GetTrianglePointDeltaNumerator(
 900308            pointZ,
 900309            edgeStart.Z,
 900310            pointDenominator);
 900311        Signed192 edgeX = WideArithmetic.SubtractSigned192(
 900312            Signed192.Raw(edgeEnd.X),
 900313            Signed192.Raw(edgeStart.X));
 900314        Signed192 edgeY = WideArithmetic.SubtractSigned192(
 900315            Signed192.Raw(edgeEnd.Y),
 900316            Signed192.Raw(edgeStart.Y));
 900317        Signed192 edgeZ = WideArithmetic.SubtractSigned192(
 900318            Signed192.Raw(edgeEnd.Z),
 900319            Signed192.Raw(edgeStart.Z));
 900320        return WideArithmetic.AddSigned576(
 900321            WideArithmetic.AddSigned576(
 900322                WideArithmetic.MultiplySigned576(deltaX, edgeX),
 900323                WideArithmetic.MultiplySigned576(deltaY, edgeY)),
 900324            WideArithmetic.MultiplySigned576(deltaZ, edgeZ));
 325    }
 326
 327    private static Signed576 GetTrianglePointDeltaNumerator(
 328        Signed576 pointCoordinate,
 329        Fixed64 triangleCoordinate,
 330        Signed320 pointDenominator) =>
 3924331        WideArithmetic.SubtractSigned576(
 3924332            pointCoordinate,
 3924333            WideArithmetic.MultiplySigned320(
 3924334                Signed320.ExtendValue(Signed192.Raw(triangleCoordinate)),
 3924335                pointDenominator));
 336
 337    private static Signed576 ScaleTriangleDot(
 338        Signed192 value,
 339        Signed320 scale) =>
 1240340        WideArithmetic.MultiplySigned320(
 1240341            Signed320.ExtendValue(value),
 1240342            scale);
 343
 344    private static Fixed64 GetTriangleUnitRatio(
 345        Signed576 numerator,
 346        Signed576 denominator)
 347    {
 629348        _ = Fixed64.TryGetSignedRawRatio(
 629349            WideArithmetic.MultiplySigned576ToSigned704(
 629350                numerator,
 629351                Signed320.ExtendValue(Signed192.One)),
 629352            Signed704.ExtendValue(denominator),
 629353            out Fixed64 ratio);
 629354        return ratio;
 355    }
 356
 357    private static Signed192 GetTriangleDifferenceDot(
 358        Vector3d leftEnd,
 359        Vector3d leftStart,
 360        Vector3d rightEnd,
 361        Vector3d rightStart) =>
 1656362        WideGeometry.GetDifferenceDotProduct3D(
 1656363            leftEnd.X,
 1656364            leftStart.X,
 1656365            leftEnd.Y,
 1656366            leftStart.Y,
 1656367            leftEnd.Z,
 1656368            leftStart.Z,
 1656369            rightEnd.X,
 1656370            rightStart.X,
 1656371            rightEnd.Y,
 1656372            rightStart.Y,
 1656373            rightEnd.Z,
 1656374            rightStart.Z);
 375
 376    private static void GetPointLocalNumerators(
 377        in FixedPointAnchor point,
 378        Vector3d frameOrigin,
 379        FixedQuaternion frameRotation,
 380        out Signed576 x,
 381        out Signed576 y,
 382        out Signed576 z,
 383        out Signed320 denominator)
 384    {
 450385        WideRationalBasis3d pointBasis = new(point.Rotation);
 450386        WideRationalBasis3d frameBasis = new(frameRotation);
 450387        denominator = WideArithmetic.MultiplySigned192(
 450388            pointBasis.Denominator,
 450389            frameBasis.Denominator);
 450390        Signed192 originX = WideArithmetic.SubtractSigned192(
 450391            Signed192.Raw(point.Origin.X),
 450392            Signed192.Raw(frameOrigin.X));
 450393        Signed192 originY = WideArithmetic.SubtractSigned192(
 450394            Signed192.Raw(point.Origin.Y),
 450395            Signed192.Raw(frameOrigin.Y));
 450396        Signed192 originZ = WideArithmetic.SubtractSigned192(
 450397            Signed192.Raw(point.Origin.Z),
 450398            Signed192.Raw(frameOrigin.Z));
 450399        Signed320 rotatedX = GetTriangleRotatedPointCoordinate(
 450400            point,
 450401            pointBasis.Xx,
 450402            pointBasis.Yx,
 450403            pointBasis.Zx);
 450404        Signed320 rotatedY = GetTriangleRotatedPointCoordinate(
 450405            point,
 450406            pointBasis.Xy,
 450407            pointBasis.Yy,
 450408            pointBasis.Zy);
 450409        Signed320 rotatedZ = GetTriangleRotatedPointCoordinate(
 450410            point,
 450411            pointBasis.Xz,
 450412            pointBasis.Yz,
 450413            pointBasis.Zz);
 450414        x = GetTriangleFrameCoordinateNumerator(
 450415            originX,
 450416            originY,
 450417            originZ,
 450418            rotatedX,
 450419            rotatedY,
 450420            rotatedZ,
 450421            pointBasis.Denominator,
 450422            frameBasis.Xx,
 450423            frameBasis.Xy,
 450424            frameBasis.Xz);
 450425        y = GetTriangleFrameCoordinateNumerator(
 450426            originX,
 450427            originY,
 450428            originZ,
 450429            rotatedX,
 450430            rotatedY,
 450431            rotatedZ,
 450432            pointBasis.Denominator,
 450433            frameBasis.Yx,
 450434            frameBasis.Yy,
 450435            frameBasis.Yz);
 450436        z = GetTriangleFrameCoordinateNumerator(
 450437            originX,
 450438            originY,
 450439            originZ,
 450440            rotatedX,
 450441            rotatedY,
 450442            rotatedZ,
 450443            pointBasis.Denominator,
 450444            frameBasis.Zx,
 450445            frameBasis.Zy,
 450446            frameBasis.Zz);
 450447    }
 448
 449    private static Signed320 GetTriangleRotatedPointCoordinate(
 450        in FixedPointAnchor point,
 451        Signed192 axisX,
 452        Signed192 axisY,
 453        Signed192 axisZ) =>
 1350454        WideArithmetic.AddSigned320(
 1350455            WideArithmetic.GetDotProduct3D(
 1350456                Signed192.Raw(point.LocalPoint.X),
 1350457                Signed192.Raw(point.LocalPoint.Y),
 1350458                Signed192.Raw(point.LocalPoint.Z),
 1350459                axisX,
 1350460                axisY,
 1350461                axisZ),
 1350462            WideArithmetic.GetDotProduct3D(
 1350463                Signed192.Raw(point.LocalDisplacement.X),
 1350464                Signed192.Raw(point.LocalDisplacement.Y),
 1350465                Signed192.Raw(point.LocalDisplacement.Z),
 1350466                axisX,
 1350467                axisY,
 1350468                axisZ));
 469
 470    private static Signed576 GetTriangleFrameCoordinateNumerator(
 471        Signed192 originX,
 472        Signed192 originY,
 473        Signed192 originZ,
 474        Signed320 rotatedX,
 475        Signed320 rotatedY,
 476        Signed320 rotatedZ,
 477        Signed192 pointDenominator,
 478        Signed192 frameAxisX,
 479        Signed192 frameAxisY,
 480        Signed192 frameAxisZ)
 481    {
 1350482        Signed320 originProjection = WideArithmetic.GetDotProduct3D(
 1350483            originX,
 1350484            originY,
 1350485            originZ,
 1350486            frameAxisX,
 1350487            frameAxisY,
 1350488            frameAxisZ);
 1350489        Signed576 rotatedProjection = WideArithmetic.AddSigned576(
 1350490            WideArithmetic.AddSigned576(
 1350491                WideArithmetic.MultiplySigned320(
 1350492                    rotatedX,
 1350493                    Signed320.ExtendValue(frameAxisX)),
 1350494                WideArithmetic.MultiplySigned320(
 1350495                    rotatedY,
 1350496                    Signed320.ExtendValue(frameAxisY))),
 1350497            WideArithmetic.MultiplySigned320(
 1350498                rotatedZ,
 1350499                Signed320.ExtendValue(frameAxisZ)));
 1350500        return WideArithmetic.AddSigned576(
 1350501            WideArithmetic.MultiplySigned320(
 1350502                originProjection,
 1350503                Signed320.ExtendValue(pointDenominator)),
 1350504            rotatedProjection);
 505    }
 506}

/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>
 13internal static partial class WideTriangleRelations
 14{
 15    internal static bool TryGetContact(
 16        FixedTriangle first,
 17        Vector3d firstOrigin,
 18        FixedQuaternion firstRotation,
 19        FixedTriangle second,
 20        Vector3d secondOrigin,
 21        FixedQuaternion secondRotation,
 22        out FixedContactAnchors contact)
 23    {
 8824        first.GetExactNormal(
 8825            out Signed192 firstNormalX,
 8826            out Signed192 firstNormalY,
 8827            out Signed192 firstNormalZ,
 8828            out Signed320 firstNormalSquared);
 8829        second.GetExactNormal(
 8830            out Signed192 secondNormalX,
 8831            out Signed192 secondNormalY,
 8832            out Signed192 secondNormalZ,
 8833            out Signed320 secondNormalSquared);
 8834        if (firstNormalSquared.IsZero || secondNormalSquared.IsZero)
 35        {
 236            contact = default;
 237            return false;
 38        }
 39
 8640        WideRationalBasis3d firstBasis = new(firstRotation);
 8641        WideRationalBasis3d secondBasis = new(secondRotation);
 8642        WideAxis3 firstNormal = WideRigidProjection.TransformLocalAxis(
 8643            firstBasis,
 8644            firstNormalX,
 8645            firstNormalY,
 8646            firstNormalZ);
 8647        WideAxis3 secondNormal = WideRigidProjection.TransformLocalAxis(
 8648            secondBasis,
 8649            secondNormalX,
 8650            secondNormalY,
 8651            secondNormalZ);
 8652        var best = default(WidePointSpanPenetration);
 8653        if (!TryKeepPairAxis(
 8654                firstNormal,
 8655                first,
 8656                firstOrigin,
 8657                firstBasis,
 8658                second,
 8659                secondOrigin,
 8660                secondBasis,
 8661                ref best)
 8662            || !TryKeepPairAxis(
 8663                secondNormal,
 8664                first,
 8665                firstOrigin,
 8666                firstBasis,
 8667                second,
 8668                secondOrigin,
 8669                secondBasis,
 8670                ref best))
 71        {
 372            contact = default;
 373            return false;
 74        }
 75
 8376        for (int firstEdgeIndex = 0;
 31577            firstEdgeIndex < FixedTriangle.EdgeCount;
 23278            firstEdgeIndex++)
 79        {
 23980            GetLocalEdge(
 23981                first,
 23982                firstEdgeIndex,
 23983                out Signed192 firstEdgeX,
 23984                out Signed192 firstEdgeY,
 23985                out Signed192 firstEdgeZ);
 23986            WideAxis3 firstEdge = WideRigidProjection.TransformLocalAxis(
 23987                firstBasis,
 23988                firstEdgeX,
 23989                firstEdgeY,
 23990                firstEdgeZ);
 23991            if (!TryKeepPairAxis(
 23992                    TransformLocalNormalCrossEdge(
 23993                        firstBasis,
 23994                        firstNormalX,
 23995                        firstNormalY,
 23996                        firstNormalZ,
 23997                        firstEdgeX,
 23998                        firstEdgeY,
 23999                        firstEdgeZ),
 239100                    first,
 239101                    firstOrigin,
 239102                    firstBasis,
 239103                    second,
 239104                    secondOrigin,
 239105                    secondBasis,
 239106                    ref best))
 107            {
 4108                contact = default;
 4109                return false;
 110            }
 111
 235112            GetLocalEdge(
 235113                second,
 235114                firstEdgeIndex,
 235115                out Signed192 secondOwnEdgeX,
 235116                out Signed192 secondOwnEdgeY,
 235117                out Signed192 secondOwnEdgeZ);
 235118            if (!TryKeepPairAxis(
 235119                    TransformLocalNormalCrossEdge(
 235120                        secondBasis,
 235121                        secondNormalX,
 235122                        secondNormalY,
 235123                        secondNormalZ,
 235124                        secondOwnEdgeX,
 235125                        secondOwnEdgeY,
 235126                        secondOwnEdgeZ),
 235127                    first,
 235128                    firstOrigin,
 235129                    firstBasis,
 235130                    second,
 235131                    secondOrigin,
 235132                    secondBasis,
 235133                    ref best))
 134            {
 1135                contact = default;
 1136                return false;
 137            }
 138
 234139            for (int secondEdgeIndex = 0;
 932140                secondEdgeIndex < FixedTriangle.EdgeCount;
 698141                secondEdgeIndex++)
 142            {
 700143                GetLocalEdge(
 700144                    second,
 700145                    secondEdgeIndex,
 700146                    out Signed192 secondEdgeX,
 700147                    out Signed192 secondEdgeY,
 700148                    out Signed192 secondEdgeZ);
 700149                WideAxis3 secondEdge = WideRigidProjection.TransformLocalAxis(
 700150                    secondBasis,
 700151                    secondEdgeX,
 700152                    secondEdgeY,
 700153                    secondEdgeZ);
 700154                if (!TryKeepPairAxis(
 700155                        WideAxis3.Cross(firstEdge, secondEdge),
 700156                        first,
 700157                        firstOrigin,
 700158                        firstBasis,
 700159                        second,
 700160                        secondOrigin,
 700161                        secondBasis,
 700162                        ref best))
 163                {
 2164                    contact = default;
 2165                    return false;
 166                }
 167            }
 168        }
 169
 76170        WideAxis3 orientedAxis = best.Negate ? -best.Axis : best.Axis;
 76171        Vector3d normal = WideNormalization.GetNormalized(
 76172            Signed576.ExtendValue(orientedAxis.X),
 76173            Signed576.ExtendValue(orientedAxis.Y),
 76174            Signed576.ExtendValue(orientedAxis.Z));
 76175        FixedPointAnchor secondCentroid = FixedPointAnchor.FromValidatedFrame(
 76176            secondOrigin,
 76177            secondRotation,
 76178            second.Centroid);
 76179        FixedPointAnchor firstAnchor = GetClosestPointAnchor(
 76180            first,
 76181            firstOrigin,
 76182            firstRotation,
 76183            secondCentroid);
 76184        FixedPointAnchor secondAnchor = GetClosestPointAnchor(
 76185            second,
 76186            secondOrigin,
 76187            secondRotation,
 76188            firstAnchor);
 76189        Fixed64 depth = best.GetRoundedDepth(out bool depthIsClamped);
 76190        contact = new FixedContactAnchors(
 76191            firstAnchor,
 76192            secondAnchor,
 76193            normal,
 76194            depth,
 76195            depthIsClamped);
 76196        return true;
 197    }
 198
 199    private static bool TryKeepPairAxis(
 200        in WideAxis3 axis,
 201        in FixedTriangle first,
 202        Vector3d firstOrigin,
 203        in WideRationalBasis3d firstBasis,
 204        in FixedTriangle second,
 205        Vector3d secondOrigin,
 206        in WideRationalBasis3d secondBasis,
 207        ref WidePointSpanPenetration best)
 208    {
 1344209        if (axis.IsZero)
 86210            return true;
 211
 1258212        GetProjectionInterval(
 1258213            first,
 1258214            firstBasis,
 1258215            axis,
 1258216            secondBasis.Denominator,
 1258217            out Signed576 firstMinimum,
 1258218            out Signed576 firstMaximum,
 1258219            out Signed576 firstSum);
 1258220        GetProjectionInterval(
 1258221            second,
 1258222            secondBasis,
 1258223            axis,
 1258224            firstBasis.Denominator,
 1258225            out Signed576 secondMinimum,
 1258226            out Signed576 secondMaximum,
 1258227            out Signed576 secondSum);
 1258228        Signed576 originCommon = WideArithmetic.MultiplySigned576(
 1258229            WideArithmetic.MultiplySigned576(
 1258230                WideRigidProjection.GetWorldOriginDifferenceProjection(
 1258231                    secondOrigin,
 1258232                    firstOrigin,
 1258233                    axis),
 1258234                firstBasis.Denominator),
 1258235            secondBasis.Denominator);
 1258236        secondMinimum = WideArithmetic.AddSigned576(
 1258237            secondMinimum,
 1258238            originCommon);
 1258239        secondMaximum = WideArithmetic.AddSigned576(
 1258240            secondMaximum,
 1258241            originCommon);
 242
 1258243        Signed576 pushNegative = WideArithmetic.SubtractSigned576(
 1258244            firstMaximum,
 1258245            secondMinimum);
 1258246        Signed576 pushPositive = WideArithmetic.SubtractSigned576(
 1258247            secondMaximum,
 1258248            firstMinimum);
 1258249        if (pushNegative.Sign < 0 || pushPositive.Sign < 0)
 10250            return false;
 251
 1248252        Signed576 overlap = WideArithmetic.SubtractSigned576(
 1248253                pushPositive,
 1248254                pushNegative).Sign < 0
 1248255            ? pushPositive
 1248256            : pushNegative;
 1248257        Signed320 commonDenominator = WideArithmetic.MultiplySigned192(
 1248258            firstBasis.Denominator,
 1248259            secondBasis.Denominator);
 1248260        Signed576 squaredAxisLength = axis.SquaredLength;
 1248261        if (!best.ShouldReplace(
 1248262                overlap,
 1248263                squaredAxisLength,
 1248264                commonDenominator))
 265        {
 1160266            return true;
 267        }
 268
 88269        Signed576 secondCentroidProjection = WideArithmetic.AddSigned576(
 88270            secondSum,
 88271            WideArithmetic.AddSigned576(
 88272                WideArithmetic.AddSigned576(originCommon, originCommon),
 88273                originCommon));
 88274        bool negate = WideArithmetic.SubtractSigned576(
 88275            secondCentroidProjection,
 88276            firstSum).Sign < 0;
 88277        best = new WidePointSpanPenetration(
 88278            axis,
 88279            negate,
 88280            overlap,
 88281            squaredAxisLength,
 88282            commonDenominator);
 88283        return true;
 284    }
 285
 286    private static void GetProjectionInterval(
 287        in FixedTriangle triangle,
 288        in WideRationalBasis3d basis,
 289        in WideAxis3 axis,
 290        Signed192 otherDenominator,
 291        out Signed576 minimum,
 292        out Signed576 maximum,
 293        out Signed576 sum)
 294    {
 2516295        WideRigidProjection.GetLocalAxisProjections(
 2516296            axis,
 2516297            basis,
 2516298            out Signed576 localAxisX,
 2516299            out Signed576 localAxisY,
 2516300            out Signed576 localAxisZ);
 2516301        Signed576 first = WideArithmetic.MultiplySigned576(
 2516302            WideRigidProjection.GetLocalOffsetProjection(
 2516303                triangle.A,
 2516304                localAxisX,
 2516305                localAxisY,
 2516306                localAxisZ),
 2516307            otherDenominator);
 2516308        minimum = first;
 2516309        maximum = first;
 2516310        Signed576 second = WideArithmetic.MultiplySigned576(
 2516311            WideRigidProjection.GetLocalOffsetProjection(
 2516312                triangle.B,
 2516313                localAxisX,
 2516314                localAxisY,
 2516315                localAxisZ),
 2516316            otherDenominator);
 2516317        Signed576 third = WideArithmetic.MultiplySigned576(
 2516318            WideRigidProjection.GetLocalOffsetProjection(
 2516319                triangle.C,
 2516320                localAxisX,
 2516321                localAxisY,
 2516322                localAxisZ),
 2516323            otherDenominator);
 2516324        WideRigidProjection.IncludeProjection(
 2516325            second,
 2516326            ref minimum,
 2516327            ref maximum);
 2516328        WideRigidProjection.IncludeProjection(
 2516329            third,
 2516330            ref minimum,
 2516331            ref maximum);
 2516332        sum = WideArithmetic.AddSigned576(
 2516333            WideArithmetic.AddSigned576(first, second),
 2516334            third);
 2516335    }
 336
 337    private static WideAxis3 TransformLocalNormalCrossEdge(
 338        WideRationalBasis3d basis,
 339        Signed192 normalX,
 340        Signed192 normalY,
 341        Signed192 normalZ,
 342        Signed192 edgeX,
 343        Signed192 edgeY,
 344        Signed192 edgeZ) =>
 474345        WideRigidProjection.TransformLocalTriangleNormalCrossEdgeAxis(
 474346            basis,
 474347            WideArithmetic.MultiplySubtract(
 474348                normalY,
 474349                edgeZ,
 474350                normalZ,
 474351                edgeY),
 474352            WideArithmetic.MultiplySubtract(
 474353                normalZ,
 474354                edgeX,
 474355                normalX,
 474356                edgeZ),
 474357            WideArithmetic.MultiplySubtract(
 474358                normalX,
 474359                edgeY,
 474360                normalY,
 474361                edgeX));
 362
 363    private static void GetLocalEdge(
 364        FixedTriangle triangle,
 365        int index,
 366        out Signed192 x,
 367        out Signed192 y,
 368        out Signed192 z)
 369    {
 370        Vector3d start;
 371        Vector3d end;
 1174372        if (index == 0)
 373        {
 398374            start = triangle.A;
 398375            end = triangle.B;
 376        }
 776377        else if (index == 1)
 378        {
 389379            start = triangle.B;
 389380            end = triangle.C;
 381        }
 382        else
 383        {
 387384            start = triangle.C;
 387385            end = triangle.A;
 386        }
 387
 1174388        x = WideArithmetic.SubtractSigned192(
 1174389            Signed192.Raw(end.X),
 1174390            Signed192.Raw(start.X));
 1174391        y = WideArithmetic.SubtractSigned192(
 1174392            Signed192.Raw(end.Y),
 1174393            Signed192.Raw(start.Y));
 1174394        z = WideArithmetic.SubtractSigned192(
 1174395            Signed192.Raw(end.Z),
 1174396            Signed192.Raw(start.Z));
 1174397    }
 398}

Methods/Properties

GetClosestPointAnchor(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Geometry.FixedPointAnchor&)
GetClosestTriangleLocalPoint(FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed320)
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&)
TryKeepPairAxis(FixedMathSharp.Geometry.WideAxis3&,FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.WideRationalBasis3d&,FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Vector3d,FixedMathSharp.Geometry.WideRationalBasis3d&,FixedMathSharp.Geometry.WidePointSpanPenetration&)
GetProjectionInterval(FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.WideRationalBasis3d&,FixedMathSharp.Geometry.WideAxis3&,FixedMathSharp.Signed192,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&)
TransformLocalNormalCrossEdge(FixedMathSharp.Geometry.WideRationalBasis3d,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192)
GetLocalEdge(FixedMathSharp.Geometry.FixedTriangle,System.Int32,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&,FixedMathSharp.Signed192&)