< Summary

Line coverage
100%
Covered lines: 2088
Uncovered lines: 0
Coverable lines: 2088
Total lines: 3004
Line coverage: 100%
Branch coverage
100%
Covered branches: 266
Total branches: 266
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: TryGetRotatedConeRelation(...)100%88100%
File 1: GetProjectedConeCeilingDistance(...)100%1616100%
File 1: FindProjectedConeCeilingDistance(...)100%44100%
File 1: GetProjectedConeClosestOffset(...)100%22100%
File 1: GetSegmentOffset(...)100%11100%
File 1: KeepCloserOffset(...)100%44100%
File 1: CompareConeDistanceToRadius(...)100%88100%
File 1: GetConeProjectionData(...)100%11100%
File 1: IsPointInConeProjectionWedge(...)100%44100%
File 1: TryCompareConeTangentDistanceToRadius(...)100%44100%
File 1: CompareConeTangentSquaredDistance(...)100%66100%
File 1: CompareRationalDistanceToRadius(...)100%22100%
File 2: .ctor(...)100%11100%
File 2: .ctor(...)100%11100%
File 2: TryGetSphereRelation(...)100%44100%
File 2: TryGetCenteredCapsuleRelation(...)100%11100%
File 2: TryGetCenteredCylinderRelation(...)100%44100%
File 2: TryGetCenteredConeRelation(...)100%66100%
File 2: TryCreateRadiallyExpandedRelation(...)100%44100%
File 2: GetRotatedLocalAxis(...)100%11100%
File 2: GetLocalOffsetNumerator(...)100%11100%
File 2: GetWorldPoint(...)100%11100%
File 2: GetCenteredAxisEndpoints(...)100%11100%
File 2: GetCenteredBasisAxisEndpoints(...)100%11100%
File 2: TryGetRadialGap(...)100%88100%
File 2: GetPointDistance(...)100%11100%
File 2: GetSegmentDistance(...)100%11100%
File 2: GetSegmentDistance(...)100%66100%
File 2: IsWithinRadius(...)100%11100%
File 2: TryGetDistance(...)100%88100%
File 2: CompareDistanceToRaw(...)100%11100%
File 2: CompareDistanceToRaw(...)100%11100%
File 2: CompareDistanceToTwiceRaw(...)100%11100%
File 2: CompareDistanceToTwiceRaw(...)100%11100%
File 2: GetOffset(...)100%11100%
File 2: GetHalfToEvenIncrement(...)100%11100%
File 2: GetLargestPositiveMagnitude(...)100%1010100%
File 3: TryGetProjectedDiskRelation(...)100%1414100%
File 3: GetProjectedDiskCeilingDistance(...)100%1616100%
File 3: FindProjectedDiskCeilingDistance(...)100%44100%
File 3: GetProjectedDiskClosestOffset(...)100%11100%
File 3: GetEllipseClosestOffset(...)100%44100%
File 3: GetEllipseConstraintCoordinate(...)100%11100%
File 3: GetProjectedDiskSegmentEndpoints(...)100%11100%
File 3: CompareProjectedDiskDistanceToRadius(...)100%1414100%
File 3: CountProjectedDiskCircleRoots(...)100%22100%
File 3: CreateProjectedDiskCirclePolynomial(...)100%22100%
File 3: GetProjectedDiskConicCoefficient(...)100%11100%
File 3: GetProjectedDiskRadialCoefficient(...)100%11100%
File 3: GetSquaredPolynomial(...)100%11100%
File 3: MultiplyBySmall(...)100%1010100%
File 3: DoubleSigned832(...)100%11100%
File 3: EvaluateProjectedDiskConic(...)100%11100%
File 4: TryGetOrientedBoxRelation(...)100%66100%
File 4: TryGetTriangleRelation(...)100%22100%
File 4: TryGetConvexRelation(...)100%66100%
File 4: TryCreateRelation(...)100%44100%
File 4: ContainsPoint(...)100%1010100%
File 4: BuildConvexHull(...)100%1212100%
File 4: SortAndDeduplicate(...)100%1010100%
File 4: ComparePoint(...)100%22100%
File 4: GetTurn(...)100%11100%
File 4: Cross(...)100%11100%
File 4: KeepCloser(...)100%22100%
File 4: CompareDistances(...)100%11100%
File 5: TryGetTriangleRelation(...)100%3232100%
File 5: GetScaledProjectedDistance(...)100%66100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Common/WidePlanarProjection.Cone.cs

