< Summary

Line coverage
100%
Covered lines: 614
Uncovered lines: 0
Coverable lines: 614
Total lines: 1600
Line coverage: 100%
Branch coverage
100%
Covered branches: 160
Total branches: 160
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: .ctor(...)100%11100%
File 1: TraceLine(...)100%44100%
File 1: TraceLineInto(...)100%44100%
File 1: TraceLineInto(...)100%44100%
File 1: TraceLine(...)100%11100%
File 1: TraceLineInto(...)100%11100%
File 1: TraceLineInto(...)100%11100%
File 1: GetCoveredVoxels(...)100%44100%
File 1: GetCoveredVoxels(...)100%11100%
File 1: GetCoveredVoxels(...)100%11100%
File 1: GetCoveredVoxelsInto(...)100%44100%
File 1: GetCoveredVoxelsInto(...)100%11100%
File 1: GetCoveredVoxelsInto(...)100%11100%
File 1: GetCoveredVoxelsInto(...)100%44100%
File 1: GetCoveredVoxelsInto(...)100%11100%
File 1: GetCoveredVoxelsInto(...)100%11100%
File 1: GetCoveredScanCells(...)100%44100%
File 1: GetCoveredScanCells(...)100%11100%
File 1: GetCoveredScanCells(...)100%11100%
File 1: GetCoveredScanCellsInto(...)100%44100%
File 1: GetCoveredScanCellsInto(...)100%11100%
File 1: GetCoveredScanCellsInto(...)100%11100%
File 1: GetCoveredScanCellsInto(...)100%44100%
File 1: GetCoveredScanCellsInto(...)100%11100%
File 1: GetCoveredScanCellsInto(...)100%11100%
File 1: AddCoveredScanCellsTo(...)100%11100%
File 1: AddCoveredScanCellsTo(...)100%11100%
File 1: AddCoveredVoxelsTo(...)100%11100%
File 1: AddCoveredVoxelsTo(...)100%11100%
File 1: AddCoveredVoxelsCore(...)100%22100%
File 1: AddCoveredScanCellsCore(...)100%22100%
File 1: GetCoveredVoxelsIterator()100%22100%
File 1: <>m__Finally1()100%11100%
File 1: AddCoveredVoxelsToMapping(...)100%22100%
File 1: GetCoveredScanCellsIterator()100%22100%
File 1: <>m__Finally1()100%11100%
File 2: AddCoveredScanCellsForGrid(...)100%44100%
File 2: AddCoveredVoxelsForGrid(...)100%22100%
File 2: AddCoveredGridVoxels(...)100%44100%
File 2: AddCoveredHexGridVoxels(...)100%1212100%
File 2: AddCoveredHexScanCellsForGrid(...)100%22100%
File 2: IsHexVoxelCenterInHorizontalCoverage(...)100%66100%
File 3: TraceLineIterator()100%22100%
File 3: <>m__Finally1()100%11100%
File 3: AddTraceLineVoxelsToMapping(...)100%22100%
File 3: AddTraceLineVoxelsTo(...)100%22100%
File 3: CreateTraceLinePlan(...)100%11100%
File 3: CalculateTraceSteps(...)100%11100%
File 3: CreateTraceEndpoint(...)100%11100%
File 3: SelectTraceCoordinate(...)100%22100%
File 3: CreatePaddedOrderedBounds(...)100%1010100%
File 3: ExpandOrderedBounds(...)100%22100%
File 3: TryGetCoveredScanCellRange(...)100%22100%
File 3: AddTraceLineVoxelsForGrid(...)100%44100%
File 3: AddTraceLineVoxelsForGrid(...)100%22100%
File 3: AddTraceLineGridVoxels(...)100%1010100%
File 3: AddHexTraceLineGridVoxels(...)100%66100%
File 3: CreateHexTraceEndpoints(...)100%11100%
File 3: CalculateHexTraceSteps(...)100%11100%
File 3: InterpolateHexTraceIndex(...)100%11100%
File 3: Interpolate(...)100%11100%
File 3: TryClipTraceSegmentToGrid(...)100%1010100%
File 3: ClipTraceSegmentAxis(...)100%1010100%
File 3: ShouldIncludeHexTraceEndIndex(...)100%44100%
File 3: InterpolateTraceSegment(...)100%11100%
File 3: InterpolateTraceAxis(...)100%66100%
File 3: AddTraceVoxelByPosition(...)100%44100%
File 3: AddTraceVoxelByIndex(...)100%44100%
File 3: ReleaseGridVoxelSets(...)100%22100%

File(s)

/home/runner/work/GridForge/GridForge/src/GridForge/Utility/GridTracer.cs

