< Summary

Information
Class: GridForge.Grids.GridScanManager
Assembly: GridForge
File(s): /home/runner/work/GridForge/GridForge/src/GridForge/Grids/Managers/GridScanManager.cs
Line coverage
100%
Covered lines: 259
Uncovered lines: 0
Coverable lines: 259
Total lines: 787
Line coverage: 100%
Branch coverage
100%
Covered branches: 130
Total branches: 130
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/GridForge/GridForge/src/GridForge/Grids/Managers/GridScanManager.cs

#LineLine coverage
 1//=======================================================================
 2// GridScanManager.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.Spatial;
 10using GridForge.Utility;
 11using SwiftCollections;
 12using SwiftCollections.Pool;
 13using System;
 14using System.Collections.Generic;
 15using System.Linq;
 16
 17namespace GridForge.Grids;
 18
 19/// <summary>
 20/// Provides efficient querying methods for retrieving occupants within a grid.
 21/// Handles spatial lookups for voxels, filtering by occupant type, and fetching occupants using unique tickets.
 22/// </summary>
 23public static class GridScanManager
 24{
 25    #region Scan Methods
 26
 27    /// <summary>
 28    /// Scans for occupants within a given radius from a specified position in the supplied world.
 29    /// </summary>
 30    public static IEnumerable<IVoxelOccupant> ScanRadius(
 31        GridWorld world,
 32        Vector3d position,
 33        Fixed64 radius,
 34        Func<IVoxelOccupant, bool>? occupantCondition = null,
 35        Func<byte, bool>? groupCondition = null)
 36    {
 1137        if (world == null || !world.IsActive)
 138            return Enumerable.Empty<IVoxelOccupant>();
 39
 1040        return ScanRadiusIterator(world, position, radius, occupantCondition, groupCondition);
 41    }
 42
 43    /// <summary>
 44    /// Scans for occupants within a 2D XZ radius on the supplied world Y layer.
 45    /// </summary>
 46    public static IEnumerable<IVoxelOccupant> ScanRadius(
 47        GridWorld world,
 48        Vector2d position,
 49        Fixed64 radius,
 50        Fixed64 layerY = default,
 51        Func<IVoxelOccupant, bool>? occupantCondition = null,
 52        Func<byte, bool>? groupCondition = null)
 53    {
 454        if (world == null || !world.IsActive)
 155            return Enumerable.Empty<IVoxelOccupant>();
 56
 357        return ScanRadius2dIterator(world, position, radius, layerY, occupantCondition, groupCondition);
 58    }
 59
 60    /// <summary>
 61    /// Scans for occupants of a specific type within a given radius in the supplied world.
 62    /// </summary>
 63    public static IEnumerable<T> ScanRadius<T>(
 64        GridWorld world,
 65        Vector3d position,
 66        Fixed64 radius,
 67        Func<IVoxelOccupant, bool>? occupantCondition = null,
 68        Func<byte, bool>? groupCondition = null) where T : IVoxelOccupant
 69    {
 170        return ScanRadius(world, position, radius, occupantCondition, groupCondition).OfType<T>();
 71    }
 72
 73    /// <summary>
 74    /// Scans for occupants of a specific type within a 2D XZ radius on the supplied world Y layer.
 75    /// </summary>
 76    public static IEnumerable<T> ScanRadius<T>(
 77        GridWorld world,
 78        Vector2d position,
 79        Fixed64 radius,
 80        Fixed64 layerY = default,
 81        Func<IVoxelOccupant, bool>? occupantCondition = null,
 82        Func<byte, bool>? groupCondition = null) where T : IVoxelOccupant
 83    {
 184        return ScanRadius(world, position, radius, layerY, occupantCondition, groupCondition).OfType<T>();
 85    }
 86
 87    /// <summary>
 88    /// Clears and fills caller-owned storage with occupants within the supplied radius.
 89    /// </summary>
 90    public static void ScanRadiusInto(
 91        GridWorld world,
 92        Vector3d position,
 93        Fixed64 radius,
 94        SwiftList<IVoxelOccupant> results,
 95        Func<IVoxelOccupant, bool>? occupantCondition = null,
 96        Func<byte, bool>? groupCondition = null)
 97    {
 1498        SwiftThrowHelper.ThrowIfNull(results, nameof(results));
 99
 13100        results.Clear();
 13101        if (world == null || !world.IsActive)
 2102            return;
 103
 11104        AddRadiusOccupantsTo(world, position, radius, results, occupantCondition, groupCondition);
 11105    }
 106
 107    /// <summary>
 108    /// Clears and fills caller-owned storage with occupants within a 2D XZ radius on the supplied world Y layer.
 109    /// </summary>
 110    public static void ScanRadiusInto(
 111        GridWorld world,
 112        Vector2d position,
 113        Fixed64 radius,
 114        SwiftList<IVoxelOccupant> results,
 115        Fixed64 layerY = default,
 116        Func<IVoxelOccupant, bool>? occupantCondition = null,
 117        Func<byte, bool>? groupCondition = null)
 118    {
 7119        SwiftThrowHelper.ThrowIfNull(results, nameof(results));
 120
 6121        results.Clear();
 6122        if (world == null || !world.IsActive)
 2123            return;
 124
 4125        AddRadiusOccupants2dTo(world, position, radius, layerY, results, occupantCondition, groupCondition);
 4126    }
 127
 128    /// <summary>
 129    /// Clears and fills caller-owned storage using caller-owned scratch collections.
 130    /// </summary>
 131    public static void ScanRadiusInto(
 132        GridWorld world,
 133        Vector3d position,
 134        Fixed64 radius,
 135        SwiftList<IVoxelOccupant> results,
 136        GridScanScratch scratch,
 137        Func<IVoxelOccupant, bool>? occupantCondition = null,
 138        Func<byte, bool>? groupCondition = null)
 139    {
 262140        SwiftThrowHelper.ThrowIfNull(results, nameof(results));
 261141        SwiftThrowHelper.ThrowIfNull(scratch, nameof(scratch));
 142
 260143        results.Clear();
 260144        if (world == null || !world.IsActive)
 2145            return;
 146
 258147        AddRadiusOccupantsTo(world, position, radius, results, scratch, occupantCondition, groupCondition);
 258148    }
 149
 150    /// <summary>
 151    /// Clears and fills caller-owned storage using caller-owned scratch collections for a 2D XZ radius.
 152    /// </summary>
 153    public static void ScanRadiusInto(
 154        GridWorld world,
 155        Vector2d position,
 156        Fixed64 radius,
 157        SwiftList<IVoxelOccupant> results,
 158        GridScanScratch scratch,
 159        Fixed64 layerY = default,
 160        Func<IVoxelOccupant, bool>? occupantCondition = null,
 161        Func<byte, bool>? groupCondition = null)
 162    {
 261163        SwiftThrowHelper.ThrowIfNull(results, nameof(results));
 261164        SwiftThrowHelper.ThrowIfNull(scratch, nameof(scratch));
 165
 260166        results.Clear();
 260167        if (world == null || !world.IsActive)
 2168            return;
 169
 258170        AddRadiusOccupants2dTo(world, position, radius, layerY, results, scratch, occupantCondition, groupCondition);
 258171    }
 172
 173    /// <summary>
 174    /// Clears and fills caller-owned storage with typed occupants within the supplied radius.
 175    /// </summary>
 176    public static void ScanRadiusInto<T>(
 177        GridWorld world,
 178        Vector3d position,
 179        Fixed64 radius,
 180        SwiftList<T> results,
 181        Func<IVoxelOccupant, bool>? occupantCondition = null,
 182        Func<byte, bool>? groupCondition = null) where T : IVoxelOccupant
 183    {
 4184        SwiftThrowHelper.ThrowIfNull(results, nameof(results));
 185
 3186        results.Clear();
 3187        if (world == null || !world.IsActive)
 2188            return;
 189
 1190        AddRadiusOccupantsTo(world, position, radius, results, occupantCondition, groupCondition);
 1191    }
 192
 193    /// <summary>
 194    /// Clears and fills caller-owned typed storage with occupants within a 2D XZ radius on the supplied world Y layer.
 195    /// </summary>
 196    public static void ScanRadiusInto<T>(
 197        GridWorld world,
 198        Vector2d position,
 199        Fixed64 radius,
 200        SwiftList<T> results,
 201        Fixed64 layerY = default,
 202        Func<IVoxelOccupant, bool>? occupantCondition = null,
 203        Func<byte, bool>? groupCondition = null) where T : IVoxelOccupant
 204    {
 5205        SwiftThrowHelper.ThrowIfNull(results, nameof(results));
 206
 4207        results.Clear();
 4208        if (world == null || !world.IsActive)
 2209            return;
 210
 2211        AddRadiusOccupants2dTo(world, position, radius, layerY, results, occupantCondition, groupCondition);
 2212    }
 213
 214    /// <summary>
 215    /// Clears and fills caller-owned typed storage using caller-owned scratch collections.
 216    /// </summary>
 217    public static void ScanRadiusInto<T>(
 218        GridWorld world,
 219        Vector3d position,
 220        Fixed64 radius,
 221        SwiftList<T> results,
 222        GridScanScratch scratch,
 223        Func<IVoxelOccupant, bool>? occupantCondition = null,
 224        Func<byte, bool>? groupCondition = null) where T : IVoxelOccupant
 225    {
 5226        SwiftThrowHelper.ThrowIfNull(results, nameof(results));
 4227        SwiftThrowHelper.ThrowIfNull(scratch, nameof(scratch));
 228
 3229        results.Clear();
 3230        if (world == null || !world.IsActive)
 2231            return;
 232
 1233        AddRadiusOccupantsTo(world, position, radius, results, scratch, occupantCondition, groupCondition);
 1234    }
 235
 236    /// <summary>
 237    /// Clears and fills caller-owned typed storage using caller-owned scratch collections for a 2D XZ radius.
 238    /// </summary>
 239    public static void ScanRadiusInto<T>(
 240        GridWorld world,
 241        Vector2d position,
 242        Fixed64 radius,
 243        SwiftList<T> results,
 244        GridScanScratch scratch,
 245        Fixed64 layerY = default,
 246        Func<IVoxelOccupant, bool>? occupantCondition = null,
 247        Func<byte, bool>? groupCondition = null) where T : IVoxelOccupant
 248    {
 4249        SwiftThrowHelper.ThrowIfNull(results, nameof(results));
 4250        SwiftThrowHelper.ThrowIfNull(scratch, nameof(scratch));
 251
 3252        results.Clear();
 3253        if (world == null || !world.IsActive)
 2254            return;
 255
 1256        AddRadiusOccupants2dTo(world, position, radius, layerY, results, scratch, occupantCondition, groupCondition);
 1257    }
 258
 259    #endregion
 260
 261    #region Occupant Registration & Retrieval
 262
 263    /// <summary>
 264    /// Retrieves all occupants of a specific type at a given world-scoped voxel identity in the supplied world.
 265    /// </summary>
 266    public static IEnumerable<T> GetVoxelOccupantsByType<T>(GridWorld world, WorldVoxelIndex index) where T : IVoxelOccu
 267    {
 3268        return world != null && world.TryGetGridAndVoxel(index, out VoxelGrid? grid, out Voxel? voxel)
 3269            ? grid!.GetVoxelOccupantsByType<T>(voxel!)
 3270            : Enumerable.Empty<T>();
 271    }
 272
 273    /// <summary>
 274    /// Retrieves all occupants of a specific type at a given world position.
 275    /// </summary>
 276    public static IEnumerable<T> GetVoxelOccupantsByType<T>(this VoxelGrid grid, Vector3d position) where T : IVoxelOccu
 277    {
 2278        return grid.TryGetVoxel(position, out Voxel? voxel)
 2279            ? grid.GetVoxelOccupantsByType<T>(voxel!)
 2280            : Enumerable.Empty<T>();
 281    }
 282
 283    /// <summary>
 284    /// Retrieves all occupants of a specific type at a given voxel coordinate.
 285    /// </summary>
 286    public static IEnumerable<T> GetVoxelOccupantsByType<T>(this VoxelGrid grid, VoxelIndex index) where T : IVoxelOccup
 287    {
 2288        return grid.TryGetVoxel(index, out Voxel? voxel)
 2289            ? grid.GetVoxelOccupantsByType<T>(voxel!)
 2290            : Enumerable.Empty<T>();
 291    }
 292
 293    /// <summary>
 294    /// Retrieves all occupants of a specific type at a given voxel.
 295    /// </summary>
 296    public static IEnumerable<T> GetVoxelOccupantsByType<T>(this VoxelGrid grid, Voxel voxel) where T : IVoxelOccupant
 297    {
 4298        return voxel == null
 4299            ? Enumerable.Empty<T>()
 4300            : grid.GetOccupants(voxel).OfType<T>();
 301    }
 302
 303    /// <summary>
 304    /// Retrieves a specific occupant at a given world-scoped voxel identity using an occupant ticket in the supplied wo
 305    /// </summary>
 306    public static bool TryGetVoxelOccupant(
 307        GridWorld world,
 308        WorldVoxelIndex index,
 309        int ticket,
 310        out IVoxelOccupant? occupant)
 311    {
 6312        occupant = null;
 6313        return world != null
 6314            && world.TryGetGridAndVoxel(index, out VoxelGrid? grid, out Voxel? voxel)
 6315            && grid!.TryGetVoxelOccupant(voxel!, ticket, out occupant);
 316    }
 317
 318    /// <summary>
 319    /// Retrieves a specific occupant at a given world position using an occupant ticket.
 320    /// </summary>
 321    public static bool TryGetVoxelOccupant(
 322        this VoxelGrid grid,
 323        Vector3d position,
 324        int ticket,
 325        out IVoxelOccupant? occupant)
 326    {
 3327        occupant = null;
 3328        return grid.TryGetVoxel(position, out Voxel? voxel)
 3329            && grid.TryGetVoxelOccupant(voxel!, ticket, out occupant);
 330    }
 331
 332    /// <summary>
 333    /// Retrieves a specific occupant at a given voxel coordinate using an occupant ticket.
 334    /// </summary>
 335    public static bool TryGetVoxelOccupant(
 336        this VoxelGrid grid,
 337        VoxelIndex index,
 338        int ticket,
 339        out IVoxelOccupant? occupant)
 340    {
 2341        occupant = null;
 2342        return grid.TryGetVoxel(index, out Voxel? voxel)
 2343            && grid.TryGetVoxelOccupant(voxel!, ticket, out occupant);
 344    }
 345
 346    /// <summary>
 347    /// Retrieves a specific occupant from a given voxel using an occupant ticket.
 348    /// </summary>
 349    public static bool TryGetVoxelOccupant(
 350        this VoxelGrid grid,
 351        Voxel voxel,
 352        int ticket,
 353        out IVoxelOccupant? occupant)
 354    {
 14355        occupant = null;
 14356        return voxel.IsOccupied
 14357            && grid.TryGetScanCell(voxel.ScanCellKey, out ScanCell? scanCell)
 14358            && scanCell!.IsOccupied
 14359            && scanCell.TryGetOccupantAt(voxel.WorldIndex, ticket, out occupant);
 360    }
 361
 362    /// <summary>
 363    /// Retrieves all occupants at a given world-scoped voxel identity in the supplied world.
 364    /// </summary>
 365    public static IEnumerable<IVoxelOccupant> GetOccupants(GridWorld world, WorldVoxelIndex index)
 366    {
 3367        if (world == null)
 1368            return Enumerable.Empty<IVoxelOccupant>();
 369
 2370        if (!world.TryGetGridAndVoxel(index, out VoxelGrid? grid, out Voxel? voxel))
 1371            return Enumerable.Empty<IVoxelOccupant>();
 372
 1373        return grid!.GetOccupants(voxel!);
 374    }
 375
 376    /// <summary>
 377    /// Retrieves all occupants at a given world position within the grid.
 378    /// </summary>
 379    public static IEnumerable<IVoxelOccupant> GetOccupants(this VoxelGrid grid, Vector3d position)
 380    {
 5381        return grid.TryGetVoxel(position, out Voxel? targetVoxel)
 5382            ? grid.GetOccupants(targetVoxel!)
 5383            : Enumerable.Empty<IVoxelOccupant>();
 384    }
 385
 386    /// <summary>
 387    /// Retrieves all occupants at a given voxel coordinate within the grid.
 388    /// </summary>
 389    public static IEnumerable<IVoxelOccupant> GetOccupants(this VoxelGrid grid, VoxelIndex index)
 390    {
 2391        return grid.TryGetVoxel(index, out Voxel? targetVoxel)
 2392            ? grid.GetOccupants(targetVoxel!)
 2393            : Enumerable.Empty<IVoxelOccupant>();
 394    }
 395
 396    /// <summary>
 397    /// Retrieves all occupants at a given voxel.
 398    /// </summary>
 399    public static IEnumerable<IVoxelOccupant> GetOccupants(this VoxelGrid grid, Voxel voxel)
 400    {
 11401        if (!voxel.IsOccupied)
 3402            return Enumerable.Empty<IVoxelOccupant>();
 403
 8404        if (!grid.TryGetScanCell(voxel.ScanCellKey, out ScanCell? scanCell))
 1405            return Enumerable.Empty<IVoxelOccupant>();
 406
 7407        return scanCell!.IsOccupied
 7408            ? scanCell.GetOccupants()
 7409            : Enumerable.Empty<IVoxelOccupant>();
 410    }
 411
 412    /// <summary>
 413    /// Retrieves occupants whose group Ids match a given condition at a world-scoped voxel identity in the supplied wor
 414    /// </summary>
 415    public static IEnumerable<IVoxelOccupant> GetConditionalOccupants(
 416        GridWorld world,
 417        WorldVoxelIndex index,
 418        Func<IVoxelOccupant, bool>? occupantCondition = null,
 419        Func<byte, bool>? groupCondition = null)
 420    {
 4421        if (world == null)
 1422            return Enumerable.Empty<IVoxelOccupant>();
 423
 3424        if (!world.TryGetGridAndVoxel(index, out VoxelGrid? grid, out Voxel? voxel))
 1425            return Enumerable.Empty<IVoxelOccupant>();
 426
 2427        return grid!.GetConditionalOccupants(voxel!, occupantCondition, groupCondition);
 428    }
 429
 430    /// <summary>
 431    /// Retrieves occupants whose group Ids match a given condition.
 432    /// </summary>
 433    public static IEnumerable<IVoxelOccupant> GetConditionalOccupants(
 434        this VoxelGrid grid,
 435        Vector3d position,
 436        Func<IVoxelOccupant, bool>? occupantCondition = null,
 437        Func<byte, bool>? groupCondition = null)
 438    {
 3439        return grid.TryGetVoxel(position, out Voxel? voxel)
 3440            ? grid.GetConditionalOccupants(voxel!, occupantCondition, groupCondition)
 3441            : Enumerable.Empty<IVoxelOccupant>();
 442    }
 443
 444    /// <summary>
 445    /// Retrieves occupants whose group Ids match a given condition.
 446    /// </summary>
 447    public static IEnumerable<IVoxelOccupant> GetConditionalOccupants(
 448        this VoxelGrid grid,
 449        VoxelIndex index,
 450        Func<IVoxelOccupant, bool>? occupantCondition = null,
 451        Func<byte, bool>? groupCondition = null)
 452    {
 4453        return grid.TryGetVoxel(index, out Voxel? voxel)
 4454            ? grid.GetConditionalOccupants(voxel!, occupantCondition, groupCondition)
 4455            : Enumerable.Empty<IVoxelOccupant>();
 456    }
 457
 458    /// <summary>
 459    /// Retrieves occupants at a given voxel that match a specified group condition.
 460    /// </summary>
 461    public static IEnumerable<IVoxelOccupant> GetConditionalOccupants(
 462        this VoxelGrid grid,
 463        Voxel targetVoxel,
 464        Func<IVoxelOccupant, bool>? occupantCondition = null,
 465        Func<byte, bool>? groupCondition = null)
 466    {
 12467        if (targetVoxel == null || !targetVoxel.IsOccupied)
 2468            return Enumerable.Empty<IVoxelOccupant>();
 469
 10470        if (!grid.TryGetScanCell(targetVoxel.ScanCellKey, out ScanCell? scanCell))
 1471            return Enumerable.Empty<IVoxelOccupant>();
 472
 9473        return scanCell!.IsOccupied
 9474            ? scanCell.GetConditionalOccupants(occupantCondition, groupCondition)
 9475            : Enumerable.Empty<IVoxelOccupant>();
 476    }
 477
 478    #endregion
 479
 480    #region Private Methods
 481
 482    private static IEnumerable<IVoxelOccupant> ScanRadiusIterator(
 483        GridWorld world,
 484        Vector3d position,
 485        Fixed64 radius,
 486        Func<IVoxelOccupant, bool>? occupantCondition,
 487        Func<byte, bool>? groupCondition)
 488    {
 10489        SwiftList<IVoxelOccupant> results = SwiftListPool<IVoxelOccupant>.Shared.Rent();
 490
 491        try
 492        {
 10493            ScanRadiusInto(world, position, radius, results, occupantCondition, groupCondition);
 494
 42495            foreach (IVoxelOccupant result in results)
 496            {
 11497                yield return result;
 498            }
 10499        }
 500        finally
 501        {
 10502            SwiftListPool<IVoxelOccupant>.Shared.Release(results);
 10503        }
 10504    }
 505
 506    private static IEnumerable<IVoxelOccupant> ScanRadius2dIterator(
 507        GridWorld world,
 508        Vector2d position,
 509        Fixed64 radius,
 510        Fixed64 layerY,
 511        Func<IVoxelOccupant, bool>? occupantCondition,
 512        Func<byte, bool>? groupCondition)
 513    {
 3514        SwiftList<IVoxelOccupant> results = SwiftListPool<IVoxelOccupant>.Shared.Rent();
 515
 516        try
 517        {
 3518            ScanRadiusInto(world, position, radius, results, layerY, occupantCondition, groupCondition);
 519
 12520            foreach (IVoxelOccupant result in results)
 521            {
 3522                yield return result;
 523            }
 3524        }
 525        finally
 526        {
 3527            SwiftListPool<IVoxelOccupant>.Shared.Release(results);
 3528        }
 3529    }
 530
 531    private static void AddRadiusOccupantsTo(
 532        GridWorld world,
 533        Vector3d position,
 534        Fixed64 radius,
 535        SwiftList<IVoxelOccupant> results,
 536        Func<IVoxelOccupant, bool>? occupantCondition,
 537        Func<byte, bool>? groupCondition)
 538    {
 11539        Fixed64 squaredRadius = radius * radius;
 11540        Vector3d boundsMin = position - radius;
 11541        Vector3d boundsMax = position + radius;
 11542        SwiftList<ScanCell> scanCells = SwiftListPool<ScanCell>.Shared.Rent();
 543
 544        try
 545        {
 11546            GridTracer.AddCoveredScanCellsTo(world, boundsMin, boundsMax, scanCells);
 547
 98548            for (int i = 0; i < scanCells.Count; i++)
 549            {
 38550                ScanCell scanCell = scanCells[i];
 38551                if (scanCell.IsOccupied)
 13552                    scanCell.AddOccupantsWithinRadiusTo(results, position, squaredRadius, occupantCondition, groupCondit
 553            }
 11554        }
 555        finally
 556        {
 11557            SwiftListPool<ScanCell>.Shared.Release(scanCells);
 11558        }
 11559    }
 560
 561    private static void AddRadiusOccupants2dTo(
 562        GridWorld world,
 563        Vector2d position,
 564        Fixed64 radius,
 565        Fixed64 layerY,
 566        SwiftList<IVoxelOccupant> results,
 567        Func<IVoxelOccupant, bool>? occupantCondition,
 568        Func<byte, bool>? groupCondition)
 569    {
 4570        Fixed64 squaredRadius = radius * radius;
 4571        Vector3d center = GridPlane2d.ToWorld(position, layerY);
 4572        Vector3d boundsMin = new(center.X - radius, center.Y, center.Z - radius);
 4573        Vector3d boundsMax = new(center.X + radius, center.Y, center.Z + radius);
 4574        SwiftList<ScanCell> scanCells = SwiftListPool<ScanCell>.Shared.Rent();
 575
 576        try
 577        {
 4578            GridTracer.AddCoveredScanCellsTo(world, boundsMin, boundsMax, scanCells);
 579
 20580            for (int i = 0; i < scanCells.Count; i++)
 581            {
 6582                ScanCell scanCell = scanCells[i];
 6583                if (scanCell.IsOccupied)
 4584                    scanCell.AddOccupantsWithinRadius2dTo(
 4585                        results,
 4586                        center,
 4587                        GetScanCellLocalLayerY(world, scanCell, layerY),
 4588                        squaredRadius,
 4589                        occupantCondition,
 4590                        groupCondition);
 591            }
 4592        }
 593        finally
 594        {
 4595            SwiftListPool<ScanCell>.Shared.Release(scanCells);
 4596        }
 4597    }
 598
 599    private static void AddRadiusOccupantsTo(
 600        GridWorld world,
 601        Vector3d position,
 602        Fixed64 radius,
 603        SwiftList<IVoxelOccupant> results,
 604        GridScanScratch scratch,
 605        Func<IVoxelOccupant, bool>? occupantCondition,
 606        Func<byte, bool>? groupCondition)
 607    {
 258608        Fixed64 squaredRadius = radius * radius;
 258609        Vector3d boundsMin = position - radius;
 258610        Vector3d boundsMax = position + radius;
 611
 258612        GridTracer.AddCoveredScanCellsTo(world, boundsMin, boundsMax, scratch.ScanCells, scratch);
 613
 2588614        for (int i = 0; i < scratch.ScanCells.Count; i++)
 615        {
 1036616            ScanCell scanCell = scratch.ScanCells[i];
 1036617            if (scanCell.IsOccupied)
 259618                scanCell.AddOccupantsWithinRadiusTo(results, position, squaredRadius, occupantCondition, groupCondition)
 619        }
 258620    }
 621
 622    private static void AddRadiusOccupants2dTo(
 623        GridWorld world,
 624        Vector2d position,
 625        Fixed64 radius,
 626        Fixed64 layerY,
 627        SwiftList<IVoxelOccupant> results,
 628        GridScanScratch scratch,
 629        Func<IVoxelOccupant, bool>? occupantCondition,
 630        Func<byte, bool>? groupCondition)
 631    {
 258632        Fixed64 squaredRadius = radius * radius;
 258633        Vector3d center = GridPlane2d.ToWorld(position, layerY);
 258634        Vector3d boundsMin = new(center.X - radius, center.Y, center.Z - radius);
 258635        Vector3d boundsMax = new(center.X + radius, center.Y, center.Z + radius);
 636
 258637        GridTracer.AddCoveredScanCellsTo(world, boundsMin, boundsMax, scratch.ScanCells, scratch);
 638
 2580639        for (int i = 0; i < scratch.ScanCells.Count; i++)
 640        {
 1032641            ScanCell scanCell = scratch.ScanCells[i];
 1032642            if (scanCell.IsOccupied)
 259643                scanCell.AddOccupantsWithinRadius2dTo(
 259644                    results,
 259645                    center,
 259646                    GetScanCellLocalLayerY(world, scanCell, layerY),
 259647                    squaredRadius,
 259648                    occupantCondition,
 259649                    groupCondition);
 650        }
 258651    }
 652
 653    private static void AddRadiusOccupantsTo<T>(
 654        GridWorld world,
 655        Vector3d position,
 656        Fixed64 radius,
 657        SwiftList<T> results,
 658        Func<IVoxelOccupant, bool>? occupantCondition,
 659        Func<byte, bool>? groupCondition) where T : IVoxelOccupant
 660    {
 1661        Fixed64 squaredRadius = radius * radius;
 1662        Vector3d boundsMin = position - radius;
 1663        Vector3d boundsMax = position + radius;
 1664        SwiftList<ScanCell> scanCells = SwiftListPool<ScanCell>.Shared.Rent();
 665
 666        try
 667        {
 1668            GridTracer.AddCoveredScanCellsTo(world, boundsMin, boundsMax, scanCells);
 669
 18670            for (int i = 0; i < scanCells.Count; i++)
 671            {
 8672                ScanCell scanCell = scanCells[i];
 8673                if (scanCell.IsOccupied)
 2674                    scanCell.AddOccupantsWithinRadiusTo(results, position, squaredRadius, occupantCondition, groupCondit
 675            }
 1676        }
 677        finally
 678        {
 1679            SwiftListPool<ScanCell>.Shared.Release(scanCells);
 1680        }
 1681    }
 682
 683    private static void AddRadiusOccupants2dTo<T>(
 684        GridWorld world,
 685        Vector2d position,
 686        Fixed64 radius,
 687        Fixed64 layerY,
 688        SwiftList<T> results,
 689        Func<IVoxelOccupant, bool>? occupantCondition,
 690        Func<byte, bool>? groupCondition) where T : IVoxelOccupant
 691    {
 2692        Fixed64 squaredRadius = radius * radius;
 2693        Vector3d center = GridPlane2d.ToWorld(position, layerY);
 2694        Vector3d boundsMin = new(center.X - radius, center.Y, center.Z - radius);
 2695        Vector3d boundsMax = new(center.X + radius, center.Y, center.Z + radius);
 2696        SwiftList<ScanCell> scanCells = SwiftListPool<ScanCell>.Shared.Rent();
 697
 698        try
 699        {
 2700            GridTracer.AddCoveredScanCellsTo(world, boundsMin, boundsMax, scanCells);
 701
 12702            for (int i = 0; i < scanCells.Count; i++)
 703            {
 4704                ScanCell scanCell = scanCells[i];
 4705                if (scanCell.IsOccupied)
 2706                    scanCell.AddOccupantsWithinRadius2dTo(
 2707                        results,
 2708                        center,
 2709                        GetScanCellLocalLayerY(world, scanCell, layerY),
 2710                        squaredRadius,
 2711                        occupantCondition,
 2712                        groupCondition);
 713            }
 2714        }
 715        finally
 716        {
 2717            SwiftListPool<ScanCell>.Shared.Release(scanCells);
 2718        }
 2719    }
 720
 721    private static void AddRadiusOccupantsTo<T>(
 722        GridWorld world,
 723        Vector3d position,
 724        Fixed64 radius,
 725        SwiftList<T> results,
 726        GridScanScratch scratch,
 727        Func<IVoxelOccupant, bool>? occupantCondition,
 728        Func<byte, bool>? groupCondition) where T : IVoxelOccupant
 729    {
 1730        Fixed64 squaredRadius = radius * radius;
 1731        Vector3d boundsMin = position - radius;
 1732        Vector3d boundsMax = position + radius;
 733
 1734        GridTracer.AddCoveredScanCellsTo(world, boundsMin, boundsMax, scratch.ScanCells, scratch);
 735
 10736        for (int i = 0; i < scratch.ScanCells.Count; i++)
 737        {
 4738            ScanCell scanCell = scratch.ScanCells[i];
 4739            if (scanCell.IsOccupied)
 1740                scanCell.AddOccupantsWithinRadiusTo(results, position, squaredRadius, occupantCondition, groupCondition)
 741        }
 1742    }
 743
 744    private static void AddRadiusOccupants2dTo<T>(
 745        GridWorld world,
 746        Vector2d position,
 747        Fixed64 radius,
 748        Fixed64 layerY,
 749        SwiftList<T> results,
 750        GridScanScratch scratch,
 751        Func<IVoxelOccupant, bool>? occupantCondition,
 752        Func<byte, bool>? groupCondition) where T : IVoxelOccupant
 753    {
 1754        Fixed64 squaredRadius = radius * radius;
 1755        Vector3d center = GridPlane2d.ToWorld(position, layerY);
 1756        Vector3d boundsMin = new(center.X - radius, center.Y, center.Z - radius);
 1757        Vector3d boundsMax = new(center.X + radius, center.Y, center.Z + radius);
 758
 1759        GridTracer.AddCoveredScanCellsTo(world, boundsMin, boundsMax, scratch.ScanCells, scratch);
 760
 10761        for (int i = 0; i < scratch.ScanCells.Count; i++)
 762        {
 4763            ScanCell scanCell = scratch.ScanCells[i];
 4764            if (scanCell.IsOccupied)
 2765                scanCell.AddOccupantsWithinRadius2dTo(
 2766                    results,
 2767                    center,
 2768                    GetScanCellLocalLayerY(world, scanCell, layerY),
 2769                    squaredRadius,
 2770                    occupantCondition,
 2771                    groupCondition);
 772        }
 1773    }
 774
 775    private static int GetScanCellLocalLayerY(
 776        GridWorld world,
 777        ScanCell scanCell,
 778        Fixed64 layerY)
 779    {
 267780        world.TryGetGrid(scanCell.GridIndex, out VoxelGrid? grid);
 267781        Vector3d layerProbe = new(grid!.BoundsMin.X, layerY, grid.BoundsMin.Z);
 267782        grid.TryGetVoxelIndex(layerProbe, out VoxelIndex layerIndex);
 267783        return layerIndex.y;
 784    }
 785
 786    #endregion
 787}

Methods/Properties

ScanRadius(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
ScanRadius(GridForge.Grids.GridWorld,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
ScanRadius(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
ScanRadius(GridForge.Grids.GridWorld,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
ScanRadiusInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,SwiftCollections.SwiftList`1<GridForge.Spatial.IVoxelOccupant>,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
ScanRadiusInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,SwiftCollections.SwiftList`1<GridForge.Spatial.IVoxelOccupant>,FixedMathSharp.Fixed64,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
ScanRadiusInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,SwiftCollections.SwiftList`1<GridForge.Spatial.IVoxelOccupant>,GridForge.Grids.GridScanScratch,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
ScanRadiusInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,SwiftCollections.SwiftList`1<GridForge.Spatial.IVoxelOccupant>,GridForge.Grids.GridScanScratch,FixedMathSharp.Fixed64,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
ScanRadiusInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,SwiftCollections.SwiftList`1<T>,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
ScanRadiusInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,SwiftCollections.SwiftList`1<T>,FixedMathSharp.Fixed64,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
ScanRadiusInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,SwiftCollections.SwiftList`1<T>,GridForge.Grids.GridScanScratch,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
ScanRadiusInto(GridForge.Grids.GridWorld,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,SwiftCollections.SwiftList`1<T>,GridForge.Grids.GridScanScratch,FixedMathSharp.Fixed64,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
GetVoxelOccupantsByType(GridForge.Grids.GridWorld,GridForge.Spatial.WorldVoxelIndex)
GetVoxelOccupantsByType(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d)
GetVoxelOccupantsByType(GridForge.Grids.VoxelGrid,GridForge.Spatial.VoxelIndex)
GetVoxelOccupantsByType(GridForge.Grids.VoxelGrid,GridForge.Grids.Voxel)
TryGetVoxelOccupant(GridForge.Grids.GridWorld,GridForge.Spatial.WorldVoxelIndex,System.Int32,GridForge.Spatial.IVoxelOccupant&)
TryGetVoxelOccupant(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d,System.Int32,GridForge.Spatial.IVoxelOccupant&)
TryGetVoxelOccupant(GridForge.Grids.VoxelGrid,GridForge.Spatial.VoxelIndex,System.Int32,GridForge.Spatial.IVoxelOccupant&)
TryGetVoxelOccupant(GridForge.Grids.VoxelGrid,GridForge.Grids.Voxel,System.Int32,GridForge.Spatial.IVoxelOccupant&)
GetOccupants(GridForge.Grids.GridWorld,GridForge.Spatial.WorldVoxelIndex)
GetOccupants(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d)
GetOccupants(GridForge.Grids.VoxelGrid,GridForge.Spatial.VoxelIndex)
GetOccupants(GridForge.Grids.VoxelGrid,GridForge.Grids.Voxel)
GetConditionalOccupants(GridForge.Grids.GridWorld,GridForge.Spatial.WorldVoxelIndex,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
GetConditionalOccupants(GridForge.Grids.VoxelGrid,FixedMathSharp.Vector3d,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
GetConditionalOccupants(GridForge.Grids.VoxelGrid,GridForge.Spatial.VoxelIndex,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
GetConditionalOccupants(GridForge.Grids.VoxelGrid,GridForge.Grids.Voxel,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
ScanRadiusIterator()
<>m__Finally1()
ScanRadius2dIterator()
<>m__Finally1()
AddRadiusOccupantsTo(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,SwiftCollections.SwiftList`1<GridForge.Spatial.IVoxelOccupant>,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
AddRadiusOccupants2dTo(GridForge.Grids.GridWorld,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,SwiftCollections.SwiftList`1<GridForge.Spatial.IVoxelOccupant>,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
AddRadiusOccupantsTo(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,SwiftCollections.SwiftList`1<GridForge.Spatial.IVoxelOccupant>,GridForge.Grids.GridScanScratch,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
AddRadiusOccupants2dTo(GridForge.Grids.GridWorld,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,SwiftCollections.SwiftList`1<GridForge.Spatial.IVoxelOccupant>,GridForge.Grids.GridScanScratch,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
AddRadiusOccupantsTo(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,SwiftCollections.SwiftList`1<T>,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
AddRadiusOccupants2dTo(GridForge.Grids.GridWorld,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,SwiftCollections.SwiftList`1<T>,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
AddRadiusOccupantsTo(GridForge.Grids.GridWorld,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,SwiftCollections.SwiftList`1<T>,GridForge.Grids.GridScanScratch,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
AddRadiusOccupants2dTo(GridForge.Grids.GridWorld,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,SwiftCollections.SwiftList`1<T>,GridForge.Grids.GridScanScratch,System.Func`2<GridForge.Spatial.IVoxelOccupant,System.Boolean>,System.Func`2<System.Byte,System.Boolean>)
GetScanCellLocalLayerY(GridForge.Grids.GridWorld,GridForge.Grids.ScanCell,FixedMathSharp.Fixed64)