#LineLine coverage
 1//=======================================================================
 2// WidePlanarProjection.Cone.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/// Exact projected-cone hull admission and tangent-segment reduction.
 14/// </content>
 15internal static partial class WidePlanarProjection
 16{
 17    private const int ConeComparisonWordCount = 56;
 18
 19    private static bool TryGetRotatedConeRelation(
 20        Vector2d circleCenter,
 21        Fixed64 circleRadius,
 22        RationalPoint baseCenter,
 23        RationalPoint apex,
 24        Signed192 coordinateDenominator,
 25        Signed192 axisDenominator,
 26        Signed192 axisX,
 27        Signed192 axisY,
 28        Signed192 axisZ,
 29        Fixed64 coneHeight,
 30        Fixed64 coneRadius,
 31        out PlanarProjectionRelation relation)
 32    {
 1233        RationalDistance baseDistance = GetPointDistance(
 1234            circleCenter,
 1235            coordinateDenominator,
 1236            baseCenter);
 1237        RationalDistance apexDistance = GetPointDistance(
 1238            circleCenter,
 1239            coordinateDenominator,
 1240            apex);
 1241        GetConeProjectionData(
 1242            baseDistance,
 1243            coordinateDenominator,
 1244            axisDenominator,
 1245            axisX,
 1246            axisY,
 1247            axisZ,
 1248            coneHeight,
 1249            coneRadius,
 1250            out Signed320 planarAxisSquared,
 1251            out Signed320 axisSquared,
 1252            out Signed576 delta,
 1253            out Signed576 axisProjection,
 1254            out Signed576 perpendicularProjection,
 1255            out Signed576 apexProjectionGap);
 56
 1257        int maximumComparison = CompareConeDistanceToRadius(
 1258            baseDistance,
 1259            apexDistance,
 1260            coordinateDenominator,
 1261            axisDenominator,
 1262            axisX,
 1263            axisY,
 1264            axisZ,
 1265            coneHeight,
 1266            coneRadius,
 1267            planarAxisSquared,
 1268            axisSquared,
 1269            delta,
 1270            axisProjection,
 1271            perpendicularProjection,
 1272            apexProjectionGap,
 1273            Signed192.Raw(circleRadius),
 1274            radiusDenominator: 1);
 1275        if (maximumComparison > 0)
 76        {
 277            relation = default;
 278            return false;
 79        }
 80
 1081        int zeroComparison = CompareConeDistanceToRadius(
 1082            baseDistance,
 1083            apexDistance,
 1084            coordinateDenominator,
 1085            axisDenominator,
 1086            axisX,
 1087            axisY,
 1088            axisZ,
 1089            coneHeight,
 1090            coneRadius,
 1091            planarAxisSquared,
 1092            axisSquared,
 1093            delta,
 1094            axisProjection,
 1095            perpendicularProjection,
 1096            apexProjectionGap,
 1097            default,
 1098            radiusDenominator: 1);
 1099        if (zeroComparison <= 0)
 100        {
 2101            relation = PlanarProjectionRelation.Contained;
 2102            return true;
 103        }
 104
 8105        GetProjectedConeClosestOffset(
 8106            baseDistance,
 8107            apexDistance,
 8108            coordinateDenominator,
 8109            axisX,
 8110            axisY,
 8111            axisZ,
 8112            coneRadius,
 8113            out Fixed64 approximateDistance,
 8114            out Vector2d direction);
 8115        long low = GetProjectedConeCeilingDistance(
 8116            baseDistance,
 8117            apexDistance,
 8118            coordinateDenominator,
 8119            axisDenominator,
 8120            axisX,
 8121            axisY,
 8122            axisZ,
 8123            coneHeight,
 8124            coneRadius,
 8125            planarAxisSquared,
 8126            axisSquared,
 8127            delta,
 8128            axisProjection,
 8129            perpendicularProjection,
 8130            apexProjectionGap,
 8131            circleRadius,
 8132            approximateDistance);
 133
 8134        long floor = low - 1L;
 8135        Signed192 midpointNumerator = WideArithmetic.AddSigned192(
 8136            WideArithmetic.AddSigned192(
 8137                Signed192.Signed(floor),
 8138                Signed192.Signed(floor)),
 8139            Signed192.Signed(1L));
 8140        int midpointComparison = CompareConeDistanceToRadius(
 8141            baseDistance,
 8142            apexDistance,
 8143            coordinateDenominator,
 8144            axisDenominator,
 8145            axisX,
 8146            axisY,
 8147            axisZ,
 8148            coneHeight,
 8149            coneRadius,
 8150            planarAxisSquared,
 8151            axisSquared,
 8152            delta,
 8153            axisProjection,
 8154            perpendicularProjection,
 8155            apexProjectionGap,
 8156            midpointNumerator,
 8157            radiusDenominator: 2);
 8158        long rounded = midpointComparison < 0
 8159            ? floor
 8160            : midpointComparison > 0
 8161                ? low
 8162                : floor + (floor & 1L);
 8163        Fixed64 distance = Fixed64.FromRaw(rounded);
 8164        relation = new PlanarProjectionRelation(
 8165            distance,
 8166            direction * distance,
 8167            direction);
 8168        return true;
 169    }
 170
 171    private static long GetProjectedConeCeilingDistance(
 172        RationalDistance baseDistance,
 173        RationalDistance apexDistance,
 174        Signed192 coordinateDenominator,
 175        Signed192 axisDenominator,
 176        Signed192 axisX,
 177        Signed192 axisY,
 178        Signed192 axisZ,
 179        Fixed64 coneHeight,
 180        Fixed64 coneRadius,
 181        Signed320 planarAxisSquared,
 182        Signed320 axisSquared,
 183        Signed576 delta,
 184        Signed576 axisProjection,
 185        Signed576 perpendicularProjection,
 186        Signed576 apexProjectionGap,
 187        Fixed64 maximum,
 188        Fixed64 approximate)
 189    {
 8190        long candidate = approximate.m_rawValue;
 8191        if (candidate > maximum.m_rawValue)
 1192            candidate = maximum.m_rawValue;
 193
 8194        int comparison = CompareConeDistanceToRadius(
 8195            baseDistance,
 8196            apexDistance,
 8197            coordinateDenominator,
 8198            axisDenominator,
 8199            axisX,
 8200            axisY,
 8201            axisZ,
 8202            coneHeight,
 8203            coneRadius,
 8204            planarAxisSquared,
 8205            axisSquared,
 8206            delta,
 8207            axisProjection,
 8208            perpendicularProjection,
 8209            apexProjectionGap,
 8210            Signed192.Signed(candidate),
 8211            radiusDenominator: 1);
 8212        if (comparison <= 0)
 213        {
 3214            long high = candidate;
 3215            long step = 1L;
 14216            while (high > 1L)
 217            {
 13218                long probe = high > step ? high - step : 0L;
 13219                if (probe == 0L
 13220                    || CompareConeDistanceToRadius(
 13221                        baseDistance,
 13222                        apexDistance,
 13223                        coordinateDenominator,
 13224                        axisDenominator,
 13225                        axisX,
 13226                        axisY,
 13227                        axisZ,
 13228                        coneHeight,
 13229                        coneRadius,
 13230                        planarAxisSquared,
 13231                        axisSquared,
 13232                        delta,
 13233                        axisProjection,
 13234                        perpendicularProjection,
 13235                        apexProjectionGap,
 13236                        Signed192.Signed(probe),
 13237                        radiusDenominator: 1) > 0)
 238                {
 2239                    return FindProjectedConeCeilingDistance(
 2240                        baseDistance,
 2241                        apexDistance,
 2242                        coordinateDenominator,
 2243                        axisDenominator,
 2244                        axisX,
 2245                        axisY,
 2246                        axisZ,
 2247                        coneHeight,
 2248                        coneRadius,
 2249                        planarAxisSquared,
 2250                        axisSquared,
 2251                        delta,
 2252                        axisProjection,
 2253                        perpendicularProjection,
 2254                        apexProjectionGap,
 2255                        probe + 1L,
 2256                        high);
 257                }
 258
 11259                high = probe;
 11260                step = (long)Math.Min(
 11261                    (ulong)step << 1,
 11262                    (ulong)high);
 263            }
 264
 1265            return 1L;
 266        }
 267
 5268        long low = candidate + 1L;
 5269        long upper = maximum.m_rawValue;
 5270        long upwardStep = 1L;
 10271        while (low < upper)
 272        {
 9273            long remaining = upper - candidate;
 9274            long probe = candidate + Math.Min(
 9275                upwardStep,
 9276                remaining);
 9277            if (CompareConeDistanceToRadius(
 9278                baseDistance,
 9279                apexDistance,
 9280                coordinateDenominator,
 9281                axisDenominator,
 9282                axisX,
 9283                axisY,
 9284                axisZ,
 9285                coneHeight,
 9286                coneRadius,
 9287                planarAxisSquared,
 9288                axisSquared,
 9289                delta,
 9290                axisProjection,
 9291                perpendicularProjection,
 9292                apexProjectionGap,
 9293                Signed192.Signed(probe),
 9294                radiusDenominator: 1) <= 0)
 295            {
 4296                return FindProjectedConeCeilingDistance(
 4297                    baseDistance,
 4298                    apexDistance,
 4299                    coordinateDenominator,
 4300                    axisDenominator,
 4301                    axisX,
 4302                    axisY,
 4303                    axisZ,
 4304                    coneHeight,
 4305                    coneRadius,
 4306                    planarAxisSquared,
 4307                    axisSquared,
 4308                    delta,
 4309                    axisProjection,
 4310                    perpendicularProjection,
 4311                    apexProjectionGap,
 4312                    low,
 4313                    probe);
 314            }
 315
 5316            low = probe + 1L;
 5317            upwardStep = (long)Math.Min(
 5318                (ulong)upwardStep << 1,
 5319                (ulong)(upper - candidate));
 320        }
 321
 1322        return upper;
 323    }
 324
 325    private static long FindProjectedConeCeilingDistance(
 326        RationalDistance baseDistance,
 327        RationalDistance apexDistance,
 328        Signed192 coordinateDenominator,
 329        Signed192 axisDenominator,
 330        Signed192 axisX,
 331        Signed192 axisY,
 332        Signed192 axisZ,
 333        Fixed64 coneHeight,
 334        Fixed64 coneRadius,
 335        Signed320 planarAxisSquared,
 336        Signed320 axisSquared,
 337        Signed576 delta,
 338        Signed576 axisProjection,
 339        Signed576 perpendicularProjection,
 340        Signed576 apexProjectionGap,
 341        long low,
 342        long high)
 343    {
 18344        while (low < high)
 345        {
 12346            long middle = low + ((high - low) >> 1);
 12347            int comparison = CompareConeDistanceToRadius(
 12348                baseDistance,
 12349                apexDistance,
 12350                coordinateDenominator,
 12351                axisDenominator,
 12352                axisX,
 12353                axisY,
 12354                axisZ,
 12355                coneHeight,
 12356                coneRadius,
 12357                planarAxisSquared,
 12358                axisSquared,
 12359                delta,
 12360                axisProjection,
 12361                perpendicularProjection,
 12362                apexProjectionGap,
 12363                Signed192.Signed(middle),
 12364                radiusDenominator: 1);
 12365            if (comparison <= 0)
 5366                high = middle;
 367            else
 7368                low = middle + 1L;
 369        }
 370
 6371        return low;
 372    }
 373
 374    private static void GetProjectedConeClosestOffset(
 375        RationalDistance baseDistance,
 376        RationalDistance apexDistance,
 377        Signed192 coordinateDenominator,
 378        Signed192 axisX,
 379        Signed192 axisY,
 380        Signed192 axisZ,
 381        Fixed64 coneRadius,
 382        out Fixed64 approximateDistance,
 383        out Vector2d direction)
 384    {
 8385        Signed320 baseX = Signed320.NarrowValue(baseDistance.X);
 8386        Signed320 baseZ = Signed320.NarrowValue(baseDistance.Z);
 8387        Signed320 apexX = WideArithmetic.SubtractSigned320(
 8388            Signed320.NarrowValue(apexDistance.X),
 8389            baseX);
 8390        Signed320 apexZ = WideArithmetic.SubtractSigned320(
 8391            Signed320.NarrowValue(apexDistance.Z),
 8392            baseZ);
 8393        Signed320 scaledRadius = WideArithmetic.MultiplySigned192(
 8394            coordinateDenominator,
 8395            Signed192.Raw(coneRadius));
 8396        Signed320 scale = GetLargestPositiveMagnitude(
 8397            baseX,
 8398            baseZ,
 8399            apexX,
 8400            apexZ,
 8401            scaledRadius);
 8402        Vector2d query = new(
 8403            -Fixed64.GetSignedRatio(baseX, scale),
 8404            -Fixed64.GetSignedRatio(baseZ, scale));
 8405        Vector2d apex = new(
 8406            Fixed64.GetSignedRatio(apexX, scale),
 8407            Fixed64.GetSignedRatio(apexZ, scale));
 8408        Vector2d axis = WideNormalization.GetNormalized(axisX, axisZ);
 8409        Vector2d perpendicular = new(-axis.Y, axis.X);
 8410        Vector2d localQuery = new(
 8411            Vector2d.Dot(query, axis),
 8412            Vector2d.Dot(query, perpendicular));
 8413        Fixed64 apexLength = Vector2d.Dot(apex, axis);
 8414        Fixed64 radius = Fixed64.GetSignedRatio(scaledRadius, scale);
 8415        Fixed64 minor = radius * FixedMath.Abs(
 8416            WideNormalization.GetNormalized(
 8417                axisX,
 8418                axisY,
 8419                axisZ).Y);
 420        Vector2d localOffset;
 8421        if (apexLength <= minor)
 422        {
 3423            localOffset = GetEllipseClosestOffset(
 3424                localQuery.X,
 3425                localQuery.Y,
 3426                minor,
 3427                radius);
 428        }
 429        else
 430        {
 5431            Fixed64 tangentX = Fixed64.MultiplyDivide(
 5432                minor,
 5433                minor,
 5434                apexLength,
 5435                out _);
 5436            Fixed64 ratio = tangentX / apexLength;
 5437            Fixed64 tangentY = radius * FixedMath.Sqrt(
 5438                FixedMath.Max(
 5439                    Fixed64.Zero,
 5440                    Fixed64.One - ratio));
 5441            Vector2d ellipseOffset = GetEllipseClosestOffset(
 5442                localQuery.X,
 5443                localQuery.Y,
 5444                minor,
 5445                radius);
 5446            Vector2d ellipsePoint = localQuery + ellipseOffset;
 5447            bool found = ellipsePoint.X <= tangentX;
 5448            localOffset = ellipseOffset;
 5449            KeepCloserOffset(
 5450                new Vector2d(apexLength, Fixed64.Zero) - localQuery,
 5451                ref found,
 5452                ref localOffset);
 5453            KeepCloserOffset(
 5454                GetSegmentOffset(
 5455                    localQuery,
 5456                    new Vector2d(tangentX, tangentY),
 5457                    new Vector2d(apexLength, Fixed64.Zero)),
 5458                ref found,
 5459                ref localOffset);
 5460            KeepCloserOffset(
 5461                GetSegmentOffset(
 5462                    localQuery,
 5463                    new Vector2d(tangentX, -tangentY),
 5464                    new Vector2d(apexLength, Fixed64.Zero)),
 5465                ref found,
 5466                ref localOffset);
 467        }
 468
 8469        Vector2d worldOffset =
 8470            axis * localOffset.X + perpendicular * localOffset.Y;
 8471        direction = worldOffset.Normalized;
 8472        Signed576 distanceNumerator =
 8473            WideArithmetic.MultiplySigned320(
 8474                scale,
 8475                Signed320.ExtendValue(
 8476                    Signed192.Raw(worldOffset.Magnitude)));
 8477        _ = Fixed64.TryGetSignedRawRatio(
 8478            distanceNumerator,
 8479            Signed576.ExtendValue(
 8480                WideArithmetic.MultiplySigned192(
 8481                    coordinateDenominator,
 8482                    Signed192.Raw(Fixed64.One))),
 8483            out approximateDistance);
 8484    }
 485
 486    private static Vector2d GetSegmentOffset(
 487        Vector2d point,
 488        Vector2d first,
 489        Vector2d second)
 490    {
 10491        Vector2d edge = second - first;
 10492        Fixed64 projection = FixedMath.Clamp(
 10493            Vector2d.Dot(point - first, edge) / edge.MagnitudeSquared,
 10494            Fixed64.Zero,
 10495            Fixed64.One);
 10496        return first + edge * projection - point;
 497    }
 498
 499    private static void KeepCloserOffset(
 500        Vector2d candidate,
 501        ref bool found,
 502        ref Vector2d best)
 503    {
 15504        if (!found || candidate.MagnitudeSquared < best.MagnitudeSquared)
 505        {
 8506            found = true;
 8507            best = candidate;
 508        }
 15509    }
 510
 511    private static int CompareConeDistanceToRadius(
 512        RationalDistance baseDistance,
 513        RationalDistance apexDistance,
 514        Signed192 coordinateDenominator,
 515        Signed192 axisDenominator,
 516        Signed192 axisX,
 517        Signed192 axisY,
 518        Signed192 axisZ,
 519        Fixed64 coneHeight,
 520        Fixed64 coneRadius,
 521        Signed320 planarAxisSquared,
 522        Signed320 axisSquared,
 523        Signed576 delta,
 524        Signed576 axisProjection,
 525        Signed576 perpendicularProjection,
 526        Signed576 apexProjectionGap,
 527        Signed192 radiusNumerator,
 528        int radiusDenominator)
 529    {
 71530        int baseComparison = CompareProjectedDiskDistanceToRadius(
 71531            baseDistance,
 71532            coordinateDenominator,
 71533            axisX,
 71534            axisY,
 71535            axisZ,
 71536            coneRadius,
 71537            radiusNumerator,
 71538            radiusDenominator);
 71539        if (delta.Sign <= 0)
 30540            return baseComparison;
 541
 41542        if (IsPointInConeProjectionWedge(
 41543                coordinateDenominator,
 41544                axisDenominator,
 41545                axisY,
 41546                coneHeight,
 41547                coneRadius,
 41548                planarAxisSquared,
 41549                delta,
 41550                axisProjection,
 41551                perpendicularProjection,
 41552                apexProjectionGap))
 553        {
 4554            return radiusNumerator.IsZero ? 0 : -1;
 555        }
 556
 37557        int comparison = Math.Min(
 37558            baseComparison,
 37559            CompareRationalDistanceToRadius(
 37560                apexDistance,
 37561                radiusNumerator,
 37562                radiusDenominator));
 37563        if (TryCompareConeTangentDistanceToRadius(
 37564                coordinateDenominator,
 37565                coneHeight,
 37566                coneRadius,
 37567                planarAxisSquared,
 37568                axisSquared,
 37569                delta,
 37570                perpendicularProjection,
 37571                apexProjectionGap,
 37572                radiusNumerator,
 37573                radiusDenominator,
 37574                out int tangentComparison))
 575        {
 20576            comparison = Math.Min(
 20577                comparison,
 20578                tangentComparison);
 579        }
 580
 37581        return comparison;
 582    }
 583
 584    private static void GetConeProjectionData(
 585        RationalDistance baseDistance,
 586        Signed192 coordinateDenominator,
 587        Signed192 axisDenominator,
 588        Signed192 axisX,
 589        Signed192 axisY,
 590        Signed192 axisZ,
 591        Fixed64 coneHeight,
 592        Fixed64 coneRadius,
 593        out Signed320 planarAxisSquared,
 594        out Signed320 axisSquared,
 595        out Signed576 delta,
 596        out Signed576 axisProjection,
 597        out Signed576 perpendicularProjection,
 598        out Signed576 apexProjectionGap)
 599    {
 12600        Signed320 relativeX = WideArithmetic.SubtractSigned320(
 12601            default,
 12602            Signed320.NarrowValue(baseDistance.X));
 12603        Signed320 relativeZ = WideArithmetic.SubtractSigned320(
 12604            default,
 12605            Signed320.NarrowValue(baseDistance.Z));
 12606        Signed320 axisX2 = WideArithmetic.MultiplySigned192(
 12607            axisX,
 12608            axisX);
 12609        Signed320 axisY2 = WideArithmetic.MultiplySigned192(
 12610            axisY,
 12611            axisY);
 12612        Signed320 axisZ2 = WideArithmetic.MultiplySigned192(
 12613            axisZ,
 12614            axisZ);
 12615        planarAxisSquared = WideArithmetic.AddSigned320(
 12616            axisX2,
 12617            axisZ2);
 12618        axisSquared = WideArithmetic.AddSigned320(
 12619            planarAxisSquared,
 12620            axisY2);
 12621        Signed320 heightSquared = WideArithmetic.MultiplySigned192(
 12622            Signed192.Raw(coneHeight),
 12623            Signed192.Raw(coneHeight));
 12624        Signed320 radiusSquared = WideArithmetic.MultiplySigned192(
 12625            Signed192.Raw(coneRadius),
 12626            Signed192.Raw(coneRadius));
 12627        delta = WideArithmetic.SubtractSigned576(
 12628            WideArithmetic.MultiplySigned320(
 12629                heightSquared,
 12630                planarAxisSquared),
 12631            WideArithmetic.MultiplySigned320(
 12632                radiusSquared,
 12633                axisY2));
 12634        axisProjection = WideArithmetic.AddSigned576(
 12635            WideArithmetic.MultiplySigned320(
 12636                relativeX,
 12637                Signed320.ExtendValue(axisX)),
 12638            WideArithmetic.MultiplySigned320(
 12639                relativeZ,
 12640                Signed320.ExtendValue(axisZ)));
 12641        perpendicularProjection = WideArithmetic.SubtractSigned576(
 12642            WideArithmetic.MultiplySigned320(
 12643                relativeZ,
 12644                Signed320.ExtendValue(axisX)),
 12645            WideArithmetic.MultiplySigned320(
 12646                relativeX,
 12647                Signed320.ExtendValue(axisZ)));
 12648        Signed576 heightTerm = WideArithmetic.MultiplySigned576(
 12649            WideArithmetic.MultiplySigned576(
 12650                Signed576.ExtendValue(planarAxisSquared),
 12651                Signed192.Raw(coneHeight)),
 12652            coordinateDenominator);
 12653        Signed576 projectionTerm = WideArithmetic.MultiplySigned576(
 12654            axisProjection,
 12655            axisDenominator);
 12656        apexProjectionGap = WideArithmetic.SubtractSigned576(
 12657            heightTerm,
 12658            projectionTerm);
 12659    }
 660
 661    private static bool IsPointInConeProjectionWedge(
 662        Signed192 coordinateDenominator,
 663        Signed192 axisDenominator,
 664        Signed192 axisY,
 665        Fixed64 coneHeight,
 666        Fixed64 coneRadius,
 667        Signed320 planarAxisSquared,
 668        Signed576 delta,
 669        Signed576 axisProjection,
 670        Signed576 perpendicularProjection,
 671        Signed576 apexProjectionGap)
 672    {
 41673        if (apexProjectionGap.Sign < 0)
 9674            return false;
 675
 32676        Signed576 tangentStartLeft = WideArithmetic.MultiplySigned576(
 32677            WideArithmetic.MultiplySigned576(
 32678                axisProjection,
 32679                Signed192.Raw(coneHeight)),
 32680            axisDenominator);
 32681        Signed576 tangentStartRight = WideArithmetic.MultiplySigned576(
 32682            WideArithmetic.MultiplySigned320(
 32683                WideArithmetic.MultiplySigned192(
 32684                    Signed192.Raw(coneRadius),
 32685                    Signed192.Raw(coneRadius)),
 32686                WideArithmetic.MultiplySigned192(
 32687                    axisY,
 32688                    axisY)),
 32689            coordinateDenominator);
 32690        if (WideArithmetic.SubtractSigned576(
 32691                tangentStartLeft,
 32692                tangentStartRight).Sign < 0)
 693        {
 8694            return false;
 695        }
 696
 24697        Signed576 absolutePerpendicular =
 24698            WideArithmetic.Absolute(perpendicularProjection);
 24699        Signed576 radiusGap = WideArithmetic.MultiplySigned576(
 24700            apexProjectionGap,
 24701            Signed192.Raw(coneRadius));
 24702        return WideArithmetic.CompareSignedLinearRadicalToZero(
 24703                   Signed832.ExtendValue(
 24704                       WideArithmetic.SubtractSigned576(
 24705                           default,
 24706                           radiusGap)),
 24707                   Signed704.ExtendValue(absolutePerpendicular),
 24708                   delta,
 24709                   Signed320.ExtendValue(Signed192.Signed(1L))) <= 0;
 710    }
 711
 712    private static bool TryCompareConeTangentDistanceToRadius(
 713        Signed192 coordinateDenominator,
 714        Fixed64 coneHeight,
 715        Fixed64 coneRadius,
 716        Signed320 planarAxisSquared,
 717        Signed320 axisSquared,
 718        Signed576 delta,
 719        Signed576 perpendicularProjection,
 720        Signed576 apexProjectionGap,
 721        Signed192 radiusNumerator,
 722        int radiusDenominator,
 723        out int comparison)
 724    {
 37725        Signed576 absolutePerpendicular =
 37726            WideArithmetic.Absolute(perpendicularProjection);
 37727        Signed576 radiusPerpendicular = WideArithmetic.MultiplySigned576(
 37728            absolutePerpendicular,
 37729            Signed192.Raw(coneRadius));
 37730        Signed704 lowerRational =
 37731            WideArithmetic.MultiplySigned576ToSigned704(
 37732                radiusPerpendicular,
 37733                axisSquared);
 37734        int lowerGate = WideArithmetic.CompareSignedLinearRadicalToZero(
 37735            Signed832.ExtendValue(lowerRational),
 37736            Signed704.ExtendValue(apexProjectionGap),
 37737            delta,
 37738            Signed320.ExtendValue(Signed192.Signed(1L)));
 37739        if (lowerGate <= 0)
 740        {
 9741            comparison = default;
 9742            return false;
 743        }
 744
 28745        Signed320 sideSquared = WideArithmetic.AddSigned320(
 28746            WideArithmetic.MultiplySigned192(
 28747                Signed192.Raw(coneHeight),
 28748                Signed192.Raw(coneHeight)),
 28749            WideArithmetic.MultiplySigned192(
 28750                Signed192.Raw(coneRadius),
 28751                Signed192.Raw(coneRadius)));
 28752        Signed576 upperCoefficient = WideArithmetic.SubtractSigned576(
 28753            WideArithmetic.MultiplySigned576(
 28754                apexProjectionGap,
 28755                Signed192.Raw(coneHeight)),
 28756            WideArithmetic.MultiplySigned576(
 28757                WideArithmetic.MultiplySigned320(
 28758                    sideSquared,
 28759                    planarAxisSquared),
 28760                coordinateDenominator));
 28761        Signed576 heightRadiusPerpendicular =
 28762            WideArithmetic.MultiplySigned576(
 28763                absolutePerpendicular,
 28764                Signed192.Raw(coneHeight),
 28765                Signed192.Raw(coneRadius));
 28766        Signed704 upperRational =
 28767            WideArithmetic.MultiplySigned576ToSigned704(
 28768                heightRadiusPerpendicular,
 28769                axisSquared);
 28770        int upperGate = WideArithmetic.CompareSignedLinearRadicalToZero(
 28771            Signed832.ExtendValue(upperRational),
 28772            Signed704.ExtendValue(upperCoefficient),
 28773            delta,
 28774            Signed320.ExtendValue(Signed192.Signed(1L)));
 28775        if (upperGate >= 0)
 776        {
 8777            comparison = default;
 8778            return false;
 779        }
 780
 20781        Signed576 radiusGap = WideArithmetic.MultiplySigned576(
 20782            apexProjectionGap,
 20783            Signed192.Raw(coneRadius));
 20784        comparison = CompareConeTangentSquaredDistance(
 20785            absolutePerpendicular,
 20786            delta,
 20787            radiusGap,
 20788            coordinateDenominator,
 20789            planarAxisSquared,
 20790            sideSquared,
 20791            radiusNumerator,
 20792            radiusDenominator);
 20793        return true;
 794    }
 795
 796    private static int CompareConeTangentSquaredDistance(
 797        Signed576 radicalCoefficient,
 798        Signed576 radicand,
 799        Signed576 rationalMagnitude,
 800        Signed192 coordinateDenominator,
 801        Signed320 planarAxisSquared,
 802        Signed320 sideSquared,
 803        Signed192 radiusNumerator,
 804        int radiusDenominator)
 805    {
 20806        Span<ulong> first = stackalloc ulong[ConeComparisonWordCount];
 20807        Span<ulong> second = stackalloc ulong[ConeComparisonWordCount];
 20808        Span<ulong> third = stackalloc ulong[ConeComparisonWordCount];
 20809        Span<ulong> result = stackalloc ulong[ConeComparisonWordCount];
 20810        Span<ulong> other = stackalloc ulong[ConeComparisonWordCount];
 20811        Span<ulong> coefficient = stackalloc ulong[ConeComparisonWordCount];
 20812        Span<ulong> delta = stackalloc ulong[ConeComparisonWordCount];
 20813        Span<ulong> rational = stackalloc ulong[ConeComparisonWordCount];
 20814        Span<ulong> radius = stackalloc ulong[ConeComparisonWordCount];
 20815        Span<ulong> denominator = stackalloc ulong[ConeComparisonWordCount];
 20816        Span<ulong> planar = stackalloc ulong[ConeComparisonWordCount];
 20817        Span<ulong> side = stackalloc ulong[ConeComparisonWordCount];
 20818        first.Clear();
 20819        second.Clear();
 20820        third.Clear();
 20821        result.Clear();
 20822        other.Clear();
 20823        coefficient.Clear();
 20824        delta.Clear();
 20825        rational.Clear();
 20826        radius.Clear();
 20827        denominator.Clear();
 20828        planar.Clear();
 20829        side.Clear();
 20830        WideArithmetic.GetMagnitude(radicalCoefficient, coefficient);
 20831        WideArithmetic.GetMagnitude(radicand, delta);
 20832        WideArithmetic.GetMagnitude(rationalMagnitude, rational);
 20833        WideArithmetic.GetMagnitude(
 20834            radiusNumerator,
 20835            out radius[2],
 20836            out radius[1],
 20837            out radius[0]);
 20838        WideArithmetic.GetMagnitude(
 20839            coordinateDenominator,
 20840            out denominator[2],
 20841            out denominator[1],
 20842            out denominator[0]);
 20843        WideArithmetic.GetMagnitude(
 20844            planarAxisSquared,
 20845            out planar[4],
 20846            out planar[3],
 20847            out planar[2],
 20848            out planar[1],
 20849            out planar[0]);
 20850        WideArithmetic.GetMagnitude(
 20851            sideSquared,
 20852            out side[4],
 20853            out side[3],
 20854            out side[2],
 20855            out side[1],
 20856            out side[0]);
 857
 20858        WideArithmetic.MultiplyMagnitudes(
 20859            coefficient,
 20860            coefficient,
 20861            first);
 20862        WideArithmetic.MultiplyMagnitudes(first, delta, second);
 20863        WideArithmetic.MultiplyMagnitudes(rational, rational, first);
 20864        WideArithmetic.AddEqualMagnitudes(second, first, result);
 20865        if (radiusDenominator == 2)
 866        {
 3867            result.CopyTo(first);
 3868            WideArithmetic.AddEqualMagnitudes(first, first, second);
 3869            WideArithmetic.AddEqualMagnitudes(second, second, result);
 870        }
 871
 20872        WideArithmetic.MultiplyMagnitudes(radius, radius, first);
 20873        WideArithmetic.MultiplyMagnitudes(
 20874            denominator,
 20875            denominator,
 20876            second);
 20877        WideArithmetic.MultiplyMagnitudes(first, second, third);
 20878        WideArithmetic.MultiplyMagnitudes(planar, planar, first);
 20879        WideArithmetic.MultiplyMagnitudes(third, first, second);
 20880        WideArithmetic.MultiplyMagnitudes(second, side, other);
 881
 20882        int rationalComparison =
 20883            WideArithmetic.CompareMagnitudeEqualLength(result, other);
 20884        if (rationalComparison <= 0)
 1885            return -1;
 19886        WideArithmetic.SubtractEqualMagnitudes(
 19887            result,
 19888            other,
 19889            rational);
 890
 19891        WideArithmetic.GetMagnitude(rationalMagnitude, result);
 19892        WideArithmetic.MultiplyMagnitudes(coefficient, result, first);
 19893        first.CopyTo(second);
 19894        WideArithmetic.AddEqualMagnitudes(second, second, first);
 19895        if (radiusDenominator == 2)
 896        {
 3897            first.CopyTo(second);
 3898            WideArithmetic.AddEqualMagnitudes(second, second, first);
 3899            first.CopyTo(second);
 3900            WideArithmetic.AddEqualMagnitudes(second, second, first);
 901        }
 19902        WideArithmetic.MultiplyMagnitudes(first, first, second);
 19903        WideArithmetic.MultiplyMagnitudes(second, delta, other);
 19904        WideArithmetic.MultiplyMagnitudes(rational, rational, result);
 19905        return WideArithmetic.CompareMagnitudeEqualLength(result, other);
 906    }
 907
 908    private static int CompareRationalDistanceToRadius(
 909        RationalDistance distance,
 910        Signed192 radiusNumerator,
 911        int radiusDenominator) =>
 37912        radiusDenominator == 1
 37913            ? CompareDistanceToRaw(distance, radiusNumerator)
 37914            : CompareDistanceToTwiceRaw(distance, radiusNumerator);
 915
 916}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Common/WidePlanarProjection.cs