#LineLine coverage
 1//=======================================================================
 2// GridTracer.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.Collections.Generic;
 9using FixedMathSharp;
 10using FixedMathSharp.Geometry;
 11using GridForge.Grids;
 12using GridForge.Spatial;
 13using SwiftCollections;
 14using SwiftCollections.Pool;
 15
 16namespace GridForge.Utility;
 17
 18/// <summary>
 19/// Provides utilities for tracing lines or bounding areas in a grid, aligning them to grid voxels.
 20/// Uses fixed-point calculations to ensure deterministic and accurate grid traversal.
 21/// </summary>
 22public static partial class GridTracer
 23{
 24    private readonly struct TraceLinePlan
 25    {
 26        public readonly Vector3d TraceStart;
 27        public readonly Fixed64 Steps;
 28        public readonly Fixed64 StepX;
 29        public readonly Fixed64 StepY;
 30        public readonly Fixed64 StepZ;
 31
 32        public TraceLinePlan(
 33            Vector3d traceStart,
 34            Fixed64 steps,
 35            Fixed64 stepX,
 36            Fixed64 stepY,
 37            Fixed64 stepZ)
 38        {
 7039            TraceStart = traceStart;
 7040            Steps = steps;
 7041            StepX = stepX;
 7042            StepY = stepY;
 7043            StepZ = stepZ;
 7044        }
 45    }
 46
 47    /// <summary>
 48    /// Traces a 3D line between two points in the supplied world.
 49    /// The traced points are returned as grid voxels.
 50    /// </summary>
 51    /// <remarks>
 52    /// Uses a fractional step algorithm inspired by Bresenham’s line algorithm.
 53    /// This implementation leverages fixed-point math to maintain precision across a deterministic grid.
 54    /// </remarks>
 55    /// <param name="world">The world whose grids should be traced.</param>
 56    /// <param name="start">Starting position in world space.</param>
 57    /// <param name="end">Ending position in world space.</param>
 58    /// <param name="padding">Value applied to the start/end positions before snapping.</param>
 59    /// <param name="includeEnd">Whether to include the end voxel in the traced line.</param>
 60    /// <returns>A collection of <see cref="GridVoxelSet"/> objects representing the traced path.</returns>
 61    public static IEnumerable<GridVoxelSet> TraceLine(
 62        GridWorld world,
 63        Vector3d start,
 64        Vector3d end,
 65        Fixed64? padding = null,
 66        bool includeEnd = true)
 67    {
 4268        if (world == null || !world.IsActive)
 269            return System.Array.Empty<GridVoxelSet>();
 70
 4071        return TraceLineIterator(world, start, end, padding, includeEnd);
 72    }
 73
 74    /// <summary>
 75    /// Clears and fills caller-owned storage with voxels traced by a 3D line.
 76    /// </summary>
 77    /// <param name="world">The world whose grids should be traced.</param>
 78    /// <param name="start">Starting position in world space.</param>
 79    /// <param name="end">Ending position in world space.</param>
 80    /// <param name="results">Caller-owned storage that receives traced voxels.</param>
 81    /// <param name="padding">Value applied to the start/end positions before snapping.</param>
 82    /// <param name="includeEnd">Whether to include the end voxel in the traced line.</param>
 83    public static void TraceLineInto(
 84        GridWorld world,
 85        Vector3d start,
 86        Vector3d end,
 87        SwiftList<Voxel> results,
 88        Fixed64? padding = null,
 89        bool includeEnd = true)
 90    {
 591        SwiftThrowHelper.ThrowIfNull(results, nameof(results));
 92
 493        results.Clear();
 494        if (world == null || !world.IsActive)
 195            return;
 96
 397        SwiftHashSet<Voxel> voxelRedundancyCheck = SwiftHashSetPool<Voxel>.Shared.Rent();
 398        SwiftList<ushort> candidateGrids = SwiftListPool<ushort>.Shared.Rent();
 99
 100        try
 101        {
 3102            AddTraceLineVoxelsTo(
 3103                world,
 3104                start,
 3105                end,
 3106                padding,
 3107                includeEnd,
 3108                results,
 3109                voxelRedundancyCheck,
 3110                candidateGrids);
 111
 3112        }
 113        finally
 114        {
 3115            SwiftHashSetPool<Voxel>.Shared.Release(voxelRedundancyCheck);
 3116            SwiftListPool<ushort>.Shared.Release(candidateGrids);
 3117        }
 3118    }
 119
 120    /// <summary>
 121    /// Clears and fills caller-owned storage with voxels traced by a 3D line using caller-owned scratch collections.
 122    /// </summary>
 123    /// <param name="world">The world whose grids should be traced.</param>
 124    /// <param name="start">Starting position in world space.</param>
 125    /// <param name="end">Ending position in world space.</param>
 126    /// <param name="results">Caller-owned storage that receives traced voxels.</param>
 127    /// <param name="scratch">Reusable scratch storage for grid candidates and duplicate-voxel guards.</param>
 128    /// <param name="padding">Value applied to the start/end positions before snapping.</param>
 129    /// <param name="includeEnd">Whether to include the end voxel in the traced line.</param>
 130    public static void TraceLineInto(
 131        GridWorld world,
 132        Vector3d start,
 133        Vector3d end,
 134        SwiftList<Voxel> results,
 135        GridTraceScratch scratch,
 136        Fixed64? padding = null,
 137        bool includeEnd = true)
 138    {
 11139        SwiftThrowHelper.ThrowIfNull(results, nameof(results));
 10140        SwiftThrowHelper.ThrowIfNull(scratch, nameof(scratch));
 141
 9142        results.Clear();
 9143        if (world == null || !world.IsActive)
 2144            return;
 145
 7146        scratch.Clear();
 7147        AddTraceLineVoxelsTo(
 7148            world,
 7149            start,
 7150            end,
 7151            padding,
 7152            includeEnd,
 7153            results,
 7154            scratch.VoxelRedundancy,
 7155            scratch.CandidateGrids);
 156
 7157    }
 158
 159    /// <summary>
 160    /// Traces a 2D XZ-plane line between two points in the supplied world, snapping them to grid coordinates.
 161    /// </summary>
 162    /// <remarks>
 163    /// This method maps <see cref="Vector2d.X"/> to world X, <see cref="Vector2d.Y"/> to world Z,
 164    /// and <paramref name="layerY"/> to world Y. The default layer is world Y = 0.
 165    /// </remarks>
 166    /// <param name="world">The world whose grids should be traced.</param>
 167    /// <param name="start">Starting XZ-plane position in world space.</param>
 168    /// <param name="end">Ending XZ-plane position in world space.</param>
 169    /// <param name="padding">Value applied to the start/end positions before snapping.</param>
 170    /// <param name="includeEnd">Whether to include the end voxel in the traced line.</param>
 171    /// <param name="layerY">The world Y layer to trace. Defaults to zero.</param>
 172    /// <returns>A collection of <see cref="GridVoxelSet"/> objects representing the traced path.</returns>
 173    public static IEnumerable<GridVoxelSet> TraceLine(
 174        GridWorld world,
 175        Vector2d start,
 176        Vector2d end,
 177        Fixed64? padding = null,
 178        bool includeEnd = true,
 179        Fixed64 layerY = default)
 180    {
 4181        Vector3d start3D = GridPlane2d.ToWorld(start, layerY);
 4182        Vector3d end3D = GridPlane2d.ToWorld(end, layerY);
 183
 4184        return TraceLine(world, start3D, end3D, padding, includeEnd);
 185    }
 186
 187    /// <summary>
 188    /// Clears and fills caller-owned storage with voxels traced by a 2D XZ-plane line.
 189    /// </summary>
 190    /// <param name="world">The world whose grids should be traced.</param>
 191    /// <param name="start">Starting XZ-plane position in world space.</param>
 192    /// <param name="end">Ending XZ-plane position in world space.</param>
 193    /// <param name="results">Caller-owned storage that receives traced voxels.</param>
 194    /// <param name="padding">Value applied to the start/end positions before snapping.</param>
 195    /// <param name="includeEnd">Whether to include the end voxel in the traced line.</param>
 196    /// <param name="layerY">The world Y layer to trace. Defaults to zero.</param>
 197    public static void TraceLineInto(
 198        GridWorld world,
 199        Vector2d start,
 200        Vector2d end,
 201        SwiftList<Voxel> results,
 202        Fixed64? padding = null,
 203        bool includeEnd = true,
 204        Fixed64 layerY = default)
 205    {
 1206        Vector3d start3D = GridPlane2d.ToWorld(start, layerY);
 1207        Vector3d end3D = GridPlane2d.ToWorld(end, layerY);
 208
 1209        TraceLineInto(world, start3D, end3D, results, padding, includeEnd);
 1210    }
 211
 212    /// <summary>
 213    /// Clears and fills caller-owned storage with voxels traced by a 2D XZ-plane line using caller-owned scratch collec
 214    /// </summary>
 215    /// <param name="world">The world whose grids should be traced.</param>
 216    /// <param name="start">Starting XZ-plane position in world space.</param>
 217    /// <param name="end">Ending XZ-plane position in world space.</param>
 218    /// <param name="results">Caller-owned storage that receives traced voxels.</param>
 219    /// <param name="scratch">Reusable scratch storage for grid candidates and duplicate-voxel guards.</param>
 220    /// <param name="padding">Value applied to the start/end positions before snapping.</param>
 221    /// <param name="includeEnd">Whether to include the end voxel in the traced line.</param>
 222    /// <param name="layerY">The world Y layer to trace. Defaults to zero.</param>
 223    public static void TraceLineInto(
 224        GridWorld world,
 225        Vector2d start,
 226        Vector2d end,
 227        SwiftList<Voxel> results,
 228        GridTraceScratch scratch,
 229        Fixed64? padding = null,
 230        bool includeEnd = true,
 231        Fixed64 layerY = default)
 232    {
 1233        Vector3d start3D = GridPlane2d.ToWorld(start, layerY);
 1234        Vector3d end3D = GridPlane2d.ToWorld(end, layerY);
 235
 1236        TraceLineInto(world, start3D, end3D, results, scratch, padding, includeEnd);
 1237    }
 238
 239    /// <summary>
 240    /// Retrieves all grid voxels covered by the given bounding area in the supplied world.
 241    /// </summary>
 242    public static IEnumerable<GridVoxelSet> GetCoveredVoxels(
 243        GridWorld world,
 244        Vector3d boundsMin,
 245        Vector3d boundsMax,
 246        Fixed64? padding = null)
 247    {
 204248        if (world == null || !world.IsActive)
 2249            return System.Array.Empty<GridVoxelSet>();
 250
 202251        return GetCoveredVoxelsIterator(world, boundsMin, boundsMax, padding);
 252    }
 253
 254    /// <summary>
 255    /// Retrieves all grid voxels covered by the given XZ-plane bounding area on the supplied world Y layer.
 256    /// </summary>
 257    /// <param name="world">The world whose grids should be queried.</param>
 258    /// <param name="boundsMin">The 2D minimum corner whose X component maps to world X and Y component maps to world Z.
 259    /// <param name="boundsMax">The 2D maximum corner whose X component maps to world X and Y component maps to world Z.
 260    /// <param name="layerY">The world Y layer to cover. Defaults to zero.</param>
 261    /// <param name="padding">Value applied to the min/max bounds before snapping.</param>
 262    /// <returns>A collection of <see cref="GridVoxelSet"/> objects representing the covered voxels.</returns>
 263    public static IEnumerable<GridVoxelSet> GetCoveredVoxels(
 264        GridWorld world,
 265        Vector2d boundsMin,
 266        Vector2d boundsMax,
 267        Fixed64 layerY = default,
 268        Fixed64? padding = null)
 269    {
 5270        (Vector3d min, Vector3d max) = GridPlane2d.ToWorldBounds(boundsMin, boundsMax, layerY);
 5271        return GetCoveredVoxels(world, min, max, padding);
 272    }
 273
 274    /// <summary>
 275    /// Retrieves all grid voxels covered by the given XZ-plane area on the supplied world Y layer.
 276    /// </summary>
 277    /// <param name="world">The world whose grids should be queried.</param>
 278    /// <param name="area">The 2D area whose X component maps to world X and Y component maps to world Z.</param>
 279    /// <param name="layerY">The world Y layer to cover. Defaults to zero.</param>
 280    /// <param name="padding">Value applied to the min/max bounds before snapping.</param>
 281    /// <returns>A collection of <see cref="GridVoxelSet"/> objects representing the covered voxels.</returns>
 282    public static IEnumerable<GridVoxelSet> GetCoveredVoxels(
 283        GridWorld world,
 284        FixedBoundArea area,
 285        Fixed64 layerY = default,
 286        Fixed64? padding = null)
 287    {
 1288        return GetCoveredVoxels(world, area.Min, area.Max, layerY, padding);
 289    }
 290
 291    /// <summary>
 292    /// Clears and fills caller-owned storage with voxels covered by the supplied bounding area.
 293    /// </summary>
 294    /// <param name="world">The world whose grids should be queried.</param>
 295    /// <param name="boundsMin">The minimum corner of the bounding area.</param>
 296    /// <param name="boundsMax">The maximum corner of the bounding area.</param>
 297    /// <param name="results">Caller-owned storage that receives covered voxels.</param>
 298    /// <param name="padding">Value applied to the min/max bounds before normalization.</param>
 299    public static void GetCoveredVoxelsInto(
 300        GridWorld world,
 301        Vector3d boundsMin,
 302        Vector3d boundsMax,
 303        SwiftList<Voxel> results,
 304        Fixed64? padding = null)
 305    {
 5306        SwiftThrowHelper.ThrowIfNull(results, nameof(results));
 307
 4308        results.Clear();
 4309        if (world == null || !world.IsActive)
 1310            return;
 311
 3312        AddCoveredVoxelsTo(world, boundsMin, boundsMax, results, padding);
 3313    }
 314
 315    /// <summary>
 316    /// Clears and fills caller-owned storage with voxels covered by the supplied XZ-plane bounding area.
 317    /// </summary>
 318    /// <param name="world">The world whose grids should be queried.</param>
 319    /// <param name="boundsMin">The 2D minimum corner whose X component maps to world X and Y component maps to world Z.
 320    /// <param name="boundsMax">The 2D maximum corner whose X component maps to world X and Y component maps to world Z.
 321    /// <param name="results">Caller-owned storage that receives covered voxels.</param>
 322    /// <param name="layerY">The world Y layer to cover. Defaults to zero.</param>
 323    /// <param name="padding">Value applied to the min/max bounds before normalization.</param>
 324    public static void GetCoveredVoxelsInto(
 325        GridWorld world,
 326        Vector2d boundsMin,
 327        Vector2d boundsMax,
 328        SwiftList<Voxel> results,
 329        Fixed64 layerY = default,
 330        Fixed64? padding = null)
 331    {
 2332        (Vector3d min, Vector3d max) = GridPlane2d.ToWorldBounds(boundsMin, boundsMax, layerY);
 2333        GetCoveredVoxelsInto(world, min, max, results, padding);
 2334    }
 335
 336    /// <summary>
 337    /// Clears and fills caller-owned storage with voxels covered by the supplied XZ-plane area.
 338    /// </summary>
 339    /// <param name="world">The world whose grids should be queried.</param>
 340    /// <param name="area">The 2D area whose X component maps to world X and Y component maps to world Z.</param>
 341    /// <param name="results">Caller-owned storage that receives covered voxels.</param>
 342    /// <param name="layerY">The world Y layer to cover. Defaults to zero.</param>
 343    /// <param name="padding">Value applied to the min/max bounds before normalization.</param>
 344    public static void GetCoveredVoxelsInto(
 345        GridWorld world,
 346        FixedBoundArea area,
 347        SwiftList<Voxel> results,
 348        Fixed64 layerY = default,
 349        Fixed64? padding = null)
 350    {
 1351        GetCoveredVoxelsInto(world, area.Min, area.Max, results, layerY, padding);
 1352    }
 353
 354    /// <summary>
 355    /// Clears and fills caller-owned storage using caller-owned scratch collections.
 356    /// </summary>
 357    /// <param name="world">The world whose grids should be queried.</param>
 358    /// <param name="boundsMin">The minimum corner of the bounding area.</param>
 359    /// <param name="boundsMax">The maximum corner of the bounding area.</param>
 360    /// <param name="results">Caller-owned storage that receives covered voxels.</param>
 361    /// <param name="scratch">Reusable scratch storage for grid candidates and duplicate-voxel guards.</param>
 362    /// <param name="padding">Value applied to the min/max bounds before normalization.</param>
 363    public static void GetCoveredVoxelsInto(
 364        GridWorld world,
 365        Vector3d boundsMin,
 366        Vector3d boundsMax,
 367        SwiftList<Voxel> results,
 368        GridTraceScratch scratch,
 369        Fixed64? padding = null)
 370    {
 18371        SwiftThrowHelper.ThrowIfNull(results, nameof(results));
 17372        SwiftThrowHelper.ThrowIfNull(scratch, nameof(scratch));
 373
 16374        results.Clear();
 16375        if (world == null || !world.IsActive)
 2376            return;
 377
 14378        AddCoveredVoxelsTo(world, boundsMin, boundsMax, results, scratch, padding);
 14379    }
 380
 381    /// <summary>
 382    /// Clears and fills caller-owned storage using caller-owned scratch collections for an XZ-plane bounding area.
 383    /// </summary>
 384    /// <param name="world">The world whose grids should be queried.</param>
 385    /// <param name="boundsMin">The 2D minimum corner whose X component maps to world X and Y component maps to world Z.
 386    /// <param name="boundsMax">The 2D maximum corner whose X component maps to world X and Y component maps to world Z.
 387    /// <param name="results">Caller-owned storage that receives covered voxels.</param>
 388    /// <param name="scratch">Reusable scratch storage for grid candidates and duplicate-voxel guards.</param>
 389    /// <param name="layerY">The world Y layer to cover. Defaults to zero.</param>
 390    /// <param name="padding">Value applied to the min/max bounds before normalization.</param>
 391    public static void GetCoveredVoxelsInto(
 392        GridWorld world,
 393        Vector2d boundsMin,
 394        Vector2d boundsMax,
 395        SwiftList<Voxel> results,
 396        GridTraceScratch scratch,
 397        Fixed64 layerY = default,
 398        Fixed64? padding = null)
 399    {
 2400        (Vector3d min, Vector3d max) = GridPlane2d.ToWorldBounds(boundsMin, boundsMax, layerY);
 2401        GetCoveredVoxelsInto(world, min, max, results, scratch, padding);
 2402    }
 403
 404    /// <summary>
 405    /// Clears and fills caller-owned storage using caller-owned scratch collections for an XZ-plane area.
 406    /// </summary>
 407    /// <param name="world">The world whose grids should be queried.</param>
 408    /// <param name="area">The 2D area whose X component maps to world X and Y component maps to world Z.</param>
 409    /// <param name="results">Caller-owned storage that receives covered voxels.</param>
 410    /// <param name="scratch">Reusable scratch storage for grid candidates and duplicate-voxel guards.</param>
 411    /// <param name="layerY">The world Y layer to cover. Defaults to zero.</param>
 412    /// <param name="padding">Value applied to the min/max bounds before normalization.</param>
 413    public static void GetCoveredVoxelsInto(
 414        GridWorld world,
 415        FixedBoundArea area,
 416        SwiftList<Voxel> results,
 417        GridTraceScratch scratch,
 418        Fixed64 layerY = default,
 419        Fixed64? padding = null)
 420    {
 1421        GetCoveredVoxelsInto(world, area.Min, area.Max, results, scratch, layerY, padding);
 1422    }
 423
 424    /// <summary>
 425    /// Retrieves all scan cells within the given bounding area across relevant grids in the supplied world.
 426    /// </summary>
 427    /// <param name="world">The world whose grids should be queried.</param>
 428    /// <param name="boundsMin">The minimum corner of the bounding area.</param>
 429    /// <param name="boundsMax">The maximum corner of the bounding area.</param>
 430    /// <param name="padding">Value applied to the min/max bounds before snapping.</param>
 431    /// <returns>An enumerable of covered scan cells grouped by grid.</returns>
 432    public static IEnumerable<ScanCell> GetCoveredScanCells(
 433        GridWorld world,
 434        Vector3d boundsMin,
 435        Vector3d boundsMax,
 436        Fixed64? padding = null)
 437    {
 20438        if (world == null || !world.IsActive)
 2439            return System.Array.Empty<ScanCell>();
 440
 18441        return GetCoveredScanCellsIterator(world, boundsMin, boundsMax, padding);
 442    }
 443
 444    /// <summary>
 445    /// Retrieves all scan cells within the given XZ-plane bounding area on the supplied world Y layer.
 446    /// </summary>
 447    /// <param name="world">The world whose grids should be queried.</param>
 448    /// <param name="boundsMin">The 2D minimum corner whose X component maps to world X and Y component maps to world Z.
 449    /// <param name="boundsMax">The 2D maximum corner whose X component maps to world X and Y component maps to world Z.
 450    /// <param name="layerY">The world Y layer to cover. Defaults to zero.</param>
 451    /// <param name="padding">Value applied to the min/max bounds before snapping.</param>
 452    /// <returns>An enumerable of covered scan cells grouped by grid.</returns>
 453    public static IEnumerable<ScanCell> GetCoveredScanCells(
 454        GridWorld world,
 455        Vector2d boundsMin,
 456        Vector2d boundsMax,
 457        Fixed64 layerY = default,
 458        Fixed64? padding = null)
 459    {
 3460        (Vector3d min, Vector3d max) = GridPlane2d.ToWorldBounds(boundsMin, boundsMax, layerY);
 3461        return GetCoveredScanCells(world, min, max, padding);
 462    }
 463
 464    /// <summary>
 465    /// Retrieves all scan cells within the given XZ-plane area on the supplied world Y layer.
 466    /// </summary>
 467    /// <param name="world">The world whose grids should be queried.</param>
 468    /// <param name="area">The 2D area whose X component maps to world X and Y component maps to world Z.</param>
 469    /// <param name="layerY">The world Y layer to cover. Defaults to zero.</param>
 470    /// <param name="padding">Value applied to the min/max bounds before snapping.</param>
 471    /// <returns>An enumerable of covered scan cells grouped by grid.</returns>
 472    public static IEnumerable<ScanCell> GetCoveredScanCells(
 473        GridWorld world,
 474        FixedBoundArea area,
 475        Fixed64 layerY = default,
 476        Fixed64? padding = null)
 477    {
 1478        return GetCoveredScanCells(world, area.Min, area.Max, layerY, padding);
 479    }
 480
 481    /// <summary>
 482    /// Clears and fills caller-owned storage with scan cells covered by the supplied bounding area.
 483    /// </summary>
 484    public static void GetCoveredScanCellsInto(
 485        GridWorld world,
 486        Vector3d boundsMin,
 487        Vector3d boundsMax,
 488        SwiftList<ScanCell> results,
 489        Fixed64? padding = null)
 490    {
 6491        SwiftThrowHelper.ThrowIfNull(results, nameof(results));
 492
 5493        results.Clear();
 5494        if (world == null || !world.IsActive)
 2495            return;
 496
 3497        AddCoveredScanCellsTo(world, boundsMin, boundsMax, results, padding);
 3498    }
 499
 500    /// <summary>
 501    /// Clears and fills caller-owned storage with scan cells covered by the supplied XZ-plane bounding area.
 502    /// </summary>
 503    public static void GetCoveredScanCellsInto(
 504        GridWorld world,
 505        Vector2d boundsMin,
 506        Vector2d boundsMax,
 507        SwiftList<ScanCell> results,
 508        Fixed64 layerY = default,
 509        Fixed64? padding = null)
 510    {
 2511        (Vector3d min, Vector3d max) = GridPlane2d.ToWorldBounds(boundsMin, boundsMax, layerY);
 2512        GetCoveredScanCellsInto(world, min, max, results, padding);
 2513    }
 514
 515    /// <summary>
 516    /// Clears and fills caller-owned storage with scan cells covered by the supplied XZ-plane area.
 517    /// </summary>
 518    public static void GetCoveredScanCellsInto(
 519        GridWorld world,
 520        FixedBoundArea area,
 521        SwiftList<ScanCell> results,
 522        Fixed64 layerY = default,
 523        Fixed64? padding = null)
 524    {
 1525        GetCoveredScanCellsInto(world, area.Min, area.Max, results, layerY, padding);
 1526    }
 527
 528    /// <summary>
 529    /// Clears and fills caller-owned storage using caller-owned scratch collections.
 530    /// </summary>
 531    public static void GetCoveredScanCellsInto(
 532        GridWorld world,
 533        Vector3d boundsMin,
 534        Vector3d boundsMax,
 535        SwiftList<ScanCell> results,
 536        GridScanScratch scratch,
 537        Fixed64? padding = null)
 538    {
 14539        SwiftThrowHelper.ThrowIfNull(results, nameof(results));
 13540        SwiftThrowHelper.ThrowIfNull(scratch, nameof(scratch));
 541
 12542        results.Clear();
 12543        if (world == null || !world.IsActive)
 2544            return;
 545
 10546        AddCoveredScanCellsTo(world, boundsMin, boundsMax, results, scratch, padding);
 10547    }
 548
 549    /// <summary>
 550    /// Clears and fills caller-owned storage using caller-owned scratch collections for an XZ-plane bounding area.
 551    /// </summary>
 552    public static void GetCoveredScanCellsInto(
 553        GridWorld world,
 554        Vector2d boundsMin,
 555        Vector2d boundsMax,
 556        SwiftList<ScanCell> results,
 557        GridScanScratch scratch,
 558        Fixed64 layerY = default,
 559        Fixed64? padding = null)
 560    {
 2561        (Vector3d min, Vector3d max) = GridPlane2d.ToWorldBounds(boundsMin, boundsMax, layerY);
 2562        GetCoveredScanCellsInto(world, min, max, results, scratch, padding);
 2563    }
 564
 565    /// <summary>
 566    /// Clears and fills caller-owned storage using caller-owned scratch collections for an XZ-plane area.
 567    /// </summary>
 568    public static void GetCoveredScanCellsInto(
 569        GridWorld world,
 570        FixedBoundArea area,
 571        SwiftList<ScanCell> results,
 572        GridScanScratch scratch,
 573        Fixed64 layerY = default,
 574        Fixed64? padding = null)
 575    {
 1576        GetCoveredScanCellsInto(world, area.Min, area.Max, results, scratch, layerY, padding);
 1577    }
 578
 579    /// <summary>
 580    /// Appends covered scan cells without allocating an iterator for hot-path callers.
 581    /// </summary>
 582    internal static void AddCoveredScanCellsTo(
 583        GridWorld world,
 584        Vector3d boundsMin,
 585        Vector3d boundsMax,
 586        SwiftList<ScanCell> scanCells,
 587        Fixed64? padding = null)
 588    {
 21589        SwiftHashSet<ScanCell> voxelRedundancyCheck = SwiftHashSetPool<ScanCell>.Shared.Rent();
 21590        SwiftList<ushort> candidateGrids = SwiftListPool<ushort>.Shared.Rent();
 591
 592        try
 593        {
 21594            AddCoveredScanCellsCore(
 21595                world,
 21596                boundsMin,
 21597                boundsMax,
 21598                scanCells,
 21599                candidateGrids,
 21600                voxelRedundancyCheck,
 21601                padding);
 21602        }
 603        finally
 604        {
 21605            SwiftHashSetPool<ScanCell>.Shared.Release(voxelRedundancyCheck);
 21606            SwiftListPool<ushort>.Shared.Release(candidateGrids);
 21607        }
 21608    }
 609
 610    /// <summary>
 611    /// Appends covered scan cells using caller-owned scratch state for allocation-sensitive scans.
 612    /// </summary>
 613    internal static void AddCoveredScanCellsTo(
 614        GridWorld world,
 615        Vector3d boundsMin,
 616        Vector3d boundsMax,
 617        SwiftList<ScanCell> scanCells,
 618        GridScanScratch scratch,
 619        Fixed64? padding = null)
 620    {
 528621        scratch.Clear();
 528622        AddCoveredScanCellsCore(
 528623            world,
 528624            boundsMin,
 528625            boundsMax,
 528626            scanCells,
 528627            scratch.CandidateGrids,
 528628            scratch.ScanCellRedundancy,
 528629            padding);
 528630    }
 631
 632    /// <summary>
 633    /// Appends covered voxels without allocating an iterator for hot-path callers.
 634    /// </summary>
 635    internal static void AddCoveredVoxelsTo(
 636        GridWorld world,
 637        Vector3d boundsMin,
 638        Vector3d boundsMax,
 639        SwiftList<Voxel> voxels,
 640        Fixed64? padding = null)
 641    {
 3642        SwiftHashSet<Voxel> voxelRedundancyCheck = SwiftHashSetPool<Voxel>.Shared.Rent();
 3643        SwiftList<ushort> candidateGrids = SwiftListPool<ushort>.Shared.Rent();
 644
 645        try
 646        {
 3647            AddCoveredVoxelsCore(
 3648                world,
 3649                boundsMin,
 3650                boundsMax,
 3651                voxels,
 3652                candidateGrids,
 3653                voxelRedundancyCheck,
 3654                padding);
 3655        }
 656        finally
 657        {
 3658            SwiftHashSetPool<Voxel>.Shared.Release(voxelRedundancyCheck);
 3659            SwiftListPool<ushort>.Shared.Release(candidateGrids);
 3660        }
 3661    }
 662
 663    /// <summary>
 664    /// Appends covered voxels using caller-owned scratch state for allocation-sensitive coverage scans.
 665    /// </summary>
 666    internal static void AddCoveredVoxelsTo(
 667        GridWorld world,
 668        Vector3d boundsMin,
 669        Vector3d boundsMax,
 670        SwiftList<Voxel> voxels,
 671        GridTraceScratch scratch,
 672        Fixed64? padding = null)
 673    {
 14674        scratch.Clear();
 14675        AddCoveredVoxelsCore(
 14676            world,
 14677            boundsMin,
 14678            boundsMax,
 14679            voxels,
 14680            scratch.CandidateGrids,
 14681            scratch.VoxelRedundancy,
 14682            padding);
 14683    }
 684
 685    private static void AddCoveredVoxelsCore(
 686        GridWorld world,
 687        Vector3d boundsMin,
 688        Vector3d boundsMax,
 689        SwiftList<Voxel> voxels,
 690        SwiftList<ushort> candidateGrids,
 691        SwiftHashSet<Voxel> voxelRedundancyCheck,
 692        Fixed64? padding = null)
 693    {
 17694        (Vector3d queryMin, Vector3d queryMax) =
 17695            CreatePaddedOrderedBounds(boundsMin, boundsMax, padding);
 17696        (Vector3d candidateMin, Vector3d candidateMax) =
 17697            ExpandOrderedBounds(queryMin, queryMax, world.MaxTopologyCellEdge);
 698
 17699        world.CollectGridCandidates(candidateMin, candidateMax, candidateGrids);
 106700        foreach (ushort gridIndex in candidateGrids)
 701        {
 36702            AddCoveredGridVoxels(
 36703                world.ActiveGrids[gridIndex],
 36704                queryMin,
 36705                queryMax,
 36706                voxels,
 36707                voxelRedundancyCheck);
 708        }
 17709    }
 710
 711    private static void AddCoveredScanCellsCore(
 712        GridWorld world,
 713        Vector3d boundsMin,
 714        Vector3d boundsMax,
 715        SwiftList<ScanCell> scanCells,
 716        SwiftList<ushort> candidateGrids,
 717        SwiftHashSet<ScanCell> voxelRedundancyCheck,
 718        Fixed64? padding = null)
 719    {
 567720        (Vector3d queryMin, Vector3d queryMax) =
 567721            CreatePaddedOrderedBounds(boundsMin, boundsMax, padding);
 567722        (Vector3d candidateMin, Vector3d candidateMax) =
 567723            ExpandOrderedBounds(queryMin, queryMax, world.MaxTopologyCellEdge);
 567724        world.CollectGridCandidates(candidateMin, candidateMax, candidateGrids);
 2332725        foreach (ushort gridIndex in candidateGrids)
 726        {
 599727            AddCoveredScanCellsForGrid(
 599728                world.ActiveGrids[gridIndex],
 599729                queryMin,
 599730                queryMax,
 599731                scanCells,
 599732                voxelRedundancyCheck);
 733        }
 567734    }
 735
 736    private static IEnumerable<GridVoxelSet> GetCoveredVoxelsIterator(
 737        GridWorld world,
 738        Vector3d boundsMin,
 739        Vector3d boundsMax,
 740        Fixed64? padding)
 741    {
 202742        SwiftList<GridVoxelSet> gridVoxelSets = SwiftListPool<GridVoxelSet>.Shared.Rent();
 202743        SwiftHashSet<Voxel> voxelRedundancyCheck = SwiftHashSetPool<Voxel>.Shared.Rent();
 202744        SwiftList<ushort> candidateGrids = SwiftListPool<ushort>.Shared.Rent();
 745
 746        try
 747        {
 202748            AddCoveredVoxelsToMapping(
 202749                world,
 202750                boundsMin,
 202751                boundsMax,
 202752                padding,
 202753                gridVoxelSets,
 202754                voxelRedundancyCheck,
 202755                candidateGrids);
 756
 834757            foreach (GridVoxelSet gridVoxelSet in gridVoxelSets)
 215758                yield return gridVoxelSet;
 202759        }
 760        finally
 761        {
 202762            ReleaseGridVoxelSets(gridVoxelSets);
 202763            SwiftHashSetPool<Voxel>.Shared.Release(voxelRedundancyCheck);
 202764            SwiftListPool<ushort>.Shared.Release(candidateGrids);
 202765        }
 202766    }
 767
 768    private static void AddCoveredVoxelsToMapping(
 769        GridWorld world,
 770        Vector3d boundsMin,
 771        Vector3d boundsMax,
 772        Fixed64? padding,
 773        SwiftList<GridVoxelSet> gridVoxelSets,
 774        SwiftHashSet<Voxel> voxelRedundancyCheck,
 775        SwiftList<ushort> candidateGrids)
 776    {
 202777        (Vector3d queryMin, Vector3d queryMax) =
 202778            CreatePaddedOrderedBounds(boundsMin, boundsMax, padding);
 202779        (Vector3d candidateMin, Vector3d candidateMax) =
 202780            ExpandOrderedBounds(queryMin, queryMax, world.MaxTopologyCellEdge);
 781
 202782        world.CollectGridCandidates(candidateMin, candidateMax, candidateGrids);
 842783        foreach (ushort gridIndex in candidateGrids)
 784        {
 219785            AddCoveredVoxelsForGrid(
 219786                world.ActiveGrids[gridIndex],
 219787                queryMin,
 219788                queryMax,
 219789                gridVoxelSets,
 219790                voxelRedundancyCheck);
 791        }
 202792    }
 793
 794    private static IEnumerable<ScanCell> GetCoveredScanCellsIterator(
 795        GridWorld world,
 796        Vector3d boundsMin,
 797        Vector3d boundsMax,
 798        Fixed64? padding)
 799    {
 18800        SwiftList<ScanCell> scanCells = SwiftListPool<ScanCell>.Shared.Rent();
 18801        SwiftHashSet<ScanCell> voxelRedundancyCheck = SwiftHashSetPool<ScanCell>.Shared.Rent();
 18802        SwiftList<ushort> candidateGrids = SwiftListPool<ushort>.Shared.Rent();
 803
 804        try
 805        {
 18806            AddCoveredScanCellsCore(
 18807                world,
 18808                boundsMin,
 18809                boundsMax,
 18810                scanCells,
 18811                candidateGrids,
 18812                voxelRedundancyCheck,
 18813                padding);
 814
 202815            foreach (ScanCell scanCell in scanCells)
 83816                yield return scanCell;
 18817        }
 818        finally
 819        {
 18820            SwiftListPool<ScanCell>.Shared.Release(scanCells);
 18821            SwiftHashSetPool<ScanCell>.Shared.Release(voxelRedundancyCheck);
 18822            SwiftListPool<ushort>.Shared.Release(candidateGrids);
 18823        }
 18824    }
 825}

