< Summary

Line coverage
100%
Covered lines: 2050
Uncovered lines: 0
Coverable lines: 2050
Total lines: 2939
Line coverage: 100%
Branch coverage
100%
Covered branches: 234
Total branches: 234
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: AreSegmentEndpointDistancesAtLeast(...)100%66100%
File 2: GetRawPoint(...)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(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        {
 223924            X = x;
 223925            Z = z;
 223926        }
 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        {
 217839            X = x;
 217840            Z = z;
 217841            Denominator = denominator;
 217842            SquaredDistance = WideArithmetic.AddSigned832(
 217843                WideArithmetic.MultiplySigned576ToSigned832(x, x),
 217844                WideArithmetic.MultiplySigned576ToSigned832(z, z));
 217845        }
 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 AreSegmentEndpointDistancesAtLeast(
 56        FixedSegment2d first,
 57        FixedSegment2d second,
 58        Fixed64 minimumDistance)
 59    {
 52760        Signed192 denominator = Signed192.Signed(1L);
 52761        RationalPoint firstStart = GetRawPoint(first.Start);
 52762        RationalPoint firstEnd = GetRawPoint(first.End);
 52763        RationalPoint secondStart = GetRawPoint(second.Start);
 52764        RationalPoint secondEnd = GetRawPoint(second.End);
 52765        Signed192 minimumRaw = Signed192.Raw(minimumDistance);
 66
 52767        return CompareDistanceToRaw(
 52768                GetSegmentDistance(
 52769                    first.Start,
 52770                    denominator,
 52771                    secondStart,
 52772                    secondEnd),
 52773                minimumRaw) >= 0
 52774            && CompareDistanceToRaw(
 52775                GetSegmentDistance(
 52776                    first.End,
 52777                    denominator,
 52778                    secondStart,
 52779                    secondEnd),
 52780                minimumRaw) >= 0
 52781            && CompareDistanceToRaw(
 52782                GetSegmentDistance(
 52783                    second.Start,
 52784                    denominator,
 52785                    firstStart,
 52786                    firstEnd),
 52787                minimumRaw) >= 0
 52788            && CompareDistanceToRaw(
 52789                GetSegmentDistance(
 52790                    second.End,
 52791                    denominator,
 52792                    firstStart,
 52793                    firstEnd),
 52794                minimumRaw) >= 0;
 95    }
 96
 97    private static RationalPoint GetRawPoint(Vector2d point) =>
 210898        new(
 210899            Signed320.ExtendValue(Signed192.Raw(point.X)),
 2108100            Signed320.ExtendValue(Signed192.Raw(point.Y)));
 101
 102    internal static bool TryGetSphereRelation(
 103        Vector2d circleCenter,
 104        Fixed64 circleRadius,
 105        Vector3d sphereCenter,
 106        Fixed64 sphereRadius,
 107        out PlanarProjectionRelation relation)
 108    {
 3109        Vector2d projectedCenter = new(
 3110            sphereCenter.X,
 3111            sphereCenter.Z);
 3112        if (WideGeometry.CompareDistanceToRadiusSum(
 3113                circleCenter,
 3114                projectedCenter,
 3115                circleRadius,
 3116                sphereRadius) > 0)
 117        {
 1118            relation = default;
 1119            return false;
 120        }
 121
 2122        if (WideGeometry.CompareDistanceToRadiusSum(
 2123                circleCenter,
 2124                projectedCenter,
 2125                Fixed64.Zero,
 2126                sphereRadius) <= 0)
 127        {
 1128            relation = PlanarProjectionRelation.Contained;
 1129            return true;
 130        }
 131
 1132        _ = WideFiniteAxisIntersection.TryGetDistanceToCenteredCapsule(
 1133            circleCenter,
 1134            projectedCenter,
 1135            Vector2d.Right,
 1136            Fixed64.Zero,
 1137            sphereRadius,
 1138            out Fixed64 distance);
 139
 1140        Vector2d normal =
 1141            WideNormalization.GetDirection(projectedCenter, circleCenter);
 1142        relation = new PlanarProjectionRelation(
 1143            distance,
 1144            -normal * distance,
 1145            -normal);
 1146        return true;
 147    }
 148
 149    internal static bool TryGetCenteredCapsuleRelation(
 150        Vector2d circleCenter,
 151        Fixed64 circleRadius,
 152        Vector3d capsuleCenter,
 153        FixedQuaternion capsuleRotation,
 154        Vector3d capsuleLocalAxis,
 155        Fixed64 capsuleAxisLength,
 156        Fixed64 capsuleRadius,
 157        out PlanarProjectionRelation relation)
 158    {
 6159        WideRationalBasis3d basis = new(capsuleRotation);
 6160        GetRotatedLocalAxis(
 6161            basis,
 6162            capsuleLocalAxis,
 6163            out Signed320 axisX,
 6164            out _,
 6165            out Signed320 axisZ);
 6166        GetCenteredAxisEndpoints(
 6167            capsuleCenter,
 6168            basis.Denominator,
 6169            axisX,
 6170            axisZ,
 6171            capsuleAxisLength,
 6172            out Signed192 axisDenominator,
 6173            out RationalPoint first,
 6174            out RationalPoint second);
 6175        RationalDistance axisDistance = GetSegmentDistance(
 6176            circleCenter,
 6177            axisDenominator,
 6178            first,
 6179            second);
 6180        return TryCreateRadiallyExpandedRelation(
 6181            axisDistance,
 6182            capsuleRadius,
 6183            circleRadius,
 6184            out relation);
 185    }
 186
 187    internal static bool TryGetCenteredCylinderRelation(
 188        Vector2d circleCenter,
 189        Fixed64 circleRadius,
 190        Vector3d cylinderCenter,
 191        FixedQuaternion cylinderRotation,
 192        Fixed64 cylinderAxisLength,
 193        Fixed64 cylinderRadius,
 194        out PlanarProjectionRelation relation)
 195    {
 16196        WideRationalBasis3d basis = new(cylinderRotation);
 16197        Signed192 axisX = basis.Yx;
 16198        Signed192 axisY = basis.Yy;
 16199        Signed192 axisZ = basis.Yz;
 16200        GetCenteredBasisAxisEndpoints(
 16201            cylinderCenter,
 16202            basis.Denominator,
 16203            axisX,
 16204            axisZ,
 16205            cylinderAxisLength,
 16206            out Signed192 axisDenominator,
 16207            out RationalPoint first,
 16208            out RationalPoint second);
 16209        RationalDistance axisDistance = GetSegmentDistance(
 16210            circleCenter,
 16211            axisDenominator,
 16212            first,
 16213            second,
 16214            out int feature);
 16215        if (feature == 0)
 216        {
 3217            return TryCreateRadiallyExpandedRelation(
 3218                axisDistance,
 3219                cylinderRadius,
 3220                circleRadius,
 3221                out relation);
 222        }
 223
 13224        return TryGetProjectedDiskRelation(
 13225            circleCenter,
 13226            circleRadius,
 13227            feature < 0 ? first : second,
 13228            axisDenominator,
 13229            axisX,
 13230            axisY,
 13231            axisZ,
 13232            cylinderRadius,
 13233            out relation);
 234    }
 235
 236    internal static bool TryGetCenteredConeRelation(
 237        Vector2d circleCenter,
 238        Fixed64 circleRadius,
 239        Vector3d coneCenter,
 240        FixedQuaternion coneRotation,
 241        Fixed64 coneHeight,
 242        Fixed64 coneRadius,
 243        out PlanarProjectionRelation relation)
 244    {
 14245        WideRationalBasis3d basis = new(coneRotation);
 14246        Signed192 axisX = basis.Yx;
 14247        Signed192 axisY = basis.Yy;
 14248        Signed192 axisZ = basis.Yz;
 14249        GetCenteredBasisAxisEndpoints(
 14250            coneCenter,
 14251            basis.Denominator,
 14252            axisX,
 14253            axisZ,
 14254            coneHeight,
 14255            out Signed192 axisDenominator,
 14256            out RationalPoint baseCenter,
 14257            out RationalPoint apex);
 14258        if (axisY.IsZero)
 259        {
 1260            GetProjectedDiskSegmentEndpoints(
 1261                baseCenter,
 1262                axisX,
 1263                axisZ,
 1264                coneRadius,
 1265                out RationalPoint first,
 1266                out RationalPoint second);
 1267            Span<RationalPoint> triangle =
 1268                stackalloc RationalPoint[3];
 1269            triangle[0] = first;
 1270            triangle[1] = second;
 1271            triangle[2] = apex;
 1272            return TryGetConvexRelation(
 1273                circleCenter,
 1274                circleRadius,
 1275                axisDenominator,
 1276                triangle,
 1277                out relation);
 278        }
 13279        if (axisX.IsZero && axisZ.IsZero)
 280        {
 1281            return TryGetProjectedDiskRelation(
 1282                circleCenter,
 1283                circleRadius,
 1284                baseCenter,
 1285                axisDenominator,
 1286                axisX,
 1287                axisY,
 1288                axisZ,
 1289                coneRadius,
 1290                out relation);
 291        }
 292
 12293        return TryGetRotatedConeRelation(
 12294            circleCenter,
 12295            circleRadius,
 12296            baseCenter,
 12297            apex,
 12298            axisDenominator,
 12299            basis.Denominator,
 12300            axisX,
 12301            axisY,
 12302            axisZ,
 12303            coneHeight,
 12304            coneRadius,
 12305            out relation);
 306    }
 307
 308    private static bool TryCreateRadiallyExpandedRelation(
 309        RationalDistance axisDistance,
 310        Fixed64 shapeRadius,
 311        Fixed64 queryRadius,
 312        out PlanarProjectionRelation relation)
 313    {
 11314        Signed576 shapeRadiusNumerator =
 11315            WideArithmetic.MultiplySigned576(
 11316                axisDistance.Denominator,
 11317                Signed192.Raw(shapeRadius));
 11318        Signed832 shapeRadiusSquared =
 11319            WideArithmetic.MultiplySigned576ToSigned832(
 11320                shapeRadiusNumerator,
 11321                shapeRadiusNumerator);
 11322        if (WideArithmetic.SubtractSigned832(
 11323                axisDistance.SquaredDistance,
 11324                shapeRadiusSquared).Sign <= 0)
 325        {
 2326            relation = PlanarProjectionRelation.Contained;
 2327            return true;
 328        }
 329
 9330        if (!TryGetRadialGap(
 9331                axisDistance,
 9332                shapeRadius,
 9333                queryRadius,
 9334                out Fixed64 distance))
 335        {
 2336            relation = default;
 2337            return false;
 338        }
 339
 7340        Vector2d direction = WideNormalization.GetNormalized(
 7341            axisDistance.X,
 7342            axisDistance.Z);
 7343        Vector2d offset = direction * distance;
 7344        relation = new PlanarProjectionRelation(
 7345            distance,
 7346            offset,
 7347            direction);
 7348        return true;
 349    }
 350
 351    private static void GetRotatedLocalAxis(
 352        WideRationalBasis3d basis,
 353        Vector3d localAxis,
 354        out Signed320 x,
 355        out Signed320 y,
 356        out Signed320 z)
 357    {
 6358        x = GetLocalOffsetNumerator(
 6359            basis.Xx,
 6360            basis.Yx,
 6361            basis.Zx,
 6362            localAxis);
 6363        y = GetLocalOffsetNumerator(
 6364            basis.Xy,
 6365            basis.Yy,
 6366            basis.Zy,
 6367            localAxis);
 6368        z = GetLocalOffsetNumerator(
 6369            basis.Xz,
 6370            basis.Yz,
 6371            basis.Zz,
 6372            localAxis);
 6373    }
 374
 375    private static Signed320 GetLocalOffsetNumerator(
 376        Signed192 x,
 377        Signed192 y,
 378        Signed192 z,
 379        Vector3d localPoint) =>
 128380        WideArithmetic.AddSigned320(
 128381            WideArithmetic.AddSigned320(
 128382                WideArithmetic.MultiplySigned192(
 128383                    x,
 128384                    Signed192.Raw(localPoint.X)),
 128385                WideArithmetic.MultiplySigned192(
 128386                    y,
 128387                    Signed192.Raw(localPoint.Y))),
 128388            WideArithmetic.MultiplySigned192(
 128389                z,
 128390                Signed192.Raw(localPoint.Z)));
 391
 392    private static RationalPoint GetWorldPoint(
 393        Vector3d origin,
 394        WideRationalBasis3d basis,
 395        Vector3d localPoint) =>
 55396        new(
 55397            WideArithmetic.AddSigned320(
 55398                WideArithmetic.MultiplySigned192(
 55399                    Signed192.Raw(origin.X),
 55400                    basis.Denominator),
 55401                GetLocalOffsetNumerator(
 55402                    basis.Xx,
 55403                    basis.Yx,
 55404                    basis.Zx,
 55405                    localPoint)),
 55406            WideArithmetic.AddSigned320(
 55407                WideArithmetic.MultiplySigned192(
 55408                    Signed192.Raw(origin.Z),
 55409                    basis.Denominator),
 55410                GetLocalOffsetNumerator(
 55411                    basis.Xz,
 55412                    basis.Yz,
 55413                    basis.Zz,
 55414                    localPoint)));
 415
 416    private static void GetCenteredAxisEndpoints(
 417        Vector3d center,
 418        Signed192 denominator,
 419        Signed320 axisX,
 420        Signed320 axisZ,
 421        Fixed64 axisLength,
 422        out Signed192 axisDenominator,
 423        out RationalPoint first,
 424        out RationalPoint second)
 425    {
 6426        Signed192 halfLengthNumerator =
 6427            Signed192.Signed(axisLength.m_rawValue);
 6428        axisDenominator = Signed192.NarrowValue(
 6429            WideArithmetic.AddSigned320(
 6430                WideArithmetic.MultiplySigned192(
 6431                    denominator,
 6432                    Signed192.Raw(Fixed64.One)),
 6433                WideArithmetic.MultiplySigned192(
 6434                    denominator,
 6435                    Signed192.Raw(Fixed64.One))));
 6436        Signed320 centerX = WideArithmetic.MultiplySigned192(
 6437            Signed192.Raw(center.X),
 6438            axisDenominator);
 6439        Signed320 centerZ = WideArithmetic.MultiplySigned192(
 6440            Signed192.Raw(center.Z),
 6441            axisDenominator);
 6442        Signed320 offsetX = Signed320.NarrowValue(
 6443            WideArithmetic.MultiplySigned320(
 6444                axisX,
 6445                Signed320.ExtendValue(halfLengthNumerator)));
 6446        Signed320 offsetZ = Signed320.NarrowValue(
 6447            WideArithmetic.MultiplySigned320(
 6448                axisZ,
 6449                Signed320.ExtendValue(halfLengthNumerator)));
 6450        first = new RationalPoint(
 6451            WideArithmetic.SubtractSigned320(centerX, offsetX),
 6452            WideArithmetic.SubtractSigned320(centerZ, offsetZ));
 6453        second = new RationalPoint(
 6454            WideArithmetic.AddSigned320(centerX, offsetX),
 6455            WideArithmetic.AddSigned320(centerZ, offsetZ));
 6456    }
 457
 458    private static void GetCenteredBasisAxisEndpoints(
 459        Vector3d center,
 460        Signed192 denominator,
 461        Signed192 axisX,
 462        Signed192 axisZ,
 463        Fixed64 axisLength,
 464        out Signed192 axisDenominator,
 465        out RationalPoint first,
 466        out RationalPoint second)
 467    {
 30468        axisDenominator = WideArithmetic.AddSigned192(
 30469            denominator,
 30470            denominator);
 30471        Signed320 centerX = WideArithmetic.MultiplySigned192(
 30472            Signed192.Raw(center.X),
 30473            axisDenominator);
 30474        Signed320 centerZ = WideArithmetic.MultiplySigned192(
 30475            Signed192.Raw(center.Z),
 30476            axisDenominator);
 30477        Signed320 offsetX = WideArithmetic.MultiplySigned192(
 30478            axisX,
 30479            Signed192.Raw(axisLength));
 30480        Signed320 offsetZ = WideArithmetic.MultiplySigned192(
 30481            axisZ,
 30482            Signed192.Raw(axisLength));
 30483        first = new RationalPoint(
 30484            WideArithmetic.SubtractSigned320(centerX, offsetX),
 30485            WideArithmetic.SubtractSigned320(centerZ, offsetZ));
 30486        second = new RationalPoint(
 30487            WideArithmetic.AddSigned320(centerX, offsetX),
 30488            WideArithmetic.AddSigned320(centerZ, offsetZ));
 30489    }
 490
 491    private static bool TryGetRadialGap(
 492        RationalDistance distance,
 493        Fixed64 shapeRadius,
 494        Fixed64 maximumGap,
 495        out Fixed64 gap)
 496    {
 9497        Signed192 shapeRaw = Signed192.Raw(shapeRadius);
 9498        Signed192 maximumRaw = WideArithmetic.AddSigned192(
 9499            shapeRaw,
 9500            Signed192.Raw(maximumGap));
 9501        if (CompareDistanceToRaw(distance, maximumRaw) > 0)
 502        {
 2503            gap = default;
 2504            return false;
 505        }
 506
 7507        long low = 0L;
 7508        long high = maximumGap.m_rawValue;
 175509        while (low < high)
 510        {
 168511            long difference = high - low;
 168512            long middle =
 168513                low + (difference >> 1) + (difference & 1L);
 168514            Signed192 candidate = WideArithmetic.AddSigned192(
 168515                shapeRaw,
 168516                Signed192.Signed(middle));
 168517            if (CompareDistanceToRaw(distance, candidate) >= 0)
 151518                low = middle;
 519            else
 17520                high = middle - 1L;
 521        }
 522
 7523        if (low != maximumGap.m_rawValue)
 524        {
 3525            Signed192 midpoint = WideArithmetic.AddSigned192(
 3526                WideArithmetic.AddSigned192(
 3527                    WideArithmetic.AddSigned192(shapeRaw, shapeRaw),
 3528                    WideArithmetic.AddSigned192(
 3529                        Signed192.Signed(low),
 3530                        Signed192.Signed(low))),
 3531                Signed192.Signed(1L));
 3532            int comparison =
 3533                CompareDistanceToTwiceRaw(distance, midpoint);
 3534            low += GetHalfToEvenIncrement(comparison, low);
 535        }
 536
 7537        gap = Fixed64.FromRaw(low);
 7538        return true;
 539    }
 540
 541    private static RationalDistance GetPointDistance(
 542        Vector2d point,
 543        Signed192 denominator,
 544        RationalPoint target)
 545    {
 1081546        Signed320 x = WideArithmetic.SubtractSigned320(
 1081547            target.X,
 1081548            WideArithmetic.MultiplySigned192(
 1081549                Signed192.Raw(point.X),
 1081550                denominator));
 1081551        Signed320 z = WideArithmetic.SubtractSigned320(
 1081552            target.Z,
 1081553            WideArithmetic.MultiplySigned192(
 1081554                Signed192.Raw(point.Y),
 1081555                denominator));
 1081556        return new RationalDistance(
 1081557            Signed576.ExtendValue(x),
 1081558            Signed576.ExtendValue(z),
 1081559            Signed576.ExtendValue(
 1081560                Signed320.ExtendValue(denominator)));
 561    }
 562
 563    private static RationalDistance GetSegmentDistance(
 564        Vector2d point,
 565        Signed192 denominator,
 566        RationalPoint first,
 567        RationalPoint second) =>
 2125568        GetSegmentDistance(
 2125569            point,
 2125570            denominator,
 2125571            first,
 2125572            second,
 2125573            out _);
 574
 575    private static RationalDistance GetSegmentDistance(
 576        Vector2d point,
 577        Signed192 denominator,
 578        RationalPoint first,
 579        RationalPoint second,
 580        out int feature)
 581    {
 2141582        Signed320 firstX = WideArithmetic.SubtractSigned320(
 2141583            first.X,
 2141584            WideArithmetic.MultiplySigned192(
 2141585                Signed192.Raw(point.X),
 2141586                denominator));
 2141587        Signed320 firstZ = WideArithmetic.SubtractSigned320(
 2141588            first.Z,
 2141589            WideArithmetic.MultiplySigned192(
 2141590                Signed192.Raw(point.Y),
 2141591                denominator));
 2141592        Signed320 edgeX = WideArithmetic.SubtractSigned320(
 2141593            second.X,
 2141594            first.X);
 2141595        Signed320 edgeZ = WideArithmetic.SubtractSigned320(
 2141596            second.Z,
 2141597            first.Z);
 2141598        Signed576 edgeSquared = WideArithmetic.AddSigned576(
 2141599            WideArithmetic.MultiplySigned320(edgeX, edgeX),
 2141600            WideArithmetic.MultiplySigned320(edgeZ, edgeZ));
 2141601        if (edgeSquared.IsZero)
 602        {
 25603            feature = -1;
 25604            return new RationalDistance(
 25605                Signed576.ExtendValue(firstX),
 25606                Signed576.ExtendValue(firstZ),
 25607                Signed576.ExtendValue(
 25608                    Signed320.ExtendValue(denominator)));
 609        }
 610
 2116611        Signed576 projection = WideArithmetic.SubtractSigned576(
 2116612            default,
 2116613            WideArithmetic.AddSigned576(
 2116614                WideArithmetic.MultiplySigned320(firstX, edgeX),
 2116615                WideArithmetic.MultiplySigned320(firstZ, edgeZ)));
 2116616        if (projection.Sign <= 0)
 617        {
 1058618            feature = -1;
 1058619            return new RationalDistance(
 1058620                Signed576.ExtendValue(firstX),
 1058621                Signed576.ExtendValue(firstZ),
 1058622                Signed576.ExtendValue(
 1058623                    Signed320.ExtendValue(denominator)));
 624        }
 1058625        if (WideArithmetic.SubtractSigned576(
 1058626                projection,
 1058627                edgeSquared).Sign >= 0)
 628        {
 1044629            feature = 1;
 1044630            return GetPointDistance(point, denominator, second);
 631        }
 632
 14633        feature = 0;
 14634        Signed576 x = WideArithmetic.AddSigned576(
 14635            WideArithmetic.MultiplySigned576(
 14636                edgeSquared,
 14637                Signed192.NarrowValue(firstX)),
 14638            WideArithmetic.MultiplySigned576(
 14639                projection,
 14640                Signed192.NarrowValue(edgeX)));
 14641        Signed576 z = WideArithmetic.AddSigned576(
 14642            WideArithmetic.MultiplySigned576(
 14643                edgeSquared,
 14644                Signed192.NarrowValue(firstZ)),
 14645            WideArithmetic.MultiplySigned576(
 14646                projection,
 14647                Signed192.NarrowValue(edgeZ)));
 14648        Signed576 combinedDenominator =
 14649            WideArithmetic.MultiplySigned576(
 14650                edgeSquared,
 14651                denominator);
 14652        return new RationalDistance(x, z, combinedDenominator);
 653    }
 654
 655    private static bool IsWithinRadius(
 656        RationalDistance distance,
 657        Fixed64 radius)
 658    {
 8659        Signed576 scaledRadius = WideArithmetic.MultiplySigned576(
 8660            distance.Denominator,
 8661            Signed192.Raw(radius));
 8662        Signed832 squaredRadius =
 8663            WideArithmetic.MultiplySigned576ToSigned832(
 8664                scaledRadius,
 8665                scaledRadius);
 8666        return WideArithmetic.SubtractSigned832(
 8667            distance.SquaredDistance,
 8668            squaredRadius).Sign <= 0;
 669    }
 670
 671    private static bool TryGetDistance(
 672        RationalDistance distance,
 673        Fixed64 maximum,
 674        out Fixed64 result)
 675    {
 8676        if (!IsWithinRadius(distance, maximum))
 677        {
 2678            result = default;
 2679            return false;
 680        }
 681
 6682        long low = 0L;
 6683        long high = maximum.m_rawValue;
 203684        while (low < high)
 685        {
 197686            long difference = high - low;
 197687            long middle =
 197688                low + (difference >> 1) + (difference & 1L);
 197689            if (CompareDistanceToRaw(distance, middle) >= 0)
 165690                low = middle;
 691            else
 32692                high = middle - 1L;
 693        }
 694
 6695        if (low != maximum.m_rawValue)
 696        {
 2697            long doubledLow = low + low;
 2698            int midpointComparison =
 2699                CompareDistanceToTwiceRaw(
 2700                    distance,
 2701                    doubledLow + 1L);
 2702            low += GetHalfToEvenIncrement(midpointComparison, low);
 703        }
 704
 6705        result = Fixed64.FromRaw(low);
 6706        return true;
 707    }
 708
 709    private static int CompareDistanceToRaw(
 710        RationalDistance distance,
 711        long raw) =>
 197712        CompareDistanceToRaw(
 197713            distance,
 197714            Signed192.Signed(raw));
 715
 716    private static int CompareDistanceToRaw(
 717        RationalDistance distance,
 718        Signed192 raw)
 719    {
 2540720        Signed576 scaled = WideArithmetic.MultiplySigned576(
 2540721            distance.Denominator,
 2540722            raw);
 2540723        Signed832 squared = WideArithmetic.MultiplySigned576ToSigned832(
 2540724            scaled,
 2540725            scaled);
 2540726        return WideArithmetic.SubtractSigned832(
 2540727            distance.SquaredDistance,
 2540728            squared).Sign;
 729    }
 730
 731    private static int CompareDistanceToTwiceRaw(
 732        RationalDistance distance,
 733        long twiceRaw) =>
 2734        CompareDistanceToTwiceRaw(
 2735            distance,
 2736            Signed192.Signed(twiceRaw));
 737
 738    private static int CompareDistanceToTwiceRaw(
 739        RationalDistance distance,
 740        Signed192 twiceRaw)
 741    {
 20742        Signed832 fourDistance = WideArithmetic.AddSigned832(
 20743            WideArithmetic.AddSigned832(
 20744                distance.SquaredDistance,
 20745                distance.SquaredDistance),
 20746            WideArithmetic.AddSigned832(
 20747                distance.SquaredDistance,
 20748                distance.SquaredDistance));
 20749        Signed576 scaled = WideArithmetic.MultiplySigned576(
 20750            distance.Denominator,
 20751            twiceRaw);
 20752        Signed832 squared = WideArithmetic.MultiplySigned576ToSigned832(
 20753            scaled,
 20754            scaled);
 20755        return WideArithmetic.SubtractSigned832(
 20756            fourDistance,
 20757            squared).Sign;
 758    }
 759
 760    private static Vector2d GetOffset(RationalDistance distance)
 761    {
 6762        _ = Fixed64.TryGetSignedRawRatio(
 6763            distance.X,
 6764            distance.Denominator,
 6765            out Fixed64 x);
 6766        _ = Fixed64.TryGetSignedRawRatio(
 6767            distance.Z,
 6768            distance.Denominator,
 6769            out Fixed64 z);
 6770        return new Vector2d(x, z);
 771    }
 772
 773    private static long GetHalfToEvenIncrement(
 774        int midpointComparison,
 775        long lowerRaw)
 776    {
 5777        int negative = (int)((uint)midpointComparison >> 31);
 5778        int nonzero = (int)(
 5779            (uint)(midpointComparison | -midpointComparison) >> 31);
 5780        int positive = nonzero & (negative ^ 1);
 5781        int zero = nonzero ^ 1;
 5782        return (long)positive | ((long)zero & (lowerRaw & 1L));
 783    }
 784
 785    private static Signed320 GetLargestPositiveMagnitude(
 786        Signed320 first,
 787        Signed320 second,
 788        Signed320 third,
 789        Signed320 fourth,
 790        Signed320 fifth)
 791    {
 16792        Signed320 largest =
 16793            WideArithmetic.CompareMagnitude(first, second) >= 0
 16794                ? first
 16795                : second;
 16796        if (WideArithmetic.CompareMagnitude(largest, third) < 0)
 4797            largest = third;
 16798        if (WideArithmetic.CompareMagnitude(largest, fourth) < 0)
 4799            largest = fourth;
 16800        if (WideArithmetic.CompareMagnitude(largest, fifth) < 0)
 2801            largest = fifth;
 16802        return largest.Sign < 0
 16803            ? WideArithmetic.SubtractSigned320(default, largest)
 16804            : largest;
 805    }
 806}