#LineLine coverage
 1//=======================================================================
 2// WidePlanarProjection.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/// <summary>
 13/// Owns exact point relations to complete X/Z projections without
 14/// materializing conceptual world-space features.
 15/// </summary>
 16internal static partial class WidePlanarProjection
 17{
 18    #region Nested Types
 19
 20    private readonly struct RationalPoint
 21    {
 22        internal RationalPoint(Signed320 x, Signed320 z)
 23        {
 13724            X = x;
 13725            Z = z;
 13726        }
 27
 28        internal readonly Signed320 X;
 29        internal readonly Signed320 Z;
 30    }
 31
 32    private readonly struct RationalDistance
 33    {
 34        internal RationalDistance(
 35            Signed576 x,
 36            Signed576 z,
 37            Signed576 denominator)
 38        {
 9339            X = x;
 9340            Z = z;
 9341            Denominator = denominator;
 9342            SquaredDistance = WideArithmetic.AddSigned832(
 9343                WideArithmetic.MultiplySigned576ToSigned832(x, x),
 9344                WideArithmetic.MultiplySigned576ToSigned832(z, z));
 9345        }
 46
 47        internal readonly Signed576 X;
 48        internal readonly Signed576 Z;
 49        internal readonly Signed576 Denominator;
 50        internal readonly Signed832 SquaredDistance;
 51    }
 52
 53    #endregion
 54
 55    internal static bool TryGetSphereRelation(
 56        Vector2d circleCenter,
 57        Fixed64 circleRadius,
 58        Vector3d sphereCenter,
 59        Fixed64 sphereRadius,
 60        out PlanarProjectionRelation relation)
 61    {
 362        Vector2d projectedCenter = new(
 363            sphereCenter.X,
 364            sphereCenter.Z);
 365        if (WideGeometry.CompareDistanceToRadiusSum(
 366                circleCenter,
 367                projectedCenter,
 368                circleRadius,
 369                sphereRadius) > 0)
 70        {
 171            relation = default;
 172            return false;
 73        }
 74
 275        if (WideGeometry.CompareDistanceToRadiusSum(
 276                circleCenter,
 277                projectedCenter,
 278                Fixed64.Zero,
 279                sphereRadius) <= 0)
 80        {
 181            relation = PlanarProjectionRelation.Contained;
 182            return true;
 83        }
 84
 185        _ = WideFiniteAxisIntersection.TryGetDistanceToCenteredCapsule(
 186            circleCenter,
 187            projectedCenter,
 188            Vector2d.Right,
 189            Fixed64.Zero,
 190            sphereRadius,
 191            out Fixed64 distance);
 92
 193        Vector2d normal =
 194            WideNormalization.GetDirection(projectedCenter, circleCenter);
 195        relation = new PlanarProjectionRelation(
 196            distance,
 197            -normal * distance,
 198            -normal);
 199        return true;
 100    }
 101
 102    internal static bool TryGetCenteredCapsuleRelation(
 103        Vector2d circleCenter,
 104        Fixed64 circleRadius,
 105        Vector3d capsuleCenter,
 106        FixedQuaternion capsuleRotation,
 107        Vector3d capsuleLocalAxis,
 108        Fixed64 capsuleAxisLength,
 109        Fixed64 capsuleRadius,
 110        out PlanarProjectionRelation relation)
 111    {
 6112        WideRationalBasis3d basis = new(capsuleRotation);
 6113        GetRotatedLocalAxis(
 6114            basis,
 6115            capsuleLocalAxis,
 6116            out Signed320 axisX,
 6117            out _,
 6118            out Signed320 axisZ);
 6119        GetCenteredAxisEndpoints(
 6120            capsuleCenter,
 6121            basis.Denominator,
 6122            axisX,
 6123            axisZ,
 6124            capsuleAxisLength,
 6125            out Signed192 axisDenominator,
 6126            out RationalPoint first,
 6127            out RationalPoint second);
 6128        RationalDistance axisDistance = GetSegmentDistance(
 6129            circleCenter,
 6130            axisDenominator,
 6131            first,
 6132            second);
 6133        return TryCreateRadiallyExpandedRelation(
 6134            axisDistance,
 6135            capsuleRadius,
 6136            circleRadius,
 6137            out relation);
 138    }
 139
 140    internal static bool TryGetCenteredCylinderRelation(
 141        Vector2d circleCenter,
 142        Fixed64 circleRadius,
 143        Vector3d cylinderCenter,
 144        FixedQuaternion cylinderRotation,
 145        Fixed64 cylinderAxisLength,
 146        Fixed64 cylinderRadius,
 147        out PlanarProjectionRelation relation)
 148    {
 16149        WideRationalBasis3d basis = new(cylinderRotation);
 16150        Signed192 axisX = basis.Yx;
 16151        Signed192 axisY = basis.Yy;
 16152        Signed192 axisZ = basis.Yz;
 16153        GetCenteredBasisAxisEndpoints(
 16154            cylinderCenter,
 16155            basis.Denominator,
 16156            axisX,
 16157            axisZ,
 16158            cylinderAxisLength,
 16159            out Signed192 axisDenominator,
 16160            out RationalPoint first,
 16161            out RationalPoint second);
 16162        RationalDistance axisDistance = GetSegmentDistance(
 16163            circleCenter,
 16164            axisDenominator,
 16165            first,
 16166            second,
 16167            out int feature);
 16168        if (feature == 0)
 169        {
 3170            return TryCreateRadiallyExpandedRelation(
 3171                axisDistance,
 3172                cylinderRadius,
 3173                circleRadius,
 3174                out relation);
 175        }
 176
 13177        return TryGetProjectedDiskRelation(
 13178            circleCenter,
 13179            circleRadius,
 13180            feature < 0 ? first : second,
 13181            axisDenominator,
 13182            axisX,
 13183            axisY,
 13184            axisZ,
 13185            cylinderRadius,
 13186            out relation);
 187    }
 188
 189    internal static bool TryGetCenteredConeRelation(
 190        Vector2d circleCenter,
 191        Fixed64 circleRadius,
 192        Vector3d coneCenter,
 193        FixedQuaternion coneRotation,
 194        Fixed64 coneHeight,
 195        Fixed64 coneRadius,
 196        out PlanarProjectionRelation relation)
 197    {
 14198        WideRationalBasis3d basis = new(coneRotation);
 14199        Signed192 axisX = basis.Yx;
 14200        Signed192 axisY = basis.Yy;
 14201        Signed192 axisZ = basis.Yz;
 14202        GetCenteredBasisAxisEndpoints(
 14203            coneCenter,
 14204            basis.Denominator,
 14205            axisX,
 14206            axisZ,
 14207            coneHeight,
 14208            out Signed192 axisDenominator,
 14209            out RationalPoint baseCenter,
 14210            out RationalPoint apex);
 14211        if (axisY.IsZero)
 212        {
 1213            GetProjectedDiskSegmentEndpoints(
 1214                baseCenter,
 1215                axisX,
 1216                axisZ,
 1217                coneRadius,
 1218                out RationalPoint first,
 1219                out RationalPoint second);
 1220            Span<RationalPoint> triangle =
 1221                stackalloc RationalPoint[3];
 1222            triangle[0] = first;
 1223            triangle[1] = second;
 1224            triangle[2] = apex;
 1225            return TryGetConvexRelation(
 1226                circleCenter,
 1227                circleRadius,
 1228                axisDenominator,
 1229                triangle,
 1230                out relation);
 231        }
 13232        if (axisX.IsZero && axisZ.IsZero)
 233        {
 1234            return TryGetProjectedDiskRelation(
 1235                circleCenter,
 1236                circleRadius,
 1237                baseCenter,
 1238                axisDenominator,
 1239                axisX,
 1240                axisY,
 1241                axisZ,
 1242                coneRadius,
 1243                out relation);
 244        }
 245
 12246        return TryGetRotatedConeRelation(
 12247            circleCenter,
 12248            circleRadius,
 12249            baseCenter,
 12250            apex,
 12251            axisDenominator,
 12252            basis.Denominator,
 12253            axisX,
 12254            axisY,
 12255            axisZ,
 12256            coneHeight,
 12257            coneRadius,
 12258            out relation);
 259    }
 260
 261    private static bool TryCreateRadiallyExpandedRelation(
 262        RationalDistance axisDistance,
 263        Fixed64 shapeRadius,
 264        Fixed64 queryRadius,
 265        out PlanarProjectionRelation relation)
 266    {
 11267        Signed576 shapeRadiusNumerator =
 11268            WideArithmetic.MultiplySigned576(
 11269                axisDistance.Denominator,
 11270                Signed192.Raw(shapeRadius));
 11271        Signed832 shapeRadiusSquared =
 11272            WideArithmetic.MultiplySigned576ToSigned832(
 11273                shapeRadiusNumerator,
 11274                shapeRadiusNumerator);
 11275        if (WideArithmetic.SubtractSigned832(
 11276                axisDistance.SquaredDistance,
 11277                shapeRadiusSquared).Sign <= 0)
 278        {
 2279            relation = PlanarProjectionRelation.Contained;
 2280            return true;
 281        }
 282
 9283        if (!TryGetRadialGap(
 9284                axisDistance,
 9285                shapeRadius,
 9286                queryRadius,
 9287                out Fixed64 distance))
 288        {
 2289            relation = default;
 2290            return false;
 291        }
 292
 7293        Vector2d direction = WideNormalization.GetNormalized(
 7294            axisDistance.X,
 7295            axisDistance.Z);
 7296        Vector2d offset = direction * distance;
 7297        relation = new PlanarProjectionRelation(
 7298            distance,
 7299            offset,
 7300            direction);
 7301        return true;
 302    }
 303
 304    private static void GetRotatedLocalAxis(
 305        WideRationalBasis3d basis,
 306        Vector3d localAxis,
 307        out Signed320 x,
 308        out Signed320 y,
 309        out Signed320 z)
 310    {
 6311        x = GetLocalOffsetNumerator(
 6312            basis.Xx,
 6313            basis.Yx,
 6314            basis.Zx,
 6315            localAxis);
 6316        y = GetLocalOffsetNumerator(
 6317            basis.Xy,
 6318            basis.Yy,
 6319            basis.Zy,
 6320            localAxis);
 6321        z = GetLocalOffsetNumerator(
 6322            basis.Xz,
 6323            basis.Yz,
 6324            basis.Zz,
 6325            localAxis);
 6326    }
 327
 328    private static Signed320 GetLocalOffsetNumerator(
 329        Signed192 x,
 330        Signed192 y,
 331        Signed192 z,
 332        Vector3d localPoint) =>
 140333        WideArithmetic.AddSigned320(
 140334            WideArithmetic.AddSigned320(
 140335                WideArithmetic.MultiplySigned192(
 140336                    x,
 140337                    Signed192.Raw(localPoint.X)),
 140338                WideArithmetic.MultiplySigned192(
 140339                    y,
 140340                    Signed192.Raw(localPoint.Y))),
 140341            WideArithmetic.MultiplySigned192(
 140342                z,
 140343                Signed192.Raw(localPoint.Z)));
 344
 345    private static RationalPoint GetWorldPoint(
 346        Vector3d origin,
 347        WideRationalBasis3d basis,
 348        Vector3d localPoint) =>
 61349        new(
 61350            WideArithmetic.AddSigned320(
 61351                WideArithmetic.MultiplySigned192(
 61352                    Signed192.Raw(origin.X),
 61353                    basis.Denominator),
 61354                GetLocalOffsetNumerator(
 61355                    basis.Xx,
 61356                    basis.Yx,
 61357                    basis.Zx,
 61358                    localPoint)),
 61359            WideArithmetic.AddSigned320(
 61360                WideArithmetic.MultiplySigned192(
 61361                    Signed192.Raw(origin.Z),
 61362                    basis.Denominator),
 61363                GetLocalOffsetNumerator(
 61364                    basis.Xz,
 61365                    basis.Yz,
 61366                    basis.Zz,
 61367                    localPoint)));
 368
 369    private static void GetCenteredAxisEndpoints(
 370        Vector3d center,
 371        Signed192 denominator,
 372        Signed320 axisX,
 373        Signed320 axisZ,
 374        Fixed64 axisLength,
 375        out Signed192 axisDenominator,
 376        out RationalPoint first,
 377        out RationalPoint second)
 378    {
 6379        Signed192 halfLengthNumerator =
 6380            Signed192.Signed(axisLength.m_rawValue);
 6381        axisDenominator = Signed192.NarrowValue(
 6382            WideArithmetic.AddSigned320(
 6383                WideArithmetic.MultiplySigned192(
 6384                    denominator,
 6385                    Signed192.Raw(Fixed64.One)),
 6386                WideArithmetic.MultiplySigned192(
 6387                    denominator,
 6388                    Signed192.Raw(Fixed64.One))));
 6389        Signed320 centerX = WideArithmetic.MultiplySigned192(
 6390            Signed192.Raw(center.X),
 6391            axisDenominator);
 6392        Signed320 centerZ = WideArithmetic.MultiplySigned192(
 6393            Signed192.Raw(center.Z),
 6394            axisDenominator);
 6395        Signed320 offsetX = Signed320.NarrowValue(
 6396            WideArithmetic.MultiplySigned320(
 6397                axisX,
 6398                Signed320.ExtendValue(halfLengthNumerator)));
 6399        Signed320 offsetZ = Signed320.NarrowValue(
 6400            WideArithmetic.MultiplySigned320(
 6401                axisZ,
 6402                Signed320.ExtendValue(halfLengthNumerator)));
 6403        first = new RationalPoint(
 6404            WideArithmetic.SubtractSigned320(centerX, offsetX),
 6405            WideArithmetic.SubtractSigned320(centerZ, offsetZ));
 6406        second = new RationalPoint(
 6407            WideArithmetic.AddSigned320(centerX, offsetX),
 6408            WideArithmetic.AddSigned320(centerZ, offsetZ));
 6409    }
 410
 411    private static void GetCenteredBasisAxisEndpoints(
 412        Vector3d center,
 413        Signed192 denominator,
 414        Signed192 axisX,
 415        Signed192 axisZ,
 416        Fixed64 axisLength,
 417        out Signed192 axisDenominator,
 418        out RationalPoint first,
 419        out RationalPoint second)
 420    {
 30421        axisDenominator = WideArithmetic.AddSigned192(
 30422            denominator,
 30423            denominator);
 30424        Signed320 centerX = WideArithmetic.MultiplySigned192(
 30425            Signed192.Raw(center.X),
 30426            axisDenominator);
 30427        Signed320 centerZ = WideArithmetic.MultiplySigned192(
 30428            Signed192.Raw(center.Z),
 30429            axisDenominator);
 30430        Signed320 offsetX = WideArithmetic.MultiplySigned192(
 30431            axisX,
 30432            Signed192.Raw(axisLength));
 30433        Signed320 offsetZ = WideArithmetic.MultiplySigned192(
 30434            axisZ,
 30435            Signed192.Raw(axisLength));
 30436        first = new RationalPoint(
 30437            WideArithmetic.SubtractSigned320(centerX, offsetX),
 30438            WideArithmetic.SubtractSigned320(centerZ, offsetZ));
 30439        second = new RationalPoint(
 30440            WideArithmetic.AddSigned320(centerX, offsetX),
 30441            WideArithmetic.AddSigned320(centerZ, offsetZ));
 30442    }
 443
 444    private static bool TryGetRadialGap(
 445        RationalDistance distance,
 446        Fixed64 shapeRadius,
 447        Fixed64 maximumGap,
 448        out Fixed64 gap)
 449    {
 9450        Signed192 shapeRaw = Signed192.Raw(shapeRadius);
 9451        Signed192 maximumRaw = WideArithmetic.AddSigned192(
 9452            shapeRaw,
 9453            Signed192.Raw(maximumGap));
 9454        if (CompareDistanceToRaw(distance, maximumRaw) > 0)
 455        {
 2456            gap = default;
 2457            return false;
 458        }
 459
 7460        long low = 0L;
 7461        long high = maximumGap.m_rawValue;
 175462        while (low < high)
 463        {
 168464            long difference = high - low;
 168465            long middle =
 168466                low + (difference >> 1) + (difference & 1L);
 168467            Signed192 candidate = WideArithmetic.AddSigned192(
 168468                shapeRaw,
 168469                Signed192.Signed(middle));
 168470            if (CompareDistanceToRaw(distance, candidate) >= 0)
 151471                low = middle;
 472            else
 17473                high = middle - 1L;
 474        }
 475
 7476        if (low != maximumGap.m_rawValue)
 477        {
 3478            Signed192 midpoint = WideArithmetic.AddSigned192(
 3479                WideArithmetic.AddSigned192(
 3480                    WideArithmetic.AddSigned192(shapeRaw, shapeRaw),
 3481                    WideArithmetic.AddSigned192(
 3482                        Signed192.Signed(low),
 3483                        Signed192.Signed(low))),
 3484                Signed192.Signed(1L));
 3485            int comparison =
 3486                CompareDistanceToTwiceRaw(distance, midpoint);
 3487            low += GetHalfToEvenIncrement(comparison, low);
 488        }
 489
 7490        gap = Fixed64.FromRaw(low);
 7491        return true;
 492    }
 493
 494    private static RationalDistance GetPointDistance(
 495        Vector2d point,
 496        Signed192 denominator,
 497        RationalPoint target)
 498    {
 50499        Signed320 x = WideArithmetic.SubtractSigned320(
 50500            target.X,
 50501            WideArithmetic.MultiplySigned192(
 50502                Signed192.Raw(point.X),
 50503                denominator));
 50504        Signed320 z = WideArithmetic.SubtractSigned320(
 50505            target.Z,
 50506            WideArithmetic.MultiplySigned192(
 50507                Signed192.Raw(point.Y),
 50508                denominator));
 50509        return new RationalDistance(
 50510            Signed576.ExtendValue(x),
 50511            Signed576.ExtendValue(z),
 50512            Signed576.ExtendValue(
 50513                Signed320.ExtendValue(denominator)));
 514    }
 515
 516    private static RationalDistance GetSegmentDistance(
 517        Vector2d point,
 518        Signed192 denominator,
 519        RationalPoint first,
 520        RationalPoint second) =>
 40521        GetSegmentDistance(
 40522            point,
 40523            denominator,
 40524            first,
 40525            second,
 40526            out _);
 527
 528    private static RationalDistance GetSegmentDistance(
 529        Vector2d point,
 530        Signed192 denominator,
 531        RationalPoint first,
 532        RationalPoint second,
 533        out int feature)
 534    {
 56535        Signed320 firstX = WideArithmetic.SubtractSigned320(
 56536            first.X,
 56537            WideArithmetic.MultiplySigned192(
 56538                Signed192.Raw(point.X),
 56539                denominator));
 56540        Signed320 firstZ = WideArithmetic.SubtractSigned320(
 56541            first.Z,
 56542            WideArithmetic.MultiplySigned192(
 56543                Signed192.Raw(point.Y),
 56544                denominator));
 56545        Signed320 edgeX = WideArithmetic.SubtractSigned320(
 56546            second.X,
 56547            first.X);
 56548        Signed320 edgeZ = WideArithmetic.SubtractSigned320(
 56549            second.Z,
 56550            first.Z);
 56551        Signed576 edgeSquared = WideArithmetic.AddSigned576(
 56552            WideArithmetic.MultiplySigned320(edgeX, edgeX),
 56553            WideArithmetic.MultiplySigned320(edgeZ, edgeZ));
 56554        if (edgeSquared.IsZero)
 555        {
 10556            feature = -1;
 10557            return new RationalDistance(
 10558                Signed576.ExtendValue(firstX),
 10559                Signed576.ExtendValue(firstZ),
 10560                Signed576.ExtendValue(
 10561                    Signed320.ExtendValue(denominator)));
 562        }
 563
 46564        Signed576 projection = WideArithmetic.SubtractSigned576(
 46565            default,
 46566            WideArithmetic.AddSigned576(
 46567                WideArithmetic.MultiplySigned320(firstX, edgeX),
 46568                WideArithmetic.MultiplySigned320(firstZ, edgeZ)));
 46569        if (projection.Sign <= 0)
 570        {
 23571            feature = -1;
 23572            return new RationalDistance(
 23573                Signed576.ExtendValue(firstX),
 23574                Signed576.ExtendValue(firstZ),
 23575                Signed576.ExtendValue(
 23576                    Signed320.ExtendValue(denominator)));
 577        }
 23578        if (WideArithmetic.SubtractSigned576(
 23579                projection,
 23580                edgeSquared).Sign >= 0)
 581        {
 13582            feature = 1;
 13583            return GetPointDistance(point, denominator, second);
 584        }
 585
 10586        feature = 0;
 10587        Signed576 x = WideArithmetic.AddSigned576(
 10588            WideArithmetic.MultiplySigned576(
 10589                edgeSquared,
 10590                Signed192.NarrowValue(firstX)),
 10591            WideArithmetic.MultiplySigned576(
 10592                projection,
 10593                Signed192.NarrowValue(edgeX)));
 10594        Signed576 z = WideArithmetic.AddSigned576(
 10595            WideArithmetic.MultiplySigned576(
 10596                edgeSquared,
 10597                Signed192.NarrowValue(firstZ)),
 10598            WideArithmetic.MultiplySigned576(
 10599                projection,
 10600                Signed192.NarrowValue(edgeZ)));
 10601        Signed576 combinedDenominator =
 10602            WideArithmetic.MultiplySigned576(
 10603                edgeSquared,
 10604                denominator);
 10605        return new RationalDistance(x, z, combinedDenominator);
 606    }
 607
 608    private static bool IsWithinRadius(
 609        RationalDistance distance,
 610        Fixed64 radius)
 611    {
 10612        Signed576 scaledRadius = WideArithmetic.MultiplySigned576(
 10613            distance.Denominator,
 10614            Signed192.Raw(radius));
 10615        Signed832 squaredRadius =
 10616            WideArithmetic.MultiplySigned576ToSigned832(
 10617                scaledRadius,
 10618                scaledRadius);
 10619        return WideArithmetic.SubtractSigned832(
 10620            distance.SquaredDistance,
 10621            squaredRadius).Sign <= 0;
 622    }
 623
 624    private static bool TryGetDistance(
 625        RationalDistance distance,
 626        Fixed64 maximum,
 627        out Fixed64 result)
 628    {
 10629        if (!IsWithinRadius(distance, maximum))
 630        {
 2631            result = default;
 2632            return false;
 633        }
 634
 8635        long low = 0L;
 8636        long high = maximum.m_rawValue;
 271637        while (low < high)
 638        {
 263639            long difference = high - low;
 263640            long middle =
 263641                low + (difference >> 1) + (difference & 1L);
 263642            if (CompareDistanceToRaw(distance, middle) >= 0)
 231643                low = middle;
 644            else
 32645                high = middle - 1L;
 646        }
 647
 8648        if (low != maximum.m_rawValue)
 649        {
 2650            long doubledLow = low + low;
 2651            int midpointComparison =
 2652                CompareDistanceToTwiceRaw(
 2653                    distance,
 2654                    doubledLow + 1L);
 2655            low += GetHalfToEvenIncrement(midpointComparison, low);
 656        }
 657
 8658        result = Fixed64.FromRaw(low);
 8659        return true;
 660    }
 661
 662    private static int CompareDistanceToRaw(
 663        RationalDistance distance,
 664        long raw) =>
 263665        CompareDistanceToRaw(
 263666            distance,
 263667            Signed192.Signed(raw));
 668
 669    private static int CompareDistanceToRaw(
 670        RationalDistance distance,
 671        Signed192 raw)
 672    {
 515673        Signed576 scaled = WideArithmetic.MultiplySigned576(
 515674            distance.Denominator,
 515675            raw);
 515676        Signed832 squared = WideArithmetic.MultiplySigned576ToSigned832(
 515677            scaled,
 515678            scaled);
 515679        return WideArithmetic.SubtractSigned832(
 515680            distance.SquaredDistance,
 515681            squared).Sign;
 682    }
 683
 684    private static int CompareDistanceToTwiceRaw(
 685        RationalDistance distance,
 686        long twiceRaw) =>
 2687        CompareDistanceToTwiceRaw(
 2688            distance,
 2689            Signed192.Signed(twiceRaw));
 690
 691    private static int CompareDistanceToTwiceRaw(
 692        RationalDistance distance,
 693        Signed192 twiceRaw)
 694    {
 20695        Signed832 fourDistance = WideArithmetic.AddSigned832(
 20696            WideArithmetic.AddSigned832(
 20697                distance.SquaredDistance,
 20698                distance.SquaredDistance),
 20699            WideArithmetic.AddSigned832(
 20700                distance.SquaredDistance,
 20701                distance.SquaredDistance));
 20702        Signed576 scaled = WideArithmetic.MultiplySigned576(
 20703            distance.Denominator,
 20704            twiceRaw);
 20705        Signed832 squared = WideArithmetic.MultiplySigned576ToSigned832(
 20706            scaled,
 20707            scaled);
 20708        return WideArithmetic.SubtractSigned832(
 20709            fourDistance,
 20710            squared).Sign;
 711    }
 712
 713    private static Vector2d GetOffset(RationalDistance distance)
 714    {
 8715        _ = Fixed64.TryGetSignedRawRatio(
 8716            distance.X,
 8717            distance.Denominator,
 8718            out Fixed64 x);
 8719        _ = Fixed64.TryGetSignedRawRatio(
 8720            distance.Z,
 8721            distance.Denominator,
 8722            out Fixed64 z);
 8723        return new Vector2d(x, z);
 724    }
 725
 726    private static long GetHalfToEvenIncrement(
 727        int midpointComparison,
 728        long lowerRaw)
 729    {
 5730        int negative = (int)((uint)midpointComparison >> 31);
 5731        int nonzero = (int)(
 5732            (uint)(midpointComparison | -midpointComparison) >> 31);
 5733        int positive = nonzero & (negative ^ 1);
 5734        int zero = nonzero ^ 1;
 5735        return (long)positive | ((long)zero & (lowerRaw & 1L));
 736    }
 737
 738    private static Signed320 GetLargestPositiveMagnitude(
 739        Signed320 first,
 740        Signed320 second,
 741        Signed320 third,
 742        Signed320 fourth,
 743        Signed320 fifth)
 744    {
 16745        Signed320 largest =
 16746            WideArithmetic.CompareMagnitude(first, second) >= 0
 16747                ? first
 16748                : second;
 16749        if (WideArithmetic.CompareMagnitude(largest, third) < 0)
 4750            largest = third;
 16751        if (WideArithmetic.CompareMagnitude(largest, fourth) < 0)
 4752            largest = fourth;
 16753        if (WideArithmetic.CompareMagnitude(largest, fifth) < 0)
 2754            largest = fifth;
 16755        return largest.Sign < 0
 16756            ? WideArithmetic.SubtractSigned320(default, largest)
 16757            : largest;
 758    }
 759}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Common/WidePlanarProjection.Disk.cs