/home/runner/work/GridForge/GridForge/src/GridForge/Utility/GridTracer.GridCoverage.cs

#LineLine coverage
 1//=======================================================================
 2// GridTracer.GridCoverage.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.Runtime.CompilerServices;
 9using FixedMathSharp;
 10using GridForge.Grids;
 11using GridForge.Grids.Topology;
 12using GridForge.Spatial;
 13using SwiftCollections;
 14using SwiftCollections.Pool;
 15
 16namespace GridForge.Utility;
 17
 18/// <content>
 19/// Grid coverage utilities for resolving scan cells and voxels that intersect
 20/// a given world-space query bounds, including specialized handling for hex-prism topologies.
 21/// </content>
 22public static partial class GridTracer
 23{
 24    private static void AddCoveredScanCellsForGrid(
 25        VoxelGrid currentGrid,
 26        Vector3d queryMin,
 27        Vector3d queryMax,
 28        SwiftList<ScanCell> scanCells,
 29        SwiftHashSet<ScanCell> voxelRedundancyCheck)
 30    {
 59931        if (currentGrid.Topology.Kind == GridTopologyKind.HexPrism)
 32        {
 733            AddCoveredHexScanCellsForGrid(
 734                currentGrid,
 735                queryMin,
 736                queryMax,
 737                scanCells,
 738                voxelRedundancyCheck);
 739            return;
 40        }
 41
 59242        if (!TryGetCoveredScanCellRange(
 59243                currentGrid,
 59244                queryMin,
 59245                queryMax,
 59246                out int xMin,
 59247                out int yMin,
 59248                out int zMin,
 59249                out int xMax,
 59250                out int yMax,
 59251                out int zMax))
 52        {
 153            return;
 54        }
 55
 59156        currentGrid.AddScanCellsInRange(
 59157            xMin,
 59158            yMin,
 59159            zMin,
 59160            xMax,
 59161            yMax,
 59162            zMax,
 59163            scanCells,
 59164            voxelRedundancyCheck);
 59165    }
 66
 67    private static void AddCoveredVoxelsForGrid(
 68        VoxelGrid currentGrid,
 69        Vector3d queryMin,
 70        Vector3d queryMax,
 71        SwiftList<GridVoxelSet> gridVoxelSets,
 72        SwiftHashSet<Voxel> voxelRedundancyCheck)
 73    {
 21974        SwiftList<Voxel> voxelList = SwiftListPool<Voxel>.Shared.Rent();
 21975        AddCoveredGridVoxels(
 21976            currentGrid,
 21977            queryMin,
 21978            queryMax,
 21979            voxelList,
 21980            voxelRedundancyCheck);
 81
 21982        if (voxelList.Count > 0)
 21583            gridVoxelSets.Add(new GridVoxelSet(currentGrid, voxelList));
 84        else
 485            SwiftListPool<Voxel>.Shared.Release(voxelList);
 486    }
 87
 88    private static void AddCoveredGridVoxels(
 89        VoxelGrid currentGrid,
 90        Vector3d queryMin,
 91        Vector3d queryMax,
 92        SwiftList<Voxel> voxelList,
 93        SwiftHashSet<Voxel> voxelRedundancyCheck)
 94    {
 25595        if (currentGrid.Topology.Kind == GridTopologyKind.HexPrism)
 96        {
 997            AddCoveredHexGridVoxels(
 998                currentGrid,
 999                queryMin,
 9100                queryMax,
 9101                voxelList);
 9102            return;
 103        }
 104
 246105        if (!TopologyVoxelRangeUtility.TryGetCandidateRange(
 246106                currentGrid,
 246107                queryMin,
 246108                queryMax,
 246109                out VoxelIndex minIndex,
 246110                out VoxelIndex maxIndex))
 111        {
 1112            return;
 113        }
 114
 245115        currentGrid.AddVoxelsInIndexRange(
 245116            minIndex,
 245117            maxIndex,
 245118            voxelList,
 245119            voxelRedundancyCheck);
 245120    }
 121
 122    private static void AddCoveredHexGridVoxels(
 123        VoxelGrid currentGrid,
 124        Vector3d queryMin,
 125        Vector3d queryMax,
 126        SwiftList<Voxel> voxelList)
 127    {
 9128        if (!TopologyVoxelRangeUtility.TryGetCandidateRange(
 9129                currentGrid,
 9130                queryMin,
 9131                queryMax,
 9132                out VoxelIndex minIndex,
 9133                out VoxelIndex maxIndex))
 134        {
 1135            return;
 136        }
 137
 8138        Fixed64 horizontalExpansion =
 8139            currentGrid.Topology.Metrics.CellRadius;
 8140        Fixed64 coverageMinX = queryMin.X - horizontalExpansion;
 8141        Fixed64 coverageMaxX = queryMax.X + horizontalExpansion;
 8142        Fixed64 coverageMinZ = queryMin.Z - horizontalExpansion;
 8143        Fixed64 coverageMaxZ = queryMax.Z + horizontalExpansion;
 144
 44145        for (long x = minIndex.x; x <= maxIndex.x; x++)
 146        {
 56147            for (long y = minIndex.y; y <= maxIndex.y; y++)
 148            {
 76149                for (long z = minIndex.z; z <= maxIndex.z; z++)
 150                {
 24151                    if (currentGrid.TryGetVoxel(
 24152                            (int)x,
 24153                            (int)y,
 24154                            (int)z,
 24155                            out Voxel? voxel)
 24156                        && IsHexVoxelCenterInHorizontalCoverage(
 24157                            voxel!,
 24158                            coverageMinX,
 24159                            coverageMaxX,
 24160                            coverageMinZ,
 24161                            coverageMaxZ))
 162                    {
 13163                        voxelList.Add(voxel!);
 164                    }
 165                }
 166            }
 167        }
 8168    }
 169
 170    private static void AddCoveredHexScanCellsForGrid(
 171        VoxelGrid currentGrid,
 172        Vector3d queryMin,
 173        Vector3d queryMax,
 174        SwiftList<ScanCell> scanCells,
 175        SwiftHashSet<ScanCell> scanCellRedundancyCheck)
 176    {
 7177        if (!TopologyVoxelRangeUtility.TryGetCandidateRange(
 7178                currentGrid,
 7179                queryMin,
 7180                queryMax,
 7181                out VoxelIndex minIndex,
 7182                out VoxelIndex maxIndex))
 183        {
 1184            return;
 185        }
 186
 6187        currentGrid.AddScanCellsInRange(
 6188            minIndex.x / currentGrid.ScanCellSize,
 6189            minIndex.y / currentGrid.ScanCellSize,
 6190            minIndex.z / currentGrid.ScanCellSize,
 6191            maxIndex.x / currentGrid.ScanCellSize,
 6192            maxIndex.y / currentGrid.ScanCellSize,
 6193            maxIndex.z / currentGrid.ScanCellSize,
 6194            scanCells,
 6195            scanCellRedundancyCheck);
 6196    }
 197
 198    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 199    private static bool IsHexVoxelCenterInHorizontalCoverage(
 200        Voxel voxel,
 201        Fixed64 coverageMinX,
 202        Fixed64 coverageMaxX,
 203        Fixed64 coverageMinZ,
 204        Fixed64 coverageMaxZ)
 205    {
 22206        Vector3d position = voxel.WorldPosition;
 22207        return position.X >= coverageMinX
 22208            && position.X <= coverageMaxX
 22209            && position.Z >= coverageMinZ
 22210            && position.Z <= coverageMaxZ;
 211    }
 212}

