< Summary

Information
Class: SwiftCollections.Query.SwiftOctree<T>
Assembly: SwiftCollections
File(s): /home/runner/work/SwiftCollections/SwiftCollections/src/SwiftCollections/Query/Octree/SwiftOctree.BoundVolume.cs
Line coverage
100%
Covered lines: 50
Uncovered lines: 0
Coverable lines: 50
Total lines: 110
Line coverage: 100%
Branch coverage
88%
Covered branches: 39
Total branches: 44
Branch coverage: 88.6%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
.ctor(...)100%66100%
ContainsBounds(...)50%1010100%
CanSubdivide(...)100%44100%
TryGetContainingChildIndex(...)100%1212100%
CreateChildBounds(...)100%1212100%

File(s)

/home/runner/work/SwiftCollections/SwiftCollections/src/SwiftCollections/Query/Octree/SwiftOctree.BoundVolume.cs

#LineLine coverage
 1using System;
 2using System.Numerics;
 3
 4namespace SwiftCollections.Query;
 5
 6/// <summary>
 7/// Represents a numerics-backed octree optimized for hierarchical spatial queries.
 8/// </summary>
 9public sealed class SwiftOctree<TKey> : SwiftOctree<TKey, BoundVolume>
 10    where TKey : notnull, IEquatable<TKey>
 11{
 12    /// <summary>
 13    /// Initializes a new instance of the <see cref="SwiftOctree{TKey}"/> class.
 14    /// </summary>
 15    /// <param name="worldBounds">The immutable world bounds covered by the octree.</param>
 16    /// <param name="options">Backend-neutral octree options.</param>
 17    /// <param name="minNodeSize">The minimum child-node axis length allowed for numerics subdivision.</param>
 18    public SwiftOctree(BoundVolume worldBounds, SwiftOctreeOptions options, float minNodeSize)
 1619        : base(worldBounds, options, new BoundVolumeOctreePartitioner(minNodeSize)) { }
 20
 21    private sealed class BoundVolumeOctreePartitioner : IOctreeBoundsPartitioner<BoundVolume>
 22    {
 23        private readonly float _minNodeSize;
 24
 1025        public BoundVolumeOctreePartitioner(float minNodeSize)
 26        {
 1027            if (float.IsNaN(minNodeSize) || float.IsInfinity(minNodeSize) || minNodeSize <= 0f)
 428                throw new ArgumentOutOfRangeException(nameof(minNodeSize), minNodeSize, "Minimum node size must be a fin
 29
 630            _minNodeSize = minNodeSize;
 631        }
 32
 33        public bool ContainsBounds(BoundVolume outer, BoundVolume inner)
 34        {
 2135            return inner.Min.X >= outer.Min.X &&
 2136                   inner.Min.Y >= outer.Min.Y &&
 2137                   inner.Min.Z >= outer.Min.Z &&
 2138                   inner.Max.X <= outer.Max.X &&
 2139                   inner.Max.Y <= outer.Max.Y &&
 2140                   inner.Max.Z <= outer.Max.Z;
 41        }
 42
 43        public bool CanSubdivide(BoundVolume bounds)
 44        {
 445            Vector3 childSize = bounds.Size * 0.5f;
 446            return childSize.X >= _minNodeSize &&
 447                   childSize.Y >= _minNodeSize &&
 448                   childSize.Z >= _minNodeSize;
 49        }
 50
 51        public bool TryGetContainingChildIndex(BoundVolume nodeBounds, BoundVolume entryBounds, out int childIndex)
 52        {
 1553            Vector3 midpoint = (nodeBounds.Min + nodeBounds.Max) * 0.5f;
 54
 55            int xBit;
 1556            if (entryBounds.Min.X >= midpoint.X)
 657                xBit = 1;
 958            else if (entryBounds.Max.X <= midpoint.X)
 859                xBit = 0;
 60            else
 61            {
 162                childIndex = -1;
 163                return false;
 64            }
 65
 66            int yBit;
 1467            if (entryBounds.Min.Y >= midpoint.Y)
 668                yBit = 1;
 869            else if (entryBounds.Max.Y <= midpoint.Y)
 770                yBit = 0;
 71            else
 72            {
 173                childIndex = -1;
 174                return false;
 75            }
 76
 77            int zBit;
 1378            if (entryBounds.Min.Z >= midpoint.Z)
 679                zBit = 1;
 780            else if (entryBounds.Max.Z <= midpoint.Z)
 681                zBit = 0;
 82            else
 83            {
 184                childIndex = -1;
 185                return false;
 86            }
 87
 1288            childIndex = xBit | (yBit << 1) | (zBit << 2);
 1289            return true;
 90        }
 91
 92        public BoundVolume CreateChildBounds(BoundVolume parentBounds, int childIndex)
 93        {
 2494            Vector3 midpoint = (parentBounds.Min + parentBounds.Max) * 0.5f;
 2495            bool upperX = (childIndex & 1) != 0;
 2496            bool upperY = (childIndex & 2) != 0;
 2497            bool upperZ = (childIndex & 4) != 0;
 98
 2499            return new BoundVolume(
 24100                new Vector3(
 24101                    upperX ? midpoint.X : parentBounds.Min.X,
 24102                    upperY ? midpoint.Y : parentBounds.Min.Y,
 24103                    upperZ ? midpoint.Z : parentBounds.Min.Z),
 24104                new Vector3(
 24105                    upperX ? parentBounds.Max.X : midpoint.X,
 24106                    upperY ? parentBounds.Max.Y : midpoint.Y,
 24107                    upperZ ? parentBounds.Max.Z : midpoint.Z));
 108        }
 109    }
 110}