#LineLine coverage
 1//=======================================================================
 2// WidePlanarProjection.Disk.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/// Exact projected-disk admission and correctly rounded planar distance.
 14/// </content>
 15internal static partial class WidePlanarProjection
 16{
 17    private static bool TryGetProjectedDiskRelation(
 18        Vector2d circleCenter,
 19        Fixed64 circleRadius,
 20        RationalPoint diskCenter,
 21        Signed192 coordinateDenominator,
 22        Signed192 axisX,
 23        Signed192 axisY,
 24        Signed192 axisZ,
 25        Fixed64 diskRadius,
 26        out PlanarProjectionRelation relation)
 27    {
 1428        if (axisY.IsZero)
 29        {
 130            GetProjectedDiskSegmentEndpoints(
 131                diskCenter,
 132                axisX,
 133                axisZ,
 134                diskRadius,
 135                out RationalPoint first,
 136                out RationalPoint second);
 137            return TryCreateRelation(
 138                GetSegmentDistance(
 139                    circleCenter,
 140                    coordinateDenominator,
 141                    first,
 142                    second),
 143                circleRadius,
 144                out relation);
 45        }
 46
 1347        RationalDistance centerDistance = GetPointDistance(
 1348            circleCenter,
 1349            coordinateDenominator,
 1350            diskCenter);
 1351        if (axisX.IsZero && axisZ.IsZero)
 52        {
 253            return TryCreateRadiallyExpandedRelation(
 254                centerDistance,
 255                diskRadius,
 256                circleRadius,
 257                out relation);
 58        }
 59
 1160        int maximumComparison = CompareProjectedDiskDistanceToRadius(
 1161            centerDistance,
 1162            coordinateDenominator,
 1163            axisX,
 1164            axisY,
 1165            axisZ,
 1166            diskRadius,
 1167            Signed192.Raw(circleRadius),
 1168            radiusDenominator: 1);
 1169        if (maximumComparison > 0)
 70        {
 171            relation = default;
 172            return false;
 73        }
 74
 1075        int zeroComparison = CompareProjectedDiskDistanceToRadius(
 1076            centerDistance,
 1077            coordinateDenominator,
 1078            axisX,
 1079            axisY,
 1080            axisZ,
 1081            diskRadius,
 1082            default,
 1083            radiusDenominator: 1);
 1084        if (zeroComparison <= 0)
 85        {
 286            relation = PlanarProjectionRelation.Contained;
 287            return true;
 88        }
 89
 890        GetProjectedDiskClosestOffset(
 891            centerDistance,
 892            coordinateDenominator,
 893            axisX,
 894            axisY,
 895            axisZ,
 896            diskRadius,
 897            out Fixed64 approximateDistance,
 898            out Vector2d direction);
 899        long low = GetProjectedDiskCeilingDistance(
 8100            centerDistance,
 8101            coordinateDenominator,
 8102            axisX,
 8103            axisY,
 8104            axisZ,
 8105            diskRadius,
 8106            circleRadius,
 8107            approximateDistance);
 108
 8109        long floor = low - 1L;
 8110        Signed192 midpointNumerator = WideArithmetic.AddSigned192(
 8111            WideArithmetic.AddSigned192(
 8112                Signed192.Signed(floor),
 8113                Signed192.Signed(floor)),
 8114            Signed192.Signed(1L));
 8115        int midpointComparison = CompareProjectedDiskDistanceToRadius(
 8116            centerDistance,
 8117            coordinateDenominator,
 8118            axisX,
 8119            axisY,
 8120            axisZ,
 8121            diskRadius,
 8122            midpointNumerator,
 8123            radiusDenominator: 2);
 8124        long rounded = midpointComparison < 0
 8125            ? floor
 8126            : midpointComparison > 0
 8127                ? low
 8128                : floor + (floor & 1L);
 8129        Fixed64 distance = Fixed64.FromRaw(rounded);
 8130        relation = new PlanarProjectionRelation(
 8131            distance,
 8132            direction * distance,
 8133            direction);
 8134        return true;
 135    }
 136
 137    private static long GetProjectedDiskCeilingDistance(
 138        RationalDistance centerDistance,
 139        Signed192 coordinateDenominator,
 140        Signed192 axisX,
 141        Signed192 axisY,
 142        Signed192 axisZ,
 143        Fixed64 diskRadius,
 144        Fixed64 maximum,
 145        Fixed64 approximate)
 146    {
 8147        long candidate = approximate.m_rawValue;
 8148        if (candidate > maximum.m_rawValue)
 2149            candidate = maximum.m_rawValue;
 150
 8151        int comparison = CompareProjectedDiskDistanceToRadius(
 8152            centerDistance,
 8153            coordinateDenominator,
 8154            axisX,
 8155            axisY,
 8156            axisZ,
 8157            diskRadius,
 8158            Signed192.Signed(candidate),
 8159            radiusDenominator: 1);
 8160        if (comparison <= 0)
 161        {
 4162            long high = candidate;
 4163            long step = 1L;
 14164            while (high > 1L)
 165            {
 12166                long probe = high > step ? high - step : 0L;
 12167                if (probe == 0L
 12168                    || CompareProjectedDiskDistanceToRadius(
 12169                        centerDistance,
 12170                        coordinateDenominator,
 12171                        axisX,
 12172                        axisY,
 12173                        axisZ,
 12174                        diskRadius,
 12175                        Signed192.Signed(probe),
 12176                        radiusDenominator: 1) > 0)
 177                {
 2178                    return FindProjectedDiskCeilingDistance(
 2179                        centerDistance,
 2180                        coordinateDenominator,
 2181                        axisX,
 2182                        axisY,
 2183                        axisZ,
 2184                        diskRadius,
 2185                        probe + 1L,
 2186                        high);
 187                }
 188
 10189                high = probe;
 10190                step = (long)Math.Min(
 10191                    (ulong)step << 1,
 10192                    (ulong)high);
 193            }
 194
 2195            return 1L;
 196        }
 197
 4198        long low = candidate + 1L;
 4199        long upper = maximum.m_rawValue;
 4200        long upwardStep = 1L;
 6201        while (low < upper)
 202        {
 3203            long remaining = upper - candidate;
 3204            long probe = candidate + Math.Min(
 3205                upwardStep,
 3206                remaining);
 3207            if (CompareProjectedDiskDistanceToRadius(
 3208                centerDistance,
 3209                coordinateDenominator,
 3210                axisX,
 3211                axisY,
 3212                axisZ,
 3213                diskRadius,
 3214                Signed192.Signed(probe),
 3215                radiusDenominator: 1) <= 0)
 216            {
 1217                return FindProjectedDiskCeilingDistance(
 1218                    centerDistance,
 1219                    coordinateDenominator,
 1220                    axisX,
 1221                    axisY,
 1222                    axisZ,
 1223                    diskRadius,
 1224                    low,
 1225                    probe);
 226            }
 227
 2228            low = probe + 1L;
 2229            upwardStep = (long)Math.Min(
 2230                (ulong)upwardStep << 1,
 2231                (ulong)(upper - candidate));
 232        }
 233
 3234        return upper;
 235    }
 236
 237    private static long FindProjectedDiskCeilingDistance(
 238        RationalDistance centerDistance,
 239        Signed192 coordinateDenominator,
 240        Signed192 axisX,
 241        Signed192 axisY,
 242        Signed192 axisZ,
 243        Fixed64 diskRadius,
 244        long low,
 245        long high)
 246    {
 13247        while (low < high)
 248        {
 10249            long middle = low + ((high - low) >> 1);
 10250            int comparison = CompareProjectedDiskDistanceToRadius(
 10251                centerDistance,
 10252                coordinateDenominator,
 10253                axisX,
 10254                axisY,
 10255                axisZ,
 10256                diskRadius,
 10257                Signed192.Signed(middle),
 10258                radiusDenominator: 1);
 10259            if (comparison <= 0)
 5260                high = middle;
 261            else
 5262                low = middle + 1L;
 263        }
 264
 3265        return low;
 266    }
 267
 268    private static void GetProjectedDiskClosestOffset(
 269        RationalDistance centerDistance,
 270        Signed192 coordinateDenominator,
 271        Signed192 axisX,
 272        Signed192 axisY,
 273        Signed192 axisZ,
 274        Fixed64 diskRadius,
 275        out Fixed64 approximateDistance,
 276        out Vector2d direction)
 277    {
 8278        Signed320 relativeX = Signed320.NarrowValue(centerDistance.X);
 8279        Signed320 relativeZ = Signed320.NarrowValue(centerDistance.Z);
 8280        Signed320 scaledRadius = WideArithmetic.MultiplySigned192(
 8281            coordinateDenominator,
 8282            Signed192.Raw(diskRadius));
 8283        Signed320 scale = GetLargestPositiveMagnitude(
 8284            relativeX,
 8285            relativeZ,
 8286            default,
 8287            scaledRadius,
 8288            default);
 8289        Fixed64 queryX = -Fixed64.GetSignedRatio(relativeX, scale);
 8290        Fixed64 queryZ = -Fixed64.GetSignedRatio(relativeZ, scale);
 8291        Fixed64 radius = Fixed64.GetSignedRatio(scaledRadius, scale);
 8292        Vector2d axis = WideNormalization.GetNormalized(axisX, axisZ);
 8293        Vector2d perpendicular = new(-axis.Y, axis.X);
 8294        Fixed64 along = Vector2d.Dot(new Vector2d(queryX, queryZ), axis);
 8295        Fixed64 across = Vector2d.Dot(
 8296            new Vector2d(queryX, queryZ),
 8297            perpendicular);
 8298        Fixed64 axisYRatio = FixedMath.Abs(
 8299            WideNormalization.GetNormalized(
 8300                axisX,
 8301                axisY,
 8302                axisZ).Y);
 8303        Fixed64 minor = radius * axisYRatio;
 8304        Vector2d localOffset = GetEllipseClosestOffset(
 8305            along,
 8306            across,
 8307            minor,
 8308            radius);
 8309        Vector2d worldOffset =
 8310            axis * localOffset.X + perpendicular * localOffset.Y;
 8311        direction = worldOffset.Normalized;
 312
 8313        Signed576 distanceNumerator =
 8314            WideArithmetic.MultiplySigned320(
 8315                scale,
 8316                Signed320.ExtendValue(
 8317                    Signed192.Raw(worldOffset.Magnitude)));
 8318        _ = Fixed64.TryGetSignedRawRatio(
 8319            distanceNumerator,
 8320            Signed576.ExtendValue(
 8321                WideArithmetic.MultiplySigned192(
 8322                    coordinateDenominator,
 8323                    Signed192.Raw(Fixed64.One))),
 8324            out approximateDistance);
 8325    }
 326
 327    private static Vector2d GetEllipseClosestOffset(
 328        Fixed64 queryX,
 329        Fixed64 queryY,
 330        Fixed64 radiusX,
 331        Fixed64 radiusY)
 332    {
 16333        Fixed64 radiusXSquared = radiusX * radiusX;
 16334        Fixed64 radiusYSquared = radiusY * radiusY;
 16335        Fixed64 low = Fixed64.Zero;
 16336        Fixed64 high = Fixed64.Two;
 544337        while (high.m_rawValue - low.m_rawValue > 1L)
 338        {
 528339            Fixed64 middle = Fixed64.FromRaw(
 528340                low.m_rawValue
 528341                + ((high.m_rawValue - low.m_rawValue) >> 1));
 528342            Fixed64 x = GetEllipseConstraintCoordinate(
 528343                radiusX,
 528344                queryX,
 528345                middle + radiusXSquared);
 528346            Fixed64 y = GetEllipseConstraintCoordinate(
 528347                radiusY,
 528348                queryY,
 528349                middle + radiusYSquared);
 528350            if (x * x + y * y > Fixed64.One)
 185351                low = middle;
 352            else
 343353                high = middle;
 354        }
 355
 16356        Fixed64 closestX = Fixed64.MultiplyDivide(
 16357            radiusXSquared,
 16358            queryX,
 16359            high + radiusXSquared,
 16360            out _);
 16361        Fixed64 closestY = Fixed64.MultiplyDivide(
 16362            radiusYSquared,
 16363            queryY,
 16364            high + radiusYSquared,
 16365            out _);
 16366        return new Vector2d(
 16367            closestX - queryX,
 16368            closestY - queryY);
 369    }
 370
 371    private static Fixed64 GetEllipseConstraintCoordinate(
 372        Fixed64 radius,
 373        Fixed64 query,
 374        Fixed64 denominator) =>
 1056375        Fixed64.MultiplyDivide(
 1056376            radius,
 1056377            query,
 1056378            denominator,
 1056379            out _);
 380
 381    private static void GetProjectedDiskSegmentEndpoints(
 382        RationalPoint diskCenter,
 383        Signed192 axisX,
 384        Signed192 axisZ,
 385        Fixed64 diskRadius,
 386        out RationalPoint first,
 387        out RationalPoint second)
 388    {
 2389        Signed192 scaledRadius = WideArithmetic.AddSigned192(
 2390            Signed192.Raw(diskRadius),
 2391            Signed192.Raw(diskRadius));
 392
 2393        Signed320 offsetX = WideArithmetic.MultiplySigned192(
 2394            WideArithmetic.SubtractSigned192(
 2395                default,
 2396                axisZ),
 2397            scaledRadius);
 2398        Signed320 offsetZ = WideArithmetic.MultiplySigned192(
 2399            axisX,
 2400            scaledRadius);
 2401        first = new RationalPoint(
 2402            WideArithmetic.AddSigned320(
 2403                diskCenter.X,
 2404                offsetX),
 2405            WideArithmetic.AddSigned320(
 2406                diskCenter.Z,
 2407                offsetZ));
 2408        second = new RationalPoint(
 2409            WideArithmetic.SubtractSigned320(
 2410                diskCenter.X,
 2411                offsetX),
 2412            WideArithmetic.SubtractSigned320(
 2413                diskCenter.Z,
 2414                offsetZ));
 2415    }
 416
 417    private static int CompareProjectedDiskDistanceToRadius(
 418        RationalDistance centerDistance,
 419        Signed192 coordinateDenominator,
 420        Signed192 axisX,
 421        Signed192 axisY,
 422        Signed192 axisZ,
 423        Fixed64 diskRadius,
 424        Signed192 radiusNumerator,
 425        int radiusDenominator)
 426    {
 132427        Signed320 relativeX = Signed320.NarrowValue(
 132428            centerDistance.X);
 132429        Signed320 relativeZ = Signed320.NarrowValue(
 132430            centerDistance.Z);
 132431        int centerSign = EvaluateProjectedDiskConic(
 132432            relativeX,
 132433            relativeZ,
 132434            coordinateDenominator,
 132435            axisX,
 132436            axisY,
 132437            axisZ,
 132438            diskRadius);
 132439        if (centerSign <= 0)
 4440            return radiusNumerator.IsZero ? 0 : -1;
 128441        if (radiusNumerator.IsZero)
 20442            return 1;
 443
 108444        int rootCount = CountProjectedDiskCircleRoots(
 108445            relativeX,
 108446            relativeZ,
 108447            coordinateDenominator,
 108448            axisX,
 108449            axisY,
 108450            axisZ,
 108451            diskRadius,
 108452            radiusNumerator,
 108453            radiusDenominator);
 108454        if (rootCount != 0)
 55455            return rootCount == 1 ? 0 : -1;
 456
 53457        int centerDistanceComparison = radiusDenominator == 1
 53458            ? CompareDistanceToRaw(
 53459                centerDistance,
 53460                radiusNumerator)
 53461            : CompareDistanceToTwiceRaw(
 53462                centerDistance,
 53463                radiusNumerator);
 53464        return centerDistanceComparison <= 0 ? -1 : 1;
 465    }
 466
 467    private static int CountProjectedDiskCircleRoots(
 468        Signed320 relativeX,
 469        Signed320 relativeZ,
 470        Signed192 coordinateDenominator,
 471        Signed192 axisX,
 472        Signed192 axisY,
 473        Signed192 axisZ,
 474        Fixed64 diskRadius,
 475        Signed192 radiusNumerator,
 476        int radiusDenominator)
 477    {
 108478        CreateProjectedDiskCirclePolynomial(
 108479            relativeX,
 108480            relativeZ,
 108481            coordinateDenominator,
 108482            axisX,
 108483            axisY,
 108484            axisZ,
 108485            diskRadius,
 108486            radiusNumerator,
 108487            radiusDenominator,
 108488            1,
 108489            0,
 108490            out Signed832 constant,
 108491            out Signed832 linear,
 108492            out Signed832 quadratic,
 108493            out Signed832 cubic,
 108494            out Signed832 quartic);
 108495        if (quartic.Sign == 0)
 496        {
 1497            CreateProjectedDiskCirclePolynomial(
 1498                relativeX,
 1499                relativeZ,
 1500                coordinateDenominator,
 1501                axisX,
 1502                axisY,
 1503                axisZ,
 1504                diskRadius,
 1505                radiusNumerator,
 1506                radiusDenominator,
 1507                -1,
 1508                0,
 1509                out constant,
 1510                out linear,
 1511                out quadratic,
 1512                out cubic,
 1513                out quartic);
 514        }
 515
 108516        return WideFiniteAxisIntersection.CountProjectionDomainQuarticRoots(
 108517            constant,
 108518            linear,
 108519            quadratic,
 108520            cubic,
 108521            quartic);
 522    }
 523
 524    private static void CreateProjectedDiskCirclePolynomial(
 525        Signed320 relativeX,
 526        Signed320 relativeZ,
 527        Signed192 coordinateDenominator,
 528        Signed192 axisX,
 529        Signed192 axisY,
 530        Signed192 axisZ,
 531        Fixed64 diskRadius,
 532        Signed192 radiusNumerator,
 533        int radiusDenominator,
 534        int directionX,
 535        int directionZ,
 536        out Signed832 constant,
 537        out Signed832 linear,
 538        out Signed832 quadratic,
 539        out Signed832 cubic,
 540        out Signed832 quartic)
 541    {
 109542        Signed320 radiusScale = WideArithmetic.MultiplySigned192(
 109543            radiusNumerator,
 109544            coordinateDenominator);
 109545        Signed320 scaledX = MultiplyBySmall(
 109546            relativeX,
 109547            radiusDenominator);
 109548        Signed320 scaledZ = MultiplyBySmall(
 109549            relativeZ,
 109550            radiusDenominator);
 109551        Signed320 radialX = MultiplyBySmall(
 109552            radiusScale,
 109553            directionX);
 109554        Signed320 radialZ = MultiplyBySmall(
 109555            radiusScale,
 109556            directionZ);
 109557        Signed320 perpendicularX = MultiplyBySmall(
 109558            radiusScale,
 109559            -directionZ * 2);
 109560        Signed320 perpendicularZ = MultiplyBySmall(
 109561            radiusScale,
 109562            directionX * 2);
 109563        Signed320 x0 = WideArithmetic.AddSigned320(
 109564            scaledX,
 109565            radialX);
 109566        Signed320 x1 = perpendicularX;
 109567        Signed320 x2 = WideArithmetic.SubtractSigned320(
 109568            scaledX,
 109569            radialX);
 109570        Signed320 z0 = WideArithmetic.AddSigned320(
 109571            scaledZ,
 109572            radialZ);
 109573        Signed320 z1 = perpendicularZ;
 109574        Signed320 z2 = WideArithmetic.SubtractSigned320(
 109575            scaledZ,
 109576            radialZ);
 577
 109578        Signed320 axisY2 = WideArithmetic.MultiplySigned192(
 109579            axisY,
 109580            axisY);
 109581        GetSquaredPolynomial(
 109582            x0,
 109583            x1,
 109584            x2,
 109585            out Signed576 xSquared0,
 109586            out Signed576 xSquared1,
 109587            out Signed576 xSquared2,
 109588            out Signed576 xSquared3,
 109589            out Signed576 xSquared4);
 109590        GetSquaredPolynomial(
 109591            z0,
 109592            z1,
 109593            z2,
 109594            out Signed576 zSquared0,
 109595            out Signed576 zSquared1,
 109596            out Signed576 zSquared2,
 109597            out Signed576 zSquared3,
 109598            out Signed576 zSquared4);
 109599        Signed576 dot0 = WideArithmetic.AddSigned576(
 109600            WideArithmetic.MultiplySigned320(
 109601                x0,
 109602                Signed320.ExtendValue(axisX)),
 109603            WideArithmetic.MultiplySigned320(
 109604                z0,
 109605                Signed320.ExtendValue(axisZ)));
 109606        Signed576 dot1 = WideArithmetic.AddSigned576(
 109607            WideArithmetic.MultiplySigned320(
 109608                x1,
 109609                Signed320.ExtendValue(axisX)),
 109610            WideArithmetic.MultiplySigned320(
 109611                z1,
 109612                Signed320.ExtendValue(axisZ)));
 109613        Signed576 dot2 = WideArithmetic.AddSigned576(
 109614            WideArithmetic.MultiplySigned320(
 109615                x2,
 109616                Signed320.ExtendValue(axisX)),
 109617            WideArithmetic.MultiplySigned320(
 109618                z2,
 109619                Signed320.ExtendValue(axisZ)));
 620
 109621        Signed192 commonDenominator = coordinateDenominator;
 109622        if (radiusDenominator == 2)
 623        {
 16624            commonDenominator = WideArithmetic.AddSigned192(
 16625                commonDenominator,
 16626                commonDenominator);
 627        }
 109628        Signed320 diskRadiusSquared = WideArithmetic.MultiplySigned192(
 109629            Signed192.Raw(diskRadius),
 109630            Signed192.Raw(diskRadius));
 109631        Signed576 diskAndAxis = WideArithmetic.MultiplySigned320(
 109632            diskRadiusSquared,
 109633            axisY2);
 109634        Signed320 denominatorSquared =
 109635            WideArithmetic.MultiplySigned192(
 109636                commonDenominator,
 109637                commonDenominator);
 109638        Signed832 limit =
 109639            WideArithmetic.MultiplySigned576ToSigned832(
 109640                diskAndAxis,
 109641                denominatorSquared);
 642
 109643        constant = WideArithmetic.SubtractSigned832(
 109644            GetProjectedDiskConicCoefficient(
 109645                xSquared0,
 109646                zSquared0,
 109647                axisY2,
 109648                dot0,
 109649                dot0),
 109650            limit);
 109651        linear = WideArithmetic.AddSigned832(
 109652            GetProjectedDiskRadialCoefficient(
 109653                xSquared1,
 109654                zSquared1,
 109655                axisY2),
 109656            DoubleSigned832(
 109657                WideArithmetic.MultiplySigned576ToSigned832(
 109658                    dot0,
 109659                    dot1)));
 109660        quadratic = WideArithmetic.AddSigned832(
 109661            GetProjectedDiskConicCoefficient(
 109662                xSquared2,
 109663                zSquared2,
 109664                axisY2,
 109665                dot1,
 109666                dot1),
 109667            DoubleSigned832(
 109668                WideArithmetic.MultiplySigned576ToSigned832(
 109669                    dot0,
 109670                    dot2)));
 109671        quadratic = WideArithmetic.SubtractSigned832(
 109672            quadratic,
 109673            DoubleSigned832(limit));
 109674        cubic = WideArithmetic.AddSigned832(
 109675            GetProjectedDiskRadialCoefficient(
 109676                xSquared3,
 109677                zSquared3,
 109678                axisY2),
 109679            DoubleSigned832(
 109680                WideArithmetic.MultiplySigned576ToSigned832(
 109681                    dot1,
 109682                    dot2)));
 109683        quartic = WideArithmetic.SubtractSigned832(
 109684            GetProjectedDiskConicCoefficient(
 109685                xSquared4,
 109686                zSquared4,
 109687                axisY2,
 109688                dot2,
 109689                dot2),
 109690            limit);
 109691    }
 692
 693    private static Signed832 GetProjectedDiskConicCoefficient(
 694        Signed576 xSquared,
 695        Signed576 zSquared,
 696        Signed320 axisYSquared,
 697        Signed576 firstDot,
 698        Signed576 secondDot) =>
 327699        WideArithmetic.AddSigned832(
 327700            GetProjectedDiskRadialCoefficient(
 327701                xSquared,
 327702                zSquared,
 327703                axisYSquared),
 327704            WideArithmetic.MultiplySigned576ToSigned832(
 327705                firstDot,
 327706                secondDot));
 707
 708    private static Signed832 GetProjectedDiskRadialCoefficient(
 709        Signed576 xSquared,
 710        Signed576 zSquared,
 711        Signed320 axisYSquared) =>
 545712        WideArithmetic.MultiplySigned576ToSigned832(
 545713            WideArithmetic.AddSigned576(
 545714                xSquared,
 545715                zSquared),
 545716            axisYSquared);
 717
 718    private static void GetSquaredPolynomial(
 719        Signed320 constant,
 720        Signed320 linear,
 721        Signed320 quadratic,
 722        out Signed576 result0,
 723        out Signed576 result1,
 724        out Signed576 result2,
 725        out Signed576 result3,
 726        out Signed576 result4)
 727    {
 218728        result0 = WideArithmetic.MultiplySigned320(
 218729            constant,
 218730            constant);
 218731        result1 = WideArithmetic.AddSigned576(
 218732            WideArithmetic.MultiplySigned320(
 218733                constant,
 218734                linear),
 218735            WideArithmetic.MultiplySigned320(
 218736                constant,
 218737                linear));
 218738        result2 = WideArithmetic.AddSigned576(
 218739            WideArithmetic.MultiplySigned320(
 218740                linear,
 218741                linear),
 218742            WideArithmetic.AddSigned576(
 218743                WideArithmetic.MultiplySigned320(
 218744                    constant,
 218745                    quadratic),
 218746                WideArithmetic.MultiplySigned320(
 218747                    constant,
 218748                    quadratic)));
 218749        result3 = WideArithmetic.AddSigned576(
 218750            WideArithmetic.MultiplySigned320(
 218751                linear,
 218752                quadratic),
 218753            WideArithmetic.MultiplySigned320(
 218754                linear,
 218755                quadratic));
 218756        result4 = WideArithmetic.MultiplySigned320(
 218757            quadratic,
 218758            quadratic);
 218759    }
 760
 761    private static Signed320 MultiplyBySmall(
 762        Signed320 value,
 763        int multiplier)
 764    {
 654765        if (multiplier == 0)
 218766            return default;
 436767        Signed320 result = multiplier < 0
 436768            ? WideArithmetic.SubtractSigned320(default, value)
 436769            : value;
 436770        return multiplier is 2 or -2
 436771            ? WideArithmetic.AddSigned320(result, result)
 436772            : result;
 773    }
 774
 775    private static Signed832 DoubleSigned832(Signed832 value) =>
 436776        WideArithmetic.AddSigned832(value, value);
 777
 778    private static int EvaluateProjectedDiskConic(
 779        Signed320 relativeX,
 780        Signed320 relativeZ,
 781        Signed192 coordinateDenominator,
 782        Signed192 axisX,
 783        Signed192 axisY,
 784        Signed192 axisZ,
 785        Fixed64 diskRadius)
 786    {
 132787        Signed576 distanceSquared = WideArithmetic.AddSigned576(
 132788            WideArithmetic.MultiplySigned320(
 132789                relativeX,
 132790                relativeX),
 132791            WideArithmetic.MultiplySigned320(
 132792                relativeZ,
 132793                relativeZ));
 132794        Signed576 dot = WideArithmetic.AddSigned576(
 132795            WideArithmetic.MultiplySigned320(
 132796                relativeX,
 132797                Signed320.ExtendValue(axisX)),
 132798            WideArithmetic.MultiplySigned320(
 132799                relativeZ,
 132800                Signed320.ExtendValue(axisZ)));
 132801        Signed320 axisY2 = WideArithmetic.MultiplySigned192(
 132802            axisY,
 132803            axisY);
 132804        Signed832 left = WideArithmetic.AddSigned832(
 132805            WideArithmetic.MultiplySigned576ToSigned832(
 132806                distanceSquared,
 132807                axisY2),
 132808            WideArithmetic.MultiplySigned576ToSigned832(
 132809                dot,
 132810                dot));
 132811        Signed320 radiusSquared = WideArithmetic.MultiplySigned192(
 132812            Signed192.Raw(diskRadius),
 132813            Signed192.Raw(diskRadius));
 132814        Signed576 radiusAndAxis = WideArithmetic.MultiplySigned320(
 132815            radiusSquared,
 132816            axisY2);
 132817        Signed320 denominatorSquared =
 132818            WideArithmetic.MultiplySigned192(
 132819                coordinateDenominator,
 132820                coordinateDenominator);
 132821        Signed832 right =
 132822            WideArithmetic.MultiplySigned576ToSigned832(
 132823                radiusAndAxis,
 132824                denominatorSquared);
 132825        return WideArithmetic.SubtractSigned832(left, right).Sign;
 826    }
 827}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Common/WidePlanarProjection.Polygon.cs