/home/runner/work/GridForge/GridForge/src/GridForge/Utility/GridTracer.TraceLine.cs

#LineLine coverage
 1//=======================================================================
 2// GridTracer.TraceLine.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.Collections.Generic;
 9using System.Runtime.CompilerServices;
 10using FixedMathSharp;
 11using GridForge.Grids;
 12using GridForge.Grids.Topology;
 13using GridForge.Spatial;
 14using SwiftCollections;
 15using SwiftCollections.Pool;
 16
 17namespace GridForge.Utility;
 18
 19/// <content>
 20/// Provides line-tracing functionality for identifying voxels intersected
 21/// along a segment between two points across one or more grids.
 22/// </content>
 23public static partial class GridTracer
 24{
 25    private static IEnumerable<GridVoxelSet> TraceLineIterator(
 26        GridWorld world,
 27        Vector3d start,
 28        Vector3d end,
 29        Fixed64? padding,
 30        bool includeEnd)
 31    {
 4032        SwiftList<GridVoxelSet> gridVoxelSets = SwiftListPool<GridVoxelSet>.Shared.Rent();
 4033        SwiftHashSet<Voxel> voxelRedundancyCheck = SwiftHashSetPool<Voxel>.Shared.Rent();
 4034        SwiftList<ushort> candidateGrids = SwiftListPool<ushort>.Shared.Rent();
 35
 36        try
 37        {
 4038            AddTraceLineVoxelsToMapping(
 4039                world,
 4040                start,
 4041                end,
 4042                padding,
 4043                includeEnd,
 4044                gridVoxelSets,
 4045                voxelRedundancyCheck,
 4046                candidateGrids);
 47
 18448            foreach (GridVoxelSet gridVoxelSet in gridVoxelSets)
 5249                yield return gridVoxelSet;
 4050        }
 51        finally
 52        {
 4053            ReleaseGridVoxelSets(gridVoxelSets);
 4054            SwiftHashSetPool<Voxel>.Shared.Release(voxelRedundancyCheck);
 4055            SwiftListPool<ushort>.Shared.Release(candidateGrids);
 4056        }
 4057    }
 58
 59    private static void AddTraceLineVoxelsToMapping(
 60        GridWorld world,
 61        Vector3d start,
 62        Vector3d end,
 63        Fixed64? padding,
 64        bool includeEnd,
 65        SwiftList<GridVoxelSet> gridVoxelSets,
 66        SwiftHashSet<Voxel> voxelRedundancyCheck,
 67        SwiftList<ushort> candidateGrids)
 68    {
 4069        (Vector3d queryMin, Vector3d queryMax) = CreatePaddedOrderedBounds(start, end, padding);
 4070        (Vector3d candidateMin, Vector3d candidateMax) =
 4071            ExpandOrderedBounds(queryMin, queryMax, world.MaxTopologyCellEdge);
 72
 4073        world.CollectGridCandidates(candidateMin, candidateMax, candidateGrids);
 19674        foreach (ushort gridIndex in candidateGrids)
 75        {
 5876            AddTraceLineVoxelsForGrid(
 5877                world.ActiveGrids[gridIndex],
 5878                start,
 5879                end,
 5880                padding,
 5881                includeEnd,
 5882                gridVoxelSets,
 5883                voxelRedundancyCheck);
 84        }
 4085    }
 86
 87    private static void AddTraceLineVoxelsTo(
 88        GridWorld world,
 89        Vector3d start,
 90        Vector3d end,
 91        Fixed64? padding,
 92        bool includeEnd,
 93        SwiftList<Voxel> voxels,
 94        SwiftHashSet<Voxel> voxelRedundancyCheck,
 95        SwiftList<ushort> candidateGrids)
 96    {
 1097        (Vector3d queryMin, Vector3d queryMax) = CreatePaddedOrderedBounds(start, end, padding);
 1098        (Vector3d candidateMin, Vector3d candidateMax) =
 1099            ExpandOrderedBounds(queryMin, queryMax, world.MaxTopologyCellEdge);
 100
 10101        world.CollectGridCandidates(candidateMin, candidateMax, candidateGrids);
 74102        foreach (ushort gridIndex in candidateGrids)
 103        {
 27104            AddTraceLineVoxelsForGrid(
 27105                world.ActiveGrids[gridIndex],
 27106                start,
 27107                end,
 27108                padding,
 27109                includeEnd,
 27110                voxels,
 27111                voxelRedundancyCheck);
 112        }
 10113    }
 114
 115    private static TraceLinePlan CreateTraceLinePlan(
 116        VoxelGrid grid,
 117        Vector3d start,
 118        Vector3d end,
 119        Fixed64? padding)
 120    {
 70121        (Vector3d snappedMin, Vector3d snappedMax) =
 70122            grid.NormalizeBounds(start, end, padding);
 123
 70124        Vector3d traceStart = CreateTraceEndpoint(start, end, snappedMin, snappedMax, useMinWhenIncreasing: true);
 70125        Vector3d traceEnd = CreateTraceEndpoint(start, end, snappedMin, snappedMax, useMinWhenIncreasing: false);
 126
 70127        Vector3d diff = traceEnd - traceStart;
 70128        Fixed64 steps = CalculateTraceSteps(grid, diff);
 129
 70130        return new TraceLinePlan(
 70131            traceStart,
 70132            steps,
 70133            diff.X / (steps + Fixed64.One),
 70134            diff.Y / (steps + Fixed64.One),
 70135            diff.Z / (steps + Fixed64.One));
 136    }
 137
 138    private static Fixed64 CalculateTraceSteps(VoxelGrid grid, Vector3d diff)
 139    {
 70140        Vector3d delta = Vector3d.Abs(diff);
 70141        Fixed64 stepX = delta.X / grid.Topology.Metrics.CellWidth;
 70142        Fixed64 stepY = delta.Y / grid.Topology.Metrics.LayerHeight;
 70143        Fixed64 stepZ = delta.Z / grid.Topology.Metrics.CellLength;
 70144        return FixedMath.Ceil(FixedMath.Max(FixedMath.Max(stepX, stepY), stepZ));
 145    }
 146
 147    private static Vector3d CreateTraceEndpoint(
 148        Vector3d start,
 149        Vector3d end,
 150        Vector3d snappedMin,
 151        Vector3d snappedMax,
 152        bool useMinWhenIncreasing)
 153    {
 154        // Preserve the caller's trace direction while still using snapped bounds for coverage lookup.
 158155        return new Vector3d(
 158156            SelectTraceCoordinate(start.X, end.X, snappedMin.X, snappedMax.X, useMinWhenIncreasing),
 158157            SelectTraceCoordinate(start.Y, end.Y, snappedMin.Y, snappedMax.Y, useMinWhenIncreasing),
 158158            SelectTraceCoordinate(start.Z, end.Z, snappedMin.Z, snappedMax.Z, useMinWhenIncreasing));
 159    }
 160
 161    private static Fixed64 SelectTraceCoordinate(
 162        Fixed64 start,
 163        Fixed64 end,
 164        Fixed64 snappedMin,
 165        Fixed64 snappedMax,
 166        bool useMinWhenIncreasing)
 167    {
 474168        return (start <= end) == useMinWhenIncreasing ? snappedMin : snappedMax;
 169    }
 170
 171    private static (Vector3d min, Vector3d max) CreatePaddedOrderedBounds(
 172        Vector3d min,
 173        Vector3d max,
 174        Fixed64? padding)
 175    {
 836176        Fixed64 fixedPadding = padding.HasValue && padding.Value > Fixed64.Zero
 836177            ? padding.Value
 836178            : Fixed64.Zero;
 179
 836180        min -= fixedPadding;
 836181        max += fixedPadding;
 182
 836183        (min.X, max.X) = min.X > max.X ? (max.X, min.X) : (min.X, max.X);
 836184        (min.Y, max.Y) = min.Y > max.Y ? (max.Y, min.Y) : (min.Y, max.Y);
 836185        (min.Z, max.Z) = min.Z > max.Z ? (max.Z, min.Z) : (min.Z, max.Z);
 186
 836187        return (min, max);
 188    }
 189
 190    private static (Vector3d min, Vector3d max) ExpandOrderedBounds(
 191        Vector3d min,
 192        Vector3d max,
 193        Fixed64 expansion)
 194    {
 836195        if (expansion <= Fixed64.Zero)
 6196            return (min, max);
 197
 830198        return (
 830199            new Vector3d(min.X - expansion, min.Y - expansion, min.Z - expansion),
 830200            new Vector3d(max.X + expansion, max.Y + expansion, max.Z + expansion));
 201    }
 202
 203    private static bool TryGetCoveredScanCellRange(
 204        VoxelGrid grid,
 205        Vector3d queryMin,
 206        Vector3d queryMax,
 207        out int xMin,
 208        out int yMin,
 209        out int zMin,
 210        out int xMax,
 211        out int yMax,
 212        out int zMax)
 213    {
 592214        xMin = 0;
 592215        yMin = 0;
 592216        zMin = 0;
 592217        xMax = 0;
 592218        yMax = 0;
 592219        zMax = 0;
 220
 592221        (Vector3d snappedMin, Vector3d snappedMax) = grid.NormalizeBounds(queryMin, queryMax);
 592222        if (!TopologyVoxelRangeUtility.TryClipBoundsToGrid(grid, snappedMin, snappedMax, out Vector3d clippedMin, out Ve
 1223            return false;
 224
 591225        (xMin, yMin, zMin) = grid.SnapToScanCell(clippedMin);
 591226        (xMax, yMax, zMax) = grid.SnapToScanCell(clippedMax);
 591227        return true;
 228    }
 229
 230    private static void AddTraceLineVoxelsForGrid(
 231        VoxelGrid currentGrid,
 232        Vector3d start,
 233        Vector3d end,
 234        Fixed64? padding,
 235        bool includeEnd,
 236        SwiftList<GridVoxelSet> gridVoxelSets,
 237        SwiftHashSet<Voxel> voxelRedundancyCheck)
 238    {
 58239        if (!TryClipTraceSegmentToGrid(
 58240            currentGrid,
 58241            start,
 58242            end,
 58243            padding,
 58244            out Vector3d traceStart,
 58245            out Vector3d traceEnd,
 58246            out bool segmentEndsBeforeGlobalEnd))
 247        {
 5248            return;
 249        }
 250
 53251        SwiftList<Voxel> voxelList = SwiftListPool<Voxel>.Shared.Rent();
 53252        AddTraceLineGridVoxels(
 53253            currentGrid,
 53254            traceStart,
 53255            traceEnd,
 53256            padding,
 53257            includeEnd || segmentEndsBeforeGlobalEnd,
 53258            voxelList,
 53259            voxelRedundancyCheck);
 260
 53261        if (voxelList.Count > 0)
 52262            gridVoxelSets.Add(new GridVoxelSet(currentGrid, voxelList));
 263        else
 1264            SwiftListPool<Voxel>.Shared.Release(voxelList);
 1265    }
 266
 267    private static void AddTraceLineVoxelsForGrid(
 268        VoxelGrid currentGrid,
 269        Vector3d start,
 270        Vector3d end,
 271        Fixed64? padding,
 272        bool includeEnd,
 273        SwiftList<Voxel> voxels,
 274        SwiftHashSet<Voxel> voxelRedundancyCheck)
 275    {
 27276        if (!TryClipTraceSegmentToGrid(
 27277            currentGrid,
 27278            start,
 27279            end,
 27280            padding,
 27281            out Vector3d traceStart,
 27282            out Vector3d traceEnd,
 27283            out bool segmentEndsBeforeGlobalEnd))
 284        {
 1285            return;
 286        }
 287
 26288        AddTraceLineGridVoxels(
 26289            currentGrid,
 26290            traceStart,
 26291            traceEnd,
 26292            padding,
 26293            includeEnd || segmentEndsBeforeGlobalEnd,
 26294            voxels,
 26295            voxelRedundancyCheck);
 26296    }
 297
 298    private static void AddTraceLineGridVoxels(
 299        VoxelGrid currentGrid,
 300        Vector3d start,
 301        Vector3d end,
 302        Fixed64? padding,
 303        bool includeEnd,
 304        SwiftList<Voxel> voxelList,
 305        SwiftHashSet<Voxel> voxelRedundancyCheck)
 306    {
 79307        if (currentGrid.Topology.Kind == GridTopologyKind.HexPrism)
 308        {
 9309            AddHexTraceLineGridVoxels(
 9310                currentGrid,
 9311                start,
 9312                end,
 9313                padding,
 9314                includeEnd,
 9315                voxelList,
 9316                voxelRedundancyCheck);
 9317            return;
 318        }
 319
 70320        TraceLinePlan plan = CreateTraceLinePlan(currentGrid, start, end, padding);
 321
 730322        for (Fixed64 i = Fixed64.Zero; i <= plan.Steps; i += Fixed64.One)
 323        {
 295324            Vector3d tracePos = currentGrid.FloorToGrid(
 295325                new Vector3d(
 295326                    plan.TraceStart.X + plan.StepX * i,
 295327                    plan.TraceStart.Y + plan.StepY * i,
 295328                    plan.TraceStart.Z + plan.StepZ * i));
 329
 295330            if (!currentGrid.TryGetVoxel(tracePos, out Voxel? voxel) || voxelRedundancyCheck.Add(voxel!) != true)
 331                continue;
 332
 256333            voxelList.Add(voxel!);
 334        }
 335
 70336        if (includeEnd)
 66337            AddTraceVoxelByPosition(currentGrid, end, voxelList, voxelRedundancyCheck);
 70338    }
 339
 340    private static void AddHexTraceLineGridVoxels(
 341        VoxelGrid currentGrid,
 342        Vector3d start,
 343        Vector3d end,
 344        Fixed64? padding,
 345        bool includeEnd,
 346        SwiftList<Voxel> voxelList,
 347        SwiftHashSet<Voxel> voxelRedundancyCheck)
 348    {
 9349        CreateHexTraceEndpoints(
 9350            currentGrid,
 9351            start,
 9352            end,
 9353            padding,
 9354            out VoxelIndex startIndex,
 9355            out VoxelIndex endIndex);
 356
 9357        int steps = CalculateHexTraceSteps(startIndex, endIndex);
 9358        if (steps == 0)
 359        {
 1360            AddTraceVoxelByIndex(currentGrid, startIndex, voxelList, voxelRedundancyCheck);
 1361            return;
 362        }
 363
 8364        bool includeEndIndex = ShouldIncludeHexTraceEndIndex(currentGrid, end, endIndex, includeEnd);
 8365        int finalStep = includeEndIndex ? steps : steps - 1;
 8366        Fixed64 stepCount = new Fixed64(steps);
 82367        for (int i = 0; i <= finalStep; i++)
 368        {
 33369            Fixed64 t = new Fixed64(i) / stepCount;
 33370            VoxelIndex traceIndex = InterpolateHexTraceIndex(startIndex, endIndex, t);
 33371            AddTraceVoxelByIndex(currentGrid, traceIndex, voxelList, voxelRedundancyCheck);
 372        }
 8373    }
 374
 375    private static void CreateHexTraceEndpoints(
 376        VoxelGrid grid,
 377        Vector3d start,
 378        Vector3d end,
 379        Fixed64? padding,
 380        out VoxelIndex startIndex,
 381        out VoxelIndex endIndex)
 382    {
 9383        (Vector3d snappedMin, Vector3d snappedMax) = grid.NormalizeBounds(start, end, padding);
 9384        Vector3d traceStart = grid.FloorToGrid(CreateTraceEndpoint(
 9385            start,
 9386            end,
 9387            snappedMin,
 9388            snappedMax,
 9389            useMinWhenIncreasing: true));
 9390        Vector3d traceEnd = grid.FloorToGrid(CreateTraceEndpoint(
 9391            start,
 9392            end,
 9393            snappedMin,
 9394            snappedMax,
 9395            useMinWhenIncreasing: false));
 396
 9397        grid.TryGetVoxelIndex(traceStart, out startIndex);
 9398        grid.TryGetVoxelIndex(traceEnd, out endIndex);
 9399    }
 400
 401    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 402    private static int CalculateHexTraceSteps(VoxelIndex start, VoxelIndex end)
 403    {
 9404        int qDelta = System.Math.Abs(end.x - start.x);
 9405        int rDelta = System.Math.Abs(end.z - start.z);
 9406        int sDelta = System.Math.Abs((-end.x - end.z) - (-start.x - start.z));
 9407        int planarSteps = System.Math.Max(qDelta, System.Math.Max(rDelta, sDelta));
 9408        int verticalSteps = System.Math.Abs(end.y - start.y);
 9409        return System.Math.Max(planarSteps, verticalSteps);
 410    }
 411
 412    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 413    private static VoxelIndex InterpolateHexTraceIndex(VoxelIndex start, VoxelIndex end, Fixed64 t)
 414    {
 33415        Fixed64 q = Interpolate(new Fixed64(start.x), new Fixed64(end.x), t);
 33416        Fixed64 y = Interpolate(new Fixed64(start.y), new Fixed64(end.y), t);
 33417        Fixed64 r = Interpolate(new Fixed64(start.z), new Fixed64(end.z), t);
 33418        return HexCoordinateUtility.RoundAxial(q, y, r);
 419    }
 420
 421    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 422    private static Fixed64 Interpolate(Fixed64 start, Fixed64 end, Fixed64 t) =>
 99423        start + (end - start) * t;
 424
 425    private static bool TryClipTraceSegmentToGrid(
 426        VoxelGrid grid,
 427        Vector3d start,
 428        Vector3d end,
 429        Fixed64? padding,
 430        out Vector3d clippedStart,
 431        out Vector3d clippedEnd,
 432        out bool segmentEndsBeforeGlobalEnd)
 433    {
 85434        clippedStart = default;
 85435        clippedEnd = default;
 85436        segmentEndsBeforeGlobalEnd = false;
 437
 85438        Fixed64 fixedPadding = padding.HasValue && padding.Value > Fixed64.Zero
 85439            ? padding.Value
 85440            : Fixed64.Zero;
 85441        Vector3d boundsMin = grid.BoundsMin - fixedPadding;
 85442        Vector3d boundsMax = grid.BoundsMax + fixedPadding;
 85443        Fixed64 tMin = Fixed64.Zero;
 85444        Fixed64 tMax = Fixed64.One;
 445
 85446        if (!(ClipTraceSegmentAxis(start.X, end.X, boundsMin.X, boundsMax.X, ref tMin, ref tMax)
 85447            && ClipTraceSegmentAxis(start.Y, end.Y, boundsMin.Y, boundsMax.Y, ref tMin, ref tMax)
 85448            && ClipTraceSegmentAxis(start.Z, end.Z, boundsMin.Z, boundsMax.Z, ref tMin, ref tMax)))
 449        {
 6450            return false;
 451        }
 452
 79453        clippedStart = InterpolateTraceSegment(start, end, boundsMin, boundsMax, tMin);
 79454        clippedEnd = InterpolateTraceSegment(start, end, boundsMin, boundsMax, tMax);
 79455        segmentEndsBeforeGlobalEnd = tMax < Fixed64.One;
 79456        return true;
 457    }
 458
 459    private static bool ClipTraceSegmentAxis(
 460        Fixed64 start,
 461        Fixed64 end,
 462        Fixed64 boundsMin,
 463        Fixed64 boundsMax,
 464        ref Fixed64 tMin,
 465        ref Fixed64 tMax)
 466    {
 249467        Fixed64 delta = end - start;
 249468        if (delta == Fixed64.Zero)
 167469            return start >= boundsMin && start <= boundsMax;
 470
 82471        Fixed64 axisMin = (boundsMin - start) / delta;
 82472        Fixed64 axisMax = (boundsMax - start) / delta;
 82473        if (axisMin > axisMax)
 5474            (axisMin, axisMax) = (axisMax, axisMin);
 475
 82476        if (axisMin > tMin)
 13477            tMin = axisMin;
 82478        if (axisMax < tMax)
 14479            tMax = axisMax;
 480
 82481        return tMin <= tMax;
 482    }
 483
 484    private static bool ShouldIncludeHexTraceEndIndex(
 485        VoxelGrid grid,
 486        Vector3d end,
 487        VoxelIndex endIndex,
 488        bool includeEnd)
 489    {
 8490        if (includeEnd)
 6491            return true;
 492
 2493        return !grid.TryGetVoxelIndex(end, out VoxelIndex actualEndIndex)
 2494            || actualEndIndex != endIndex;
 495    }
 496
 497    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 498    private static Vector3d InterpolateTraceSegment(
 499        Vector3d start,
 500        Vector3d end,
 501        Vector3d boundsMin,
 502        Vector3d boundsMax,
 503        Fixed64 t) =>
 158504        new(
 158505            InterpolateTraceAxis(start.X, end.X, boundsMin.X, boundsMax.X, t),
 158506            InterpolateTraceAxis(start.Y, end.Y, boundsMin.Y, boundsMax.Y, t),
 158507            InterpolateTraceAxis(start.Z, end.Z, boundsMin.Z, boundsMax.Z, t));
 508
 509    private static Fixed64 InterpolateTraceAxis(
 510        Fixed64 start,
 511        Fixed64 end,
 512        Fixed64 boundsMin,
 513        Fixed64 boundsMax,
 514        Fixed64 t)
 515    {
 474516        Fixed64 delta = end - start;
 474517        if (delta == Fixed64.Zero)
 332518            return start;
 519
 142520        if ((boundsMin - start) / delta == t)
 32521            return boundsMin;
 110522        if ((boundsMax - start) / delta == t)
 27523            return boundsMax;
 524
 83525        return start + delta * t;
 526    }
 527
 528    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 529    private static void AddTraceVoxelByPosition(
 530        VoxelGrid grid,
 531        Vector3d position,
 532        SwiftList<Voxel> voxelList,
 533        SwiftHashSet<Voxel> voxelRedundancyCheck)
 534    {
 66535        if (grid.TryGetVoxel(grid.FloorToGrid(position), out Voxel? voxel)
 66536            && voxelRedundancyCheck.Add(voxel!))
 537        {
 22538            voxelList.Add(voxel!);
 539        }
 66540    }
 541
 542    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 543    private static void AddTraceVoxelByIndex(
 544        VoxelGrid grid,
 545        VoxelIndex index,
 546        SwiftList<Voxel> voxelList,
 547        SwiftHashSet<Voxel> voxelRedundancyCheck)
 548    {
 37549        if (grid.TryGetVoxel(index, out Voxel? voxel)
 37550            && voxelRedundancyCheck.Add(voxel!))
 551        {
 33552            voxelList.Add(voxel!);
 553        }
 37554    }
 555
 556    private static void ReleaseGridVoxelSets(SwiftList<GridVoxelSet> gridVoxelSets)
 557    {
 1018558        foreach (GridVoxelSet gridVoxelSet in gridVoxelSets)
 267559            SwiftListPool<Voxel>.Shared.Release(gridVoxelSet.Voxels);
 560
 242561        SwiftListPool<GridVoxelSet>.Shared.Release(gridVoxelSets);
 242562    }
 563}

Methods/Properties

.ctor(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
TraceLine(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Nullable`1<FixedMathSharp.Fixed64>,System.Boolean)
TraceLineInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,System.Nullable`1<FixedMathSharp.Fixed64>,System.Boolean)
TraceLineInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,GridForge.Grids.GridTraceScratch,System.Nullable`1<FixedMathSharp.Fixed64>,System.Boolean)
TraceLine(GridForge.Grids.GridWorld,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,System.Nullable`1<FixedMathSharp.Fixed64>,System.Boolean,FixedMathSharp.Fixed64)
TraceLineInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,System.Nullable`1<FixedMathSharp.Fixed64>,System.Boolean,FixedMathSharp.Fixed64)
TraceLineInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,GridForge.Grids.GridTraceScratch,System.Nullable`1<FixedMathSharp.Fixed64>,System.Boolean,FixedMathSharp.Fixed64)
GetCoveredVoxels(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Nullable`1<FixedMathSharp.Fixed64>)
GetCoveredVoxels(GridForge.Grids.GridWorld,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,System.Nullable`1<FixedMathSharp.Fixed64>)
GetCoveredVoxels(GridForge.Grids.GridWorld,FixedMathSharp.Geometry.FixedBoundArea,FixedMathSharp.Fixed64,System.Nullable`1<FixedMathSharp.Fixed64>)
GetCoveredVoxelsInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,System.Nullable`1<FixedMathSharp.Fixed64>)
GetCoveredVoxelsInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,FixedMathSharp.Fixed64,System.Nullable`1<FixedMathSharp.Fixed64>)
GetCoveredVoxelsInto(GridForge.Grids.GridWorld,FixedMathSharp.Geometry.FixedBoundArea,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,FixedMathSharp.Fixed64,System.Nullable`1<FixedMathSharp.Fixed64>)
GetCoveredVoxelsInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,GridForge.Grids.GridTraceScratch,System.Nullable`1<FixedMathSharp.Fixed64>)
GetCoveredVoxelsInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,GridForge.Grids.GridTraceScratch,FixedMathSharp.Fixed64,System.Nullable`1<FixedMathSharp.Fixed64>)
GetCoveredVoxelsInto(GridForge.Grids.GridWorld,FixedMathSharp.Geometry.FixedBoundArea,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,GridForge.Grids.GridTraceScratch,FixedMathSharp.Fixed64,System.Nullable`1<FixedMathSharp.Fixed64>)
GetCoveredScanCells(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Nullable`1<FixedMathSharp.Fixed64>)
GetCoveredScanCells(GridForge.Grids.GridWorld,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,System.Nullable`1<FixedMathSharp.Fixed64>)
GetCoveredScanCells(GridForge.Grids.GridWorld,FixedMathSharp.Geometry.FixedBoundArea,FixedMathSharp.Fixed64,System.Nullable`1<FixedMathSharp.Fixed64>)
GetCoveredScanCellsInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,SwiftCollections.SwiftList`1<GridForge.Grids.ScanCell>,System.Nullable`1<FixedMathSharp.Fixed64>)
GetCoveredScanCellsInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,SwiftCollections.SwiftList`1<GridForge.Grids.ScanCell>,FixedMathSharp.Fixed64,System.Nullable`1<FixedMathSharp.Fixed64>)
GetCoveredScanCellsInto(GridForge.Grids.GridWorld,FixedMathSharp.Geometry.FixedBoundArea,SwiftCollections.SwiftList`1<GridForge.Grids.ScanCell>,FixedMathSharp.Fixed64,System.Nullable`1<FixedMathSharp.Fixed64>)
GetCoveredScanCellsInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,SwiftCollections.SwiftList`1<GridForge.Grids.ScanCell>,GridForge.Grids.GridScanScratch,System.Nullable`1<FixedMathSharp.Fixed64>)
GetCoveredScanCellsInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d,SwiftCollections.SwiftList`1<GridForge.Grids.ScanCell>,GridForge.Grids.GridScanScratch,FixedMathSharp.Fixed64,System.Nullable`1<FixedMathSharp.Fixed64>)
GetCoveredScanCellsInto(GridForge.Grids.GridWorld,FixedMathSharp.Geometry.FixedBoundArea,SwiftCollections.SwiftList`1<GridForge.Grids.ScanCell>,GridForge.Grids.GridScanScratch,FixedMathSharp.Fixed64,System.Nullable`1<FixedMathSharp.Fixed64>)
AddCoveredScanCellsTo(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,SwiftCollections.SwiftList`1<GridForge.Grids.ScanCell>,System.Nullable`1<FixedMathSharp.Fixed64>)
AddCoveredScanCellsTo(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,SwiftCollections.SwiftList`1<GridForge.Grids.ScanCell>,GridForge.Grids.GridScanScratch,System.Nullable`1<FixedMathSharp.Fixed64>)
AddCoveredVoxelsTo(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,System.Nullable`1<FixedMathSharp.Fixed64>)
AddCoveredVoxelsTo(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,GridForge.Grids.GridTraceScratch,System.Nullable`1<FixedMathSharp.Fixed64>)
AddCoveredVoxelsCore(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,SwiftCollections.SwiftList`1<System.UInt16>,SwiftCollections.SwiftHashSet`1<GridForge.Grids.Voxel>,System.Nullable`1<FixedMathSharp.Fixed64>)
AddCoveredScanCellsCore(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,SwiftCollections.SwiftList`1<GridForge.Grids.ScanCell>,SwiftCollections.SwiftList`1<System.UInt16>,SwiftCollections.SwiftHashSet`1<GridForge.Grids.ScanCell>,System.Nullable`1<FixedMathSharp.Fixed64>)
GetCoveredVoxelsIterator()
<>m__Finally1()
AddCoveredVoxelsToMapping(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Nullable`1<FixedMathSharp.Fixed64>,SwiftCollections.SwiftList`1<GridForge.GridVoxelSet>,SwiftCollections.SwiftHashSet`1<GridForge.Grids.Voxel>,SwiftCollections.SwiftList`1<System.UInt16>)
GetCoveredScanCellsIterator()
<>m__Finally1()
AddCoveredScanCellsForGrid(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,SwiftCollections.SwiftList`1<GridForge.Grids.ScanCell>,SwiftCollections.SwiftHashSet`1<GridForge.Grids.ScanCell>)
AddCoveredVoxelsForGrid(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,SwiftCollections.SwiftList`1<GridForge.GridVoxelSet>,SwiftCollections.SwiftHashSet`1<GridForge.Grids.Voxel>)
AddCoveredGridVoxels(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,SwiftCollections.SwiftHashSet`1<GridForge.Grids.Voxel>)
AddCoveredHexGridVoxels(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>)
AddCoveredHexScanCellsForGrid(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,SwiftCollections.SwiftList`1<GridForge.Grids.ScanCell>,SwiftCollections.SwiftHashSet`1<GridForge.Grids.ScanCell>)
IsHexVoxelCenterInHorizontalCoverage(GridForge.Grids.Voxel,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
TraceLineIterator()
<>m__Finally1()
AddTraceLineVoxelsToMapping(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Nullable`1<FixedMathSharp.Fixed64>,System.Boolean,SwiftCollections.SwiftList`1<GridForge.GridVoxelSet>,SwiftCollections.SwiftHashSet`1<GridForge.Grids.Voxel>,SwiftCollections.SwiftList`1<System.UInt16>)
AddTraceLineVoxelsTo(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Nullable`1<FixedMathSharp.Fixed64>,System.Boolean,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,SwiftCollections.SwiftHashSet`1<GridForge.Grids.Voxel>,SwiftCollections.SwiftList`1<System.UInt16>)
CreateTraceLinePlan(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Nullable`1<FixedMathSharp.Fixed64>)
CalculateTraceSteps(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d)
CreateTraceEndpoint(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Boolean)
SelectTraceCoordinate(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Boolean)
CreatePaddedOrderedBounds(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Nullable`1<FixedMathSharp.Fixed64>)
ExpandOrderedBounds(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
TryGetCoveredScanCellRange(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Int32&,System.Int32&,System.Int32&,System.Int32&,System.Int32&,System.Int32&)
AddTraceLineVoxelsForGrid(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Nullable`1<FixedMathSharp.Fixed64>,System.Boolean,SwiftCollections.SwiftList`1<GridForge.GridVoxelSet>,SwiftCollections.SwiftHashSet`1<GridForge.Grids.Voxel>)
AddTraceLineVoxelsForGrid(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Nullable`1<FixedMathSharp.Fixed64>,System.Boolean,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,SwiftCollections.SwiftHashSet`1<GridForge.Grids.Voxel>)
AddTraceLineGridVoxels(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Nullable`1<FixedMathSharp.Fixed64>,System.Boolean,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,SwiftCollections.SwiftHashSet`1<GridForge.Grids.Voxel>)
AddHexTraceLineGridVoxels(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Nullable`1<FixedMathSharp.Fixed64>,System.Boolean,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,SwiftCollections.SwiftHashSet`1<GridForge.Grids.Voxel>)
CreateHexTraceEndpoints(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Nullable`1<FixedMathSharp.Fixed64>,GridForge.Spatial.VoxelIndex&,GridForge.Spatial.VoxelIndex&)
CalculateHexTraceSteps(GridForge.Spatial.VoxelIndex,GridForge.Spatial.VoxelIndex)
InterpolateHexTraceIndex(GridForge.Spatial.VoxelIndex,GridForge.Spatial.VoxelIndex,FixedMathSharp.Fixed64)
Interpolate(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
TryClipTraceSegmentToGrid(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Nullable`1<FixedMathSharp.Fixed64>,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&,System.Boolean&)
ClipTraceSegmentAxis(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
ShouldIncludeHexTraceEndIndex(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d,GridForge.Spatial.VoxelIndex,System.Boolean)
InterpolateTraceSegment(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
InterpolateTraceAxis(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
AddTraceVoxelByPosition(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,SwiftCollections.SwiftHashSet`1<GridForge.Grids.Voxel>)
AddTraceVoxelByIndex(GridForge.Grids.VoxelGrid,GridForge.Spatial.VoxelIndex,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,SwiftCollections.SwiftHashSet`1<GridForge.Grids.Voxel>)
ReleaseGridVoxelSets(SwiftCollections.SwiftList`1<GridForge.GridVoxelSet>)