/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    {
 563        WideRationalBasis3d basis = new(triangleRotation);
 564        Span<RationalPoint> vertices = stackalloc RationalPoint[3];
 565        vertices[0] = GetWorldPoint(
 566            triangleOrigin,
 567            basis,
 568            triangle.A);
 569        vertices[1] = GetWorldPoint(
 570            triangleOrigin,
 571            basis,
 572            triangle.B);
 573        vertices[2] = GetWorldPoint(
 574            triangleOrigin,
 575            basis,
 576            triangle.C);
 77
 578        if (ContainsPoint(
 579                circleCenter,
 580                basis.Denominator,
 581                vertices))
 82        {
 183            relation = PlanarProjectionRelation.Contained;
 184            return true;
 85        }
 86
 487        RationalDistance best = GetSegmentDistance(
 488            circleCenter,
 489            basis.Denominator,
 490            vertices[0],
 491            vertices[1]);
 492        KeepCloser(
 493            GetSegmentDistance(
 494                circleCenter,
 495                basis.Denominator,
 496                vertices[1],
 497                vertices[2]),
 498            ref best);
 499        KeepCloser(
 4100            GetSegmentDistance(
 4101                circleCenter,
 4102                basis.Denominator,
 4103                vertices[2],
 4104                vertices[0]),
 4105            ref best);
 4106        return TryCreateRelation(
 4107            best,
 4108            circleRadius,
 4109            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    {
 9158        if (distance.SquaredDistance.IsZero)
 159        {
 1160            relation = PlanarProjectionRelation.Contained;
 1161            return true;
 162        }
 163
 8164        if (!TryGetDistance(
 8165                distance,
 8166                circleRadius,
 8167                out Fixed64 result))
 168        {
 2169            relation = default;
 2170            return false;
 171        }
 172
 6173        relation = new PlanarProjectionRelation(
 6174            result,
 6175            GetOffset(distance),
 6176            WideNormalization.GetNormalized(
 6177                distance.X,
 6178                distance.Z));
 6179        return true;
 180    }
 181
 182    private static bool ContainsPoint(
 183        Vector2d point,
 184        Signed192 denominator,
 185        ReadOnlySpan<RationalPoint> vertices)
 186    {
 11187        int winding = 0;
 11188        Signed320 pointX = WideArithmetic.MultiplySigned192(
 11189            Signed192.Raw(point.X),
 11190            denominator);
 11191        Signed320 pointZ = WideArithmetic.MultiplySigned192(
 11192            Signed192.Raw(point.Y),
 11193            denominator);
 78194        for (int index = 0; index < vertices.Length; index++)
 195        {
 34196            RationalPoint first = vertices[index];
 34197            RationalPoint second = vertices[
 34198                index + 1 == vertices.Length ? 0 : index + 1];
 34199            Signed576 cross = Cross(
 34200                WideArithmetic.SubtractSigned320(
 34201                    second.X,
 34202                    first.X),
 34203                WideArithmetic.SubtractSigned320(
 34204                    second.Z,
 34205                    first.Z),
 34206                WideArithmetic.SubtractSigned320(
 34207                    pointX,
 34208                    first.X),
 34209                WideArithmetic.SubtractSigned320(
 34210                    pointZ,
 34211                    first.Z));
 34212            int sign = cross.Sign;
 34213            if (sign == 0)
 214                continue;
 26215            if (winding == 0)
 9216                winding = sign;
 17217            else if (winding != sign)
 6218                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) =>
 54330        WideArithmetic.SubtractSigned576(
 54331            WideArithmetic.MultiplySigned320(
 54332                firstX,
 54333                secondZ),
 54334            WideArithmetic.MultiplySigned320(
 54335                firstZ,
 54336                secondX));
 337
 338    private static void KeepCloser(
 339        RationalDistance candidate,
 340        ref RationalDistance best)
 341    {
 19342        if (CompareDistances(candidate, best) < 0)
 5343            best = candidate;
 19344    }
 345
 346    private static int CompareDistances(
 347        RationalDistance first,
 348        RationalDistance second)
 349    {
 19350        Signed832 firstDenominatorSquared =
 19351            WideArithmetic.MultiplySigned576ToSigned832(
 19352                first.Denominator,
 19353                first.Denominator);
 19354        Signed832 secondDenominatorSquared =
 19355            WideArithmetic.MultiplySigned576ToSigned832(
 19356                second.Denominator,
 19357                second.Denominator);
 19358        Span<ulong> firstSquaredMagnitude = stackalloc ulong[13];
 19359        Span<ulong> secondSquaredMagnitude = stackalloc ulong[13];
 19360        Span<ulong> firstDenominatorMagnitude = stackalloc ulong[13];
 19361        Span<ulong> secondDenominatorMagnitude = stackalloc ulong[13];
 19362        WideArithmetic.GetMagnitude(
 19363            first.SquaredDistance,
 19364            firstSquaredMagnitude);
 19365        WideArithmetic.GetMagnitude(
 19366            second.SquaredDistance,
 19367            secondSquaredMagnitude);
 19368        WideArithmetic.GetMagnitude(
 19369            firstDenominatorSquared,
 19370            firstDenominatorMagnitude);
 19371        WideArithmetic.GetMagnitude(
 19372            secondDenominatorSquared,
 19373            secondDenominatorMagnitude);
 19374        Span<ulong> left =
 19375            stackalloc ulong[DistanceComparisonWordCount];
 19376        Span<ulong> right =
 19377            stackalloc ulong[DistanceComparisonWordCount];
 19378        WideArithmetic.MultiplyMagnitudes(
 19379            firstSquaredMagnitude,
 19380            secondDenominatorMagnitude,
 19381            left);
 19382        WideArithmetic.MultiplyMagnitudes(
 19383            secondSquaredMagnitude,
 19384            firstDenominatorMagnitude,
 19385            right);
 19386        return WideArithmetic.CompareMagnitudeEqualLength(
 19387            left,
 19388            right);
 389    }
 390}

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)
AreSegmentEndpointDistancesAtLeast(FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Geometry.FixedSegment2d,FixedMathSharp.Fixed64)
GetRawPoint(FixedMathSharp.Vector2d)
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)