< Summary

Information
Class: GridForge.Spatial.HexCoordinateUtility
Assembly: GridForge
File(s): /home/runner/work/GridForge/GridForge/src/GridForge/Spatial/HexCoordinateUtility.cs
Line coverage
100%
Covered lines: 42
Uncovered lines: 0
Coverable lines: 42
Total lines: 105
Line coverage: 100%
Branch coverage
100%
Covered branches: 12
Total branches: 12
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
AxialToWorldOffset(...)100%22100%
WorldOffsetToAxial(...)100%22100%
RoundAxial(...)100%11100%
RoundCube(...)100%66100%
CeilToIntWithTolerance(...)100%22100%
RoundToInt(...)100%11100%

File(s)

/home/runner/work/GridForge/GridForge/src/GridForge/Spatial/HexCoordinateUtility.cs

#LineLine coverage
 1//=======================================================================
 2// HexCoordinateUtility.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024–present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System;
 9using System.Runtime.CompilerServices;
 10using FixedMathSharp;
 11using GridForge.Grids.Topology;
 12
 13namespace GridForge.Spatial;
 14
 15internal static class HexCoordinateUtility
 16{
 17    internal const long Sqrt3Raw = 7439101574L;
 18
 119    internal static readonly Fixed64 Sqrt3 = Fixed64.FromRaw(Sqrt3Raw);
 20
 121    private static readonly Fixed64 RawRoundingTolerance = Fixed64.FromRaw(4096);
 22
 23    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 24    internal static Vector3d AxialToWorldOffset(VoxelIndex index, GridTopologyMetrics metrics)
 25    {
 271426        Fixed64 q = new(index.x);
 271427        Fixed64 r = new(index.z);
 271428        Fixed64 y = index.y * metrics.LayerHeight;
 29
 271430        if (metrics.HexOrientation == HexOrientation.FlatTop)
 31        {
 107832            return new Vector3d(
 107833                metrics.CellRadius * Fixed64.Three * Fixed64.Half * q,
 107834                y,
 107835                metrics.CellRadius * Sqrt3 * (r + q * Fixed64.Half));
 36        }
 37
 163638        return new Vector3d(
 163639            metrics.CellRadius * Sqrt3 * (q + r * Fixed64.Half),
 163640            y,
 163641            metrics.CellRadius * Fixed64.Three * Fixed64.Half * r);
 42    }
 43
 44    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 45    internal static void WorldOffsetToAxial(
 46        Fixed64 worldX,
 47        Fixed64 worldZ,
 48        GridTopologyMetrics metrics,
 49        out Fixed64 q,
 50        out Fixed64 r)
 51    {
 48752        if (metrics.HexOrientation == HexOrientation.FlatTop)
 53        {
 4954            q = (Fixed64.Two * worldX / Fixed64.Three) / metrics.CellRadius;
 4955            r = ((Sqrt3 * worldZ / Fixed64.Three) - (worldX / Fixed64.Three)) / metrics.CellRadius;
 4956            return;
 57        }
 58
 43859        q = ((Sqrt3 * worldX / Fixed64.Three) - (worldZ / Fixed64.Three)) / metrics.CellRadius;
 43860        r = (Fixed64.Two * worldZ / Fixed64.Three) / metrics.CellRadius;
 43861    }
 62
 63    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 64    internal static VoxelIndex RoundAxial(Fixed64 q, Fixed64 y, Fixed64 r)
 65    {
 12366        RoundCube(q, r, out int roundedQ, out int roundedR);
 12367        return new VoxelIndex(roundedQ, y.FloorToInt(), roundedR);
 68    }
 69
 70    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 71    internal static void RoundCube(Fixed64 q, Fixed64 r, out int roundedQ, out int roundedR)
 72    {
 15773        Fixed64 s = -q - r;
 74
 15775        int qCandidate = RoundToInt(q);
 15776        int rCandidate = RoundToInt(r);
 15777        int sCandidate = RoundToInt(s);
 78
 15779        Fixed64 qDiff = (new Fixed64(qCandidate) - q).Abs();
 15780        Fixed64 rDiff = (new Fixed64(rCandidate) - r).Abs();
 15781        Fixed64 sDiff = (new Fixed64(sCandidate) - s).Abs();
 82
 15783        if (qDiff > rDiff && qDiff > sDiff)
 384            qCandidate = -rCandidate - sCandidate;
 15485        else if (rDiff > sDiff)
 386            rCandidate = -qCandidate - sCandidate;
 87
 15788        roundedQ = qCandidate;
 15789        roundedR = rCandidate;
 15790    }
 91
 92    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 93    internal static int CeilToIntWithTolerance(Fixed64 value)
 94    {
 43595        int rounded = RoundToInt(value);
 43596        if ((new Fixed64(rounded) - value).Abs() <= RawRoundingTolerance)
 41497            return rounded;
 98
 2199        return value.CeilToInt();
 100    }
 101
 102    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 103    private static int RoundToInt(Fixed64 value) =>
 906104        (int)(FixedMath.Round(value, MidpointRounding.AwayFromZero).m_rawValue >> FixedMath.SHIFT_AMOUNT_I);
 105}