< 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 FixedMathSharp;
 9using GridForge.Grids.Topology;
 10using System;
 11using System.Runtime.CompilerServices;
 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    {
 265226        Fixed64 q = new(index.x);
 265227        Fixed64 r = new(index.z);
 265228        Fixed64 y = index.y * metrics.LayerHeight;
 29
 265230        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
 157438        return new Vector3d(
 157439            metrics.CellRadius * Sqrt3 * (q + r * Fixed64.Half),
 157440            y,
 157441            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    {
 39352        if (metrics.HexOrientation == HexOrientation.FlatTop)
 53        {
 5154            q = (Fixed64.Two * worldX / Fixed64.Three) / metrics.CellRadius;
 5155            r = ((Sqrt3 * worldZ / Fixed64.Three) - (worldX / Fixed64.Three)) / metrics.CellRadius;
 5156            return;
 57        }
 58
 34259        q = ((Sqrt3 * worldX / Fixed64.Three) - (worldZ / Fixed64.Three)) / metrics.CellRadius;
 34260        r = (Fixed64.Two * worldZ / Fixed64.Three) / metrics.CellRadius;
 34261    }
 62
 63    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 64    internal static VoxelIndex RoundAxial(Fixed64 q, Fixed64 y, Fixed64 r)
 65    {
 11466        RoundCube(q, r, out int roundedQ, out int roundedR);
 11467        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    {
 13873        Fixed64 s = -q - r;
 74
 13875        int qCandidate = RoundToInt(q);
 13876        int rCandidate = RoundToInt(r);
 13877        int sCandidate = RoundToInt(s);
 78
 13879        Fixed64 qDiff = (new Fixed64(qCandidate) - q).Abs();
 13880        Fixed64 rDiff = (new Fixed64(rCandidate) - r).Abs();
 13881        Fixed64 sDiff = (new Fixed64(sCandidate) - s).Abs();
 82
 13883        if (qDiff > rDiff && qDiff > sDiff)
 384            qCandidate = -rCandidate - sCandidate;
 13585        else if (rDiff > sDiff)
 386            rCandidate = -qCandidate - sCandidate;
 87
 13888        roundedQ = qCandidate;
 13889        roundedR = rCandidate;
 13890    }
 91
 92    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 93    internal static int CeilToIntWithTolerance(Fixed64 value)
 94    {
 37395        int rounded = RoundToInt(value);
 37396        if ((new Fixed64(rounded) - value).Abs() <= RawRoundingTolerance)
 35397            return rounded;
 98
 2099        return value.CeilToInt();
 100    }
 101
 102    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 103    private static int RoundToInt(Fixed64 value) =>
 787104        (int)(FixedMath.Round(value, MidpointRounding.AwayFromZero).m_rawValue >> FixedMath.SHIFT_AMOUNT_I);
 105}