#LineLine coverage
 1//=======================================================================
 2// WidePlanarProjection.Polygon.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/// Exact rational polygon projection and closest-feature reduction.
 14/// </content>
 15internal static partial class WidePlanarProjection
 16{
 17    private const int DistanceComparisonWordCount = 36;
 18
 19    internal static bool TryGetOrientedBoxRelation(
 20        Vector2d circleCenter,
 21        Fixed64 circleRadius,
 22        FixedOrientedBox box,
 23        out PlanarProjectionRelation relation)
 24    {
 525        WideRationalBasis3d basis = new(box.Orientation);
 526        Span<RationalPoint> corners = stackalloc RationalPoint[8];
 527        int index = 0;
 3028        for (int x = -1; x <= 1; x += 2)
 29        {
 6030            for (int y = -1; y <= 1; y += 2)
 31            {
 12032                for (int z = -1; z <= 1; z += 2)
 33                {
 4034                    corners[index++] = GetWorldPoint(
 4035                        box.Center,
 4036                        basis,
 4037                        new Vector3d(
 4038                            x * box.HalfExtents.X,
 4039                            y * box.HalfExtents.Y,
 4040                            z * box.HalfExtents.Z));
 41                }
 42            }
 43        }
 44
 545        Span<RationalPoint> hull = stackalloc RationalPoint[8];
 546        int count = BuildConvexHull(corners, hull);
 547        return TryGetConvexRelation(
 548            circleCenter,
 549            circleRadius,
 550            basis.Denominator,
 551            hull[..count],
 552            out relation);
 53    }
 54
 55    internal static bool TryGetTriangleRelation(
 56        Vector2d circleCenter,
 57        Fixed64 circleRadius,
 58        FixedTriangle triangle,
 59        Vector3d triangleOrigin,
 60        FixedQuaternion triangleRotation,
 61        out PlanarProjectionRelation relation)
 62    {
 763        WideRationalBasis3d basis = new(triangleRotation);
 764        Span<RationalPoint> vertices = stackalloc RationalPoint[3];
 765        vertices[0] = GetWorldPoint(
 766            triangleOrigin,
 767            basis,
 768            triangle.A);
 769        vertices[1] = GetWorldPoint(
 770            triangleOrigin,
 771            basis,
 772            triangle.B);
 773        vertices[2] = GetWorldPoint(
 774            triangleOrigin,
 775            basis,
 776            triangle.C);
 77
 778        if (ContainsPoint(
 779                circleCenter,
 780                basis.Denominator,
 781                vertices))
 82        {
 183            relation = PlanarProjectionRelation.Contained;
 184            return true;
 85        }
 86
 687        RationalDistance best = GetSegmentDistance(
 688            circleCenter,
 689            basis.Denominator,
 690            vertices[0],
 691            vertices[1]);
 692        KeepCloser(
 693            GetSegmentDistance(
 694                circleCenter,
 695                basis.Denominator,
 696                vertices[1],
 697                vertices[2]),
 698            ref best);
 699        KeepCloser(
 6100            GetSegmentDistance(
 6101                circleCenter,
 6102                basis.Denominator,
 6103                vertices[2],
 6104                vertices[0]),
 6105            ref best);
 6106        return TryCreateRelation(
 6107            best,
 6108            circleRadius,
 6109            out relation);
 110    }
 111
 112    private static bool TryGetConvexRelation(
 113        Vector2d circleCenter,
 114        Fixed64 circleRadius,
 115        Signed192 denominator,
 116        ReadOnlySpan<RationalPoint> vertices,
 117        out PlanarProjectionRelation relation)
 118    {
 6119        if (ContainsPoint(
 6120                circleCenter,
 6121                denominator,
 6122                vertices))
 123        {
 2124            relation = PlanarProjectionRelation.Contained;
 2125            return true;
 126        }
 127
 4128        RationalDistance best = GetSegmentDistance(
 4129            circleCenter,
 4130            denominator,
 4131            vertices[0],
 4132            vertices[1]);
 30133        for (int index = 1; index < vertices.Length; index++)
 134        {
 11135            KeepCloser(
 11136                GetSegmentDistance(
 11137                    circleCenter,
 11138                    denominator,
 11139                    vertices[index],
 11140                    vertices[
 11141                        index + 1 == vertices.Length
 11142                            ? 0
 11143                            : index + 1]),
 11144                ref best);
 145        }
 146
 4147        return TryCreateRelation(
 4148            best,
 4149            circleRadius,
 4150            out relation);
 151    }
 152
 153    private static bool TryCreateRelation(
 154        RationalDistance distance,
 155        Fixed64 circleRadius,
 156        out PlanarProjectionRelation relation)
 157    {
 11158        if (distance.SquaredDistance.IsZero)
 159        {
 1160            relation = PlanarProjectionRelation.Contained;
 1161            return true;
 162        }
 163
 10164        if (!TryGetDistance(
 10165                distance,
 10166                circleRadius,
 10167                out Fixed64 result))
 168        {
 2169            relation = default;
 2170            return false;
 171        }
 172
 8173        relation = new PlanarProjectionRelation(
 8174            result,
 8175            GetOffset(distance),
 8176            WideNormalization.GetNormalized(
 8177                distance.X,
 8178                distance.Z));
 8179        return true;
 180    }
 181
 182    private static bool ContainsPoint(
 183        Vector2d point,
 184        Signed192 denominator,
 185        ReadOnlySpan<RationalPoint> vertices)
 186    {
 13187        int winding = 0;
 13188        Signed320 pointX = WideArithmetic.MultiplySigned192(
 13189            Signed192.Raw(point.X),
 13190            denominator);
 13191        Signed320 pointZ = WideArithmetic.MultiplySigned192(
 13192            Signed192.Raw(point.Y),
 13193            denominator);
 90194        for (int index = 0; index < vertices.Length; index++)
 195        {
 40196            RationalPoint first = vertices[index];
 40197            RationalPoint second = vertices[
 40198                index + 1 == vertices.Length ? 0 : index + 1];
 40199            Signed576 cross = Cross(
 40200                WideArithmetic.SubtractSigned320(
 40201                    second.X,
 40202                    first.X),
 40203                WideArithmetic.SubtractSigned320(
 40204                    second.Z,
 40205                    first.Z),
 40206                WideArithmetic.SubtractSigned320(
 40207                    pointX,
 40208                    first.X),
 40209                WideArithmetic.SubtractSigned320(
 40210                    pointZ,
 40211                    first.Z));
 40212            int sign = cross.Sign;
 40213            if (sign == 0)
 214                continue;
 30215            if (winding == 0)
 11216                winding = sign;
 19217            else if (winding != sign)
 8218                return false;
 219        }
 220
 5221        return winding != 0;
 222    }
 223
 224    private static int BuildConvexHull(
 225        Span<RationalPoint> points,
 226        Span<RationalPoint> hull)
 227    {
 5228        SortAndDeduplicate(points, out int uniqueCount);
 5229        Span<RationalPoint> work =
 5230            stackalloc RationalPoint[16];
 5231        int count = 0;
 50232        for (int index = 0; index < uniqueCount; index++)
 233        {
 25234            while (count >= 2
 25235                   && GetTurn(
 25236                       work[count - 2],
 25237                       work[count - 1],
 25238                       points[index]) <= 0)
 239            {
 5240                count--;
 241            }
 20242            work[count++] = points[index];
 243        }
 244
 5245        int lowerCount = count;
 40246        for (int index = uniqueCount - 2; index >= 0; index--)
 247        {
 20248            while (count > lowerCount
 20249                   && GetTurn(
 20250                       work[count - 2],
 20251                       work[count - 1],
 20252                       points[index]) <= 0)
 253            {
 5254                count--;
 255            }
 15256            work[count++] = points[index];
 257        }
 258
 5259        count--;
 5260        work[..count].CopyTo(hull);
 5261        return count;
 262    }
 263
 264    private static void SortAndDeduplicate(
 265        Span<RationalPoint> points,
 266        out int count)
 267    {
 80268        for (int index = 1; index < points.Length; index++)
 269        {
 35270            RationalPoint value = points[index];
 35271            int destination = index;
 65272            while (destination > 0
 65273                   && ComparePoint(
 65274                       value,
 65275                       points[destination - 1]) < 0)
 276            {
 30277                points[destination] =
 30278                    points[destination - 1];
 30279                destination--;
 280            }
 35281            points[destination] = value;
 282        }
 283
 5284        count = 1;
 80285        for (int index = 1; index < points.Length; index++)
 286        {
 35287            if (ComparePoint(points[index], points[count - 1]) == 0)
 288                continue;
 15289            points[count++] = points[index];
 290        }
 5291    }
 292
 293    private static int ComparePoint(
 294        RationalPoint first,
 295        RationalPoint second)
 296    {
 97297        int comparison = WideArithmetic.SubtractSigned320(
 97298            first.X,
 97299            second.X).Sign;
 97300        return comparison != 0
 97301            ? comparison
 97302            : WideArithmetic.SubtractSigned320(
 97303                first.Z,
 97304                second.Z).Sign;
 305    }
 306
 307    private static int GetTurn(
 308        RationalPoint first,
 309        RationalPoint second,
 310        RationalPoint third) =>
 20311        Cross(
 20312            WideArithmetic.SubtractSigned320(
 20313                second.X,
 20314                first.X),
 20315            WideArithmetic.SubtractSigned320(
 20316                second.Z,
 20317                first.Z),
 20318            WideArithmetic.SubtractSigned320(
 20319                third.X,
 20320                second.X),
 20321            WideArithmetic.SubtractSigned320(
 20322                third.Z,
 20323                second.Z)).Sign;
 324
 325    private static Signed576 Cross(
 326        Signed320 firstX,
 327        Signed320 firstZ,
 328        Signed320 secondX,
 329        Signed320 secondZ) =>
 60330        WideArithmetic.SubtractSigned576(
 60331            WideArithmetic.MultiplySigned320(
 60332                firstX,
 60333                secondZ),
 60334            WideArithmetic.MultiplySigned320(
 60335                firstZ,
 60336                secondX));
 337
 338    private static void KeepCloser(
 339        RationalDistance candidate,
 340        ref RationalDistance best)
 341    {
 23342        if (CompareDistances(candidate, best) < 0)
 5343            best = candidate;
 23344    }
 345
 346    private static int CompareDistances(
 347        RationalDistance first,
 348        RationalDistance second)
 349    {
 23350        Signed832 firstDenominatorSquared =
 23351            WideArithmetic.MultiplySigned576ToSigned832(
 23352                first.Denominator,
 23353                first.Denominator);
 23354        Signed832 secondDenominatorSquared =
 23355            WideArithmetic.MultiplySigned576ToSigned832(
 23356                second.Denominator,
 23357                second.Denominator);
 23358        Span<ulong> firstSquaredMagnitude = stackalloc ulong[13];
 23359        Span<ulong> secondSquaredMagnitude = stackalloc ulong[13];
 23360        Span<ulong> firstDenominatorMagnitude = stackalloc ulong[13];
 23361        Span<ulong> secondDenominatorMagnitude = stackalloc ulong[13];
 23362        WideArithmetic.GetMagnitude(
 23363            first.SquaredDistance,
 23364            firstSquaredMagnitude);
 23365        WideArithmetic.GetMagnitude(
 23366            second.SquaredDistance,
 23367            secondSquaredMagnitude);
 23368        WideArithmetic.GetMagnitude(
 23369            firstDenominatorSquared,
 23370            firstDenominatorMagnitude);
 23371        WideArithmetic.GetMagnitude(
 23372            secondDenominatorSquared,
 23373            secondDenominatorMagnitude);
 23374        Span<ulong> left =
 23375            stackalloc ulong[DistanceComparisonWordCount];
 23376        Span<ulong> right =
 23377            stackalloc ulong[DistanceComparisonWordCount];
 23378        WideArithmetic.MultiplyMagnitudes(
 23379            firstSquaredMagnitude,
 23380            secondDenominatorMagnitude,
 23381            left);
 23382        WideArithmetic.MultiplyMagnitudes(
 23383            secondSquaredMagnitude,
 23384            firstDenominatorMagnitude,
 23385            right);
 23386        return WideArithmetic.CompareMagnitudeEqualLength(
 23387            left,
 23388            right);
 389    }
 390}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Wide/Common/WidePlanarProjection.ScaledTriangle.cs

#LineLine coverage
 1//=======================================================================
 2// WidePlanarProjection.ScaledTriangle.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 exact scaled source triangles through projected finite-feature selection.</content>
 13internal static partial class WidePlanarProjection
 14{
 15    internal static bool TryGetTriangleRelation(Vector2d center, Fixed64 radius, in FixedTriangle triangle,
 16        in ScaledRigidFrame3d frame, out PlanarProjectionRelation relation)
 17    {
 2218        if (frame.IsRigid)
 219            return TryGetTriangleRelation(center, radius, triangle, frame.RigidOrigin, frame.Rotation, out relation);
 2020        Span<RationalPoint3d> points = stackalloc RationalPoint3d[3]
 2021            { frame.GetPoint(triangle.A), frame.GetPoint(triangle.B), frame.GetPoint(triangle.C) };
 4022        Span<Signed320> x = stackalloc Signed320[3], z = stackalloc Signed320[3];
 16023        for (int corner = 0; corner < 3; corner++)
 24        {
 6025            x[corner] = Signed320.NarrowValue(WideArithmetic.SubtractSigned576(Signed576.ExtendValue(points[corner].X),
 6026                WideArithmetic.MultiplySigned320(frame.Denominator, Signed192.Raw(center.X))));
 6027            z[corner] = Signed320.NarrowValue(WideArithmetic.SubtractSigned576(Signed576.ExtendValue(points[corner].Z),
 6028                WideArithmetic.MultiplySigned320(frame.Denominator, Signed192.Raw(center.Y))));
 29        }
 4030        int winding = 0; bool contained = true;
 16031        for (int edge = 0; edge < 3; edge++)
 32        {
 6033            int end = (edge + 1) % 3;
 6034            Signed576 cross = WideArithmetic.SubtractSigned576(WideArithmetic.MultiplySigned320(x[edge], z[end]),
 6035                WideArithmetic.MultiplySigned320(z[edge], x[end]));
 6036            if (cross.IsZero) continue;
 2237            if (winding == 0) winding = cross.Sign;
 1538            else if (winding != cross.Sign) contained = false;
 39        }
 2440        if (contained && winding != 0) { relation = PlanarProjectionRelation.Contained; return true; }
 41
 42        // Endpoint offsets need <263 bits. An interior edge projection retains
 43        // <750-bit numerators and its squared distance in transient 2048-bit banks.
 44        const int words = 32;
 3645        Span<ulong> storage = stackalloc ulong[16 * words]; Span<int> signs = stackalloc int[16];
 1846        var bestN = ContactQuadratic.At(storage, signs, 0, words);
 1847        var bestD = ContactQuadratic.At(storage, signs, 1, words);
 1848        var distance = ContactQuadratic.At(storage, signs, 2, words);
 1849        var denominator = ContactQuadratic.At(storage, signs, 3, words);
 1850        var coefficient = ContactQuadratic.At(storage, signs, 4, words);
 1851        var term = ContactQuadratic.At(storage, signs, 5, words);
 1852        var limit = ContactQuadratic.At(storage, signs, 6, words);
 1853        var scaled = ContactQuadratic.At(storage, signs, 7, words);
 5454        Signed832 bestX = default, bestZ = default, bestDenominator = default;
 14455        for (int edge = 0; edge < 3; edge++)
 56        {
 5457            int end = (edge + 1) % 3;
 5458            GetScaledProjectedDistance(x[edge], z[edge], x[end], z[end], frame.Denominator,
 5459                out Signed832 dx, out Signed832 dz, out Signed832 divisor);
 10860            coefficient.Set(dx); ContactQuadratic.Multiply(coefficient, coefficient, ReadOnlySpan<ulong>.Empty, distance
 16261            coefficient.Set(dz); ContactQuadratic.Multiply(coefficient, coefficient, ReadOnlySpan<ulong>.Empty, term); d
 10862            coefficient.Set(divisor); ContactQuadratic.Multiply(coefficient, coefficient, ReadOnlySpan<ulong>.Empty, den
 5463            if (edge != 0 && ContactQuadratic.CompareRatios(distance, denominator, ReadOnlySpan<ulong>.Empty,
 5464                bestN, bestD, ReadOnlySpan<ulong>.Empty) >= 0) continue;
 3865            distance.CopyTo(bestN); denominator.CopyTo(bestD);
 5766            bestX = dx; bestZ = dz; bestDenominator = divisor;
 67        }
 2268        if (bestN.Signs[0] == 0) { relation = PlanarProjectionRelation.Contained; return true; }
 1669        Signed576 rawRadius = Signed576.ExtendValue(Signed320.ExtendValue(Signed192.Raw(radius)));
 3270        ContactQuadratic.Scale(bestD, rawRadius, limit); ContactQuadratic.Scale(limit, rawRadius, scaled);
 1671        if (ContactQuadratic.CompareRatios(bestN, bestD, ReadOnlySpan<ulong>.Empty,
 1672                scaled, bestD, ReadOnlySpan<ulong>.Empty) > 0)
 1473        { relation = default; return false; }
 974        ulong floor = WideArithmetic.GetRatioFloorSquareRoot(bestN.Rational, bestD.Rational, (ulong)radius.m_rawValue);
 975        Signed192 midpoint = WideArithmetic.AddSigned192(WideArithmetic.AddSigned192(Signed192.Signed((long)floor),
 976            Signed192.Signed((long)floor)), Signed192.Signed(1));
 977        Signed576 rawMidpoint = Signed576.ExtendValue(Signed320.ExtendValue(midpoint));
 1878        ContactQuadratic.Scale(bestD, rawMidpoint, limit); ContactQuadratic.Scale(limit, rawMidpoint, scaled);
 979        ContactQuadratic.Scale(bestN, Signed576.ExtendValue(Signed320.ExtendValue(Signed192.Signed(4))), limit);
 980        scaled.Add(limit, -1);
 1281        if (scaled.Signs[0] < 0 || scaled.Signs[0] == 0 && (floor & 1UL) != 0) floor++;
 982        _ = Fixed64.TryGetSignedRawRatio(bestX, bestDenominator, 0, out Fixed64 offsetX);
 983        _ = Fixed64.TryGetSignedRawRatio(bestZ, bestDenominator, 0, out Fixed64 offsetZ);
 984        relation = new PlanarProjectionRelation(Fixed64.FromRaw((long)floor), new Vector2d(offsetX, offsetZ),
 985            WideNormalization.GetNormalized(bestX, bestZ));
 986        return true;
 87    }
 88
 89    private static void GetScaledProjectedDistance(Signed320 ax, Signed320 az, Signed320 bx, Signed320 bz,
 90        Signed320 denominator, out Signed832 x, out Signed832 z, out Signed832 divisor)
 91    {
 10892        Signed320 ex = WideArithmetic.SubtractSigned320(bx, ax), ez = WideArithmetic.SubtractSigned320(bz, az);
 5493        Signed576 squared = WideArithmetic.AddSigned576(WideArithmetic.MultiplySigned320(ex, ex), WideArithmetic.Multipl
 5494        Signed576 projection = WideArithmetic.SubtractSigned576(default,
 5495            WideArithmetic.AddSigned576(WideArithmetic.MultiplySigned320(ax, ex), WideArithmetic.MultiplySigned320(az, e
 5496        if (squared.IsZero || projection.Sign <= 0)
 97        {
 8298            x = Signed832.ExtendValue(Signed576.ExtendValue(ax)); z = Signed832.ExtendValue(Signed576.ExtendValue(az));
 8299            divisor = Signed832.ExtendValue(Signed576.ExtendValue(denominator)); return;
 100        }
 13101        if (WideArithmetic.SubtractSigned576(projection, squared).Sign >= 0)
 102        {
 10103            x = Signed832.ExtendValue(Signed576.ExtendValue(bx)); z = Signed832.ExtendValue(Signed576.ExtendValue(bz));
 10104            divisor = Signed832.ExtendValue(Signed576.ExtendValue(denominator)); return;
 105        }
 8106        x = WideArithmetic.AddSigned832(WideArithmetic.MultiplySigned576ToSigned832(squared, ax),
 8107            WideArithmetic.MultiplySigned576ToSigned832(projection, ex));
 8108        z = WideArithmetic.AddSigned832(WideArithmetic.MultiplySigned576ToSigned832(squared, az),
 8109            WideArithmetic.MultiplySigned576ToSigned832(projection, ez));
 8110        divisor = WideArithmetic.MultiplySigned576ToSigned832(squared, denominator);
 8111    }
 112}

Methods/Properties

TryGetRotatedConeRelation(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint,FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.PlanarProjectionRelation&)
GetProjectedConeCeilingDistance(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
FindProjectedConeCeilingDistance(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,System.Int64,System.Int64)
GetProjectedConeClosestOffset(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Vector2d&)
GetSegmentOffset(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d)
KeepCloserOffset(FixedMathSharp.Vector2d,System.Boolean&,FixedMathSharp.Vector2d&)
CompareConeDistanceToRadius(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed192,System.Int32)
GetConeProjectionData(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&)
IsPointInConeProjectionWedge(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed320,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576)
TryCompareConeTangentDistanceToRadius(FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed192,System.Int32,System.Int32&)
CompareConeTangentSquaredDistance(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed192,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed192,System.Int32)
CompareRationalDistanceToRadius(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Signed192,System.Int32)
.ctor(FixedMathSharp.Signed320,FixedMathSharp.Signed320)
.ctor(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed576)
TryGetSphereRelation(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.PlanarProjectionRelation&)
TryGetCenteredCapsuleRelation(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.PlanarProjectionRelation&)
TryGetCenteredCylinderRelation(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.PlanarProjectionRelation&)
TryGetCenteredConeRelation(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.PlanarProjectionRelation&)
TryCreateRadiallyExpandedRelation(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.PlanarProjectionRelation&)
GetRotatedLocalAxis(FixedMathSharp.Geometry.WideRationalBasis3d,FixedMathSharp.Vector3d,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&,FixedMathSharp.Signed320&)
GetLocalOffsetNumerator(FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Vector3d)
GetWorldPoint(FixedMathSharp.Vector3d,FixedMathSharp.Geometry.WideRationalBasis3d,FixedMathSharp.Vector3d)
GetCenteredAxisEndpoints(FixedMathSharp.Vector3d,FixedMathSharp.Signed192,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Fixed64,FixedMathSharp.Signed192&,FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint&,FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint&)
GetCenteredBasisAxisEndpoints(FixedMathSharp.Vector3d,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Signed192&,FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint&,FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint&)
TryGetRadialGap(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
GetPointDistance(FixedMathSharp.Vector2d,FixedMathSharp.Signed192,FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint)
GetSegmentDistance(FixedMathSharp.Vector2d,FixedMathSharp.Signed192,FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint,FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint)
GetSegmentDistance(FixedMathSharp.Vector2d,FixedMathSharp.Signed192,FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint,FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint,System.Int32&)
IsWithinRadius(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Fixed64)
TryGetDistance(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
CompareDistanceToRaw(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,System.Int64)
CompareDistanceToRaw(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Signed192)
CompareDistanceToTwiceRaw(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,System.Int64)
CompareDistanceToTwiceRaw(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Signed192)
GetOffset(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance)
GetHalfToEvenIncrement(System.Int32,System.Int64)
GetLargestPositiveMagnitude(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320)
TryGetProjectedDiskRelation(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.PlanarProjectionRelation&)
GetProjectedDiskCeilingDistance(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
FindProjectedDiskCeilingDistance(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,System.Int64,System.Int64)
GetProjectedDiskClosestOffset(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Vector2d&)
GetEllipseClosestOffset(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
GetEllipseConstraintCoordinate(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
GetProjectedDiskSegmentEndpoints(FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint&,FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint&)
CompareProjectedDiskDistanceToRadius(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,System.Int32)
CountProjectedDiskCircleRoots(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,System.Int32)
CreateProjectedDiskCirclePolynomial(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,System.Int32,System.Int32,System.Int32,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&)
GetProjectedDiskConicCoefficient(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed320,FixedMathSharp.Signed576,FixedMathSharp.Signed576)
GetProjectedDiskRadialCoefficient(FixedMathSharp.Signed576,FixedMathSharp.Signed576,FixedMathSharp.Signed320)
GetSquaredPolynomial(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&,FixedMathSharp.Signed576&)
MultiplyBySmall(FixedMathSharp.Signed320,System.Int32)
DoubleSigned832(FixedMathSharp.Signed832)
EvaluateProjectedDiskConic(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Signed192,FixedMathSharp.Fixed64)
TryGetOrientedBoxRelation(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.FixedOrientedBox,FixedMathSharp.Geometry.PlanarProjectionRelation&)
TryGetTriangleRelation(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.FixedTriangle,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Geometry.PlanarProjectionRelation&)
TryGetConvexRelation(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Signed192,System.ReadOnlySpan`1<FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint>,FixedMathSharp.Geometry.PlanarProjectionRelation&)
TryCreateRelation(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.PlanarProjectionRelation&)
ContainsPoint(FixedMathSharp.Vector2d,FixedMathSharp.Signed192,System.ReadOnlySpan`1<FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint>)
BuildConvexHull(System.Span`1<FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint>,System.Span`1<FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint>)
SortAndDeduplicate(System.Span`1<FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint>,System.Int32&)
ComparePoint(FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint,FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint)
GetTurn(FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint,FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint,FixedMathSharp.Geometry.WidePlanarProjection/RationalPoint)
Cross(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320)
KeepCloser(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance&)
CompareDistances(FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance,FixedMathSharp.Geometry.WidePlanarProjection/RationalDistance)
TryGetTriangleRelation(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Geometry.FixedTriangle&,FixedMathSharp.Geometry.ScaledRigidFrame3d&,FixedMathSharp.Geometry.PlanarProjectionRelation&)
GetScaledProjectedDistance(FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed320,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&,FixedMathSharp.Signed832&)