< Summary

Class:Towel.DataStructures.OmnitreeBoundsLinked<T1, T2, T3, T4>
Assembly:Towel
File(s):File 1: /home/runner/work/Towel/Towel/Sources/Towel/DataStructures/Omnitree.cs
Covered lines:0
Uncovered lines:861
Coverable lines:861
Total lines:30951
Line coverage:0% (0 of 861)
Covered branches:0
Total branches:284
Branch coverage:0% (0 of 284)

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
File 1: .cctor()100%10%
File 1: .ctor(...)100%10%
File 1: .ctor(...)100%10%
File 1: get_Item(...)0%80%
File 1: set_Item(...)0%140%
File 1: get_Depth()0%20%
File 1: .ctor(...)100%10%
File 1: .ctor(...)100%10%
File 1: .ctor(...)0%20%
File 1: Add(...)100%10%
File 1: Clone()100%10%
File 1: .ctor(...)0%80%
File 1: .ctor(...)0%120%
File 1: .ctor(...)0%120%
File 1: get_Dimensions()100%10%
File 1: get_GetBounds()100%10%
File 1: get_Compare1()100%10%
File 1: get_Compare2()100%10%
File 1: get_Compare3()100%10%
File 1: get_Count()100%10%
File 1: get_MaxDepth()0%40%
File 1: get_NodeCount()0%20%
File 1: TryAdd(...)100%10%
File 1: Add(...)0%80%
File 1: Add(...)0%140%
File 1: DetermineMedians(...)0%80%
File 1: DetermineChildBounds(...)0%60%
File 1: Clear()100%10%
File 1: Clone()100%10%
File 1: CountSubSpaceEncapsulated(...)100%10%
File 1: CountSubSpaceEncapsulated(...)100%10%
File 1: CountSubSpaceEncapsulated(...)100%10%
File 1: CountSubSpaceEncapsulated(...)100%10%
File 1: CountSubSpaceOverlapped(...)100%10%
File 1: CountSubSpaceOverlapped(...)100%10%
File 1: CountSubSpaceOverlapped(...)100%10%
File 1: CountSubSpaceOverlapped(...)100%10%
File 1: CountSubSpaceEncapsulated(...)100%10%
File 1: CountSubSpaceOverlapped(...)100%10%
File 1: CountSubSpaceBase(...)0%140%
File 1: Update()100%10%
File 1: Update(...)0%160%
File 1: Update(...)100%10%
File 1: Update(...)100%10%
File 1: Update(...)100%10%
File 1: Update(...)100%10%
File 1: Update(...)0%180%
File 1: Remove(...)100%10%
File 1: Remove(...)0%200%
File 1: RemoveEncapsulated(...)100%10%
File 1: RemoveEncapsulated(...)100%10%
File 1: RemoveEncapsulated(...)100%10%
File 1: RemoveEncapsulated(...)100%10%
File 1: RemoveOverlapped(...)100%10%
File 1: RemoveOverlapped(...)100%10%
File 1: RemoveOverlapped(...)100%10%
File 1: RemoveBase(...)0%180%
File 1: RemoveEncapsulated(...)100%10%
File 1: RemoveEncapsulated(...)100%10%
File 1: RemoveEncapsulated(...)100%10%
File 1: RemoveOverlapped(...)100%10%
File 1: RemoveOverlapped(...)100%10%
File 1: RemoveOverlapped(...)100%10%
File 1: RemoveBase(...)0%200%
File 1: TryRemove(...)100%10%
File 1: Remove(...)100%10%
File 1: Remove(...)100%10%
File 1: RemoveOverlapped(...)100%10%
File 1: RemoveOverlapped(...)100%10%
File 1: Stepper(...)100%10%
File 1: Stepper(...)0%60%
File 1: StepperBreak(...)100%10%
File 1: StepperBreak(...)0%100%
File 1: Stepper(...)100%10%
File 1: Stepper(...)0%100%
File 1: StepperEncapsulated(...)100%10%
File 1: StepperEncapsulated(...)100%10%
File 1: StepperEncapsulated(...)100%10%
File 1: StepperOverlapped(...)100%10%
File 1: StepperOverlapped(...)100%10%
File 1: StepperOverlapped(...)100%10%
File 1: StepperBase(...)0%120%
File 1: StepperEncapsulated(...)100%10%
File 1: StepperEncapsulated(...)100%10%
File 1: StepperEncapsulated(...)100%10%
File 1: StepperOverlapped(...)100%10%
File 1: StepperOverlapped(...)100%10%
File 1: StepperOverlapped(...)100%10%
File 1: StepperBase(...)0%180%
File 1: StepperOverlapped(...)100%10%
File 1: StepperOverlapped(...)100%10%
File 1: System.Collections.IEnumerable.GetEnumerator()100%10%
File 1: GetEnumerator()100%10%
File 1: ToArray()100%10%
File 1: StraddlesLines(...)100%10%
File 1: DetermineChildIndex(...)0%140%
File 1: ShrinkChild(...)0%20%
File 1: ReduceParentCounts(...)100%10%
File 1: IncreaseParentCounts(...)0%20%
File 1: InclusionCheck(...)100%10%
File 1: EncapsulationCheck(...)100%10%
File 1: EncapsulationCheck(...)100%10%
File 1: EqualsCheck(...)100%10%
File 1: GetEncapsulationParent(...)0%40%
File 1: GetBoundings(...)100%10%

File(s)

/home/runner/work/Towel/Towel/Sources/Towel/DataStructures/Omnitree.cs

#LineLine coverage
 1//------------------------------------------------------------------------------
 2// <auto-generated>
 3//  This code was generated from the "Omnitree.tt" T4 Text Template.
 4// </auto-generated>
 5//------------------------------------------------------------------------------
 6
 7#pragma warning disable
 8
 9using System;
 10using System.Numerics;
 11using static Towel.Statics;
 12
 13namespace Towel.DataStructures
 14{
 15  #region Notes
 16
 17  // Visualizations--------------------------------------------------
 18  //
 19  // 1 Dimensional:
 20  //
 21  //  -1D |-----------|-----------| +1D
 22  //
 23  //       <--- 0 ---> <--- 1 --->
 24  //
 25  // 2 Dimensional:
 26  //       _____________________
 27  //      |          |          |  +2D
 28  //      |          |          |   ^
 29  //      |     2    |     3    |   |
 30  //      |          |          |   |
 31  //      |----------|----------|   |
 32  //      |          |          |   |
 33  //      |          |          |   |
 34  //      |     0    |     1    |   |
 35  //      |          |          |   v
 36  //      |__________|__________|  -2D
 37  //
 38  //       -1D <-----------> +1D
 39  //
 40  // 3 Dimensional:
 41  //
 42  //            +3D     _____________________
 43  //           7       /         /          /|
 44  //          /       /    6    /     7    / |
 45  //         /       /---------/----------/  |
 46  //        /       /    2    /     3    /|  |
 47  //       L       /_________/__________/ |  |
 48  //    -3D       |          |          | | /|          +2D
 49  //              |          |          | |/ |           ^
 50  //              |     2    |     3    | /  |           |
 51  //              |          |          |/|  | <-- 5     |
 52  //              |----------|----------| |  |           |
 53  //              |          |          | |  /           |
 54  //              |          |          | | /            |
 55  //              |     0    |     1    | |/             |
 56  //              |          |          | /              v
 57  //              |__________|__________|/              -2D
 58  //
 59  //                   ^
 60  //                   |
 61  //                   4 (behind 0)
 62  //
 63  //               -1D <-----------> +1D
 64
 65  #endregion
 66
 67  /// <summary>Contains the necessary type definitions for the various omnitree types.</summary>
 68  public static partial class Omnitree
 69  {
 70    #region Spacial Types (Bound, Vector, Bounds), Location/Bounding Delegates, And Dimensional Helper Methods
 71
 72    #region 1 Dimensional
 73
 74    /// <summary>Represents a 1D vector.</summary>
 75    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 76    public struct Vector<A1
 77      >
 78    {
 79      /// <summary>The value along axis 1.</summary>
 80      public A1 Axis1;
 81
 82      /// <summary>Returns a vector with defaulted values.</summary>
 83      public static Vector<A1
 84        > Default =>
 85        new Vector<A1
 86          >(default(A1)
 87          );
 88
 89      /// <summary>A location along each axis.</summary>
 90      /// <param name="axis1">The location along axis 1.</param>
 91      public Vector(A1 axis1
 92        )
 93      {
 94        this.Axis1 = axis1;
 95      }
 96    }
 97
 98    /// <summary>Represents a 1D bounding box.</summary>
 99    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 100    public struct Bounds<A1
 101>
 102    {
 103      /// <summary>The minimum value along the 1 dimension.</summary>
 104      public Bound<A1> Min1;
 105      /// <summary>The maximum value along the 1 dimension.</summary>
 106      public Bound<A1> Max1;
 107
 108      /// <summary>Extends infinitely along each axis.</summary>
 109      public static Bounds<A1
 110        > None =>
 111        new Bounds<A1
 112          >(Bound<A1>.None, Bound<A1>.None
 113          );
 114
 115      /// <summary>A set of values denoting a range (or lack of range) along each axis.</summary>
 116      public Bounds(
 117        Bound<A1> min1, Bound<A1> max1
 118        )
 119      {
 120        this.Min1 = min1;
 121        this.Max1 = max1;
 122      }
 123    }
 124
 125    /// <summary>Delegate for locating an item in 1D space.</summary>
 126    /// <typeparam name="T">The generic type of the item to locate.</typeparam>
 127    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 128    /// <param name="item">The item to locate.</param>
 129    /// <param name="axis1">The location of the item along the 1 dimension.</param>
 130    public delegate void Location<T, A1
 131      >(T item, out A1 axis1
 132      );
 133
 134    /// <summary>Delegate for getting the 1D bounding box of an item.</summary>
 135    /// <typeparam name="T">The generic type of the item to get the bounding box of.</typeparam>
 136    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 137    /// <param name="item">The item to get the bounding box of.</param>
 138    /// <param name="min1">The minimum bound of the item along the 1 dimension.</param>
 139    /// <param name="max1">The maximum bound of the item along the 1 dimension.</param>
 140    public delegate void GetBounds<T, A1
 141      >(T item, out Bound<A1> min1, out Bound<A1> max1
 142      );
 143
 144    /// <summary>Delegate for getting the 1D bounding box of an item.</summary>
 145    /// <typeparam name="T">The generic type of the item to get the bounding box of.</typeparam>
 146    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 147    /// <param name="item">The item to get the bounding box of.</param>
 148    /// <param name="min1">The minimum bound of the item along the 1 dimension.</param>
 149    /// <param name="max1">The maximum bound of the item along the 1 dimension.</param>
 150    public delegate void GetBoundings<T, A1
 151      >(T item, out A1 min1, out A1 max1
 152      );
 153
 154    /// <summary>Converts an Omnitree.GetBoundings delegate into an Omnitree.GetBounds delegate.</summary>
 155    /// <typeparam name="T">The generic type to get the bounds of.</typeparam>
 156    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 157    /// <param name="getBoundings">The Omnitree.GetBoundings to convert into a Omnitree.GetBounds.</param>
 158    /// <returns>The converted Omnitree.GetBounds delegate.</returns>
 159    public static GetBounds<T, A1
 160      > ConvertToGetBounds<T, A1
 161      >(GetBoundings<T, A1
 162      > getBoundings) =>
 163      (T item
 164      , out Bound<A1> minBound1, out Bound<A1> maxBound1) =>
 165      {
 166        A1 min1; A1 max1;
 167        getBoundings(item
 168          , out min1, out max1
 169          );
 170        minBound1 = min1; maxBound1 = max1;
 171      };
 172
 173    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 174    /// <returns>True if the spaces overlap; False if not.</returns>
 175    public static bool InclusionCheck<Axis1>(Omnitree.Bounds<Axis1> a, Omnitree.Bounds<Axis1> b,
 176      Func<Axis1, Axis1, CompareResult> compare1) =>
 177      a.Max1.Exists && b.Min1.Exists && compare1(a.Max1.Value, b.Min1.Value) is Less ? false :
 178      a.Min1.Exists && b.Max1.Exists && compare1(a.Min1.Value, b.Max1.Value) is Greater ? false :
 179      true;
 180
 181    /// <summary>Checks if a space encapsulates a point.</summary>
 182    /// <returns>True if the space encapsulates the point; False if not.</returns>
 183    public static bool EncapsulationCheck<Axis1>(Omnitree.Bounds<Axis1> bounds, Omnitree.Vector<Axis1> vector,
 184      Func<Axis1, Axis1, CompareResult> compare1) =>
 185      // if the location is not outside the bounds, it must be inside
 186      bounds.Min1.Exists && compare1(vector.Axis1, bounds.Min1.Value) is CompareResult.Less ? false :
 187      bounds.Max1.Exists && compare1(vector.Axis1, bounds.Max1.Value) is CompareResult.Greater ? false :
 188      true;
 189
 190    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 191    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 192    public static bool EncapsulationCheck<Axis1>(Omnitree.Bounds<Axis1> a, Omnitree.Bounds<Axis1> b,
 193      Func<Axis1, Axis1, CompareResult> compare1) =>
 194      (a.Min1.Exists && !b.Min1.Exists)
 195      ? false :
 196      (a.Max1.Exists && !b.Max1.Exists)
 197      ? false :
 198      b.Min1.Exists && a.Min1.Exists && compare1(a.Min1.Value, b.Min1.Value) != CompareResult.Less ? false :
 199      b.Max1.Exists && a.Max1.Exists && compare1(a.Max1.Value, b.Max1.Value) != CompareResult.Greater ? false :
 200      true;
 201
 202    /// <summary>Checks for equality between two locations.</summary>
 203    /// <returns>True if equal; False if not;</returns>
 204    public static bool EqualsCheck<Axis1>(Omnitree.Vector<Axis1> a, Omnitree.Vector<Axis1> b,
 205      Func<Axis1, Axis1, bool> equate1) =>
 206      !equate1(a.Axis1, b.Axis1) ? false :
 207      true;
 208
 209    /// <summary>Checks if a bounds straddles a point if the point extended as a plane along each dimension.</summary>
 210    /// <typeparam name="Axis1">The generic type of the 1 dimension.</typeparam>
 211    /// <param name="bounds">The bounds to determine if it straddles the extended point.</param>
 212    /// <param name="vector">The point representing an extended plan along each axis.</param>
 213    /// <param name="compare1">The delegate for comparing values along the the 1 dimension.</param>
 214    /// <returns>True if the extended point was straddled or false if not.</returns>
 215    public static bool StraddlesLines<Axis1>(Omnitree.Bounds<Axis1> bounds, Omnitree.Vector<Axis1> vector,
 216      Func<Axis1, Axis1, CompareResult> compare1) =>
 217      (!bounds.Min1.Exists || (bounds.Min1.Exists && compare1(bounds.Min1.Value, vector.Axis1) != CompareResult.Greater)
 218      (!bounds.Max1.Exists || (bounds.Max1.Exists && compare1(bounds.Max1.Value, vector.Axis1) != CompareResult.Less)) ?
 219      false;
 220
 221    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 222    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 223    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 224    /// <param name="omnitree">The omnitree to remove from.</param>
 225    /// <param name="removal">The value to have all occurences removed.</param>
 226    public static void Remove<T, Axis1>(this IOmnitreePoints<T, Axis1> omnitree, T removal) => Remove(omnitree, removal,
 227
 228    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 229    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 230    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 231    /// <param name="omnitree">The omnitree to remove from.</param>
 232    /// <param name="removal">The value to have all occurences removed.</param>
 233    /// <param name="equate">The delegate for checking for equality.</param>
 234    public static void Remove<T, Axis1>(this IOmnitreePoints<T, Axis1> omnitree, T removal, Func<T, T, bool> equate)
 235    {
 236      Axis1 axis1;
 237      omnitree.Locate(removal, out axis1
 238        );
 239      omnitree.Remove(
 240        axis1,
 241        x => equate(x, removal));
 242    }
 243
 244    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 245    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 246    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 247    /// <param name="omnitree">The omnitree to remove from.</param>
 248    /// <param name="removal">The value to have all occurences removed.</param>
 249    public static void Remove<T, Axis1>(this IOmnitreeBounds<T, Axis1> omnitree, T removal) => Remove(omnitree, removal,
 250
 251    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 252    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 253    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 254    /// <param name="omnitree">The omnitree to remove from.</param>
 255    /// <param name="removal">The value to have all occurences removed.</param>
 256    /// <param name="equate">The delegate for checking for equality.</param>
 257    public static void Remove<T, Axis1>(this IOmnitreeBounds<T, Axis1> omnitree,T removal, Func<T, T, bool> equate)
 258    {
 259      Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 260      omnitree.GetBounds(removal, out min1, out max1
 261        );
 262      omnitree.RemoveOverlapped(min1, max1
 263        , x => equate(x, removal));
 264    }
 265
 266    #endregion
 267
 268    #region 2 Dimensional
 269
 270    /// <summary>Represents a 2D vector.</summary>
 271    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 272    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 273    public struct Vector<A1
 274      , A2
 275      >
 276    {
 277      /// <summary>The value along axis 1.</summary>
 278      public A1 Axis1;
 279      /// <summary>The value along axis 2.</summary>
 280      public A2 Axis2;
 281
 282      /// <summary>Returns a vector with defaulted values.</summary>
 283      public static Vector<A1
 284, A2
 285        > Default =>
 286        new Vector<A1
 287          , A2
 288          >(default(A1)
 289          , default(A2)
 290          );
 291
 292      /// <summary>A location along each axis.</summary>
 293      /// <param name="axis1">The location along axis 1.</param>
 294      /// <param name="axis2">The location along axis 2.</param>
 295      public Vector(A1 axis1
 296        , A2 axis2
 297        )
 298      {
 299        this.Axis1 = axis1;
 300        this.Axis2 = axis2;
 301      }
 302    }
 303
 304    /// <summary>Represents a 2D bounding box.</summary>
 305    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 306    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 307    public struct Bounds<A1
 308      , A2
 309>
 310    {
 311      /// <summary>The minimum value along the 1 dimension.</summary>
 312      public Bound<A1> Min1;
 313      /// <summary>The maximum value along the 1 dimension.</summary>
 314      public Bound<A1> Max1;
 315      /// <summary>The minimum value along the 2 dimension.</summary>
 316      public Bound<A2> Min2;
 317      /// <summary>The maximum value along the 2 dimension.</summary>
 318      public Bound<A2> Max2;
 319
 320      /// <summary>Extends infinitely along each axis.</summary>
 321      public static Bounds<A1
 322        , A2
 323        > None =>
 324        new Bounds<A1
 325          , A2
 326          >(Bound<A1>.None, Bound<A1>.None
 327          , Bound<A2>.None, Bound<A2>.None
 328          );
 329
 330      /// <summary>A set of values denoting a range (or lack of range) along each axis.</summary>
 331      public Bounds(
 332        Bound<A1> min1, Bound<A1> max1
 333        , Bound<A2> min2, Bound<A2> max2
 334        )
 335      {
 336        this.Min1 = min1;
 337        this.Max1 = max1;
 338        this.Min2 = min2;
 339        this.Max2 = max2;
 340      }
 341    }
 342
 343    /// <summary>Delegate for locating an item in 2D space.</summary>
 344    /// <typeparam name="T">The generic type of the item to locate.</typeparam>
 345    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 346    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 347    /// <param name="item">The item to locate.</param>
 348    /// <param name="axis1">The location of the item along the 1 dimension.</param>
 349    /// <param name="axis2">The location of the item along the 2 dimension.</param>
 350    public delegate void Location<T, A1
 351      , A2
 352      >(T item, out A1 axis1
 353      , out A2 axis2
 354      );
 355
 356    /// <summary>Delegate for getting the 2D bounding box of an item.</summary>
 357    /// <typeparam name="T">The generic type of the item to get the bounding box of.</typeparam>
 358    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 359    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 360    /// <param name="item">The item to get the bounding box of.</param>
 361    /// <param name="min1">The minimum bound of the item along the 1 dimension.</param>
 362    /// <param name="max1">The maximum bound of the item along the 1 dimension.</param>
 363    /// <param name="min2">The minimum bound of the item along the 2 dimension.</param>
 364    /// <param name="max2">The maximum bound of the item along the 2 dimension.</param>
 365    public delegate void GetBounds<T, A1
 366      , A2
 367      >(T item, out Bound<A1> min1, out Bound<A1> max1
 368      , out Bound<A2> min2, out Bound<A2> max2
 369      );
 370
 371    /// <summary>Delegate for getting the 2D bounding box of an item.</summary>
 372    /// <typeparam name="T">The generic type of the item to get the bounding box of.</typeparam>
 373    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 374    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 375    /// <param name="item">The item to get the bounding box of.</param>
 376    /// <param name="min1">The minimum bound of the item along the 1 dimension.</param>
 377    /// <param name="max1">The maximum bound of the item along the 1 dimension.</param>
 378    /// <param name="min2">The minimum bound of the item along the 2 dimension.</param>
 379    /// <param name="max2">The maximum bound of the item along the 2 dimension.</param>
 380    public delegate void GetBoundings<T, A1
 381      , A2
 382      >(T item, out A1 min1, out A1 max1
 383      , out A2 min2, out A2 max2
 384      );
 385
 386    /// <summary>Converts an Omnitree.GetBoundings delegate into an Omnitree.GetBounds delegate.</summary>
 387    /// <typeparam name="T">The generic type to get the bounds of.</typeparam>
 388    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 389    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 390    /// <param name="getBoundings">The Omnitree.GetBoundings to convert into a Omnitree.GetBounds.</param>
 391    /// <returns>The converted Omnitree.GetBounds delegate.</returns>
 392    public static GetBounds<T, A1
 393      , A2
 394      > ConvertToGetBounds<T, A1
 395      , A2
 396      >(GetBoundings<T, A1
 397      , A2
 398      > getBoundings) =>
 399      (T item
 400      , out Bound<A1> minBound1, out Bound<A1> maxBound1      , out Bound<A2> minBound2, out Bound<A2> maxBound2) =>
 401      {
 402        A1 min1; A1 max1;
 403        A2 min2; A2 max2;
 404        getBoundings(item
 405          , out min1, out max1
 406          , out min2, out max2
 407          );
 408        minBound1 = min1; maxBound1 = max1;
 409        minBound2 = min2; maxBound2 = max2;
 410      };
 411
 412    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 413    /// <returns>True if the spaces overlap; False if not.</returns>
 414    public static bool InclusionCheck<Axis1, Axis2>(Omnitree.Bounds<Axis1, Axis2> a, Omnitree.Bounds<Axis1, Axis2> b,
 415      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2) =>
 416      a.Max1.Exists && b.Min1.Exists && compare1(a.Max1.Value, b.Min1.Value) is Less ? false :
 417      a.Min1.Exists && b.Max1.Exists && compare1(a.Min1.Value, b.Max1.Value) is Greater ? false :
 418      a.Max2.Exists && b.Min2.Exists && compare2(a.Max2.Value, b.Min2.Value) is Less ? false :
 419      a.Min2.Exists && b.Max2.Exists && compare2(a.Min2.Value, b.Max2.Value) is Greater ? false :
 420      true;
 421
 422    /// <summary>Checks if a space encapsulates a point.</summary>
 423    /// <returns>True if the space encapsulates the point; False if not.</returns>
 424    public static bool EncapsulationCheck<Axis1, Axis2>(Omnitree.Bounds<Axis1, Axis2> bounds, Omnitree.Vector<Axis1, Axi
 425      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2) =>
 426      // if the location is not outside the bounds, it must be inside
 427      bounds.Min1.Exists && compare1(vector.Axis1, bounds.Min1.Value) is CompareResult.Less ? false :
 428      bounds.Max1.Exists && compare1(vector.Axis1, bounds.Max1.Value) is CompareResult.Greater ? false :
 429      bounds.Min2.Exists && compare2(vector.Axis2, bounds.Min2.Value) is CompareResult.Less ? false :
 430      bounds.Max2.Exists && compare2(vector.Axis2, bounds.Max2.Value) is CompareResult.Greater ? false :
 431      true;
 432
 433    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 434    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 435    public static bool EncapsulationCheck<Axis1, Axis2>(Omnitree.Bounds<Axis1, Axis2> a, Omnitree.Bounds<Axis1, Axis2> b
 436      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2) =>
 437      (a.Min1.Exists && !b.Min1.Exists)
 438      || (a.Min2.Exists && !b.Min2.Exists)
 439      ? false :
 440      (a.Max1.Exists && !b.Max1.Exists)
 441      || (a.Max2.Exists && !b.Max2.Exists)
 442      ? false :
 443      b.Min1.Exists && a.Min1.Exists && compare1(a.Min1.Value, b.Min1.Value) != CompareResult.Less ? false :
 444      b.Max1.Exists && a.Max1.Exists && compare1(a.Max1.Value, b.Max1.Value) != CompareResult.Greater ? false :
 445      b.Min2.Exists && a.Min2.Exists && compare2(a.Min2.Value, b.Min2.Value) != CompareResult.Less ? false :
 446      b.Max2.Exists && a.Max2.Exists && compare2(a.Max2.Value, b.Max2.Value) != CompareResult.Greater ? false :
 447      true;
 448
 449    /// <summary>Checks for equality between two locations.</summary>
 450    /// <returns>True if equal; False if not;</returns>
 451    public static bool EqualsCheck<Axis1, Axis2>(Omnitree.Vector<Axis1, Axis2> a, Omnitree.Vector<Axis1, Axis2> b,
 452      Func<Axis1, Axis1, bool> equate1, Func<Axis2, Axis2, bool> equate2) =>
 453      !equate1(a.Axis1, b.Axis1) ? false :
 454      !equate2(a.Axis2, b.Axis2) ? false :
 455      true;
 456
 457    /// <summary>Checks if a bounds straddles a point if the point extended as a plane along each dimension.</summary>
 458    /// <typeparam name="Axis1">The generic type of the 1 dimension.</typeparam>
 459    /// <typeparam name="Axis2">The generic type of the 2 dimension.</typeparam>
 460    /// <param name="bounds">The bounds to determine if it straddles the extended point.</param>
 461    /// <param name="vector">The point representing an extended plan along each axis.</param>
 462    /// <param name="compare1">The delegate for comparing values along the the 1 dimension.</param>
 463    /// <param name="compare2">The delegate for comparing values along the the 2 dimension.</param>
 464    /// <returns>True if the extended point was straddled or false if not.</returns>
 465    public static bool StraddlesLines<Axis1, Axis2>(Omnitree.Bounds<Axis1, Axis2> bounds, Omnitree.Vector<Axis1, Axis2> 
 466      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2) =>
 467      (!bounds.Min1.Exists || (bounds.Min1.Exists && compare1(bounds.Min1.Value, vector.Axis1) != CompareResult.Greater)
 468      (!bounds.Max1.Exists || (bounds.Max1.Exists && compare1(bounds.Max1.Value, vector.Axis1) != CompareResult.Less)) ?
 469      (!bounds.Min2.Exists || (bounds.Min2.Exists && compare2(bounds.Min2.Value, vector.Axis2) != CompareResult.Greater)
 470      (!bounds.Max2.Exists || (bounds.Max2.Exists && compare2(bounds.Max2.Value, vector.Axis2) != CompareResult.Less)) ?
 471      false;
 472
 473    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 474    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 475    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 476    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 477    /// <param name="omnitree">The omnitree to remove from.</param>
 478    /// <param name="removal">The value to have all occurences removed.</param>
 479    public static void Remove<T, Axis1, Axis2>(this IOmnitreePoints<T, Axis1, Axis2> omnitree, T removal) => Remove(omni
 480
 481    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 482    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 483    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 484    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 485    /// <param name="omnitree">The omnitree to remove from.</param>
 486    /// <param name="removal">The value to have all occurences removed.</param>
 487    /// <param name="equate">The delegate for checking for equality.</param>
 488    public static void Remove<T, Axis1, Axis2>(this IOmnitreePoints<T, Axis1, Axis2> omnitree, T removal, Func<T, T, boo
 489    {
 490      Axis1 axis1;
 491      Axis2 axis2;
 492      omnitree.Locate(removal, out axis1
 493        , out axis2
 494        );
 495      omnitree.Remove(
 496        axis1,
 497        axis2,
 498        x => equate(x, removal));
 499    }
 500
 501    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 502    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 503    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 504    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 505    /// <param name="omnitree">The omnitree to remove from.</param>
 506    /// <param name="removal">The value to have all occurences removed.</param>
 507    public static void Remove<T, Axis1, Axis2>(this IOmnitreeBounds<T, Axis1, Axis2> omnitree, T removal) => Remove(omni
 508
 509    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 510    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 511    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 512    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 513    /// <param name="omnitree">The omnitree to remove from.</param>
 514    /// <param name="removal">The value to have all occurences removed.</param>
 515    /// <param name="equate">The delegate for checking for equality.</param>
 516    public static void Remove<T, Axis1, Axis2>(this IOmnitreeBounds<T, Axis1, Axis2> omnitree,T removal, Func<T, T, bool
 517    {
 518      Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 519      Omnitree.Bound<Axis2> min2; Omnitree.Bound<Axis2> max2;
 520      omnitree.GetBounds(removal, out min1, out max1
 521        , out min2, out max2
 522        );
 523      omnitree.RemoveOverlapped(min1, max1
 524        , min2, max2
 525        , x => equate(x, removal));
 526    }
 527
 528    #endregion
 529
 530    #region 3 Dimensional
 531
 532    /// <summary>Represents a 3D vector.</summary>
 533    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 534    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 535    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 536    public struct Vector<A1
 537      , A2
 538      , A3
 539      >
 540    {
 541      /// <summary>The value along axis 1.</summary>
 542      public A1 Axis1;
 543      /// <summary>The value along axis 2.</summary>
 544      public A2 Axis2;
 545      /// <summary>The value along axis 3.</summary>
 546      public A3 Axis3;
 547
 548      /// <summary>Returns a vector with defaulted values.</summary>
 549      public static Vector<A1
 550, A2
 551, A3
 552        > Default =>
 553        new Vector<A1
 554          , A2
 555          , A3
 556          >(default(A1)
 557          , default(A2)
 558          , default(A3)
 559          );
 560
 561      /// <summary>A location along each axis.</summary>
 562      /// <param name="axis1">The location along axis 1.</param>
 563      /// <param name="axis2">The location along axis 2.</param>
 564      /// <param name="axis3">The location along axis 3.</param>
 565      public Vector(A1 axis1
 566        , A2 axis2
 567        , A3 axis3
 568        )
 569      {
 570        this.Axis1 = axis1;
 571        this.Axis2 = axis2;
 572        this.Axis3 = axis3;
 573      }
 574    }
 575
 576    /// <summary>Represents a 3D bounding box.</summary>
 577    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 578    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 579    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 580    public struct Bounds<A1
 581      , A2
 582      , A3
 583>
 584    {
 585      /// <summary>The minimum value along the 1 dimension.</summary>
 586      public Bound<A1> Min1;
 587      /// <summary>The maximum value along the 1 dimension.</summary>
 588      public Bound<A1> Max1;
 589      /// <summary>The minimum value along the 2 dimension.</summary>
 590      public Bound<A2> Min2;
 591      /// <summary>The maximum value along the 2 dimension.</summary>
 592      public Bound<A2> Max2;
 593      /// <summary>The minimum value along the 3 dimension.</summary>
 594      public Bound<A3> Min3;
 595      /// <summary>The maximum value along the 3 dimension.</summary>
 596      public Bound<A3> Max3;
 597
 598      /// <summary>Extends infinitely along each axis.</summary>
 599      public static Bounds<A1
 600        , A2
 601        , A3
 602        > None =>
 603        new Bounds<A1
 604          , A2
 605          , A3
 606          >(Bound<A1>.None, Bound<A1>.None
 607          , Bound<A2>.None, Bound<A2>.None
 608          , Bound<A3>.None, Bound<A3>.None
 609          );
 610
 611      /// <summary>A set of values denoting a range (or lack of range) along each axis.</summary>
 612      public Bounds(
 613        Bound<A1> min1, Bound<A1> max1
 614        , Bound<A2> min2, Bound<A2> max2
 615        , Bound<A3> min3, Bound<A3> max3
 616        )
 617      {
 618        this.Min1 = min1;
 619        this.Max1 = max1;
 620        this.Min2 = min2;
 621        this.Max2 = max2;
 622        this.Min3 = min3;
 623        this.Max3 = max3;
 624      }
 625    }
 626
 627    /// <summary>Delegate for locating an item in 3D space.</summary>
 628    /// <typeparam name="T">The generic type of the item to locate.</typeparam>
 629    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 630    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 631    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 632    /// <param name="item">The item to locate.</param>
 633    /// <param name="axis1">The location of the item along the 1 dimension.</param>
 634    /// <param name="axis2">The location of the item along the 2 dimension.</param>
 635    /// <param name="axis3">The location of the item along the 3 dimension.</param>
 636    public delegate void Location<T, A1
 637      , A2
 638      , A3
 639      >(T item, out A1 axis1
 640      , out A2 axis2
 641      , out A3 axis3
 642      );
 643
 644    /// <summary>Delegate for getting the 3D bounding box of an item.</summary>
 645    /// <typeparam name="T">The generic type of the item to get the bounding box of.</typeparam>
 646    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 647    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 648    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 649    /// <param name="item">The item to get the bounding box of.</param>
 650    /// <param name="min1">The minimum bound of the item along the 1 dimension.</param>
 651    /// <param name="max1">The maximum bound of the item along the 1 dimension.</param>
 652    /// <param name="min2">The minimum bound of the item along the 2 dimension.</param>
 653    /// <param name="max2">The maximum bound of the item along the 2 dimension.</param>
 654    /// <param name="min3">The minimum bound of the item along the 3 dimension.</param>
 655    /// <param name="max3">The maximum bound of the item along the 3 dimension.</param>
 656    public delegate void GetBounds<T, A1
 657      , A2
 658      , A3
 659      >(T item, out Bound<A1> min1, out Bound<A1> max1
 660      , out Bound<A2> min2, out Bound<A2> max2
 661      , out Bound<A3> min3, out Bound<A3> max3
 662      );
 663
 664    /// <summary>Delegate for getting the 3D bounding box of an item.</summary>
 665    /// <typeparam name="T">The generic type of the item to get the bounding box of.</typeparam>
 666    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 667    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 668    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 669    /// <param name="item">The item to get the bounding box of.</param>
 670    /// <param name="min1">The minimum bound of the item along the 1 dimension.</param>
 671    /// <param name="max1">The maximum bound of the item along the 1 dimension.</param>
 672    /// <param name="min2">The minimum bound of the item along the 2 dimension.</param>
 673    /// <param name="max2">The maximum bound of the item along the 2 dimension.</param>
 674    /// <param name="min3">The minimum bound of the item along the 3 dimension.</param>
 675    /// <param name="max3">The maximum bound of the item along the 3 dimension.</param>
 676    public delegate void GetBoundings<T, A1
 677      , A2
 678      , A3
 679      >(T item, out A1 min1, out A1 max1
 680      , out A2 min2, out A2 max2
 681      , out A3 min3, out A3 max3
 682      );
 683
 684    /// <summary>Converts an Omnitree.GetBoundings delegate into an Omnitree.GetBounds delegate.</summary>
 685    /// <typeparam name="T">The generic type to get the bounds of.</typeparam>
 686    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 687    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 688    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 689    /// <param name="getBoundings">The Omnitree.GetBoundings to convert into a Omnitree.GetBounds.</param>
 690    /// <returns>The converted Omnitree.GetBounds delegate.</returns>
 691    public static GetBounds<T, A1
 692      , A2
 693      , A3
 694      > ConvertToGetBounds<T, A1
 695      , A2
 696      , A3
 697      >(GetBoundings<T, A1
 698      , A2
 699      , A3
 700      > getBoundings) =>
 701      (T item
 702      , out Bound<A1> minBound1, out Bound<A1> maxBound1      , out Bound<A2> minBound2, out Bound<A2> maxBound2      , 
 703      {
 704        A1 min1; A1 max1;
 705        A2 min2; A2 max2;
 706        A3 min3; A3 max3;
 707        getBoundings(item
 708          , out min1, out max1
 709          , out min2, out max2
 710          , out min3, out max3
 711          );
 712        minBound1 = min1; maxBound1 = max1;
 713        minBound2 = min2; maxBound2 = max2;
 714        minBound3 = min3; maxBound3 = max3;
 715      };
 716
 717    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 718    /// <returns>True if the spaces overlap; False if not.</returns>
 719    public static bool InclusionCheck<Axis1, Axis2, Axis3>(Omnitree.Bounds<Axis1, Axis2, Axis3> a, Omnitree.Bounds<Axis1
 720      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 721      a.Max1.Exists && b.Min1.Exists && compare1(a.Max1.Value, b.Min1.Value) is Less ? false :
 722      a.Min1.Exists && b.Max1.Exists && compare1(a.Min1.Value, b.Max1.Value) is Greater ? false :
 723      a.Max2.Exists && b.Min2.Exists && compare2(a.Max2.Value, b.Min2.Value) is Less ? false :
 724      a.Min2.Exists && b.Max2.Exists && compare2(a.Min2.Value, b.Max2.Value) is Greater ? false :
 725      a.Max3.Exists && b.Min3.Exists && compare3(a.Max3.Value, b.Min3.Value) is Less ? false :
 726      a.Min3.Exists && b.Max3.Exists && compare3(a.Min3.Value, b.Max3.Value) is Greater ? false :
 727      true;
 728
 729    /// <summary>Checks if a space encapsulates a point.</summary>
 730    /// <returns>True if the space encapsulates the point; False if not.</returns>
 731    public static bool EncapsulationCheck<Axis1, Axis2, Axis3>(Omnitree.Bounds<Axis1, Axis2, Axis3> bounds, Omnitree.Vec
 732      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 733      // if the location is not outside the bounds, it must be inside
 734      bounds.Min1.Exists && compare1(vector.Axis1, bounds.Min1.Value) is CompareResult.Less ? false :
 735      bounds.Max1.Exists && compare1(vector.Axis1, bounds.Max1.Value) is CompareResult.Greater ? false :
 736      bounds.Min2.Exists && compare2(vector.Axis2, bounds.Min2.Value) is CompareResult.Less ? false :
 737      bounds.Max2.Exists && compare2(vector.Axis2, bounds.Max2.Value) is CompareResult.Greater ? false :
 738      bounds.Min3.Exists && compare3(vector.Axis3, bounds.Min3.Value) is CompareResult.Less ? false :
 739      bounds.Max3.Exists && compare3(vector.Axis3, bounds.Max3.Value) is CompareResult.Greater ? false :
 740      true;
 741
 742    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 743    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 744    public static bool EncapsulationCheck<Axis1, Axis2, Axis3>(Omnitree.Bounds<Axis1, Axis2, Axis3> a, Omnitree.Bounds<A
 745      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 746      (a.Min1.Exists && !b.Min1.Exists)
 747      || (a.Min2.Exists && !b.Min2.Exists)
 748      || (a.Min3.Exists && !b.Min3.Exists)
 749      ? false :
 750      (a.Max1.Exists && !b.Max1.Exists)
 751      || (a.Max2.Exists && !b.Max2.Exists)
 752      || (a.Max3.Exists && !b.Max3.Exists)
 753      ? false :
 754      b.Min1.Exists && a.Min1.Exists && compare1(a.Min1.Value, b.Min1.Value) != CompareResult.Less ? false :
 755      b.Max1.Exists && a.Max1.Exists && compare1(a.Max1.Value, b.Max1.Value) != CompareResult.Greater ? false :
 756      b.Min2.Exists && a.Min2.Exists && compare2(a.Min2.Value, b.Min2.Value) != CompareResult.Less ? false :
 757      b.Max2.Exists && a.Max2.Exists && compare2(a.Max2.Value, b.Max2.Value) != CompareResult.Greater ? false :
 758      b.Min3.Exists && a.Min3.Exists && compare3(a.Min3.Value, b.Min3.Value) != CompareResult.Less ? false :
 759      b.Max3.Exists && a.Max3.Exists && compare3(a.Max3.Value, b.Max3.Value) != CompareResult.Greater ? false :
 760      true;
 761
 762    /// <summary>Checks for equality between two locations.</summary>
 763    /// <returns>True if equal; False if not;</returns>
 764    public static bool EqualsCheck<Axis1, Axis2, Axis3>(Omnitree.Vector<Axis1, Axis2, Axis3> a, Omnitree.Vector<Axis1, A
 765      Func<Axis1, Axis1, bool> equate1, Func<Axis2, Axis2, bool> equate2, Func<Axis3, Axis3, bool> equate3) =>
 766      !equate1(a.Axis1, b.Axis1) ? false :
 767      !equate2(a.Axis2, b.Axis2) ? false :
 768      !equate3(a.Axis3, b.Axis3) ? false :
 769      true;
 770
 771    /// <summary>Checks if a bounds straddles a point if the point extended as a plane along each dimension.</summary>
 772    /// <typeparam name="Axis1">The generic type of the 1 dimension.</typeparam>
 773    /// <typeparam name="Axis2">The generic type of the 2 dimension.</typeparam>
 774    /// <typeparam name="Axis3">The generic type of the 3 dimension.</typeparam>
 775    /// <param name="bounds">The bounds to determine if it straddles the extended point.</param>
 776    /// <param name="vector">The point representing an extended plan along each axis.</param>
 777    /// <param name="compare1">The delegate for comparing values along the the 1 dimension.</param>
 778    /// <param name="compare2">The delegate for comparing values along the the 2 dimension.</param>
 779    /// <param name="compare3">The delegate for comparing values along the the 3 dimension.</param>
 780    /// <returns>True if the extended point was straddled or false if not.</returns>
 781    public static bool StraddlesLines<Axis1, Axis2, Axis3>(Omnitree.Bounds<Axis1, Axis2, Axis3> bounds, Omnitree.Vector<
 782      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 783      (!bounds.Min1.Exists || (bounds.Min1.Exists && compare1(bounds.Min1.Value, vector.Axis1) != CompareResult.Greater)
 784      (!bounds.Max1.Exists || (bounds.Max1.Exists && compare1(bounds.Max1.Value, vector.Axis1) != CompareResult.Less)) ?
 785      (!bounds.Min2.Exists || (bounds.Min2.Exists && compare2(bounds.Min2.Value, vector.Axis2) != CompareResult.Greater)
 786      (!bounds.Max2.Exists || (bounds.Max2.Exists && compare2(bounds.Max2.Value, vector.Axis2) != CompareResult.Less)) ?
 787      (!bounds.Min3.Exists || (bounds.Min3.Exists && compare3(bounds.Min3.Value, vector.Axis3) != CompareResult.Greater)
 788      (!bounds.Max3.Exists || (bounds.Max3.Exists && compare3(bounds.Max3.Value, vector.Axis3) != CompareResult.Less)) ?
 789      false;
 790
 791    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 792    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 793    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 794    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 795    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 796    /// <param name="omnitree">The omnitree to remove from.</param>
 797    /// <param name="removal">The value to have all occurences removed.</param>
 798    public static void Remove<T, Axis1, Axis2, Axis3>(this IOmnitreePoints<T, Axis1, Axis2, Axis3> omnitree, T removal) 
 799
 800    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 801    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 802    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 803    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 804    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 805    /// <param name="omnitree">The omnitree to remove from.</param>
 806    /// <param name="removal">The value to have all occurences removed.</param>
 807    /// <param name="equate">The delegate for checking for equality.</param>
 808    public static void Remove<T, Axis1, Axis2, Axis3>(this IOmnitreePoints<T, Axis1, Axis2, Axis3> omnitree, T removal, 
 809    {
 810      Axis1 axis1;
 811      Axis2 axis2;
 812      Axis3 axis3;
 813      omnitree.Locate(removal, out axis1
 814        , out axis2
 815        , out axis3
 816        );
 817      omnitree.Remove(
 818        axis1,
 819        axis2,
 820        axis3,
 821        x => equate(x, removal));
 822    }
 823
 824    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 825    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 826    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 827    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 828    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 829    /// <param name="omnitree">The omnitree to remove from.</param>
 830    /// <param name="removal">The value to have all occurences removed.</param>
 831    public static void Remove<T, Axis1, Axis2, Axis3>(this IOmnitreeBounds<T, Axis1, Axis2, Axis3> omnitree, T removal) 
 832
 833    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 834    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 835    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 836    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 837    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 838    /// <param name="omnitree">The omnitree to remove from.</param>
 839    /// <param name="removal">The value to have all occurences removed.</param>
 840    /// <param name="equate">The delegate for checking for equality.</param>
 841    public static void Remove<T, Axis1, Axis2, Axis3>(this IOmnitreeBounds<T, Axis1, Axis2, Axis3> omnitree,T removal, F
 842    {
 843      Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 844      Omnitree.Bound<Axis2> min2; Omnitree.Bound<Axis2> max2;
 845      Omnitree.Bound<Axis3> min3; Omnitree.Bound<Axis3> max3;
 846      omnitree.GetBounds(removal, out min1, out max1
 847        , out min2, out max2
 848        , out min3, out max3
 849        );
 850      omnitree.RemoveOverlapped(min1, max1
 851        , min2, max2
 852        , min3, max3
 853        , x => equate(x, removal));
 854    }
 855
 856    #endregion
 857
 858    #region 4 Dimensional
 859
 860    /// <summary>Represents a 4D vector.</summary>
 861    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 862    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 863    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 864    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 865    public struct Vector<A1
 866      , A2
 867      , A3
 868      , A4
 869      >
 870    {
 871      /// <summary>The value along axis 1.</summary>
 872      public A1 Axis1;
 873      /// <summary>The value along axis 2.</summary>
 874      public A2 Axis2;
 875      /// <summary>The value along axis 3.</summary>
 876      public A3 Axis3;
 877      /// <summary>The value along axis 4.</summary>
 878      public A4 Axis4;
 879
 880      /// <summary>Returns a vector with defaulted values.</summary>
 881      public static Vector<A1
 882, A2
 883, A3
 884, A4
 885        > Default =>
 886        new Vector<A1
 887          , A2
 888          , A3
 889          , A4
 890          >(default(A1)
 891          , default(A2)
 892          , default(A3)
 893          , default(A4)
 894          );
 895
 896      /// <summary>A location along each axis.</summary>
 897      /// <param name="axis1">The location along axis 1.</param>
 898      /// <param name="axis2">The location along axis 2.</param>
 899      /// <param name="axis3">The location along axis 3.</param>
 900      /// <param name="axis4">The location along axis 4.</param>
 901      public Vector(A1 axis1
 902        , A2 axis2
 903        , A3 axis3
 904        , A4 axis4
 905        )
 906      {
 907        this.Axis1 = axis1;
 908        this.Axis2 = axis2;
 909        this.Axis3 = axis3;
 910        this.Axis4 = axis4;
 911      }
 912    }
 913
 914    /// <summary>Represents a 4D bounding box.</summary>
 915    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 916    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 917    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 918    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 919    public struct Bounds<A1
 920      , A2
 921      , A3
 922      , A4
 923>
 924    {
 925      /// <summary>The minimum value along the 1 dimension.</summary>
 926      public Bound<A1> Min1;
 927      /// <summary>The maximum value along the 1 dimension.</summary>
 928      public Bound<A1> Max1;
 929      /// <summary>The minimum value along the 2 dimension.</summary>
 930      public Bound<A2> Min2;
 931      /// <summary>The maximum value along the 2 dimension.</summary>
 932      public Bound<A2> Max2;
 933      /// <summary>The minimum value along the 3 dimension.</summary>
 934      public Bound<A3> Min3;
 935      /// <summary>The maximum value along the 3 dimension.</summary>
 936      public Bound<A3> Max3;
 937      /// <summary>The minimum value along the 4 dimension.</summary>
 938      public Bound<A4> Min4;
 939      /// <summary>The maximum value along the 4 dimension.</summary>
 940      public Bound<A4> Max4;
 941
 942      /// <summary>Extends infinitely along each axis.</summary>
 943      public static Bounds<A1
 944        , A2
 945        , A3
 946        , A4
 947        > None =>
 948        new Bounds<A1
 949          , A2
 950          , A3
 951          , A4
 952          >(Bound<A1>.None, Bound<A1>.None
 953          , Bound<A2>.None, Bound<A2>.None
 954          , Bound<A3>.None, Bound<A3>.None
 955          , Bound<A4>.None, Bound<A4>.None
 956          );
 957
 958      /// <summary>A set of values denoting a range (or lack of range) along each axis.</summary>
 959      public Bounds(
 960        Bound<A1> min1, Bound<A1> max1
 961        , Bound<A2> min2, Bound<A2> max2
 962        , Bound<A3> min3, Bound<A3> max3
 963        , Bound<A4> min4, Bound<A4> max4
 964        )
 965      {
 966        this.Min1 = min1;
 967        this.Max1 = max1;
 968        this.Min2 = min2;
 969        this.Max2 = max2;
 970        this.Min3 = min3;
 971        this.Max3 = max3;
 972        this.Min4 = min4;
 973        this.Max4 = max4;
 974      }
 975    }
 976
 977    /// <summary>Delegate for locating an item in 4D space.</summary>
 978    /// <typeparam name="T">The generic type of the item to locate.</typeparam>
 979    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 980    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 981    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 982    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 983    /// <param name="item">The item to locate.</param>
 984    /// <param name="axis1">The location of the item along the 1 dimension.</param>
 985    /// <param name="axis2">The location of the item along the 2 dimension.</param>
 986    /// <param name="axis3">The location of the item along the 3 dimension.</param>
 987    /// <param name="axis4">The location of the item along the 4 dimension.</param>
 988    public delegate void Location<T, A1
 989      , A2
 990      , A3
 991      , A4
 992      >(T item, out A1 axis1
 993      , out A2 axis2
 994      , out A3 axis3
 995      , out A4 axis4
 996      );
 997
 998    /// <summary>Delegate for getting the 4D bounding box of an item.</summary>
 999    /// <typeparam name="T">The generic type of the item to get the bounding box of.</typeparam>
 1000    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 1001    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 1002    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 1003    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 1004    /// <param name="item">The item to get the bounding box of.</param>
 1005    /// <param name="min1">The minimum bound of the item along the 1 dimension.</param>
 1006    /// <param name="max1">The maximum bound of the item along the 1 dimension.</param>
 1007    /// <param name="min2">The minimum bound of the item along the 2 dimension.</param>
 1008    /// <param name="max2">The maximum bound of the item along the 2 dimension.</param>
 1009    /// <param name="min3">The minimum bound of the item along the 3 dimension.</param>
 1010    /// <param name="max3">The maximum bound of the item along the 3 dimension.</param>
 1011    /// <param name="min4">The minimum bound of the item along the 4 dimension.</param>
 1012    /// <param name="max4">The maximum bound of the item along the 4 dimension.</param>
 1013    public delegate void GetBounds<T, A1
 1014      , A2
 1015      , A3
 1016      , A4
 1017      >(T item, out Bound<A1> min1, out Bound<A1> max1
 1018      , out Bound<A2> min2, out Bound<A2> max2
 1019      , out Bound<A3> min3, out Bound<A3> max3
 1020      , out Bound<A4> min4, out Bound<A4> max4
 1021      );
 1022
 1023    /// <summary>Delegate for getting the 4D bounding box of an item.</summary>
 1024    /// <typeparam name="T">The generic type of the item to get the bounding box of.</typeparam>
 1025    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 1026    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 1027    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 1028    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 1029    /// <param name="item">The item to get the bounding box of.</param>
 1030    /// <param name="min1">The minimum bound of the item along the 1 dimension.</param>
 1031    /// <param name="max1">The maximum bound of the item along the 1 dimension.</param>
 1032    /// <param name="min2">The minimum bound of the item along the 2 dimension.</param>
 1033    /// <param name="max2">The maximum bound of the item along the 2 dimension.</param>
 1034    /// <param name="min3">The minimum bound of the item along the 3 dimension.</param>
 1035    /// <param name="max3">The maximum bound of the item along the 3 dimension.</param>
 1036    /// <param name="min4">The minimum bound of the item along the 4 dimension.</param>
 1037    /// <param name="max4">The maximum bound of the item along the 4 dimension.</param>
 1038    public delegate void GetBoundings<T, A1
 1039      , A2
 1040      , A3
 1041      , A4
 1042      >(T item, out A1 min1, out A1 max1
 1043      , out A2 min2, out A2 max2
 1044      , out A3 min3, out A3 max3
 1045      , out A4 min4, out A4 max4
 1046      );
 1047
 1048    /// <summary>Converts an Omnitree.GetBoundings delegate into an Omnitree.GetBounds delegate.</summary>
 1049    /// <typeparam name="T">The generic type to get the bounds of.</typeparam>
 1050    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 1051    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 1052    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 1053    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 1054    /// <param name="getBoundings">The Omnitree.GetBoundings to convert into a Omnitree.GetBounds.</param>
 1055    /// <returns>The converted Omnitree.GetBounds delegate.</returns>
 1056    public static GetBounds<T, A1
 1057      , A2
 1058      , A3
 1059      , A4
 1060      > ConvertToGetBounds<T, A1
 1061      , A2
 1062      , A3
 1063      , A4
 1064      >(GetBoundings<T, A1
 1065      , A2
 1066      , A3
 1067      , A4
 1068      > getBoundings) =>
 1069      (T item
 1070      , out Bound<A1> minBound1, out Bound<A1> maxBound1      , out Bound<A2> minBound2, out Bound<A2> maxBound2      , 
 1071      {
 1072        A1 min1; A1 max1;
 1073        A2 min2; A2 max2;
 1074        A3 min3; A3 max3;
 1075        A4 min4; A4 max4;
 1076        getBoundings(item
 1077          , out min1, out max1
 1078          , out min2, out max2
 1079          , out min3, out max3
 1080          , out min4, out max4
 1081          );
 1082        minBound1 = min1; maxBound1 = max1;
 1083        minBound2 = min2; maxBound2 = max2;
 1084        minBound3 = min3; maxBound3 = max3;
 1085        minBound4 = min4; maxBound4 = max4;
 1086      };
 1087
 1088    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 1089    /// <returns>True if the spaces overlap; False if not.</returns>
 1090    public static bool InclusionCheck<Axis1, Axis2, Axis3, Axis4>(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> a, Omnitre
 1091      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 1092      a.Max1.Exists && b.Min1.Exists && compare1(a.Max1.Value, b.Min1.Value) is Less ? false :
 1093      a.Min1.Exists && b.Max1.Exists && compare1(a.Min1.Value, b.Max1.Value) is Greater ? false :
 1094      a.Max2.Exists && b.Min2.Exists && compare2(a.Max2.Value, b.Min2.Value) is Less ? false :
 1095      a.Min2.Exists && b.Max2.Exists && compare2(a.Min2.Value, b.Max2.Value) is Greater ? false :
 1096      a.Max3.Exists && b.Min3.Exists && compare3(a.Max3.Value, b.Min3.Value) is Less ? false :
 1097      a.Min3.Exists && b.Max3.Exists && compare3(a.Min3.Value, b.Max3.Value) is Greater ? false :
 1098      a.Max4.Exists && b.Min4.Exists && compare4(a.Max4.Value, b.Min4.Value) is Less ? false :
 1099      a.Min4.Exists && b.Max4.Exists && compare4(a.Min4.Value, b.Max4.Value) is Greater ? false :
 1100      true;
 1101
 1102    /// <summary>Checks if a space encapsulates a point.</summary>
 1103    /// <returns>True if the space encapsulates the point; False if not.</returns>
 1104    public static bool EncapsulationCheck<Axis1, Axis2, Axis3, Axis4>(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds
 1105      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 1106      // if the location is not outside the bounds, it must be inside
 1107      bounds.Min1.Exists && compare1(vector.Axis1, bounds.Min1.Value) is CompareResult.Less ? false :
 1108      bounds.Max1.Exists && compare1(vector.Axis1, bounds.Max1.Value) is CompareResult.Greater ? false :
 1109      bounds.Min2.Exists && compare2(vector.Axis2, bounds.Min2.Value) is CompareResult.Less ? false :
 1110      bounds.Max2.Exists && compare2(vector.Axis2, bounds.Max2.Value) is CompareResult.Greater ? false :
 1111      bounds.Min3.Exists && compare3(vector.Axis3, bounds.Min3.Value) is CompareResult.Less ? false :
 1112      bounds.Max3.Exists && compare3(vector.Axis3, bounds.Max3.Value) is CompareResult.Greater ? false :
 1113      bounds.Min4.Exists && compare4(vector.Axis4, bounds.Min4.Value) is CompareResult.Less ? false :
 1114      bounds.Max4.Exists && compare4(vector.Axis4, bounds.Max4.Value) is CompareResult.Greater ? false :
 1115      true;
 1116
 1117    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 1118    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 1119    public static bool EncapsulationCheck<Axis1, Axis2, Axis3, Axis4>(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> a, Omn
 1120      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 1121      (a.Min1.Exists && !b.Min1.Exists)
 1122      || (a.Min2.Exists && !b.Min2.Exists)
 1123      || (a.Min3.Exists && !b.Min3.Exists)
 1124      || (a.Min4.Exists && !b.Min4.Exists)
 1125      ? false :
 1126      (a.Max1.Exists && !b.Max1.Exists)
 1127      || (a.Max2.Exists && !b.Max2.Exists)
 1128      || (a.Max3.Exists && !b.Max3.Exists)
 1129      || (a.Max4.Exists && !b.Max4.Exists)
 1130      ? false :
 1131      b.Min1.Exists && a.Min1.Exists && compare1(a.Min1.Value, b.Min1.Value) != CompareResult.Less ? false :
 1132      b.Max1.Exists && a.Max1.Exists && compare1(a.Max1.Value, b.Max1.Value) != CompareResult.Greater ? false :
 1133      b.Min2.Exists && a.Min2.Exists && compare2(a.Min2.Value, b.Min2.Value) != CompareResult.Less ? false :
 1134      b.Max2.Exists && a.Max2.Exists && compare2(a.Max2.Value, b.Max2.Value) != CompareResult.Greater ? false :
 1135      b.Min3.Exists && a.Min3.Exists && compare3(a.Min3.Value, b.Min3.Value) != CompareResult.Less ? false :
 1136      b.Max3.Exists && a.Max3.Exists && compare3(a.Max3.Value, b.Max3.Value) != CompareResult.Greater ? false :
 1137      b.Min4.Exists && a.Min4.Exists && compare4(a.Min4.Value, b.Min4.Value) != CompareResult.Less ? false :
 1138      b.Max4.Exists && a.Max4.Exists && compare4(a.Max4.Value, b.Max4.Value) != CompareResult.Greater ? false :
 1139      true;
 1140
 1141    /// <summary>Checks for equality between two locations.</summary>
 1142    /// <returns>True if equal; False if not;</returns>
 1143    public static bool EqualsCheck<Axis1, Axis2, Axis3, Axis4>(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> a, Omnitree.V
 1144      Func<Axis1, Axis1, bool> equate1, Func<Axis2, Axis2, bool> equate2, Func<Axis3, Axis3, bool> equate3, Func<Axis4, 
 1145      !equate1(a.Axis1, b.Axis1) ? false :
 1146      !equate2(a.Axis2, b.Axis2) ? false :
 1147      !equate3(a.Axis3, b.Axis3) ? false :
 1148      !equate4(a.Axis4, b.Axis4) ? false :
 1149      true;
 1150
 1151    /// <summary>Checks if a bounds straddles a point if the point extended as a plane along each dimension.</summary>
 1152    /// <typeparam name="Axis1">The generic type of the 1 dimension.</typeparam>
 1153    /// <typeparam name="Axis2">The generic type of the 2 dimension.</typeparam>
 1154    /// <typeparam name="Axis3">The generic type of the 3 dimension.</typeparam>
 1155    /// <typeparam name="Axis4">The generic type of the 4 dimension.</typeparam>
 1156    /// <param name="bounds">The bounds to determine if it straddles the extended point.</param>
 1157    /// <param name="vector">The point representing an extended plan along each axis.</param>
 1158    /// <param name="compare1">The delegate for comparing values along the the 1 dimension.</param>
 1159    /// <param name="compare2">The delegate for comparing values along the the 2 dimension.</param>
 1160    /// <param name="compare3">The delegate for comparing values along the the 3 dimension.</param>
 1161    /// <param name="compare4">The delegate for comparing values along the the 4 dimension.</param>
 1162    /// <returns>True if the extended point was straddled or false if not.</returns>
 1163    public static bool StraddlesLines<Axis1, Axis2, Axis3, Axis4>(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds, Om
 1164      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 1165      (!bounds.Min1.Exists || (bounds.Min1.Exists && compare1(bounds.Min1.Value, vector.Axis1) != CompareResult.Greater)
 1166      (!bounds.Max1.Exists || (bounds.Max1.Exists && compare1(bounds.Max1.Value, vector.Axis1) != CompareResult.Less)) ?
 1167      (!bounds.Min2.Exists || (bounds.Min2.Exists && compare2(bounds.Min2.Value, vector.Axis2) != CompareResult.Greater)
 1168      (!bounds.Max2.Exists || (bounds.Max2.Exists && compare2(bounds.Max2.Value, vector.Axis2) != CompareResult.Less)) ?
 1169      (!bounds.Min3.Exists || (bounds.Min3.Exists && compare3(bounds.Min3.Value, vector.Axis3) != CompareResult.Greater)
 1170      (!bounds.Max3.Exists || (bounds.Max3.Exists && compare3(bounds.Max3.Value, vector.Axis3) != CompareResult.Less)) ?
 1171      (!bounds.Min4.Exists || (bounds.Min4.Exists && compare4(bounds.Min4.Value, vector.Axis4) != CompareResult.Greater)
 1172      (!bounds.Max4.Exists || (bounds.Max4.Exists && compare4(bounds.Max4.Value, vector.Axis4) != CompareResult.Less)) ?
 1173      false;
 1174
 1175    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 1176    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 1177    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 1178    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 1179    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 1180    /// <typeparam name="Axis4">The geneic type of the 4D axis.</typeparam>
 1181    /// <param name="omnitree">The omnitree to remove from.</param>
 1182    /// <param name="removal">The value to have all occurences removed.</param>
 1183    public static void Remove<T, Axis1, Axis2, Axis3, Axis4>(this IOmnitreePoints<T, Axis1, Axis2, Axis3, Axis4> omnitre
 1184
 1185    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 1186    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 1187    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 1188    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 1189    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 1190    /// <typeparam name="Axis4">The geneic type of the 4D axis.</typeparam>
 1191    /// <param name="omnitree">The omnitree to remove from.</param>
 1192    /// <param name="removal">The value to have all occurences removed.</param>
 1193    /// <param name="equate">The delegate for checking for equality.</param>
 1194    public static void Remove<T, Axis1, Axis2, Axis3, Axis4>(this IOmnitreePoints<T, Axis1, Axis2, Axis3, Axis4> omnitre
 1195    {
 1196      Axis1 axis1;
 1197      Axis2 axis2;
 1198      Axis3 axis3;
 1199      Axis4 axis4;
 1200      omnitree.Locate(removal, out axis1
 1201        , out axis2
 1202        , out axis3
 1203        , out axis4
 1204        );
 1205      omnitree.Remove(
 1206        axis1,
 1207        axis2,
 1208        axis3,
 1209        axis4,
 1210        x => equate(x, removal));
 1211    }
 1212
 1213    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 1214    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 1215    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 1216    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 1217    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 1218    /// <typeparam name="Axis4">The geneic type of the 4D axis.</typeparam>
 1219    /// <param name="omnitree">The omnitree to remove from.</param>
 1220    /// <param name="removal">The value to have all occurences removed.</param>
 1221    public static void Remove<T, Axis1, Axis2, Axis3, Axis4>(this IOmnitreeBounds<T, Axis1, Axis2, Axis3, Axis4> omnitre
 1222
 1223    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 1224    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 1225    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 1226    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 1227    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 1228    /// <typeparam name="Axis4">The geneic type of the 4D axis.</typeparam>
 1229    /// <param name="omnitree">The omnitree to remove from.</param>
 1230    /// <param name="removal">The value to have all occurences removed.</param>
 1231    /// <param name="equate">The delegate for checking for equality.</param>
 1232    public static void Remove<T, Axis1, Axis2, Axis3, Axis4>(this IOmnitreeBounds<T, Axis1, Axis2, Axis3, Axis4> omnitre
 1233    {
 1234      Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 1235      Omnitree.Bound<Axis2> min2; Omnitree.Bound<Axis2> max2;
 1236      Omnitree.Bound<Axis3> min3; Omnitree.Bound<Axis3> max3;
 1237      Omnitree.Bound<Axis4> min4; Omnitree.Bound<Axis4> max4;
 1238      omnitree.GetBounds(removal, out min1, out max1
 1239        , out min2, out max2
 1240        , out min3, out max3
 1241        , out min4, out max4
 1242        );
 1243      omnitree.RemoveOverlapped(min1, max1
 1244        , min2, max2
 1245        , min3, max3
 1246        , min4, max4
 1247        , x => equate(x, removal));
 1248    }
 1249
 1250    #endregion
 1251
 1252    #region 5 Dimensional
 1253
 1254    /// <summary>Represents a 5D vector.</summary>
 1255    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 1256    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 1257    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 1258    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 1259    /// <typeparam name="A5">The generic type of the 5 dimension.</typeparam>
 1260    public struct Vector<A1
 1261      , A2
 1262      , A3
 1263      , A4
 1264      , A5
 1265      >
 1266    {
 1267      /// <summary>The value along axis 1.</summary>
 1268      public A1 Axis1;
 1269      /// <summary>The value along axis 2.</summary>
 1270      public A2 Axis2;
 1271      /// <summary>The value along axis 3.</summary>
 1272      public A3 Axis3;
 1273      /// <summary>The value along axis 4.</summary>
 1274      public A4 Axis4;
 1275      /// <summary>The value along axis 5.</summary>
 1276      public A5 Axis5;
 1277
 1278      /// <summary>Returns a vector with defaulted values.</summary>
 1279      public static Vector<A1
 1280, A2
 1281, A3
 1282, A4
 1283, A5
 1284        > Default =>
 1285        new Vector<A1
 1286          , A2
 1287          , A3
 1288          , A4
 1289          , A5
 1290          >(default(A1)
 1291          , default(A2)
 1292          , default(A3)
 1293          , default(A4)
 1294          , default(A5)
 1295          );
 1296
 1297      /// <summary>A location along each axis.</summary>
 1298      /// <param name="axis1">The location along axis 1.</param>
 1299      /// <param name="axis2">The location along axis 2.</param>
 1300      /// <param name="axis3">The location along axis 3.</param>
 1301      /// <param name="axis4">The location along axis 4.</param>
 1302      /// <param name="axis5">The location along axis 5.</param>
 1303      public Vector(A1 axis1
 1304        , A2 axis2
 1305        , A3 axis3
 1306        , A4 axis4
 1307        , A5 axis5
 1308        )
 1309      {
 1310        this.Axis1 = axis1;
 1311        this.Axis2 = axis2;
 1312        this.Axis3 = axis3;
 1313        this.Axis4 = axis4;
 1314        this.Axis5 = axis5;
 1315      }
 1316    }
 1317
 1318    /// <summary>Represents a 5D bounding box.</summary>
 1319    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 1320    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 1321    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 1322    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 1323    /// <typeparam name="A5">The generic type of the 5 dimension.</typeparam>
 1324    public struct Bounds<A1
 1325      , A2
 1326      , A3
 1327      , A4
 1328      , A5
 1329>
 1330    {
 1331      /// <summary>The minimum value along the 1 dimension.</summary>
 1332      public Bound<A1> Min1;
 1333      /// <summary>The maximum value along the 1 dimension.</summary>
 1334      public Bound<A1> Max1;
 1335      /// <summary>The minimum value along the 2 dimension.</summary>
 1336      public Bound<A2> Min2;
 1337      /// <summary>The maximum value along the 2 dimension.</summary>
 1338      public Bound<A2> Max2;
 1339      /// <summary>The minimum value along the 3 dimension.</summary>
 1340      public Bound<A3> Min3;
 1341      /// <summary>The maximum value along the 3 dimension.</summary>
 1342      public Bound<A3> Max3;
 1343      /// <summary>The minimum value along the 4 dimension.</summary>
 1344      public Bound<A4> Min4;
 1345      /// <summary>The maximum value along the 4 dimension.</summary>
 1346      public Bound<A4> Max4;
 1347      /// <summary>The minimum value along the 5 dimension.</summary>
 1348      public Bound<A5> Min5;
 1349      /// <summary>The maximum value along the 5 dimension.</summary>
 1350      public Bound<A5> Max5;
 1351
 1352      /// <summary>Extends infinitely along each axis.</summary>
 1353      public static Bounds<A1
 1354        , A2
 1355        , A3
 1356        , A4
 1357        , A5
 1358        > None =>
 1359        new Bounds<A1
 1360          , A2
 1361          , A3
 1362          , A4
 1363          , A5
 1364          >(Bound<A1>.None, Bound<A1>.None
 1365          , Bound<A2>.None, Bound<A2>.None
 1366          , Bound<A3>.None, Bound<A3>.None
 1367          , Bound<A4>.None, Bound<A4>.None
 1368          , Bound<A5>.None, Bound<A5>.None
 1369          );
 1370
 1371      /// <summary>A set of values denoting a range (or lack of range) along each axis.</summary>
 1372      public Bounds(
 1373        Bound<A1> min1, Bound<A1> max1
 1374        , Bound<A2> min2, Bound<A2> max2
 1375        , Bound<A3> min3, Bound<A3> max3
 1376        , Bound<A4> min4, Bound<A4> max4
 1377        , Bound<A5> min5, Bound<A5> max5
 1378        )
 1379      {
 1380        this.Min1 = min1;
 1381        this.Max1 = max1;
 1382        this.Min2 = min2;
 1383        this.Max2 = max2;
 1384        this.Min3 = min3;
 1385        this.Max3 = max3;
 1386        this.Min4 = min4;
 1387        this.Max4 = max4;
 1388        this.Min5 = min5;
 1389        this.Max5 = max5;
 1390      }
 1391    }
 1392
 1393    /// <summary>Delegate for locating an item in 5D space.</summary>
 1394    /// <typeparam name="T">The generic type of the item to locate.</typeparam>
 1395    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 1396    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 1397    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 1398    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 1399    /// <typeparam name="A5">The generic type of the 5 dimension.</typeparam>
 1400    /// <param name="item">The item to locate.</param>
 1401    /// <param name="axis1">The location of the item along the 1 dimension.</param>
 1402    /// <param name="axis2">The location of the item along the 2 dimension.</param>
 1403    /// <param name="axis3">The location of the item along the 3 dimension.</param>
 1404    /// <param name="axis4">The location of the item along the 4 dimension.</param>
 1405    /// <param name="axis5">The location of the item along the 5 dimension.</param>
 1406    public delegate void Location<T, A1
 1407      , A2
 1408      , A3
 1409      , A4
 1410      , A5
 1411      >(T item, out A1 axis1
 1412      , out A2 axis2
 1413      , out A3 axis3
 1414      , out A4 axis4
 1415      , out A5 axis5
 1416      );
 1417
 1418    /// <summary>Delegate for getting the 5D bounding box of an item.</summary>
 1419    /// <typeparam name="T">The generic type of the item to get the bounding box of.</typeparam>
 1420    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 1421    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 1422    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 1423    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 1424    /// <typeparam name="A5">The generic type of the 5 dimension.</typeparam>
 1425    /// <param name="item">The item to get the bounding box of.</param>
 1426    /// <param name="min1">The minimum bound of the item along the 1 dimension.</param>
 1427    /// <param name="max1">The maximum bound of the item along the 1 dimension.</param>
 1428    /// <param name="min2">The minimum bound of the item along the 2 dimension.</param>
 1429    /// <param name="max2">The maximum bound of the item along the 2 dimension.</param>
 1430    /// <param name="min3">The minimum bound of the item along the 3 dimension.</param>
 1431    /// <param name="max3">The maximum bound of the item along the 3 dimension.</param>
 1432    /// <param name="min4">The minimum bound of the item along the 4 dimension.</param>
 1433    /// <param name="max4">The maximum bound of the item along the 4 dimension.</param>
 1434    /// <param name="min5">The minimum bound of the item along the 5 dimension.</param>
 1435    /// <param name="max5">The maximum bound of the item along the 5 dimension.</param>
 1436    public delegate void GetBounds<T, A1
 1437      , A2
 1438      , A3
 1439      , A4
 1440      , A5
 1441      >(T item, out Bound<A1> min1, out Bound<A1> max1
 1442      , out Bound<A2> min2, out Bound<A2> max2
 1443      , out Bound<A3> min3, out Bound<A3> max3
 1444      , out Bound<A4> min4, out Bound<A4> max4
 1445      , out Bound<A5> min5, out Bound<A5> max5
 1446      );
 1447
 1448    /// <summary>Delegate for getting the 5D bounding box of an item.</summary>
 1449    /// <typeparam name="T">The generic type of the item to get the bounding box of.</typeparam>
 1450    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 1451    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 1452    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 1453    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 1454    /// <typeparam name="A5">The generic type of the 5 dimension.</typeparam>
 1455    /// <param name="item">The item to get the bounding box of.</param>
 1456    /// <param name="min1">The minimum bound of the item along the 1 dimension.</param>
 1457    /// <param name="max1">The maximum bound of the item along the 1 dimension.</param>
 1458    /// <param name="min2">The minimum bound of the item along the 2 dimension.</param>
 1459    /// <param name="max2">The maximum bound of the item along the 2 dimension.</param>
 1460    /// <param name="min3">The minimum bound of the item along the 3 dimension.</param>
 1461    /// <param name="max3">The maximum bound of the item along the 3 dimension.</param>
 1462    /// <param name="min4">The minimum bound of the item along the 4 dimension.</param>
 1463    /// <param name="max4">The maximum bound of the item along the 4 dimension.</param>
 1464    /// <param name="min5">The minimum bound of the item along the 5 dimension.</param>
 1465    /// <param name="max5">The maximum bound of the item along the 5 dimension.</param>
 1466    public delegate void GetBoundings<T, A1
 1467      , A2
 1468      , A3
 1469      , A4
 1470      , A5
 1471      >(T item, out A1 min1, out A1 max1
 1472      , out A2 min2, out A2 max2
 1473      , out A3 min3, out A3 max3
 1474      , out A4 min4, out A4 max4
 1475      , out A5 min5, out A5 max5
 1476      );
 1477
 1478    /// <summary>Converts an Omnitree.GetBoundings delegate into an Omnitree.GetBounds delegate.</summary>
 1479    /// <typeparam name="T">The generic type to get the bounds of.</typeparam>
 1480    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 1481    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 1482    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 1483    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 1484    /// <typeparam name="A5">The generic type of the 5 dimension.</typeparam>
 1485    /// <param name="getBoundings">The Omnitree.GetBoundings to convert into a Omnitree.GetBounds.</param>
 1486    /// <returns>The converted Omnitree.GetBounds delegate.</returns>
 1487    public static GetBounds<T, A1
 1488      , A2
 1489      , A3
 1490      , A4
 1491      , A5
 1492      > ConvertToGetBounds<T, A1
 1493      , A2
 1494      , A3
 1495      , A4
 1496      , A5
 1497      >(GetBoundings<T, A1
 1498      , A2
 1499      , A3
 1500      , A4
 1501      , A5
 1502      > getBoundings) =>
 1503      (T item
 1504      , out Bound<A1> minBound1, out Bound<A1> maxBound1      , out Bound<A2> minBound2, out Bound<A2> maxBound2      , 
 1505      {
 1506        A1 min1; A1 max1;
 1507        A2 min2; A2 max2;
 1508        A3 min3; A3 max3;
 1509        A4 min4; A4 max4;
 1510        A5 min5; A5 max5;
 1511        getBoundings(item
 1512          , out min1, out max1
 1513          , out min2, out max2
 1514          , out min3, out max3
 1515          , out min4, out max4
 1516          , out min5, out max5
 1517          );
 1518        minBound1 = min1; maxBound1 = max1;
 1519        minBound2 = min2; maxBound2 = max2;
 1520        minBound3 = min3; maxBound3 = max3;
 1521        minBound4 = min4; maxBound4 = max4;
 1522        minBound5 = min5; maxBound5 = max5;
 1523      };
 1524
 1525    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 1526    /// <returns>True if the spaces overlap; False if not.</returns>
 1527    public static bool InclusionCheck<Axis1, Axis2, Axis3, Axis4, Axis5>(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axi
 1528      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 1529      a.Max1.Exists && b.Min1.Exists && compare1(a.Max1.Value, b.Min1.Value) is Less ? false :
 1530      a.Min1.Exists && b.Max1.Exists && compare1(a.Min1.Value, b.Max1.Value) is Greater ? false :
 1531      a.Max2.Exists && b.Min2.Exists && compare2(a.Max2.Value, b.Min2.Value) is Less ? false :
 1532      a.Min2.Exists && b.Max2.Exists && compare2(a.Min2.Value, b.Max2.Value) is Greater ? false :
 1533      a.Max3.Exists && b.Min3.Exists && compare3(a.Max3.Value, b.Min3.Value) is Less ? false :
 1534      a.Min3.Exists && b.Max3.Exists && compare3(a.Min3.Value, b.Max3.Value) is Greater ? false :
 1535      a.Max4.Exists && b.Min4.Exists && compare4(a.Max4.Value, b.Min4.Value) is Less ? false :
 1536      a.Min4.Exists && b.Max4.Exists && compare4(a.Min4.Value, b.Max4.Value) is Greater ? false :
 1537      a.Max5.Exists && b.Min5.Exists && compare5(a.Max5.Value, b.Min5.Value) is Less ? false :
 1538      a.Min5.Exists && b.Max5.Exists && compare5(a.Min5.Value, b.Max5.Value) is Greater ? false :
 1539      true;
 1540
 1541    /// <summary>Checks if a space encapsulates a point.</summary>
 1542    /// <returns>True if the space encapsulates the point; False if not.</returns>
 1543    public static bool EncapsulationCheck<Axis1, Axis2, Axis3, Axis4, Axis5>(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4,
 1544      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 1545      // if the location is not outside the bounds, it must be inside
 1546      bounds.Min1.Exists && compare1(vector.Axis1, bounds.Min1.Value) is CompareResult.Less ? false :
 1547      bounds.Max1.Exists && compare1(vector.Axis1, bounds.Max1.Value) is CompareResult.Greater ? false :
 1548      bounds.Min2.Exists && compare2(vector.Axis2, bounds.Min2.Value) is CompareResult.Less ? false :
 1549      bounds.Max2.Exists && compare2(vector.Axis2, bounds.Max2.Value) is CompareResult.Greater ? false :
 1550      bounds.Min3.Exists && compare3(vector.Axis3, bounds.Min3.Value) is CompareResult.Less ? false :
 1551      bounds.Max3.Exists && compare3(vector.Axis3, bounds.Max3.Value) is CompareResult.Greater ? false :
 1552      bounds.Min4.Exists && compare4(vector.Axis4, bounds.Min4.Value) is CompareResult.Less ? false :
 1553      bounds.Max4.Exists && compare4(vector.Axis4, bounds.Max4.Value) is CompareResult.Greater ? false :
 1554      bounds.Min5.Exists && compare5(vector.Axis5, bounds.Min5.Value) is CompareResult.Less ? false :
 1555      bounds.Max5.Exists && compare5(vector.Axis5, bounds.Max5.Value) is CompareResult.Greater ? false :
 1556      true;
 1557
 1558    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 1559    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 1560    public static bool EncapsulationCheck<Axis1, Axis2, Axis3, Axis4, Axis5>(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4,
 1561      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 1562      (a.Min1.Exists && !b.Min1.Exists)
 1563      || (a.Min2.Exists && !b.Min2.Exists)
 1564      || (a.Min3.Exists && !b.Min3.Exists)
 1565      || (a.Min4.Exists && !b.Min4.Exists)
 1566      || (a.Min5.Exists && !b.Min5.Exists)
 1567      ? false :
 1568      (a.Max1.Exists && !b.Max1.Exists)
 1569      || (a.Max2.Exists && !b.Max2.Exists)
 1570      || (a.Max3.Exists && !b.Max3.Exists)
 1571      || (a.Max4.Exists && !b.Max4.Exists)
 1572      || (a.Max5.Exists && !b.Max5.Exists)
 1573      ? false :
 1574      b.Min1.Exists && a.Min1.Exists && compare1(a.Min1.Value, b.Min1.Value) != CompareResult.Less ? false :
 1575      b.Max1.Exists && a.Max1.Exists && compare1(a.Max1.Value, b.Max1.Value) != CompareResult.Greater ? false :
 1576      b.Min2.Exists && a.Min2.Exists && compare2(a.Min2.Value, b.Min2.Value) != CompareResult.Less ? false :
 1577      b.Max2.Exists && a.Max2.Exists && compare2(a.Max2.Value, b.Max2.Value) != CompareResult.Greater ? false :
 1578      b.Min3.Exists && a.Min3.Exists && compare3(a.Min3.Value, b.Min3.Value) != CompareResult.Less ? false :
 1579      b.Max3.Exists && a.Max3.Exists && compare3(a.Max3.Value, b.Max3.Value) != CompareResult.Greater ? false :
 1580      b.Min4.Exists && a.Min4.Exists && compare4(a.Min4.Value, b.Min4.Value) != CompareResult.Less ? false :
 1581      b.Max4.Exists && a.Max4.Exists && compare4(a.Max4.Value, b.Max4.Value) != CompareResult.Greater ? false :
 1582      b.Min5.Exists && a.Min5.Exists && compare5(a.Min5.Value, b.Min5.Value) != CompareResult.Less ? false :
 1583      b.Max5.Exists && a.Max5.Exists && compare5(a.Max5.Value, b.Max5.Value) != CompareResult.Greater ? false :
 1584      true;
 1585
 1586    /// <summary>Checks for equality between two locations.</summary>
 1587    /// <returns>True if equal; False if not;</returns>
 1588    public static bool EqualsCheck<Axis1, Axis2, Axis3, Axis4, Axis5>(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5>
 1589      Func<Axis1, Axis1, bool> equate1, Func<Axis2, Axis2, bool> equate2, Func<Axis3, Axis3, bool> equate3, Func<Axis4, 
 1590      !equate1(a.Axis1, b.Axis1) ? false :
 1591      !equate2(a.Axis2, b.Axis2) ? false :
 1592      !equate3(a.Axis3, b.Axis3) ? false :
 1593      !equate4(a.Axis4, b.Axis4) ? false :
 1594      !equate5(a.Axis5, b.Axis5) ? false :
 1595      true;
 1596
 1597    /// <summary>Checks if a bounds straddles a point if the point extended as a plane along each dimension.</summary>
 1598    /// <typeparam name="Axis1">The generic type of the 1 dimension.</typeparam>
 1599    /// <typeparam name="Axis2">The generic type of the 2 dimension.</typeparam>
 1600    /// <typeparam name="Axis3">The generic type of the 3 dimension.</typeparam>
 1601    /// <typeparam name="Axis4">The generic type of the 4 dimension.</typeparam>
 1602    /// <typeparam name="Axis5">The generic type of the 5 dimension.</typeparam>
 1603    /// <param name="bounds">The bounds to determine if it straddles the extended point.</param>
 1604    /// <param name="vector">The point representing an extended plan along each axis.</param>
 1605    /// <param name="compare1">The delegate for comparing values along the the 1 dimension.</param>
 1606    /// <param name="compare2">The delegate for comparing values along the the 2 dimension.</param>
 1607    /// <param name="compare3">The delegate for comparing values along the the 3 dimension.</param>
 1608    /// <param name="compare4">The delegate for comparing values along the the 4 dimension.</param>
 1609    /// <param name="compare5">The delegate for comparing values along the the 5 dimension.</param>
 1610    /// <returns>True if the extended point was straddled or false if not.</returns>
 1611    public static bool StraddlesLines<Axis1, Axis2, Axis3, Axis4, Axis5>(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axi
 1612      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 1613      (!bounds.Min1.Exists || (bounds.Min1.Exists && compare1(bounds.Min1.Value, vector.Axis1) != CompareResult.Greater)
 1614      (!bounds.Max1.Exists || (bounds.Max1.Exists && compare1(bounds.Max1.Value, vector.Axis1) != CompareResult.Less)) ?
 1615      (!bounds.Min2.Exists || (bounds.Min2.Exists && compare2(bounds.Min2.Value, vector.Axis2) != CompareResult.Greater)
 1616      (!bounds.Max2.Exists || (bounds.Max2.Exists && compare2(bounds.Max2.Value, vector.Axis2) != CompareResult.Less)) ?
 1617      (!bounds.Min3.Exists || (bounds.Min3.Exists && compare3(bounds.Min3.Value, vector.Axis3) != CompareResult.Greater)
 1618      (!bounds.Max3.Exists || (bounds.Max3.Exists && compare3(bounds.Max3.Value, vector.Axis3) != CompareResult.Less)) ?
 1619      (!bounds.Min4.Exists || (bounds.Min4.Exists && compare4(bounds.Min4.Value, vector.Axis4) != CompareResult.Greater)
 1620      (!bounds.Max4.Exists || (bounds.Max4.Exists && compare4(bounds.Max4.Value, vector.Axis4) != CompareResult.Less)) ?
 1621      (!bounds.Min5.Exists || (bounds.Min5.Exists && compare5(bounds.Min5.Value, vector.Axis5) != CompareResult.Greater)
 1622      (!bounds.Max5.Exists || (bounds.Max5.Exists && compare5(bounds.Max5.Value, vector.Axis5) != CompareResult.Less)) ?
 1623      false;
 1624
 1625    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 1626    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 1627    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 1628    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 1629    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 1630    /// <typeparam name="Axis4">The geneic type of the 4D axis.</typeparam>
 1631    /// <typeparam name="Axis5">The geneic type of the 5D axis.</typeparam>
 1632    /// <param name="omnitree">The omnitree to remove from.</param>
 1633    /// <param name="removal">The value to have all occurences removed.</param>
 1634    public static void Remove<T, Axis1, Axis2, Axis3, Axis4, Axis5>(this IOmnitreePoints<T, Axis1, Axis2, Axis3, Axis4, 
 1635
 1636    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 1637    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 1638    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 1639    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 1640    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 1641    /// <typeparam name="Axis4">The geneic type of the 4D axis.</typeparam>
 1642    /// <typeparam name="Axis5">The geneic type of the 5D axis.</typeparam>
 1643    /// <param name="omnitree">The omnitree to remove from.</param>
 1644    /// <param name="removal">The value to have all occurences removed.</param>
 1645    /// <param name="equate">The delegate for checking for equality.</param>
 1646    public static void Remove<T, Axis1, Axis2, Axis3, Axis4, Axis5>(this IOmnitreePoints<T, Axis1, Axis2, Axis3, Axis4, 
 1647    {
 1648      Axis1 axis1;
 1649      Axis2 axis2;
 1650      Axis3 axis3;
 1651      Axis4 axis4;
 1652      Axis5 axis5;
 1653      omnitree.Locate(removal, out axis1
 1654        , out axis2
 1655        , out axis3
 1656        , out axis4
 1657        , out axis5
 1658        );
 1659      omnitree.Remove(
 1660        axis1,
 1661        axis2,
 1662        axis3,
 1663        axis4,
 1664        axis5,
 1665        x => equate(x, removal));
 1666    }
 1667
 1668    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 1669    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 1670    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 1671    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 1672    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 1673    /// <typeparam name="Axis4">The geneic type of the 4D axis.</typeparam>
 1674    /// <typeparam name="Axis5">The geneic type of the 5D axis.</typeparam>
 1675    /// <param name="omnitree">The omnitree to remove from.</param>
 1676    /// <param name="removal">The value to have all occurences removed.</param>
 1677    public static void Remove<T, Axis1, Axis2, Axis3, Axis4, Axis5>(this IOmnitreeBounds<T, Axis1, Axis2, Axis3, Axis4, 
 1678
 1679    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 1680    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 1681    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 1682    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 1683    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 1684    /// <typeparam name="Axis4">The geneic type of the 4D axis.</typeparam>
 1685    /// <typeparam name="Axis5">The geneic type of the 5D axis.</typeparam>
 1686    /// <param name="omnitree">The omnitree to remove from.</param>
 1687    /// <param name="removal">The value to have all occurences removed.</param>
 1688    /// <param name="equate">The delegate for checking for equality.</param>
 1689    public static void Remove<T, Axis1, Axis2, Axis3, Axis4, Axis5>(this IOmnitreeBounds<T, Axis1, Axis2, Axis3, Axis4, 
 1690    {
 1691      Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 1692      Omnitree.Bound<Axis2> min2; Omnitree.Bound<Axis2> max2;
 1693      Omnitree.Bound<Axis3> min3; Omnitree.Bound<Axis3> max3;
 1694      Omnitree.Bound<Axis4> min4; Omnitree.Bound<Axis4> max4;
 1695      Omnitree.Bound<Axis5> min5; Omnitree.Bound<Axis5> max5;
 1696      omnitree.GetBounds(removal, out min1, out max1
 1697        , out min2, out max2
 1698        , out min3, out max3
 1699        , out min4, out max4
 1700        , out min5, out max5
 1701        );
 1702      omnitree.RemoveOverlapped(min1, max1
 1703        , min2, max2
 1704        , min3, max3
 1705        , min4, max4
 1706        , min5, max5
 1707        , x => equate(x, removal));
 1708    }
 1709
 1710    #endregion
 1711
 1712    #region 6 Dimensional
 1713
 1714    /// <summary>Represents a 6D vector.</summary>
 1715    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 1716    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 1717    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 1718    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 1719    /// <typeparam name="A5">The generic type of the 5 dimension.</typeparam>
 1720    /// <typeparam name="A6">The generic type of the 6 dimension.</typeparam>
 1721    public struct Vector<A1
 1722      , A2
 1723      , A3
 1724      , A4
 1725      , A5
 1726      , A6
 1727      >
 1728    {
 1729      /// <summary>The value along axis 1.</summary>
 1730      public A1 Axis1;
 1731      /// <summary>The value along axis 2.</summary>
 1732      public A2 Axis2;
 1733      /// <summary>The value along axis 3.</summary>
 1734      public A3 Axis3;
 1735      /// <summary>The value along axis 4.</summary>
 1736      public A4 Axis4;
 1737      /// <summary>The value along axis 5.</summary>
 1738      public A5 Axis5;
 1739      /// <summary>The value along axis 6.</summary>
 1740      public A6 Axis6;
 1741
 1742      /// <summary>Returns a vector with defaulted values.</summary>
 1743      public static Vector<A1
 1744, A2
 1745, A3
 1746, A4
 1747, A5
 1748, A6
 1749        > Default =>
 1750        new Vector<A1
 1751          , A2
 1752          , A3
 1753          , A4
 1754          , A5
 1755          , A6
 1756          >(default(A1)
 1757          , default(A2)
 1758          , default(A3)
 1759          , default(A4)
 1760          , default(A5)
 1761          , default(A6)
 1762          );
 1763
 1764      /// <summary>A location along each axis.</summary>
 1765      /// <param name="axis1">The location along axis 1.</param>
 1766      /// <param name="axis2">The location along axis 2.</param>
 1767      /// <param name="axis3">The location along axis 3.</param>
 1768      /// <param name="axis4">The location along axis 4.</param>
 1769      /// <param name="axis5">The location along axis 5.</param>
 1770      /// <param name="axis6">The location along axis 6.</param>
 1771      public Vector(A1 axis1
 1772        , A2 axis2
 1773        , A3 axis3
 1774        , A4 axis4
 1775        , A5 axis5
 1776        , A6 axis6
 1777        )
 1778      {
 1779        this.Axis1 = axis1;
 1780        this.Axis2 = axis2;
 1781        this.Axis3 = axis3;
 1782        this.Axis4 = axis4;
 1783        this.Axis5 = axis5;
 1784        this.Axis6 = axis6;
 1785      }
 1786    }
 1787
 1788    /// <summary>Represents a 6D bounding box.</summary>
 1789    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 1790    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 1791    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 1792    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 1793    /// <typeparam name="A5">The generic type of the 5 dimension.</typeparam>
 1794    /// <typeparam name="A6">The generic type of the 6 dimension.</typeparam>
 1795    public struct Bounds<A1
 1796      , A2
 1797      , A3
 1798      , A4
 1799      , A5
 1800      , A6
 1801>
 1802    {
 1803      /// <summary>The minimum value along the 1 dimension.</summary>
 1804      public Bound<A1> Min1;
 1805      /// <summary>The maximum value along the 1 dimension.</summary>
 1806      public Bound<A1> Max1;
 1807      /// <summary>The minimum value along the 2 dimension.</summary>
 1808      public Bound<A2> Min2;
 1809      /// <summary>The maximum value along the 2 dimension.</summary>
 1810      public Bound<A2> Max2;
 1811      /// <summary>The minimum value along the 3 dimension.</summary>
 1812      public Bound<A3> Min3;
 1813      /// <summary>The maximum value along the 3 dimension.</summary>
 1814      public Bound<A3> Max3;
 1815      /// <summary>The minimum value along the 4 dimension.</summary>
 1816      public Bound<A4> Min4;
 1817      /// <summary>The maximum value along the 4 dimension.</summary>
 1818      public Bound<A4> Max4;
 1819      /// <summary>The minimum value along the 5 dimension.</summary>
 1820      public Bound<A5> Min5;
 1821      /// <summary>The maximum value along the 5 dimension.</summary>
 1822      public Bound<A5> Max5;
 1823      /// <summary>The minimum value along the 6 dimension.</summary>
 1824      public Bound<A6> Min6;
 1825      /// <summary>The maximum value along the 6 dimension.</summary>
 1826      public Bound<A6> Max6;
 1827
 1828      /// <summary>Extends infinitely along each axis.</summary>
 1829      public static Bounds<A1
 1830        , A2
 1831        , A3
 1832        , A4
 1833        , A5
 1834        , A6
 1835        > None =>
 1836        new Bounds<A1
 1837          , A2
 1838          , A3
 1839          , A4
 1840          , A5
 1841          , A6
 1842          >(Bound<A1>.None, Bound<A1>.None
 1843          , Bound<A2>.None, Bound<A2>.None
 1844          , Bound<A3>.None, Bound<A3>.None
 1845          , Bound<A4>.None, Bound<A4>.None
 1846          , Bound<A5>.None, Bound<A5>.None
 1847          , Bound<A6>.None, Bound<A6>.None
 1848          );
 1849
 1850      /// <summary>A set of values denoting a range (or lack of range) along each axis.</summary>
 1851      public Bounds(
 1852        Bound<A1> min1, Bound<A1> max1
 1853        , Bound<A2> min2, Bound<A2> max2
 1854        , Bound<A3> min3, Bound<A3> max3
 1855        , Bound<A4> min4, Bound<A4> max4
 1856        , Bound<A5> min5, Bound<A5> max5
 1857        , Bound<A6> min6, Bound<A6> max6
 1858        )
 1859      {
 1860        this.Min1 = min1;
 1861        this.Max1 = max1;
 1862        this.Min2 = min2;
 1863        this.Max2 = max2;
 1864        this.Min3 = min3;
 1865        this.Max3 = max3;
 1866        this.Min4 = min4;
 1867        this.Max4 = max4;
 1868        this.Min5 = min5;
 1869        this.Max5 = max5;
 1870        this.Min6 = min6;
 1871        this.Max6 = max6;
 1872      }
 1873    }
 1874
 1875    /// <summary>Delegate for locating an item in 6D space.</summary>
 1876    /// <typeparam name="T">The generic type of the item to locate.</typeparam>
 1877    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 1878    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 1879    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 1880    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 1881    /// <typeparam name="A5">The generic type of the 5 dimension.</typeparam>
 1882    /// <typeparam name="A6">The generic type of the 6 dimension.</typeparam>
 1883    /// <param name="item">The item to locate.</param>
 1884    /// <param name="axis1">The location of the item along the 1 dimension.</param>
 1885    /// <param name="axis2">The location of the item along the 2 dimension.</param>
 1886    /// <param name="axis3">The location of the item along the 3 dimension.</param>
 1887    /// <param name="axis4">The location of the item along the 4 dimension.</param>
 1888    /// <param name="axis5">The location of the item along the 5 dimension.</param>
 1889    /// <param name="axis6">The location of the item along the 6 dimension.</param>
 1890    public delegate void Location<T, A1
 1891      , A2
 1892      , A3
 1893      , A4
 1894      , A5
 1895      , A6
 1896      >(T item, out A1 axis1
 1897      , out A2 axis2
 1898      , out A3 axis3
 1899      , out A4 axis4
 1900      , out A5 axis5
 1901      , out A6 axis6
 1902      );
 1903
 1904    /// <summary>Delegate for getting the 6D bounding box of an item.</summary>
 1905    /// <typeparam name="T">The generic type of the item to get the bounding box of.</typeparam>
 1906    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 1907    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 1908    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 1909    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 1910    /// <typeparam name="A5">The generic type of the 5 dimension.</typeparam>
 1911    /// <typeparam name="A6">The generic type of the 6 dimension.</typeparam>
 1912    /// <param name="item">The item to get the bounding box of.</param>
 1913    /// <param name="min1">The minimum bound of the item along the 1 dimension.</param>
 1914    /// <param name="max1">The maximum bound of the item along the 1 dimension.</param>
 1915    /// <param name="min2">The minimum bound of the item along the 2 dimension.</param>
 1916    /// <param name="max2">The maximum bound of the item along the 2 dimension.</param>
 1917    /// <param name="min3">The minimum bound of the item along the 3 dimension.</param>
 1918    /// <param name="max3">The maximum bound of the item along the 3 dimension.</param>
 1919    /// <param name="min4">The minimum bound of the item along the 4 dimension.</param>
 1920    /// <param name="max4">The maximum bound of the item along the 4 dimension.</param>
 1921    /// <param name="min5">The minimum bound of the item along the 5 dimension.</param>
 1922    /// <param name="max5">The maximum bound of the item along the 5 dimension.</param>
 1923    /// <param name="min6">The minimum bound of the item along the 6 dimension.</param>
 1924    /// <param name="max6">The maximum bound of the item along the 6 dimension.</param>
 1925    public delegate void GetBounds<T, A1
 1926      , A2
 1927      , A3
 1928      , A4
 1929      , A5
 1930      , A6
 1931      >(T item, out Bound<A1> min1, out Bound<A1> max1
 1932      , out Bound<A2> min2, out Bound<A2> max2
 1933      , out Bound<A3> min3, out Bound<A3> max3
 1934      , out Bound<A4> min4, out Bound<A4> max4
 1935      , out Bound<A5> min5, out Bound<A5> max5
 1936      , out Bound<A6> min6, out Bound<A6> max6
 1937      );
 1938
 1939    /// <summary>Delegate for getting the 6D bounding box of an item.</summary>
 1940    /// <typeparam name="T">The generic type of the item to get the bounding box of.</typeparam>
 1941    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 1942    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 1943    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 1944    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 1945    /// <typeparam name="A5">The generic type of the 5 dimension.</typeparam>
 1946    /// <typeparam name="A6">The generic type of the 6 dimension.</typeparam>
 1947    /// <param name="item">The item to get the bounding box of.</param>
 1948    /// <param name="min1">The minimum bound of the item along the 1 dimension.</param>
 1949    /// <param name="max1">The maximum bound of the item along the 1 dimension.</param>
 1950    /// <param name="min2">The minimum bound of the item along the 2 dimension.</param>
 1951    /// <param name="max2">The maximum bound of the item along the 2 dimension.</param>
 1952    /// <param name="min3">The minimum bound of the item along the 3 dimension.</param>
 1953    /// <param name="max3">The maximum bound of the item along the 3 dimension.</param>
 1954    /// <param name="min4">The minimum bound of the item along the 4 dimension.</param>
 1955    /// <param name="max4">The maximum bound of the item along the 4 dimension.</param>
 1956    /// <param name="min5">The minimum bound of the item along the 5 dimension.</param>
 1957    /// <param name="max5">The maximum bound of the item along the 5 dimension.</param>
 1958    /// <param name="min6">The minimum bound of the item along the 6 dimension.</param>
 1959    /// <param name="max6">The maximum bound of the item along the 6 dimension.</param>
 1960    public delegate void GetBoundings<T, A1
 1961      , A2
 1962      , A3
 1963      , A4
 1964      , A5
 1965      , A6
 1966      >(T item, out A1 min1, out A1 max1
 1967      , out A2 min2, out A2 max2
 1968      , out A3 min3, out A3 max3
 1969      , out A4 min4, out A4 max4
 1970      , out A5 min5, out A5 max5
 1971      , out A6 min6, out A6 max6
 1972      );
 1973
 1974    /// <summary>Converts an Omnitree.GetBoundings delegate into an Omnitree.GetBounds delegate.</summary>
 1975    /// <typeparam name="T">The generic type to get the bounds of.</typeparam>
 1976    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 1977    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 1978    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 1979    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 1980    /// <typeparam name="A5">The generic type of the 5 dimension.</typeparam>
 1981    /// <typeparam name="A6">The generic type of the 6 dimension.</typeparam>
 1982    /// <param name="getBoundings">The Omnitree.GetBoundings to convert into a Omnitree.GetBounds.</param>
 1983    /// <returns>The converted Omnitree.GetBounds delegate.</returns>
 1984    public static GetBounds<T, A1
 1985      , A2
 1986      , A3
 1987      , A4
 1988      , A5
 1989      , A6
 1990      > ConvertToGetBounds<T, A1
 1991      , A2
 1992      , A3
 1993      , A4
 1994      , A5
 1995      , A6
 1996      >(GetBoundings<T, A1
 1997      , A2
 1998      , A3
 1999      , A4
 2000      , A5
 2001      , A6
 2002      > getBoundings) =>
 2003      (T item
 2004      , out Bound<A1> minBound1, out Bound<A1> maxBound1      , out Bound<A2> minBound2, out Bound<A2> maxBound2      , 
 2005      {
 2006        A1 min1; A1 max1;
 2007        A2 min2; A2 max2;
 2008        A3 min3; A3 max3;
 2009        A4 min4; A4 max4;
 2010        A5 min5; A5 max5;
 2011        A6 min6; A6 max6;
 2012        getBoundings(item
 2013          , out min1, out max1
 2014          , out min2, out max2
 2015          , out min3, out max3
 2016          , out min4, out max4
 2017          , out min5, out max5
 2018          , out min6, out max6
 2019          );
 2020        minBound1 = min1; maxBound1 = max1;
 2021        minBound2 = min2; maxBound2 = max2;
 2022        minBound3 = min3; maxBound3 = max3;
 2023        minBound4 = min4; maxBound4 = max4;
 2024        minBound5 = min5; maxBound5 = max5;
 2025        minBound6 = min6; maxBound6 = max6;
 2026      };
 2027
 2028    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 2029    /// <returns>True if the spaces overlap; False if not.</returns>
 2030    public static bool InclusionCheck<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(Omnitree.Bounds<Axis1, Axis2, Axis3, Axi
 2031      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 2032      a.Max1.Exists && b.Min1.Exists && compare1(a.Max1.Value, b.Min1.Value) is Less ? false :
 2033      a.Min1.Exists && b.Max1.Exists && compare1(a.Min1.Value, b.Max1.Value) is Greater ? false :
 2034      a.Max2.Exists && b.Min2.Exists && compare2(a.Max2.Value, b.Min2.Value) is Less ? false :
 2035      a.Min2.Exists && b.Max2.Exists && compare2(a.Min2.Value, b.Max2.Value) is Greater ? false :
 2036      a.Max3.Exists && b.Min3.Exists && compare3(a.Max3.Value, b.Min3.Value) is Less ? false :
 2037      a.Min3.Exists && b.Max3.Exists && compare3(a.Min3.Value, b.Max3.Value) is Greater ? false :
 2038      a.Max4.Exists && b.Min4.Exists && compare4(a.Max4.Value, b.Min4.Value) is Less ? false :
 2039      a.Min4.Exists && b.Max4.Exists && compare4(a.Min4.Value, b.Max4.Value) is Greater ? false :
 2040      a.Max5.Exists && b.Min5.Exists && compare5(a.Max5.Value, b.Min5.Value) is Less ? false :
 2041      a.Min5.Exists && b.Max5.Exists && compare5(a.Min5.Value, b.Max5.Value) is Greater ? false :
 2042      a.Max6.Exists && b.Min6.Exists && compare6(a.Max6.Value, b.Min6.Value) is Less ? false :
 2043      a.Min6.Exists && b.Max6.Exists && compare6(a.Min6.Value, b.Max6.Value) is Greater ? false :
 2044      true;
 2045
 2046    /// <summary>Checks if a space encapsulates a point.</summary>
 2047    /// <returns>True if the space encapsulates the point; False if not.</returns>
 2048    public static bool EncapsulationCheck<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(Omnitree.Bounds<Axis1, Axis2, Axis3,
 2049      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 2050      // if the location is not outside the bounds, it must be inside
 2051      bounds.Min1.Exists && compare1(vector.Axis1, bounds.Min1.Value) is CompareResult.Less ? false :
 2052      bounds.Max1.Exists && compare1(vector.Axis1, bounds.Max1.Value) is CompareResult.Greater ? false :
 2053      bounds.Min2.Exists && compare2(vector.Axis2, bounds.Min2.Value) is CompareResult.Less ? false :
 2054      bounds.Max2.Exists && compare2(vector.Axis2, bounds.Max2.Value) is CompareResult.Greater ? false :
 2055      bounds.Min3.Exists && compare3(vector.Axis3, bounds.Min3.Value) is CompareResult.Less ? false :
 2056      bounds.Max3.Exists && compare3(vector.Axis3, bounds.Max3.Value) is CompareResult.Greater ? false :
 2057      bounds.Min4.Exists && compare4(vector.Axis4, bounds.Min4.Value) is CompareResult.Less ? false :
 2058      bounds.Max4.Exists && compare4(vector.Axis4, bounds.Max4.Value) is CompareResult.Greater ? false :
 2059      bounds.Min5.Exists && compare5(vector.Axis5, bounds.Min5.Value) is CompareResult.Less ? false :
 2060      bounds.Max5.Exists && compare5(vector.Axis5, bounds.Max5.Value) is CompareResult.Greater ? false :
 2061      bounds.Min6.Exists && compare6(vector.Axis6, bounds.Min6.Value) is CompareResult.Less ? false :
 2062      bounds.Max6.Exists && compare6(vector.Axis6, bounds.Max6.Value) is CompareResult.Greater ? false :
 2063      true;
 2064
 2065    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 2066    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 2067    public static bool EncapsulationCheck<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(Omnitree.Bounds<Axis1, Axis2, Axis3,
 2068      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 2069      (a.Min1.Exists && !b.Min1.Exists)
 2070      || (a.Min2.Exists && !b.Min2.Exists)
 2071      || (a.Min3.Exists && !b.Min3.Exists)
 2072      || (a.Min4.Exists && !b.Min4.Exists)
 2073      || (a.Min5.Exists && !b.Min5.Exists)
 2074      || (a.Min6.Exists && !b.Min6.Exists)
 2075      ? false :
 2076      (a.Max1.Exists && !b.Max1.Exists)
 2077      || (a.Max2.Exists && !b.Max2.Exists)
 2078      || (a.Max3.Exists && !b.Max3.Exists)
 2079      || (a.Max4.Exists && !b.Max4.Exists)
 2080      || (a.Max5.Exists && !b.Max5.Exists)
 2081      || (a.Max6.Exists && !b.Max6.Exists)
 2082      ? false :
 2083      b.Min1.Exists && a.Min1.Exists && compare1(a.Min1.Value, b.Min1.Value) != CompareResult.Less ? false :
 2084      b.Max1.Exists && a.Max1.Exists && compare1(a.Max1.Value, b.Max1.Value) != CompareResult.Greater ? false :
 2085      b.Min2.Exists && a.Min2.Exists && compare2(a.Min2.Value, b.Min2.Value) != CompareResult.Less ? false :
 2086      b.Max2.Exists && a.Max2.Exists && compare2(a.Max2.Value, b.Max2.Value) != CompareResult.Greater ? false :
 2087      b.Min3.Exists && a.Min3.Exists && compare3(a.Min3.Value, b.Min3.Value) != CompareResult.Less ? false :
 2088      b.Max3.Exists && a.Max3.Exists && compare3(a.Max3.Value, b.Max3.Value) != CompareResult.Greater ? false :
 2089      b.Min4.Exists && a.Min4.Exists && compare4(a.Min4.Value, b.Min4.Value) != CompareResult.Less ? false :
 2090      b.Max4.Exists && a.Max4.Exists && compare4(a.Max4.Value, b.Max4.Value) != CompareResult.Greater ? false :
 2091      b.Min5.Exists && a.Min5.Exists && compare5(a.Min5.Value, b.Min5.Value) != CompareResult.Less ? false :
 2092      b.Max5.Exists && a.Max5.Exists && compare5(a.Max5.Value, b.Max5.Value) != CompareResult.Greater ? false :
 2093      b.Min6.Exists && a.Min6.Exists && compare6(a.Min6.Value, b.Min6.Value) != CompareResult.Less ? false :
 2094      b.Max6.Exists && a.Max6.Exists && compare6(a.Max6.Value, b.Max6.Value) != CompareResult.Greater ? false :
 2095      true;
 2096
 2097    /// <summary>Checks for equality between two locations.</summary>
 2098    /// <returns>True if equal; False if not;</returns>
 2099    public static bool EqualsCheck<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4,
 2100      Func<Axis1, Axis1, bool> equate1, Func<Axis2, Axis2, bool> equate2, Func<Axis3, Axis3, bool> equate3, Func<Axis4, 
 2101      !equate1(a.Axis1, b.Axis1) ? false :
 2102      !equate2(a.Axis2, b.Axis2) ? false :
 2103      !equate3(a.Axis3, b.Axis3) ? false :
 2104      !equate4(a.Axis4, b.Axis4) ? false :
 2105      !equate5(a.Axis5, b.Axis5) ? false :
 2106      !equate6(a.Axis6, b.Axis6) ? false :
 2107      true;
 2108
 2109    /// <summary>Checks if a bounds straddles a point if the point extended as a plane along each dimension.</summary>
 2110    /// <typeparam name="Axis1">The generic type of the 1 dimension.</typeparam>
 2111    /// <typeparam name="Axis2">The generic type of the 2 dimension.</typeparam>
 2112    /// <typeparam name="Axis3">The generic type of the 3 dimension.</typeparam>
 2113    /// <typeparam name="Axis4">The generic type of the 4 dimension.</typeparam>
 2114    /// <typeparam name="Axis5">The generic type of the 5 dimension.</typeparam>
 2115    /// <typeparam name="Axis6">The generic type of the 6 dimension.</typeparam>
 2116    /// <param name="bounds">The bounds to determine if it straddles the extended point.</param>
 2117    /// <param name="vector">The point representing an extended plan along each axis.</param>
 2118    /// <param name="compare1">The delegate for comparing values along the the 1 dimension.</param>
 2119    /// <param name="compare2">The delegate for comparing values along the the 2 dimension.</param>
 2120    /// <param name="compare3">The delegate for comparing values along the the 3 dimension.</param>
 2121    /// <param name="compare4">The delegate for comparing values along the the 4 dimension.</param>
 2122    /// <param name="compare5">The delegate for comparing values along the the 5 dimension.</param>
 2123    /// <param name="compare6">The delegate for comparing values along the the 6 dimension.</param>
 2124    /// <returns>True if the extended point was straddled or false if not.</returns>
 2125    public static bool StraddlesLines<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(Omnitree.Bounds<Axis1, Axis2, Axis3, Axi
 2126      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 2127      (!bounds.Min1.Exists || (bounds.Min1.Exists && compare1(bounds.Min1.Value, vector.Axis1) != CompareResult.Greater)
 2128      (!bounds.Max1.Exists || (bounds.Max1.Exists && compare1(bounds.Max1.Value, vector.Axis1) != CompareResult.Less)) ?
 2129      (!bounds.Min2.Exists || (bounds.Min2.Exists && compare2(bounds.Min2.Value, vector.Axis2) != CompareResult.Greater)
 2130      (!bounds.Max2.Exists || (bounds.Max2.Exists && compare2(bounds.Max2.Value, vector.Axis2) != CompareResult.Less)) ?
 2131      (!bounds.Min3.Exists || (bounds.Min3.Exists && compare3(bounds.Min3.Value, vector.Axis3) != CompareResult.Greater)
 2132      (!bounds.Max3.Exists || (bounds.Max3.Exists && compare3(bounds.Max3.Value, vector.Axis3) != CompareResult.Less)) ?
 2133      (!bounds.Min4.Exists || (bounds.Min4.Exists && compare4(bounds.Min4.Value, vector.Axis4) != CompareResult.Greater)
 2134      (!bounds.Max4.Exists || (bounds.Max4.Exists && compare4(bounds.Max4.Value, vector.Axis4) != CompareResult.Less)) ?
 2135      (!bounds.Min5.Exists || (bounds.Min5.Exists && compare5(bounds.Min5.Value, vector.Axis5) != CompareResult.Greater)
 2136      (!bounds.Max5.Exists || (bounds.Max5.Exists && compare5(bounds.Max5.Value, vector.Axis5) != CompareResult.Less)) ?
 2137      (!bounds.Min6.Exists || (bounds.Min6.Exists && compare6(bounds.Min6.Value, vector.Axis6) != CompareResult.Greater)
 2138      (!bounds.Max6.Exists || (bounds.Max6.Exists && compare6(bounds.Max6.Value, vector.Axis6) != CompareResult.Less)) ?
 2139      false;
 2140
 2141    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 2142    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 2143    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 2144    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 2145    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 2146    /// <typeparam name="Axis4">The geneic type of the 4D axis.</typeparam>
 2147    /// <typeparam name="Axis5">The geneic type of the 5D axis.</typeparam>
 2148    /// <typeparam name="Axis6">The geneic type of the 6D axis.</typeparam>
 2149    /// <param name="omnitree">The omnitree to remove from.</param>
 2150    /// <param name="removal">The value to have all occurences removed.</param>
 2151    public static void Remove<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(this IOmnitreePoints<T, Axis1, Axis2, Axis3, 
 2152
 2153    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 2154    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 2155    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 2156    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 2157    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 2158    /// <typeparam name="Axis4">The geneic type of the 4D axis.</typeparam>
 2159    /// <typeparam name="Axis5">The geneic type of the 5D axis.</typeparam>
 2160    /// <typeparam name="Axis6">The geneic type of the 6D axis.</typeparam>
 2161    /// <param name="omnitree">The omnitree to remove from.</param>
 2162    /// <param name="removal">The value to have all occurences removed.</param>
 2163    /// <param name="equate">The delegate for checking for equality.</param>
 2164    public static void Remove<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(this IOmnitreePoints<T, Axis1, Axis2, Axis3, 
 2165    {
 2166      Axis1 axis1;
 2167      Axis2 axis2;
 2168      Axis3 axis3;
 2169      Axis4 axis4;
 2170      Axis5 axis5;
 2171      Axis6 axis6;
 2172      omnitree.Locate(removal, out axis1
 2173        , out axis2
 2174        , out axis3
 2175        , out axis4
 2176        , out axis5
 2177        , out axis6
 2178        );
 2179      omnitree.Remove(
 2180        axis1,
 2181        axis2,
 2182        axis3,
 2183        axis4,
 2184        axis5,
 2185        axis6,
 2186        x => equate(x, removal));
 2187    }
 2188
 2189    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 2190    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 2191    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 2192    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 2193    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 2194    /// <typeparam name="Axis4">The geneic type of the 4D axis.</typeparam>
 2195    /// <typeparam name="Axis5">The geneic type of the 5D axis.</typeparam>
 2196    /// <typeparam name="Axis6">The geneic type of the 6D axis.</typeparam>
 2197    /// <param name="omnitree">The omnitree to remove from.</param>
 2198    /// <param name="removal">The value to have all occurences removed.</param>
 2199    public static void Remove<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(this IOmnitreeBounds<T, Axis1, Axis2, Axis3, 
 2200
 2201    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 2202    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 2203    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 2204    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 2205    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 2206    /// <typeparam name="Axis4">The geneic type of the 4D axis.</typeparam>
 2207    /// <typeparam name="Axis5">The geneic type of the 5D axis.</typeparam>
 2208    /// <typeparam name="Axis6">The geneic type of the 6D axis.</typeparam>
 2209    /// <param name="omnitree">The omnitree to remove from.</param>
 2210    /// <param name="removal">The value to have all occurences removed.</param>
 2211    /// <param name="equate">The delegate for checking for equality.</param>
 2212    public static void Remove<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(this IOmnitreeBounds<T, Axis1, Axis2, Axis3, 
 2213    {
 2214      Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 2215      Omnitree.Bound<Axis2> min2; Omnitree.Bound<Axis2> max2;
 2216      Omnitree.Bound<Axis3> min3; Omnitree.Bound<Axis3> max3;
 2217      Omnitree.Bound<Axis4> min4; Omnitree.Bound<Axis4> max4;
 2218      Omnitree.Bound<Axis5> min5; Omnitree.Bound<Axis5> max5;
 2219      Omnitree.Bound<Axis6> min6; Omnitree.Bound<Axis6> max6;
 2220      omnitree.GetBounds(removal, out min1, out max1
 2221        , out min2, out max2
 2222        , out min3, out max3
 2223        , out min4, out max4
 2224        , out min5, out max5
 2225        , out min6, out max6
 2226        );
 2227      omnitree.RemoveOverlapped(min1, max1
 2228        , min2, max2
 2229        , min3, max3
 2230        , min4, max4
 2231        , min5, max5
 2232        , min6, max6
 2233        , x => equate(x, removal));
 2234    }
 2235
 2236    #endregion
 2237
 2238    #region 7 Dimensional
 2239
 2240    /// <summary>Represents a 7D vector.</summary>
 2241    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 2242    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 2243    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 2244    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 2245    /// <typeparam name="A5">The generic type of the 5 dimension.</typeparam>
 2246    /// <typeparam name="A6">The generic type of the 6 dimension.</typeparam>
 2247    /// <typeparam name="A7">The generic type of the 7 dimension.</typeparam>
 2248    public struct Vector<A1
 2249      , A2
 2250      , A3
 2251      , A4
 2252      , A5
 2253      , A6
 2254      , A7
 2255      >
 2256    {
 2257      /// <summary>The value along axis 1.</summary>
 2258      public A1 Axis1;
 2259      /// <summary>The value along axis 2.</summary>
 2260      public A2 Axis2;
 2261      /// <summary>The value along axis 3.</summary>
 2262      public A3 Axis3;
 2263      /// <summary>The value along axis 4.</summary>
 2264      public A4 Axis4;
 2265      /// <summary>The value along axis 5.</summary>
 2266      public A5 Axis5;
 2267      /// <summary>The value along axis 6.</summary>
 2268      public A6 Axis6;
 2269      /// <summary>The value along axis 7.</summary>
 2270      public A7 Axis7;
 2271
 2272      /// <summary>Returns a vector with defaulted values.</summary>
 2273      public static Vector<A1
 2274, A2
 2275, A3
 2276, A4
 2277, A5
 2278, A6
 2279, A7
 2280        > Default =>
 2281        new Vector<A1
 2282          , A2
 2283          , A3
 2284          , A4
 2285          , A5
 2286          , A6
 2287          , A7
 2288          >(default(A1)
 2289          , default(A2)
 2290          , default(A3)
 2291          , default(A4)
 2292          , default(A5)
 2293          , default(A6)
 2294          , default(A7)
 2295          );
 2296
 2297      /// <summary>A location along each axis.</summary>
 2298      /// <param name="axis1">The location along axis 1.</param>
 2299      /// <param name="axis2">The location along axis 2.</param>
 2300      /// <param name="axis3">The location along axis 3.</param>
 2301      /// <param name="axis4">The location along axis 4.</param>
 2302      /// <param name="axis5">The location along axis 5.</param>
 2303      /// <param name="axis6">The location along axis 6.</param>
 2304      /// <param name="axis7">The location along axis 7.</param>
 2305      public Vector(A1 axis1
 2306        , A2 axis2
 2307        , A3 axis3
 2308        , A4 axis4
 2309        , A5 axis5
 2310        , A6 axis6
 2311        , A7 axis7
 2312        )
 2313      {
 2314        this.Axis1 = axis1;
 2315        this.Axis2 = axis2;
 2316        this.Axis3 = axis3;
 2317        this.Axis4 = axis4;
 2318        this.Axis5 = axis5;
 2319        this.Axis6 = axis6;
 2320        this.Axis7 = axis7;
 2321      }
 2322    }
 2323
 2324    /// <summary>Represents a 7D bounding box.</summary>
 2325    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 2326    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 2327    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 2328    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 2329    /// <typeparam name="A5">The generic type of the 5 dimension.</typeparam>
 2330    /// <typeparam name="A6">The generic type of the 6 dimension.</typeparam>
 2331    /// <typeparam name="A7">The generic type of the 7 dimension.</typeparam>
 2332    public struct Bounds<A1
 2333      , A2
 2334      , A3
 2335      , A4
 2336      , A5
 2337      , A6
 2338      , A7
 2339>
 2340    {
 2341      /// <summary>The minimum value along the 1 dimension.</summary>
 2342      public Bound<A1> Min1;
 2343      /// <summary>The maximum value along the 1 dimension.</summary>
 2344      public Bound<A1> Max1;
 2345      /// <summary>The minimum value along the 2 dimension.</summary>
 2346      public Bound<A2> Min2;
 2347      /// <summary>The maximum value along the 2 dimension.</summary>
 2348      public Bound<A2> Max2;
 2349      /// <summary>The minimum value along the 3 dimension.</summary>
 2350      public Bound<A3> Min3;
 2351      /// <summary>The maximum value along the 3 dimension.</summary>
 2352      public Bound<A3> Max3;
 2353      /// <summary>The minimum value along the 4 dimension.</summary>
 2354      public Bound<A4> Min4;
 2355      /// <summary>The maximum value along the 4 dimension.</summary>
 2356      public Bound<A4> Max4;
 2357      /// <summary>The minimum value along the 5 dimension.</summary>
 2358      public Bound<A5> Min5;
 2359      /// <summary>The maximum value along the 5 dimension.</summary>
 2360      public Bound<A5> Max5;
 2361      /// <summary>The minimum value along the 6 dimension.</summary>
 2362      public Bound<A6> Min6;
 2363      /// <summary>The maximum value along the 6 dimension.</summary>
 2364      public Bound<A6> Max6;
 2365      /// <summary>The minimum value along the 7 dimension.</summary>
 2366      public Bound<A7> Min7;
 2367      /// <summary>The maximum value along the 7 dimension.</summary>
 2368      public Bound<A7> Max7;
 2369
 2370      /// <summary>Extends infinitely along each axis.</summary>
 2371      public static Bounds<A1
 2372        , A2
 2373        , A3
 2374        , A4
 2375        , A5
 2376        , A6
 2377        , A7
 2378        > None =>
 2379        new Bounds<A1
 2380          , A2
 2381          , A3
 2382          , A4
 2383          , A5
 2384          , A6
 2385          , A7
 2386          >(Bound<A1>.None, Bound<A1>.None
 2387          , Bound<A2>.None, Bound<A2>.None
 2388          , Bound<A3>.None, Bound<A3>.None
 2389          , Bound<A4>.None, Bound<A4>.None
 2390          , Bound<A5>.None, Bound<A5>.None
 2391          , Bound<A6>.None, Bound<A6>.None
 2392          , Bound<A7>.None, Bound<A7>.None
 2393          );
 2394
 2395      /// <summary>A set of values denoting a range (or lack of range) along each axis.</summary>
 2396      public Bounds(
 2397        Bound<A1> min1, Bound<A1> max1
 2398        , Bound<A2> min2, Bound<A2> max2
 2399        , Bound<A3> min3, Bound<A3> max3
 2400        , Bound<A4> min4, Bound<A4> max4
 2401        , Bound<A5> min5, Bound<A5> max5
 2402        , Bound<A6> min6, Bound<A6> max6
 2403        , Bound<A7> min7, Bound<A7> max7
 2404        )
 2405      {
 2406        this.Min1 = min1;
 2407        this.Max1 = max1;
 2408        this.Min2 = min2;
 2409        this.Max2 = max2;
 2410        this.Min3 = min3;
 2411        this.Max3 = max3;
 2412        this.Min4 = min4;
 2413        this.Max4 = max4;
 2414        this.Min5 = min5;
 2415        this.Max5 = max5;
 2416        this.Min6 = min6;
 2417        this.Max6 = max6;
 2418        this.Min7 = min7;
 2419        this.Max7 = max7;
 2420      }
 2421    }
 2422
 2423    /// <summary>Delegate for locating an item in 7D space.</summary>
 2424    /// <typeparam name="T">The generic type of the item to locate.</typeparam>
 2425    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 2426    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 2427    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 2428    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 2429    /// <typeparam name="A5">The generic type of the 5 dimension.</typeparam>
 2430    /// <typeparam name="A6">The generic type of the 6 dimension.</typeparam>
 2431    /// <typeparam name="A7">The generic type of the 7 dimension.</typeparam>
 2432    /// <param name="item">The item to locate.</param>
 2433    /// <param name="axis1">The location of the item along the 1 dimension.</param>
 2434    /// <param name="axis2">The location of the item along the 2 dimension.</param>
 2435    /// <param name="axis3">The location of the item along the 3 dimension.</param>
 2436    /// <param name="axis4">The location of the item along the 4 dimension.</param>
 2437    /// <param name="axis5">The location of the item along the 5 dimension.</param>
 2438    /// <param name="axis6">The location of the item along the 6 dimension.</param>
 2439    /// <param name="axis7">The location of the item along the 7 dimension.</param>
 2440    public delegate void Location<T, A1
 2441      , A2
 2442      , A3
 2443      , A4
 2444      , A5
 2445      , A6
 2446      , A7
 2447      >(T item, out A1 axis1
 2448      , out A2 axis2
 2449      , out A3 axis3
 2450      , out A4 axis4
 2451      , out A5 axis5
 2452      , out A6 axis6
 2453      , out A7 axis7
 2454      );
 2455
 2456    /// <summary>Delegate for getting the 7D bounding box of an item.</summary>
 2457    /// <typeparam name="T">The generic type of the item to get the bounding box of.</typeparam>
 2458    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 2459    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 2460    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 2461    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 2462    /// <typeparam name="A5">The generic type of the 5 dimension.</typeparam>
 2463    /// <typeparam name="A6">The generic type of the 6 dimension.</typeparam>
 2464    /// <typeparam name="A7">The generic type of the 7 dimension.</typeparam>
 2465    /// <param name="item">The item to get the bounding box of.</param>
 2466    /// <param name="min1">The minimum bound of the item along the 1 dimension.</param>
 2467    /// <param name="max1">The maximum bound of the item along the 1 dimension.</param>
 2468    /// <param name="min2">The minimum bound of the item along the 2 dimension.</param>
 2469    /// <param name="max2">The maximum bound of the item along the 2 dimension.</param>
 2470    /// <param name="min3">The minimum bound of the item along the 3 dimension.</param>
 2471    /// <param name="max3">The maximum bound of the item along the 3 dimension.</param>
 2472    /// <param name="min4">The minimum bound of the item along the 4 dimension.</param>
 2473    /// <param name="max4">The maximum bound of the item along the 4 dimension.</param>
 2474    /// <param name="min5">The minimum bound of the item along the 5 dimension.</param>
 2475    /// <param name="max5">The maximum bound of the item along the 5 dimension.</param>
 2476    /// <param name="min6">The minimum bound of the item along the 6 dimension.</param>
 2477    /// <param name="max6">The maximum bound of the item along the 6 dimension.</param>
 2478    /// <param name="min7">The minimum bound of the item along the 7 dimension.</param>
 2479    /// <param name="max7">The maximum bound of the item along the 7 dimension.</param>
 2480    public delegate void GetBounds<T, A1
 2481      , A2
 2482      , A3
 2483      , A4
 2484      , A5
 2485      , A6
 2486      , A7
 2487      >(T item, out Bound<A1> min1, out Bound<A1> max1
 2488      , out Bound<A2> min2, out Bound<A2> max2
 2489      , out Bound<A3> min3, out Bound<A3> max3
 2490      , out Bound<A4> min4, out Bound<A4> max4
 2491      , out Bound<A5> min5, out Bound<A5> max5
 2492      , out Bound<A6> min6, out Bound<A6> max6
 2493      , out Bound<A7> min7, out Bound<A7> max7
 2494      );
 2495
 2496    /// <summary>Delegate for getting the 7D bounding box of an item.</summary>
 2497    /// <typeparam name="T">The generic type of the item to get the bounding box of.</typeparam>
 2498    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 2499    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 2500    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 2501    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 2502    /// <typeparam name="A5">The generic type of the 5 dimension.</typeparam>
 2503    /// <typeparam name="A6">The generic type of the 6 dimension.</typeparam>
 2504    /// <typeparam name="A7">The generic type of the 7 dimension.</typeparam>
 2505    /// <param name="item">The item to get the bounding box of.</param>
 2506    /// <param name="min1">The minimum bound of the item along the 1 dimension.</param>
 2507    /// <param name="max1">The maximum bound of the item along the 1 dimension.</param>
 2508    /// <param name="min2">The minimum bound of the item along the 2 dimension.</param>
 2509    /// <param name="max2">The maximum bound of the item along the 2 dimension.</param>
 2510    /// <param name="min3">The minimum bound of the item along the 3 dimension.</param>
 2511    /// <param name="max3">The maximum bound of the item along the 3 dimension.</param>
 2512    /// <param name="min4">The minimum bound of the item along the 4 dimension.</param>
 2513    /// <param name="max4">The maximum bound of the item along the 4 dimension.</param>
 2514    /// <param name="min5">The minimum bound of the item along the 5 dimension.</param>
 2515    /// <param name="max5">The maximum bound of the item along the 5 dimension.</param>
 2516    /// <param name="min6">The minimum bound of the item along the 6 dimension.</param>
 2517    /// <param name="max6">The maximum bound of the item along the 6 dimension.</param>
 2518    /// <param name="min7">The minimum bound of the item along the 7 dimension.</param>
 2519    /// <param name="max7">The maximum bound of the item along the 7 dimension.</param>
 2520    public delegate void GetBoundings<T, A1
 2521      , A2
 2522      , A3
 2523      , A4
 2524      , A5
 2525      , A6
 2526      , A7
 2527      >(T item, out A1 min1, out A1 max1
 2528      , out A2 min2, out A2 max2
 2529      , out A3 min3, out A3 max3
 2530      , out A4 min4, out A4 max4
 2531      , out A5 min5, out A5 max5
 2532      , out A6 min6, out A6 max6
 2533      , out A7 min7, out A7 max7
 2534      );
 2535
 2536    /// <summary>Converts an Omnitree.GetBoundings delegate into an Omnitree.GetBounds delegate.</summary>
 2537    /// <typeparam name="T">The generic type to get the bounds of.</typeparam>
 2538    /// <typeparam name="A1">The generic type of the 1 dimension.</typeparam>
 2539    /// <typeparam name="A2">The generic type of the 2 dimension.</typeparam>
 2540    /// <typeparam name="A3">The generic type of the 3 dimension.</typeparam>
 2541    /// <typeparam name="A4">The generic type of the 4 dimension.</typeparam>
 2542    /// <typeparam name="A5">The generic type of the 5 dimension.</typeparam>
 2543    /// <typeparam name="A6">The generic type of the 6 dimension.</typeparam>
 2544    /// <typeparam name="A7">The generic type of the 7 dimension.</typeparam>
 2545    /// <param name="getBoundings">The Omnitree.GetBoundings to convert into a Omnitree.GetBounds.</param>
 2546    /// <returns>The converted Omnitree.GetBounds delegate.</returns>
 2547    public static GetBounds<T, A1
 2548      , A2
 2549      , A3
 2550      , A4
 2551      , A5
 2552      , A6
 2553      , A7
 2554      > ConvertToGetBounds<T, A1
 2555      , A2
 2556      , A3
 2557      , A4
 2558      , A5
 2559      , A6
 2560      , A7
 2561      >(GetBoundings<T, A1
 2562      , A2
 2563      , A3
 2564      , A4
 2565      , A5
 2566      , A6
 2567      , A7
 2568      > getBoundings) =>
 2569      (T item
 2570      , out Bound<A1> minBound1, out Bound<A1> maxBound1      , out Bound<A2> minBound2, out Bound<A2> maxBound2      , 
 2571      {
 2572        A1 min1; A1 max1;
 2573        A2 min2; A2 max2;
 2574        A3 min3; A3 max3;
 2575        A4 min4; A4 max4;
 2576        A5 min5; A5 max5;
 2577        A6 min6; A6 max6;
 2578        A7 min7; A7 max7;
 2579        getBoundings(item
 2580          , out min1, out max1
 2581          , out min2, out max2
 2582          , out min3, out max3
 2583          , out min4, out max4
 2584          , out min5, out max5
 2585          , out min6, out max6
 2586          , out min7, out max7
 2587          );
 2588        minBound1 = min1; maxBound1 = max1;
 2589        minBound2 = min2; maxBound2 = max2;
 2590        minBound3 = min3; maxBound3 = max3;
 2591        minBound4 = min4; maxBound4 = max4;
 2592        minBound5 = min5; maxBound5 = max5;
 2593        minBound6 = min6; maxBound6 = max6;
 2594        minBound7 = min7; maxBound7 = max7;
 2595      };
 2596
 2597    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 2598    /// <returns>True if the spaces overlap; False if not.</returns>
 2599    public static bool InclusionCheck<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(Omnitree.Bounds<Axis1, Axis2, Axi
 2600      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 2601      a.Max1.Exists && b.Min1.Exists && compare1(a.Max1.Value, b.Min1.Value) is Less ? false :
 2602      a.Min1.Exists && b.Max1.Exists && compare1(a.Min1.Value, b.Max1.Value) is Greater ? false :
 2603      a.Max2.Exists && b.Min2.Exists && compare2(a.Max2.Value, b.Min2.Value) is Less ? false :
 2604      a.Min2.Exists && b.Max2.Exists && compare2(a.Min2.Value, b.Max2.Value) is Greater ? false :
 2605      a.Max3.Exists && b.Min3.Exists && compare3(a.Max3.Value, b.Min3.Value) is Less ? false :
 2606      a.Min3.Exists && b.Max3.Exists && compare3(a.Min3.Value, b.Max3.Value) is Greater ? false :
 2607      a.Max4.Exists && b.Min4.Exists && compare4(a.Max4.Value, b.Min4.Value) is Less ? false :
 2608      a.Min4.Exists && b.Max4.Exists && compare4(a.Min4.Value, b.Max4.Value) is Greater ? false :
 2609      a.Max5.Exists && b.Min5.Exists && compare5(a.Max5.Value, b.Min5.Value) is Less ? false :
 2610      a.Min5.Exists && b.Max5.Exists && compare5(a.Min5.Value, b.Max5.Value) is Greater ? false :
 2611      a.Max6.Exists && b.Min6.Exists && compare6(a.Max6.Value, b.Min6.Value) is Less ? false :
 2612      a.Min6.Exists && b.Max6.Exists && compare6(a.Min6.Value, b.Max6.Value) is Greater ? false :
 2613      a.Max7.Exists && b.Min7.Exists && compare7(a.Max7.Value, b.Min7.Value) is Less ? false :
 2614      a.Min7.Exists && b.Max7.Exists && compare7(a.Min7.Value, b.Max7.Value) is Greater ? false :
 2615      true;
 2616
 2617    /// <summary>Checks if a space encapsulates a point.</summary>
 2618    /// <returns>True if the space encapsulates the point; False if not.</returns>
 2619    public static bool EncapsulationCheck<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(Omnitree.Bounds<Axis1, Axis2,
 2620      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 2621      // if the location is not outside the bounds, it must be inside
 2622      bounds.Min1.Exists && compare1(vector.Axis1, bounds.Min1.Value) is CompareResult.Less ? false :
 2623      bounds.Max1.Exists && compare1(vector.Axis1, bounds.Max1.Value) is CompareResult.Greater ? false :
 2624      bounds.Min2.Exists && compare2(vector.Axis2, bounds.Min2.Value) is CompareResult.Less ? false :
 2625      bounds.Max2.Exists && compare2(vector.Axis2, bounds.Max2.Value) is CompareResult.Greater ? false :
 2626      bounds.Min3.Exists && compare3(vector.Axis3, bounds.Min3.Value) is CompareResult.Less ? false :
 2627      bounds.Max3.Exists && compare3(vector.Axis3, bounds.Max3.Value) is CompareResult.Greater ? false :
 2628      bounds.Min4.Exists && compare4(vector.Axis4, bounds.Min4.Value) is CompareResult.Less ? false :
 2629      bounds.Max4.Exists && compare4(vector.Axis4, bounds.Max4.Value) is CompareResult.Greater ? false :
 2630      bounds.Min5.Exists && compare5(vector.Axis5, bounds.Min5.Value) is CompareResult.Less ? false :
 2631      bounds.Max5.Exists && compare5(vector.Axis5, bounds.Max5.Value) is CompareResult.Greater ? false :
 2632      bounds.Min6.Exists && compare6(vector.Axis6, bounds.Min6.Value) is CompareResult.Less ? false :
 2633      bounds.Max6.Exists && compare6(vector.Axis6, bounds.Max6.Value) is CompareResult.Greater ? false :
 2634      bounds.Min7.Exists && compare7(vector.Axis7, bounds.Min7.Value) is CompareResult.Less ? false :
 2635      bounds.Max7.Exists && compare7(vector.Axis7, bounds.Max7.Value) is CompareResult.Greater ? false :
 2636      true;
 2637
 2638    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 2639    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 2640    public static bool EncapsulationCheck<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(Omnitree.Bounds<Axis1, Axis2,
 2641      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 2642      (a.Min1.Exists && !b.Min1.Exists)
 2643      || (a.Min2.Exists && !b.Min2.Exists)
 2644      || (a.Min3.Exists && !b.Min3.Exists)
 2645      || (a.Min4.Exists && !b.Min4.Exists)
 2646      || (a.Min5.Exists && !b.Min5.Exists)
 2647      || (a.Min6.Exists && !b.Min6.Exists)
 2648      || (a.Min7.Exists && !b.Min7.Exists)
 2649      ? false :
 2650      (a.Max1.Exists && !b.Max1.Exists)
 2651      || (a.Max2.Exists && !b.Max2.Exists)
 2652      || (a.Max3.Exists && !b.Max3.Exists)
 2653      || (a.Max4.Exists && !b.Max4.Exists)
 2654      || (a.Max5.Exists && !b.Max5.Exists)
 2655      || (a.Max6.Exists && !b.Max6.Exists)
 2656      || (a.Max7.Exists && !b.Max7.Exists)
 2657      ? false :
 2658      b.Min1.Exists && a.Min1.Exists && compare1(a.Min1.Value, b.Min1.Value) != CompareResult.Less ? false :
 2659      b.Max1.Exists && a.Max1.Exists && compare1(a.Max1.Value, b.Max1.Value) != CompareResult.Greater ? false :
 2660      b.Min2.Exists && a.Min2.Exists && compare2(a.Min2.Value, b.Min2.Value) != CompareResult.Less ? false :
 2661      b.Max2.Exists && a.Max2.Exists && compare2(a.Max2.Value, b.Max2.Value) != CompareResult.Greater ? false :
 2662      b.Min3.Exists && a.Min3.Exists && compare3(a.Min3.Value, b.Min3.Value) != CompareResult.Less ? false :
 2663      b.Max3.Exists && a.Max3.Exists && compare3(a.Max3.Value, b.Max3.Value) != CompareResult.Greater ? false :
 2664      b.Min4.Exists && a.Min4.Exists && compare4(a.Min4.Value, b.Min4.Value) != CompareResult.Less ? false :
 2665      b.Max4.Exists && a.Max4.Exists && compare4(a.Max4.Value, b.Max4.Value) != CompareResult.Greater ? false :
 2666      b.Min5.Exists && a.Min5.Exists && compare5(a.Min5.Value, b.Min5.Value) != CompareResult.Less ? false :
 2667      b.Max5.Exists && a.Max5.Exists && compare5(a.Max5.Value, b.Max5.Value) != CompareResult.Greater ? false :
 2668      b.Min6.Exists && a.Min6.Exists && compare6(a.Min6.Value, b.Min6.Value) != CompareResult.Less ? false :
 2669      b.Max6.Exists && a.Max6.Exists && compare6(a.Max6.Value, b.Max6.Value) != CompareResult.Greater ? false :
 2670      b.Min7.Exists && a.Min7.Exists && compare7(a.Min7.Value, b.Min7.Value) != CompareResult.Less ? false :
 2671      b.Max7.Exists && a.Max7.Exists && compare7(a.Max7.Value, b.Max7.Value) != CompareResult.Greater ? false :
 2672      true;
 2673
 2674    /// <summary>Checks for equality between two locations.</summary>
 2675    /// <returns>True if equal; False if not;</returns>
 2676    public static bool EqualsCheck<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(Omnitree.Vector<Axis1, Axis2, Axis3,
 2677      Func<Axis1, Axis1, bool> equate1, Func<Axis2, Axis2, bool> equate2, Func<Axis3, Axis3, bool> equate3, Func<Axis4, 
 2678      !equate1(a.Axis1, b.Axis1) ? false :
 2679      !equate2(a.Axis2, b.Axis2) ? false :
 2680      !equate3(a.Axis3, b.Axis3) ? false :
 2681      !equate4(a.Axis4, b.Axis4) ? false :
 2682      !equate5(a.Axis5, b.Axis5) ? false :
 2683      !equate6(a.Axis6, b.Axis6) ? false :
 2684      !equate7(a.Axis7, b.Axis7) ? false :
 2685      true;
 2686
 2687    /// <summary>Checks if a bounds straddles a point if the point extended as a plane along each dimension.</summary>
 2688    /// <typeparam name="Axis1">The generic type of the 1 dimension.</typeparam>
 2689    /// <typeparam name="Axis2">The generic type of the 2 dimension.</typeparam>
 2690    /// <typeparam name="Axis3">The generic type of the 3 dimension.</typeparam>
 2691    /// <typeparam name="Axis4">The generic type of the 4 dimension.</typeparam>
 2692    /// <typeparam name="Axis5">The generic type of the 5 dimension.</typeparam>
 2693    /// <typeparam name="Axis6">The generic type of the 6 dimension.</typeparam>
 2694    /// <typeparam name="Axis7">The generic type of the 7 dimension.</typeparam>
 2695    /// <param name="bounds">The bounds to determine if it straddles the extended point.</param>
 2696    /// <param name="vector">The point representing an extended plan along each axis.</param>
 2697    /// <param name="compare1">The delegate for comparing values along the the 1 dimension.</param>
 2698    /// <param name="compare2">The delegate for comparing values along the the 2 dimension.</param>
 2699    /// <param name="compare3">The delegate for comparing values along the the 3 dimension.</param>
 2700    /// <param name="compare4">The delegate for comparing values along the the 4 dimension.</param>
 2701    /// <param name="compare5">The delegate for comparing values along the the 5 dimension.</param>
 2702    /// <param name="compare6">The delegate for comparing values along the the 6 dimension.</param>
 2703    /// <param name="compare7">The delegate for comparing values along the the 7 dimension.</param>
 2704    /// <returns>True if the extended point was straddled or false if not.</returns>
 2705    public static bool StraddlesLines<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(Omnitree.Bounds<Axis1, Axis2, Axi
 2706      Func<Axis1, Axis1, CompareResult> compare1, Func<Axis2, Axis2, CompareResult> compare2, Func<Axis3, Axis3, Compare
 2707      (!bounds.Min1.Exists || (bounds.Min1.Exists && compare1(bounds.Min1.Value, vector.Axis1) != CompareResult.Greater)
 2708      (!bounds.Max1.Exists || (bounds.Max1.Exists && compare1(bounds.Max1.Value, vector.Axis1) != CompareResult.Less)) ?
 2709      (!bounds.Min2.Exists || (bounds.Min2.Exists && compare2(bounds.Min2.Value, vector.Axis2) != CompareResult.Greater)
 2710      (!bounds.Max2.Exists || (bounds.Max2.Exists && compare2(bounds.Max2.Value, vector.Axis2) != CompareResult.Less)) ?
 2711      (!bounds.Min3.Exists || (bounds.Min3.Exists && compare3(bounds.Min3.Value, vector.Axis3) != CompareResult.Greater)
 2712      (!bounds.Max3.Exists || (bounds.Max3.Exists && compare3(bounds.Max3.Value, vector.Axis3) != CompareResult.Less)) ?
 2713      (!bounds.Min4.Exists || (bounds.Min4.Exists && compare4(bounds.Min4.Value, vector.Axis4) != CompareResult.Greater)
 2714      (!bounds.Max4.Exists || (bounds.Max4.Exists && compare4(bounds.Max4.Value, vector.Axis4) != CompareResult.Less)) ?
 2715      (!bounds.Min5.Exists || (bounds.Min5.Exists && compare5(bounds.Min5.Value, vector.Axis5) != CompareResult.Greater)
 2716      (!bounds.Max5.Exists || (bounds.Max5.Exists && compare5(bounds.Max5.Value, vector.Axis5) != CompareResult.Less)) ?
 2717      (!bounds.Min6.Exists || (bounds.Min6.Exists && compare6(bounds.Min6.Value, vector.Axis6) != CompareResult.Greater)
 2718      (!bounds.Max6.Exists || (bounds.Max6.Exists && compare6(bounds.Max6.Value, vector.Axis6) != CompareResult.Less)) ?
 2719      (!bounds.Min7.Exists || (bounds.Min7.Exists && compare7(bounds.Min7.Value, vector.Axis7) != CompareResult.Greater)
 2720      (!bounds.Max7.Exists || (bounds.Max7.Exists && compare7(bounds.Max7.Value, vector.Axis7) != CompareResult.Less)) ?
 2721      false;
 2722
 2723    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 2724    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 2725    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 2726    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 2727    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 2728    /// <typeparam name="Axis4">The geneic type of the 4D axis.</typeparam>
 2729    /// <typeparam name="Axis5">The geneic type of the 5D axis.</typeparam>
 2730    /// <typeparam name="Axis6">The geneic type of the 6D axis.</typeparam>
 2731    /// <typeparam name="Axis7">The geneic type of the 7D axis.</typeparam>
 2732    /// <param name="omnitree">The omnitree to remove from.</param>
 2733    /// <param name="removal">The value to have all occurences removed.</param>
 2734    public static void Remove<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(this IOmnitreePoints<T, Axis1, Axis2, 
 2735
 2736    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 2737    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 2738    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 2739    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 2740    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 2741    /// <typeparam name="Axis4">The geneic type of the 4D axis.</typeparam>
 2742    /// <typeparam name="Axis5">The geneic type of the 5D axis.</typeparam>
 2743    /// <typeparam name="Axis6">The geneic type of the 6D axis.</typeparam>
 2744    /// <typeparam name="Axis7">The geneic type of the 7D axis.</typeparam>
 2745    /// <param name="omnitree">The omnitree to remove from.</param>
 2746    /// <param name="removal">The value to have all occurences removed.</param>
 2747    /// <param name="equate">The delegate for checking for equality.</param>
 2748    public static void Remove<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(this IOmnitreePoints<T, Axis1, Axis2, 
 2749    {
 2750      Axis1 axis1;
 2751      Axis2 axis2;
 2752      Axis3 axis3;
 2753      Axis4 axis4;
 2754      Axis5 axis5;
 2755      Axis6 axis6;
 2756      Axis7 axis7;
 2757      omnitree.Locate(removal, out axis1
 2758        , out axis2
 2759        , out axis3
 2760        , out axis4
 2761        , out axis5
 2762        , out axis6
 2763        , out axis7
 2764        );
 2765      omnitree.Remove(
 2766        axis1,
 2767        axis2,
 2768        axis3,
 2769        axis4,
 2770        axis5,
 2771        axis6,
 2772        axis7,
 2773        x => equate(x, removal));
 2774    }
 2775
 2776    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 2777    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 2778    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 2779    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 2780    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 2781    /// <typeparam name="Axis4">The geneic type of the 4D axis.</typeparam>
 2782    /// <typeparam name="Axis5">The geneic type of the 5D axis.</typeparam>
 2783    /// <typeparam name="Axis6">The geneic type of the 6D axis.</typeparam>
 2784    /// <typeparam name="Axis7">The geneic type of the 7D axis.</typeparam>
 2785    /// <param name="omnitree">The omnitree to remove from.</param>
 2786    /// <param name="removal">The value to have all occurences removed.</param>
 2787    public static void Remove<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(this IOmnitreeBounds<T, Axis1, Axis2, 
 2788
 2789    /// <summary>Removes all occurences of a value from the omnitree.</summary>
 2790    /// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
 2791    /// <typeparam name="Axis1">The geneic type of the 1D axis.</typeparam>
 2792    /// <typeparam name="Axis2">The geneic type of the 2D axis.</typeparam>
 2793    /// <typeparam name="Axis3">The geneic type of the 3D axis.</typeparam>
 2794    /// <typeparam name="Axis4">The geneic type of the 4D axis.</typeparam>
 2795    /// <typeparam name="Axis5">The geneic type of the 5D axis.</typeparam>
 2796    /// <typeparam name="Axis6">The geneic type of the 6D axis.</typeparam>
 2797    /// <typeparam name="Axis7">The geneic type of the 7D axis.</typeparam>
 2798    /// <param name="omnitree">The omnitree to remove from.</param>
 2799    /// <param name="removal">The value to have all occurences removed.</param>
 2800    /// <param name="equate">The delegate for checking for equality.</param>
 2801    public static void Remove<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(this IOmnitreeBounds<T, Axis1, Axis2, 
 2802    {
 2803      Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 2804      Omnitree.Bound<Axis2> min2; Omnitree.Bound<Axis2> max2;
 2805      Omnitree.Bound<Axis3> min3; Omnitree.Bound<Axis3> max3;
 2806      Omnitree.Bound<Axis4> min4; Omnitree.Bound<Axis4> max4;
 2807      Omnitree.Bound<Axis5> min5; Omnitree.Bound<Axis5> max5;
 2808      Omnitree.Bound<Axis6> min6; Omnitree.Bound<Axis6> max6;
 2809      Omnitree.Bound<Axis7> min7; Omnitree.Bound<Axis7> max7;
 2810      omnitree.GetBounds(removal, out min1, out max1
 2811        , out min2, out max2
 2812        , out min3, out max3
 2813        , out min4, out max4
 2814        , out min5, out max5
 2815        , out min6, out max6
 2816        , out min7, out max7
 2817        );
 2818      omnitree.RemoveOverlapped(min1, max1
 2819        , min2, max2
 2820        , min3, max3
 2821        , min4, max4
 2822        , min5, max5
 2823        , min6, max6
 2824        , min7, max7
 2825        , x => equate(x, removal));
 2826    }
 2827
 2828    #endregion
 2829
 2830    #endregion
 2831  }
 2832
 2833  #region Omnitree
 2834
 2835  #region 1 Dimensional
 2836
 2837  /// <summary>Inheritance base for 1D omnitrees.</summary>
 2838  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 2839  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 2840  public interface IOmnitree<T, Axis1> : IOmnitree<T> { }
 2841
 2842  #endregion
 2843
 2844  #region 2 Dimensional
 2845
 2846  /// <summary>Inheritance base for 2D omnitrees.</summary>
 2847  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 2848  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 2849  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 2850  public interface IOmnitree<T, Axis1, Axis2> : IOmnitree<T> { }
 2851
 2852  #endregion
 2853
 2854  #region 3 Dimensional
 2855
 2856  /// <summary>Inheritance base for 3D omnitrees.</summary>
 2857  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 2858  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 2859  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 2860  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 2861  public interface IOmnitree<T, Axis1, Axis2, Axis3> : IOmnitree<T> { }
 2862
 2863  #endregion
 2864
 2865  #region 4 Dimensional
 2866
 2867  /// <summary>Inheritance base for 4D omnitrees.</summary>
 2868  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 2869  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 2870  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 2871  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 2872  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 2873  public interface IOmnitree<T, Axis1, Axis2, Axis3, Axis4> : IOmnitree<T> { }
 2874
 2875  #endregion
 2876
 2877  #region 5 Dimensional
 2878
 2879  /// <summary>Inheritance base for 5D omnitrees.</summary>
 2880  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 2881  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 2882  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 2883  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 2884  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 2885  /// <typeparam name="Axis5">The type 5D axis.</typeparam>
 2886  public interface IOmnitree<T, Axis1, Axis2, Axis3, Axis4, Axis5> : IOmnitree<T> { }
 2887
 2888  #endregion
 2889
 2890  #region 6 Dimensional
 2891
 2892  /// <summary>Inheritance base for 6D omnitrees.</summary>
 2893  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 2894  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 2895  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 2896  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 2897  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 2898  /// <typeparam name="Axis5">The type 5D axis.</typeparam>
 2899  /// <typeparam name="Axis6">The type 6D axis.</typeparam>
 2900  public interface IOmnitree<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> : IOmnitree<T> { }
 2901
 2902  #endregion
 2903
 2904  #region 7 Dimensional
 2905
 2906  /// <summary>Inheritance base for 7D omnitrees.</summary>
 2907  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 2908  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 2909  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 2910  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 2911  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 2912  /// <typeparam name="Axis5">The type 5D axis.</typeparam>
 2913  /// <typeparam name="Axis6">The type 6D axis.</typeparam>
 2914  /// <typeparam name="Axis7">The type 7D axis.</typeparam>
 2915  public interface IOmnitree<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> : IOmnitree<T> { }
 2916
 2917  #endregion
 2918
 2919  #endregion
 2920
 2921  #region OmnitreePoints
 2922
 2923  #region 1 Dimensional
 2924
 2925  /// <summary>Inheritance base for 1D omnitrees that store points.</summary>
 2926  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 2927  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 2928  public interface IOmnitreePoints<T, Axis1> : IOmnitree<T, Axis1>
 2929  {
 2930    #region Properties
 2931
 2932    /// <summary>Steps through the values at a given location.</summary>
 2933    /// <param name="axis1">The coordinate along the 1D axis.</param>
 2934
 2935    /// <returns>A Stepper of the items at the given coordinates.</returns>
 2936    Action<Action<T>> this[Axis1 axis1] { get; }
 2937
 2938    /// <summary>The number of dimensions in this tree.</summary>
 2939    int Dimensions { get; }
 2940
 2941    /// <summary>The delegate being used by the omnitree to locate items in 1D space.</summary>
 2942    Omnitree.Location<T, Axis1
 2943      > Locate { get; }
 2944
 2945    #endregion
 2946
 2947    #region Methods
 2948
 2949    /// <summary>Counts the number of items in a sub space.</summary>
 2950    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 2951    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 2952    /// <returns>The number of items in the provided sub space.</returns>
 2953    int CountSubSpace(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1);
 2954
 2955    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 2956    void Update();
 2957    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 2958    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 2959    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 2960    void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1);
 2961
 2962    /// <summary>Removes all the items in a given space.</summary>
 2963    /// <param name="axis1">The coordinate along the 1D axis.</param>
 2964    void Remove(Axis1 axis1);
 2965    /// <summary>Removes all the items in a given space.</summary>
 2966    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 2967    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 2968    void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1);
 2969    /// <summary>Removes all the items in a given space where equality is met.</summary>
 2970    /// <param name="axis1">The coordinate along the 1D axis.</param>
 2971    /// <param name="where">The equality constraint of the removal.</param>
 2972    void Remove(Axis1 axis1, Predicate<T> where);
 2973    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 2974    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 2975    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 2976    /// <param name="where">The predicate constraint of the removal.</param>
 2977    void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Predicate<T> where);
 2978
 2979    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 2980    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 2981    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 2982    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 2983    void Stepper(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1);
 2984    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 2985    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 2986    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 2987    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 2988    StepStatus Stepper(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1);
 2989    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 2990    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 2991    /// <param name="axis1">The coordinate along the 1D axis.</param>
 2992    void Stepper(Action<T> step, Axis1 axis1);
 2993    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 2994    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 2995    /// <param name="axis1">The coordinate along the 1D axis.</param>
 2996    StepStatus Stepper(Func<T, StepStatus> step, Axis1 axis1);
 2997
 2998    #endregion
 2999  }
 3000
 3001  /// <summary>Omnitree that stores points along 1 dimensions implemented as a linked tree.</summary>
 3002  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 3003  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 3004  public class OmnitreePointsLinked<T, Axis1> : IOmnitreePoints<T, Axis1>
 3005  {
 3006    internal const int _dimensions = 1;
 3007    internal static int _children_per_node = (int)BigInteger.Pow(2, 1);
 3008
 3009    internal Node _top;
 3010    internal int _naturalLogLower = 1; // caching the next time to calculate loads (lower count)
 3011    internal int _naturalLogUpper = -1; // caching the next time to calculate loads (upper count)
 3012    internal int _load; // ln(count); min = _defaultLoad
 3013    internal Omnitree.Location<T, Axis1
 3014      > _locate;
 3015    internal bool _defaultCompare1;
 3016    internal Func<Axis1, Axis1, CompareResult> _compare1;
 3017    internal Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1>> _subdivisionOverride1;
 3018
 3019    #region Nested Types
 3020
 3021    /// <summary>Can be a leaf or a branch.</summary>
 3022    internal abstract class Node
 3023    {
 3024      internal Omnitree.Bounds<Axis1> Bounds;
 3025      internal Branch Parent;
 3026      internal int Index;
 3027      internal int Count;
 3028
 3029      /// <summary>The depth this node is located in the Omnitree.</summary>
 3030      internal int Depth
 3031      {
 3032        get
 3033        {
 3034          int depth = -1;
 3035          for (Node node = this; node is not null; node = node.Parent)
 3036            depth++;
 3037          return depth;
 3038        }
 3039      }
 3040
 3041      /// <summary>Constructs a node.</summary>
 3042      /// <param name="bounds">The bounds of this node.</param>
 3043      /// <param name="parent">The parent of this node.</param>
 3044      /// <param name="index">The number of values stored in this node and its children.</param>
 3045      internal Node(Omnitree.Bounds<Axis1> bounds, Branch parent, int index)
 3046      {
 3047        Bounds = bounds;
 3048        Parent = parent;
 3049        Index = index;
 3050      }
 3051
 3052      internal Node(Node nodeToClone)
 3053      {
 3054        this.Bounds = nodeToClone.Bounds;
 3055        this.Parent = nodeToClone.Parent;
 3056        this.Index = nodeToClone.Index;
 3057        this.Count = nodeToClone.Count;
 3058      }
 3059
 3060      internal abstract Node Clone();
 3061    }
 3062
 3063    /// <summary>A branch in the tree. Only contains nodes.</summary>
 3064    internal class Branch : Node
 3065    {
 3066      internal Node[] Children;
 3067      internal Omnitree.Vector<Axis1> PointOfDivision;
 3068
 3069      /// <summary>Gets child by index.</summary>
 3070      /// <param name="child_index">The index of the child to get.</param>
 3071      /// <returns>The child of the given index or null if non-existent.</returns>
 3072      internal Node this[int child_index]
 3073      {
 3074        get
 3075        {
 3076          if (Children is null)
 3077            return null;
 3078          if (Children.Length == OmnitreePointsLinked<T, Axis1>._children_per_node)
 3079            return Children[(int)child_index];
 3080          foreach (Node node in Children)
 3081            if (node.Index == child_index)
 3082              return node;
 3083          return null;
 3084        }
 3085        set
 3086        {
 3087          // This error check should be unnecessary... but fuck it... might as well
 3088          if (value.Index != child_index)
 3089            throw new System.Exception("Bug in Omnitree (index/property mis-match when setting a child on a branch)");
 3090
 3091          // no children yet
 3092          if (Children is null)
 3093          {
 3094            Children = â±¯(value);
 3095            return;
 3096          }
 3097          // max children overwrite
 3098          else if (this.Children.Length == OmnitreePointsLinked<T, Axis1>._children_per_node)
 3099          {
 3100            Children[(int)child_index] = value;
 3101            return;
 3102          }
 3103          // non-max child overwrite
 3104          for (int i = 0; i < Children.Length; i++)
 3105            if (Children[i].Index == child_index)
 3106            {
 3107              Children[i] = value;
 3108              return;
 3109            }
 3110          // new child
 3111          Node[] newArray = new Node[Children.Length + 1];
 3112          if (newArray.Length == OmnitreePointsLinked<T, Axis1>._children_per_node)
 3113          {
 3114            // new child resulting in a max children branch (sorting required)
 3115            for (int i = 0; i < Children.Length; i++)
 3116            {
 3117              newArray[(int)Children[i].Index] = Children[i];
 3118            }
 3119            newArray[(int)value.Index] = value;
 3120          }
 3121          else
 3122          {
 3123            // new child resulting in a non-max children branch
 3124            Array.Copy(Children, newArray, Children.Length);
 3125            newArray[newArray.Length - 1] = value;
 3126          }
 3127          this.Children = newArray;
 3128        }
 3129      }
 3130
 3131      internal Branch(Omnitree.Vector<Axis1> pointOfDivision, Omnitree.Bounds<Axis1> bounds, Branch parent, int index)
 3132        : base(bounds, parent, index)
 3133      {
 3134        this.PointOfDivision = pointOfDivision;
 3135      }
 3136
 3137      internal Branch(Branch branchToClone) : base(branchToClone)
 3138      {
 3139        Children = branchToClone.Children.Clone() as Node[];
 3140        PointOfDivision = branchToClone.PointOfDivision;
 3141      }
 3142
 3143      internal override Node Clone() =>
 3144        new Branch(this);
 3145    }
 3146
 3147    /// <summary>A branch in the tree. Only contains items.</summary>
 3148    internal class Leaf : Node
 3149    {
 3150      internal class Node
 3151      {
 3152        internal T Value;
 3153        internal Leaf.Node Next;
 3154
 3155        internal Node(T value, Leaf.Node next)
 3156        {
 3157          Value = value;
 3158          Next = next;
 3159        }
 3160      }
 3161
 3162      internal Leaf.Node Head;
 3163
 3164      internal Leaf(Omnitree.Bounds<Axis1> bounds, Branch parent, int index)
 3165        : base(bounds, parent, index)
 3166      { }
 3167
 3168      internal Leaf(Leaf leaf) : base(leaf)
 3169      {
 3170        Head = new Node(leaf.Head.Value, null);
 3171        Node a = Head;
 3172        Node b = leaf.Head;
 3173        while (b is not null)
 3174        {
 3175          a.Next = new Node(b.Next.Value, null);
 3176          a = a.Next;
 3177          b = b.Next;
 3178        }
 3179      }
 3180
 3181      internal void Add(T addition)
 3182      {
 3183        Head = new Leaf.Node(addition, Head);
 3184        this.Count++;
 3185      }
 3186
 3187      internal override OmnitreePointsLinked<T, Axis1>.Node Clone() =>
 3188        new Leaf(this);
 3189    }
 3190
 3191    #endregion
 3192
 3193    #region Constructors
 3194
 3195    /// <summary>This constructor is for cloning purposes</summary>
 3196    internal OmnitreePointsLinked(OmnitreePointsLinked<T, Axis1> omnitree)
 3197    {
 3198      this._top = omnitree._top.Clone();
 3199      this._load = omnitree._load;
 3200      this._locate = omnitree._locate;
 3201      this._defaultCompare1 = omnitree._defaultCompare1;
 3202      this._compare1 = omnitree._compare1;
 3203      this._subdivisionOverride1 = omnitree._subdivisionOverride1;
 3204    }
 3205
 3206    internal OmnitreePointsLinked(
 3207      Omnitree.Location<T, Axis1> locate,
 3208      bool defaultCompare1,
 3209      Func<Axis1, Axis1, CompareResult> compare1,
 3210      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1>> subdivisionOverride1
 3211      )
 3212    {
 3213      if (locate is null)
 3214      {
 3215        throw new ArgumentNullException(nameof(locate));
 3216      }
 3217      if (compare1 is null)
 3218      {
 3219        throw new ArgumentNullException(nameof(compare1));
 3220      }
 3221
 3222      this._locate = locate;
 3223      this._defaultCompare1 = defaultCompare1;
 3224      this._compare1 = compare1;
 3225      this._subdivisionOverride1 = subdivisionOverride1;
 3226      this._top = new Leaf(Omnitree.Bounds<Axis1>.None, null, -1);
 3227      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 3228    }
 3229
 3230    /// <summary>Constructs a new 1D omnitree that stores points.</summary>
 3231    /// <param name="locate">The delegate for locating items in 1D space.</param>
 3232
 3233    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 3234
 3235    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 3236    public OmnitreePointsLinked(
 3237      Omnitree.Location<T, Axis1> locate,
 3238      Func<Axis1, Axis1, CompareResult> compare1 = null,
 3239      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1>> subdivisionOverride1 = null
 3240      )
 3241      : this(
 3242        locate,
 3243        compare1 is null ? true : false,
 3244        compare1 ?? Compare,
 3245        subdivisionOverride1
 3246        ) { }
 3247
 3248    #endregion
 3249
 3250    #region Properties
 3251
 3252    /// <summary>Steps through all the items at a given coordinate.</summary>
 3253    /// <param name="axis1">The coordinate along axis 1.</param>
 3254    /// <returns>The stepper for the items at the given coordinate.</returns>
 3255    public Action<Action<T>> this[Axis1 axis1] =>
 3256      step => Stepper(step, axis1);
 3257
 3258    /// <summary>The number of dimensions in this tree.</summary>
 3259    public int Dimensions { get { return _dimensions; } }
 3260
 3261    /// <summary>The location function the Omnitree is using.</summary>
 3262    public Omnitree.Location<T, Axis1> Locate { get { return this._locate; } }
 3263
 3264    /// <summary>The comparison function the Omnitree is using along the 1D axis.</summary>
 3265    public Func<Axis1, Axis1, CompareResult> Compare1 { get { return this._compare1; } }
 3266
 3267    /// <summary>The current number of items in the tree.</summary>
 3268    public int Count { get { return this._top.Count; } }
 3269
 3270    internal delegate void MaxDepthFinder(Node node, int current_depth, ref int max_depth);
 3271    /// <summary>Finds the current maximum depth of the tree. NOT AN O(1) OPERATION. Intended for educational purposes o
 3272    public int MaxDepth
 3273    {
 3274      get
 3275      {
 3276        MaxDepthFinder maxDepthFinder = null;
 3277        maxDepthFinder =
 3278          (Node node, int current_depth, ref int max_depth) =>
 3279          {
 3280            if (current_depth > max_depth)
 3281              max_depth = current_depth;
 3282            if (node is Branch)
 3283              foreach (Node child in (node as Branch).Children)
 3284                maxDepthFinder(child, current_depth + 1, ref max_depth);
 3285          };
 3286        int _max_depth = -1;
 3287        maxDepthFinder(this._top, 0, ref _max_depth);
 3288        return _max_depth;
 3289      }
 3290    }
 3291
 3292    internal delegate void NodeCountFinder(Node node, ref int current_count);
 3293    /// <summary>Counts the current number of nodes in the tree. NOT AN O(1) OPERATION. Intended for educational purpose
 3294    public int NodeCount
 3295    {
 3296      get
 3297      {
 3298        NodeCountFinder nodeCountFinder = null;
 3299        nodeCountFinder =
 3300          (Node node, ref int current_count) =>
 3301          {
 3302            current_count++;
 3303            if (node is Branch)
 3304              foreach (Node child in (node as Branch).Children)
 3305                nodeCountFinder(child, ref current_count);
 3306          };
 3307
 3308        int _current_count = 0;
 3309        nodeCountFinder(this._top, ref _current_count);
 3310        return _current_count;
 3311      }
 3312    }
 3313
 3314    internal delegate void BranchCountFinder(Node node, ref int current_count);
 3315    /// <summary>Counts the current number of branches in the tree. NOT AN O(1) OPERATION. Intended for educational purp
 3316    public int BranchCount
 3317    {
 3318      get
 3319      {
 3320        BranchCountFinder branchCountFinder = null;
 3321        branchCountFinder =
 3322          (Node node, ref int current_count) =>
 3323          {
 3324            if (node is Branch)
 3325            {
 3326              current_count++;
 3327              foreach (Node child in (node as Branch).Children)
 3328                branchCountFinder(child, ref current_count);
 3329            }
 3330          };
 3331
 3332        int _current_count = 0;
 3333        branchCountFinder(this._top, ref _current_count);
 3334        return _current_count;
 3335      }
 3336    }
 3337
 3338    internal delegate void LeafCountFinder(Node node, ref int current_count);
 3339    /// <summary>Counts the current number of leaves in the tree. NOT AN O(1) OPERATION. Intended for educational purpos
 3340    public int LeafCount
 3341    {
 3342      get
 3343      {
 3344        LeafCountFinder leafCountFinder = null;
 3345        leafCountFinder =
 3346          (Node node, ref int current_count) =>
 3347          {
 3348            if (node is Leaf)
 3349              current_count++;
 3350            else
 3351              foreach (Node child in (node as Branch).Children)
 3352                leafCountFinder(child, ref current_count);
 3353          };
 3354
 3355        int _current_count = 0;
 3356        leafCountFinder(this._top, ref _current_count);
 3357        return _current_count;
 3358      }
 3359    }
 3360
 3361    #endregion
 3362
 3363    #region Methods
 3364
 3365    #region Add
 3366
 3367
 3368    #region single
 3369
 3370    /// <summary>Tries to add a value.</summary>
 3371    /// <param name="value">The value to be added.</param>
 3372    /// <returns>True if successful or false if not.</returns>
 3373    public (bool Success, Exception? Exception) TryAdd(T value)
 3374    {
 3375      Add(value);
 3376      return (true, null);
 3377    }
 3378
 3379    /// <summary>Adds an item to the tree.</summary>
 3380    /// <param name="addition">The item to be added.</param>
 3381    public void Add(T addition)
 3382    {
 3383      if (this._top.Count is int.MaxValue)
 3384        throw new System.InvalidOperationException("(Count is int.MaxValue) max Omnitree size reached (change ints to lo
 3385
 3386      // dynamic tree sizes
 3387      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 3388
 3389      Omnitree.Vector<Axis1> location = LocateVector(addition);
 3390
 3391      // grow the first branch of the tree
 3392      if (this._top is Leaf && (this._top as Leaf).Count >= _load)
 3393      {
 3394        Leaf top = this._top as Leaf;
 3395
 3396        // create the new branch from the median values
 3397        this._top = new Branch(DetermineMedians(top), Omnitree.Bounds<Axis1>.None, null, -1);
 3398
 3399        // iterate through the values and add them to the appropriate children
 3400        for (Leaf.Node list = top.Head; list is not null; list = list.Next)
 3401          Add(list.Value, this._top, LocateVector(list.Value), 0);
 3402      }
 3403
 3404      this.Add(addition, this._top, location, 0);
 3405    }
 3406
 3407    /// <summary>Recursive version of the add function.</summary>
 3408    /// <param name="addition">The item to be added.</param>
 3409    /// <param name="node">The current node for tree trversal.</param>
 3410    /// <param name="location">The location of the addition.</param>
 3411    /// <param name="depth">The current depth of iteration.</param>
 3412    internal void Add(T addition, Node node, Omnitree.Vector<Axis1> location, int depth)
 3413    {
 3414      if (node is Leaf)
 3415      {
 3416        Leaf leaf = node as Leaf;
 3417        if (depth >= _load || !(leaf.Count >= _load))
 3418        {
 3419          leaf.Add(addition);
 3420          return;
 3421        }
 3422        else
 3423        {
 3424          Branch parent = node.Parent;
 3425          int child_index = this.DetermineChildIndex(parent.PointOfDivision, location);
 3426          Branch growth = new Branch(DetermineMedians(leaf), leaf.Bounds, parent, child_index);
 3427          parent[child_index] = growth;
 3428          for (Leaf.Node list = leaf.Head; list is not null; list = list.Next)
 3429          {
 3430            Omnitree.Vector<Axis1> temp_location = LocateVector(list.Value);
 3431            if (EncapsulationCheck(growth.Bounds, temp_location))
 3432              Add(list.Value, growth, temp_location, depth);
 3433            else
 3434            {
 3435              ReduceParentCounts(parent, 1);
 3436              Add(list.Value, this._top, temp_location, depth);
 3437            }
 3438          }
 3439
 3440          Add(addition, growth, location, depth);
 3441          return;
 3442        }
 3443      }
 3444      else
 3445      {
 3446        Branch branch = node as Branch;
 3447        int child_index = this.DetermineChildIndex(branch.PointOfDivision, location); // determine the child "index" (0 
 3448        Node child_node = branch[child_index];
 3449
 3450        // null children in branches are just empty leaves
 3451        if (child_node is null)
 3452        {
 3453          Leaf new_leaf = new Leaf(DetermineChildBounds(branch, child_index), branch, child_index);
 3454          branch[child_index] = new_leaf;
 3455          new_leaf.Add(addition);
 3456        }
 3457        else
 3458          // child exists already, continue adding
 3459          Add(addition, child_node, location, depth + 1);
 3460
 3461        branch.Count++;
 3462        return;
 3463      }
 3464    }
 3465
 3466    internal Omnitree.Vector<Axis1> DetermineMedians(Leaf leaf)
 3467    {
 3468
 3469      Axis1 division1;
 3470      if (!(_subdivisionOverride1 is null))
 3471      {
 3472        division1 = _subdivisionOverride1(leaf.Bounds, x =>
 3473          {
 3474            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 3475            {
 3476              x(node.Value);
 3477            }
 3478          });
 3479      }
 3480      else
 3481      {
 3482        Axis1[] values = new Axis1[leaf.Count];
 3483        Leaf.Node for_current = leaf.Head;
 3484        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 3485          this._locate(for_current.Value
 3486          , out values[i]
 3487          );
 3488        if (_defaultCompare1) Array.Sort(values);
 3489        else SortQuick<Axis1>(values, this._compare1);
 3490        int index = (leaf.Count - 1) / 2;
 3491        division1 = values[index];
 3492      }
 3493
 3494      return new Omnitree.Vector<Axis1>(
 3495        division1
 3496
 3497        );
 3498    }
 3499
 3500    #endregion
 3501
 3502    #region Add Helpers
 3503
 3504    internal Omnitree.Bounds<Axis1> DetermineChildBounds(Branch branch, int child_index)
 3505    {
 3506
 3507      Omnitree.Bound<Axis1> min1, max1;
 3508      if (child_index >= 1)
 3509      {
 3510        min1 = branch.PointOfDivision.Axis1;
 3511        max1 = branch.Bounds.Max1;
 3512        child_index -= 1;
 3513      }
 3514      else
 3515      {
 3516        min1 = branch.Bounds.Min1;
 3517        max1 = branch.PointOfDivision.Axis1;
 3518      }
 3519
 3520      return new Omnitree.Bounds<Axis1>(min1, max1);
 3521    }
 3522
 3523    #endregion
 3524
 3525    #endregion
 3526
 3527    #region Clear
 3528
 3529    /// <summary>Returns the tree to an empty state.</summary>
 3530    public void Clear()
 3531    {
 3532      this._top = new Leaf(Omnitree.Bounds<Axis1>.None, null, -1);
 3533      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 3534    }
 3535
 3536    #endregion
 3537
 3538    #region Clone
 3539
 3540    /// <summary>Creates a shallow clone of this data structure.</summary>
 3541    /// <returns>A shallow clone of this data structure.</returns>
 3542    public OmnitreePointsLinked<T, Axis1> Clone()
 3543    {
 3544      return new OmnitreePointsLinked<T, Axis1>(this);
 3545    }
 3546
 3547    #endregion
 3548
 3549    #region Count
 3550
 3551    /// <summary>Counts the number of items in a sub space.</summary>
 3552    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 3553    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 3554    /// <returns>The number of items in the provided sub space.</returns>
 3555    public int CountSubSpace(Axis1 min1, Axis1 max1)
 3556    {
 3557      return CountSubSpace(_top, new Omnitree.Bounds<Axis1>(min1, max1));
 3558    }
 3559    /// <summary>Counts the number of items in a sub space.</summary>
 3560    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 3561    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 3562    /// <returns>The number of items in the provided sub space.</returns>
 3563    public int CountSubSpace(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1)
 3564    {
 3565      return CountSubSpace(_top, new Omnitree.Bounds<Axis1>(min1, max1));
 3566    }
 3567    /// <summary>Counts the number of items in a sub space.</summary>
 3568    /// <param name="axis1">The coordinate along the 1D axis.</param>
 3569    /// <returns>The number of items in the provided sub space.</returns>
 3570    public int CountSubSpace(Axis1 axis1)
 3571    {
 3572      return CountSubSpace(_top, new Omnitree.Bounds<Axis1>(axis1, axis1));
 3573    }
 3574    /// <summary>Counts the number of items in a sub space.</summary>
 3575    /// <param name="axis1">The coordinate along the 1D axis.</param>
 3576    /// <returns>The number of items in the provided sub space.</returns>
 3577    public int CountSubSpace(Omnitree.Bound<Axis1> axis1)
 3578    {
 3579      return CountSubSpace(_top, new Omnitree.Bounds<Axis1>(axis1, axis1));
 3580    }
 3581    /// <summary>Counts the number of items in a sub space.</summary>
 3582    /// <param name="node">The current traversal node.</param>
 3583    /// <param name="bounds">The bounds of the sub space being counted.</param>
 3584    /// <returns>The number of items in the provided sub space.</returns>
 3585    internal int CountSubSpace(Node node, Omnitree.Bounds<Axis1> bounds)
 3586    {
 3587      // adjust min/max values
 3588      int count = 0;
 3589      if (EncapsulationCheck(bounds, node.Bounds))
 3590        count += node.Count;
 3591      else if (node is Leaf)
 3592      {
 3593        for (Leaf.Node list = (node as Leaf).Head; list is null; list = list.Next)
 3594          if (EncapsulationCheck(bounds, LocateVector(list.Value)))
 3595            count++;
 3596      }
 3597      else
 3598      {
 3599        Branch branch = node as Branch;
 3600        if (!StraddlesLines(branch.Bounds, branch.PointOfDivision))
 3601        {
 3602          int child_index = DetermineChildIndex(branch.PointOfDivision, new Omnitree.Vector<Axis1>(bounds.Min1.Value
 3603            ));
 3604          Node child = branch[child_index];
 3605          if (child is not null)
 3606          {
 3607            count += this.CountSubSpace(child, bounds);
 3608          }
 3609        }
 3610        else
 3611        {
 3612          foreach (Node child in (node as Branch).Children)
 3613            count += this.CountSubSpace(child, bounds);
 3614        }
 3615      }
 3616      return count;
 3617    }
 3618
 3619    #endregion
 3620
 3621    #region Update
 3622
 3623    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 3624    public void Update()
 3625    {
 3626      this.Update(this._top, 0);
 3627    }
 3628
 3629    /// <summary>Recursive version of the Update method.</summary>
 3630    /// <param name="node">The current node of iteration.</param>
 3631    /// <param name="depth">The current depth of iteration.</param>
 3632    internal int Update(Node node, int depth)
 3633    {
 3634      int removals = 0;
 3635
 3636      if (node is Leaf)
 3637      {
 3638        Leaf leaf = node as Leaf;
 3639        Leaf.Node current = leaf.Head;
 3640        Leaf.Node previous = null;
 3641        while (current is not null)
 3642        {
 3643          Omnitree.Vector<Axis1> location = LocateVector(current.Value);
 3644          if (!this.EncapsulationCheck(node.Bounds, location))
 3645          {
 3646            removals++;
 3647            T updated = current.Value;
 3648            if (previous is null)
 3649            {
 3650              leaf.Head = current.Next;
 3651              goto HeadRemoved;
 3652            }
 3653            else
 3654              previous.Next = current.Next;
 3655
 3656            Node whereToAdd = GetEncapsulationParent(node.Parent, location);
 3657
 3658            if (whereToAdd is null)
 3659              throw new System.Exception("an item was updated outside the range of the omnitree");
 3660
 3661            this.Add(updated, whereToAdd, location, whereToAdd.Depth);
 3662          }
 3663          previous = current;
 3664        HeadRemoved:
 3665          current = current.Next;
 3666        }
 3667        leaf.Count -= removals;
 3668        return removals;
 3669      }
 3670      else
 3671      {
 3672        Branch branch = node as Branch;
 3673        int skipped = 0;
 3674        for (int i = 0; i + skipped < branch.Children.Length; )
 3675        {
 3676          removals += this.Update(branch.Children[i], depth + 1);
 3677          if (branch.Children[i].Count is 0)
 3678            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 3679          else
 3680            i++;
 3681        }
 3682        Node[] newArray = new Node[branch.Children.Length - skipped];
 3683        Array.Copy(branch.Children, newArray, newArray.Length);
 3684        branch.Children = newArray;
 3685
 3686        branch.Count -= removals;
 3687
 3688        if (branch.Count < _load && branch.Count != 0)
 3689          ShrinkChild(branch.Parent, branch.Index);
 3690      }
 3691
 3692      return removals;
 3693    }
 3694
 3695    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 3696    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 3697    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 3698    public void Update(Axis1 min1, Axis1 max1)
 3699    {
 3700      this.Update(new Omnitree.Bounds<Axis1>(min1, max1), this._top, 0);
 3701    }
 3702    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 3703    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 3704    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 3705    public void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1)
 3706    {
 3707      this.Update(new Omnitree.Bounds<Axis1>(min1, max1), this._top, 0);
 3708    }
 3709    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 3710    /// <param name="axis1">The coordinate along the 1D axis.</param>
 3711    public void Update(Axis1 axis1)
 3712    {
 3713      this.Update(new Omnitree.Bounds<Axis1>(axis1, axis1), this._top, 0);
 3714    }
 3715    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 3716    /// <param name="axis1">The coordinate along the 1D axis.</param>
 3717    public void Update(Omnitree.Bound<Axis1> axis1)
 3718    {
 3719      this.Update(new Omnitree.Bounds<Axis1>(axis1, axis1), this._top, 0);
 3720    }
 3721    internal int Update(Omnitree.Bounds<Axis1> bounds, Node node, int depth)
 3722    {
 3723      if (!InclusionCheck(bounds, node.Bounds))
 3724        return 0;
 3725
 3726      int removals = 0;
 3727
 3728      if (node is Leaf)
 3729      {
 3730        Leaf leaf = node as Leaf;
 3731        Leaf.Node current = leaf.Head;
 3732        Leaf.Node previous = null;
 3733        while (current is not null)
 3734        {
 3735          Omnitree.Vector<Axis1> location = LocateVector(current.Value);
 3736          if (!this.EncapsulationCheck(node.Bounds, location))
 3737          {
 3738            removals++;
 3739            T updated = current.Value;
 3740            if (previous is null)
 3741            {
 3742              leaf.Head = current.Next;
 3743              goto HeadRemoved;
 3744            }
 3745            else
 3746              previous.Next = current.Next;
 3747            Node whereToAdd = GetEncapsulationParent(node.Parent, location);
 3748            if (whereToAdd is null)
 3749              throw new System.Exception("an item was updates outside the range of the omnitree");
 3750            this.Add(updated, whereToAdd, location, whereToAdd.Depth);
 3751          }
 3752          previous = current;
 3753        HeadRemoved:
 3754          current = current.Next;
 3755        }
 3756        leaf.Count -= removals;
 3757        return removals;
 3758      }
 3759      else
 3760      {
 3761        Branch branch = node as Branch;
 3762        int skipped = 0;
 3763        for (int i = 0; i + skipped < branch.Children.Length; )
 3764        {
 3765          removals += this.Update(branch.Children[i], depth + 1);
 3766          if (branch.Children[i].Count is 0)
 3767            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 3768          else
 3769            i++;
 3770        }
 3771        Node[] newArray = new Node[branch.Children.Length - skipped];
 3772        Array.Copy(branch.Children, newArray, newArray.Length);
 3773        branch.Children = newArray;
 3774
 3775        branch.Count -= removals;
 3776
 3777        if (branch.Count < _load && branch.Count != 0)
 3778          ShrinkChild(branch.Parent, branch.Index);
 3779      }
 3780
 3781      return removals;
 3782    }
 3783
 3784    #endregion
 3785
 3786    #region Remove
 3787
 3788    /// <summary>Removes all the items qualified by the delegate.</summary>
 3789    /// <param name="where">The predicate to qualify removals.</param>
 3790    public void Remove(Predicate<T> where)
 3791    {
 3792      this.Remove(this._top, where);
 3793      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 3794    }
 3795
 3796    /// <summary>Recursive version of the remove method.</summary>
 3797    /// <param name="node">The current node of traversal.</param>
 3798    /// <param name="where">The predicate to qualify removals.</param>
 3799    internal int Remove(Node node, Predicate<T> where)
 3800    {
 3801      int removals = 0;
 3802      if (node is Leaf)
 3803      {
 3804        Leaf leaf = node as Leaf;
 3805        while (leaf.Head is not null && where(leaf.Head.Value))
 3806        {
 3807          leaf.Head = leaf.Head.Next;
 3808          removals++;
 3809        }
 3810        if (leaf.Head is not null)
 3811        {
 3812          Leaf.Node list = leaf.Head;
 3813          while (list.Next is not null)
 3814          {
 3815            if (where(list.Next.Value))
 3816            {
 3817              list.Next = list.Next.Next;
 3818              removals++;
 3819            }
 3820          }
 3821        }
 3822
 3823        leaf.Count -= removals;
 3824        return removals;
 3825      }
 3826      else
 3827      {
 3828        Branch branch = node as Branch;
 3829        int skipped = 0;
 3830        for (int i = 0; i + skipped < branch.Children.Length; )
 3831        {
 3832          removals += this.Remove(branch.Children[i], where);
 3833          if (branch.Children[i].Count is 0)
 3834            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 3835          else
 3836            i++;
 3837        }
 3838        Node[] newArray = new Node[branch.Children.Length - skipped];
 3839        Array.Copy(branch.Children, newArray, newArray.Length);
 3840        branch.Children = newArray;
 3841
 3842        branch.Count -= removals;
 3843
 3844        if (branch.Count < _load && branch.Count != 0)
 3845          ShrinkChild(branch.Parent, branch.Index);
 3846
 3847        return removals;
 3848      }
 3849    }
 3850
 3851    /// <summary>Removes all the items in a given space.</summary>
 3852    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 3853    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 3854    /// <returns>The number of items that were removed.</returns>
 3855    public void Remove(Axis1 min1, Axis1 max1)
 3856    {
 3857      this.Remove(this._top, new Omnitree.Bounds<Axis1>(min1, max1));
 3858      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 3859    }
 3860    /// <summary>Removes all the items in a given space.</summary>
 3861    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 3862    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 3863    /// <returns>The number of items that were removed.</returns>
 3864    public void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1)
 3865    {
 3866      this.Remove(this._top, new Omnitree.Bounds<Axis1>(min1, max1));
 3867      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 3868    }
 3869    internal int Remove(Node node, Omnitree.Bounds<Axis1> bounds)
 3870    {
 3871      int removals = 0;
 3872      if (InclusionCheck(bounds, node.Bounds))
 3873      {
 3874        if (node is Leaf)
 3875        {
 3876          Leaf leaf = node as Leaf;
 3877          Leaf.Node current_node = leaf.Head;
 3878          Leaf.Node previous_node = null;
 3879          while (!(current_node is null))
 3880          {
 3881            Leaf.Node temp_previous = current_node;
 3882            if (EncapsulationCheck(bounds, LocateVector(current_node.Value)))
 3883            {
 3884              removals++;
 3885              if (current_node == leaf.Head)
 3886                leaf.Head = leaf.Head.Next;
 3887              else
 3888              {
 3889                previous_node.Next = current_node.Next;
 3890                temp_previous = previous_node;
 3891              }
 3892            }
 3893            previous_node = temp_previous;
 3894            current_node = current_node.Next;
 3895          }
 3896          leaf.Count -= removals;
 3897        }
 3898        else
 3899        {
 3900          Branch branch = node as Branch;
 3901          int skipped = 0;
 3902          for (int i = 0; i + skipped < branch.Children.Length; )
 3903          {
 3904            removals += this.Remove(branch.Children[i], bounds);
 3905            if (branch.Children[i].Count is 0)
 3906              branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 3907            else
 3908              i++;
 3909          }
 3910          Node[] newArray = new Node[branch.Children.Length - skipped];
 3911          Array.Copy(branch.Children, newArray, newArray.Length);
 3912          branch.Children = newArray;
 3913
 3914          branch.Count -= removals;
 3915          // convert this branch back into a leaf
 3916          // Note: if count is zero, it will be chopped off
 3917          if (branch.Count < _load && branch.Count > 0)
 3918            ShrinkChild(branch.Parent, branch.Index);
 3919        }
 3920      }
 3921
 3922      return removals;
 3923    }
 3924
 3925    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 3926    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 3927    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 3928    /// <param name="where">The equality constraint of the removal.</param>
 3929    public void Remove(Axis1 min1, Axis1 max1, Predicate<T> where)
 3930    {
 3931      this.Remove(this._top, new Omnitree.Bounds<Axis1>(min1, max1), where);
 3932      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 3933    }
 3934    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 3935    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 3936    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 3937    /// <param name="where">The equality constraint of the removal.</param>
 3938    public void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Predicate<T> where)
 3939    {
 3940      this.Remove(this._top, new Omnitree.Bounds<Axis1>(min1, max1), where);
 3941      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 3942    }
 3943    internal int Remove(Node node, Omnitree.Bounds<Axis1> bounds, Predicate<T> where)
 3944    {
 3945      if (!InclusionCheck(node.Bounds, bounds))
 3946        return 0;
 3947      int removals = 0;
 3948      if (node is Leaf)
 3949      {
 3950        Leaf leaf = node as Leaf;
 3951        Leaf.Node current = leaf.Head;
 3952        Leaf.Node previous = null;
 3953        while (current is not null)
 3954        {
 3955          if (this.EncapsulationCheck(bounds, LocateVector(current.Value)) && where(current.Value))
 3956          {
 3957            removals++;
 3958            if (previous is null)
 3959            {
 3960              leaf.Head = current.Next;
 3961              goto HeadRemoved;
 3962            }
 3963            else
 3964              previous.Next = current.Next;
 3965          }
 3966          previous = current;
 3967        HeadRemoved:
 3968          current = current.Next;
 3969        }
 3970
 3971        leaf.Count -= removals;
 3972        return removals;
 3973      }
 3974      else
 3975      {
 3976        Branch branch = node as Branch;
 3977        int skipped = 0;
 3978        for (int i = 0; i + skipped < branch.Children.Length; )
 3979        {
 3980          removals += this.Remove(branch.Children[i], bounds, where);
 3981          if (branch.Children[i].Count is 0)
 3982            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 3983          else
 3984            i++;
 3985        }
 3986        Node[] newArray = new Node[branch.Children.Length - skipped];
 3987        Array.Copy(branch.Children, newArray, newArray.Length);
 3988        branch.Children = newArray;
 3989
 3990        node.Count -= removals;
 3991
 3992        if (node.Count < _load && node.Count != 0)
 3993          ShrinkChild(node.Parent, node.Index);
 3994
 3995        return removals;
 3996      }
 3997    }
 3998
 3999    /// <summary>Tries to remove a value.</summary>
 4000    /// <param name="value">The value to remove.</param>
 4001    /// <returns>True if successful or false if not.</returns>
 4002    public (bool Success, Exception? Exception) TryRemove(T value)
 4003    {
 4004      Remove(value);
 4005      return (true, null);
 4006    }
 4007
 4008    /// <summary>Removes all instances of a given value.</summary>
 4009    public void Remove(T removal) => Omnitree.Remove(this, removal);
 4010
 4011    /// <summary>Removes all instances of a given value.</summary>
 4012    public void Remove(T removal, Func<T, T, bool> equate) => Omnitree.Remove(this, removal, equate);
 4013
 4014    /// <summary>Removes all the items in a given space.</summary>
 4015    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 4016    /// <returns>The number of items that were removed.</returns>
 4017    public void Remove(Axis1 axis1
 4018      )
 4019    {
 4020      this.Remove(this._top, new Omnitree.Vector<Axis1>(axis1
 4021        ));
 4022      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 4023    }
 4024    internal int Remove(Node node, Omnitree.Vector<Axis1> vector)
 4025    {
 4026      int removals = 0;
 4027      if (node is Leaf)
 4028      {
 4029        Leaf leaf = node as Leaf;
 4030        Leaf.Node current_node = leaf.Head;
 4031        Leaf.Node previous_node = null;
 4032        while (!(current_node is null))
 4033        {
 4034          Leaf.Node temp_previous = current_node;
 4035          if (EqualsCheck(vector, LocateVector(current_node.Value)))
 4036          {
 4037            removals++;
 4038            if (current_node == leaf.Head)
 4039              leaf.Head = leaf.Head.Next;
 4040            else
 4041            {
 4042              previous_node.Next = current_node.Next;
 4043              temp_previous = previous_node;
 4044            }
 4045          }
 4046          previous_node = temp_previous;
 4047          current_node = current_node.Next;
 4048        }
 4049        leaf.Count -= removals;
 4050      }
 4051      else
 4052      {
 4053        Branch branch = node as Branch;
 4054        int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 4055        removals += Remove(branch[child_index], vector);
 4056        branch.Count -= removals;
 4057        // convert this branch back into a leaf
 4058        // Note: if count is zero, it will be chopped off
 4059        if (branch.Count < _load && branch.Count > 0)
 4060          ShrinkChild(branch.Parent, branch.Index);
 4061      }
 4062
 4063      return removals;
 4064    }
 4065
 4066    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 4067    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 4068    /// <param name="where">The equality constraint of the removal.</param>
 4069    public void Remove(Axis1 axis1, Predicate<T> where)
 4070    {
 4071      this.Remove(this._top, new Omnitree.Vector<Axis1>(axis1), where);
 4072      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 4073    }
 4074    internal int Remove(Node node, Omnitree.Vector<Axis1> vector, Predicate<T> where)
 4075    {
 4076      int removals = 0;
 4077      if (node is Leaf)
 4078      {
 4079        Leaf leaf = node as Leaf;
 4080        Leaf.Node current_node = leaf.Head;
 4081        Leaf.Node previous_node = null;
 4082        while (!(current_node is null))
 4083        {
 4084          Leaf.Node temp_previous = current_node;
 4085          if (EqualsCheck(vector, LocateVector(current_node.Value)) && where(current_node.Value))
 4086          {
 4087            removals++;
 4088            if (current_node == leaf.Head)
 4089              leaf.Head = leaf.Head.Next;
 4090            else
 4091            {
 4092              previous_node.Next = current_node.Next;
 4093              temp_previous = previous_node;
 4094            }
 4095          }
 4096          previous_node = temp_previous;
 4097          current_node = current_node.Next;
 4098        }
 4099        leaf.Count -= removals;
 4100      }
 4101      else
 4102      {
 4103        Branch branch = node as Branch;
 4104        int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 4105        removals += Remove(branch[child_index], vector, where);
 4106        branch.Count -= removals;
 4107        // convert this branch back into a leaf
 4108        // Note: if count is zero, it will be chopped off
 4109        if (branch.Count < _load && branch.Count > 0)
 4110          ShrinkChild(branch.Parent, branch.Index);
 4111      }
 4112      return removals;
 4113    }
 4114
 4115    #endregion
 4116
 4117    #region Stepper And IEnumerable
 4118
 4119    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 4120    /// <param name="step">The delegate to perform on every item in the tree.</param>
 4121    public void Stepper(Action<T> step) =>
 4122      this.Stepper(step, this._top);
 4123
 4124    internal void Stepper(Action<T> step, Node node)
 4125    {
 4126      if (node is Leaf)
 4127      {
 4128        Leaf.Node list = (node as Leaf).Head;
 4129        while (list is not null)
 4130        {
 4131          step(list.Value);
 4132          list = list.Next;
 4133        }
 4134      }
 4135      else
 4136      {
 4137        foreach (Node child in (node as Branch).Children)
 4138          this.Stepper(step, child);
 4139      }
 4140    }
 4141
 4142    public StepStatus StepperBreak<TStep>(TStep step = default)
 4143      where TStep : struct, IFunc<T, StepStatus> =>
 4144      StepperBreak(_top, step);
 4145
 4146    internal StepStatus StepperBreak<TStep>(Node node, TStep step)
 4147      where TStep : struct, IFunc<T, StepStatus>
 4148    {
 4149      StepStatus status = StepStatus.Continue;
 4150      if (node is Leaf leaf)
 4151      {
 4152        for (Leaf.Node list = leaf.Head; list is not null; list = list.Next)
 4153        {
 4154          if (step.Invoke(list.Value) is Break) return Break;
 4155        }
 4156      }
 4157      else if (node is Branch branch)
 4158      {
 4159        foreach (Node child in branch.Children)
 4160        {
 4161          if (StepperBreak(child, step) is Break) return Break;
 4162        }
 4163      }
 4164      return Continue;
 4165    }
 4166
 4167    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 4168    /// <param name="step">The delegate to perform on every item in the tree.</param>
 4169    public StepStatus Stepper(Func<T, StepStatus> step) =>
 4170      Stepper(step, _top);
 4171
 4172    internal StepStatus Stepper(Func<T, StepStatus> step, Node node)
 4173    {
 4174      StepStatus status = StepStatus.Continue;
 4175      if (node is Leaf)
 4176      {
 4177        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 4178          if ((status = step(list.Value)) != StepStatus.Continue)
 4179            break;
 4180      }
 4181      else
 4182      {
 4183        foreach (Node child in (node as Branch).Children)
 4184          if ((status = Stepper(step, child)) != StepStatus.Continue)
 4185            break;
 4186      }
 4187      return status;
 4188    }
 4189
 4190    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 4191    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 4192    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 4193    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 4194    public void Stepper(Action<T> step, Axis1 min1, Axis1 max1) =>
 4195      Stepper(step, _top, new Omnitree.Bounds<Axis1>(min1, max1));
 4196
 4197    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 4198    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 4199    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 4200    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 4201    public void Stepper(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1) =>
 4202      Stepper(step, _top, new Omnitree.Bounds<Axis1>(min1, max1));
 4203
 4204    internal void Stepper(Action<T> step, Node node, Omnitree.Bounds<Axis1> bounds)
 4205    {
 4206      if (node is Leaf)
 4207      {
 4208        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 4209          if (EncapsulationCheck(bounds, LocateVector(list.Value)))
 4210            step(list.Value);
 4211      }
 4212      else
 4213      {
 4214        foreach (Node child in (node as Branch).Children)
 4215          // optimization: stop bounds checking if space encapsulates node
 4216          if (EncapsulationCheck(bounds, child.Bounds))
 4217            this.Stepper(step, child);
 4218          else if (InclusionCheck(child.Bounds, bounds))
 4219            this.Stepper(step, child, bounds);
 4220      }
 4221    }
 4222
 4223    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 4224    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 4225    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 4226    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 4227    public StepStatus Stepper(Func<T, StepStatus> step, Axis1 min1, Axis1 max1) =>
 4228      Stepper(step, _top, new Omnitree.Bounds<Axis1>(min1, max1));
 4229
 4230    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 4231    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 4232    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 4233    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 4234    public StepStatus Stepper(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1) =>
 4235      Stepper(step, _top, new Omnitree.Bounds<Axis1>(min1, max1));
 4236
 4237    internal StepStatus Stepper(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1> bounds)
 4238    {
 4239      StepStatus status = StepStatus.Continue;
 4240      if (node is Leaf)
 4241      {
 4242        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 4243          if (EncapsulationCheck(bounds, LocateVector(list.Value)) &&
 4244            (status = step(list.Value)) != StepStatus.Continue)
 4245            break;
 4246      }
 4247      else
 4248      {
 4249        foreach (Node child in (node as Branch).Children)
 4250          // optimization: stop bounds checking if space encapsulates node
 4251          if (EncapsulationCheck(bounds, child.Bounds) &&
 4252            (status = this.Stepper(step, child)) != StepStatus.Continue)
 4253            break;
 4254          else if (InclusionCheck(child.Bounds, bounds) &&
 4255            (status = this.Stepper(step, child, bounds)) != StepStatus.Continue)
 4256            break;
 4257      }
 4258      return status;
 4259    }
 4260
 4261    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 4262    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 4263    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 4264    public void Stepper(Action<T> step, Axis1 axis1) =>
 4265      Stepper(step, _top, new Omnitree.Vector<Axis1>(axis1));
 4266
 4267    internal void Stepper(Action<T> step, Node node, Omnitree.Vector<Axis1> vector)
 4268    {
 4269      Node current = node;
 4270      while (current is not null)
 4271      {
 4272        if (current is Leaf)
 4273        {
 4274          for (Leaf.Node leaf_node = (current as Leaf).Head; leaf_node is not null; leaf_node = leaf_node.Next)
 4275            if (EqualsCheck(vector, LocateVector(leaf_node.Value)))
 4276              step(leaf_node.Value);
 4277          break;
 4278        }
 4279        else
 4280        {
 4281          Branch branch = current as Branch;
 4282          int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 4283          current = branch[child_index];
 4284        }
 4285      }
 4286    }
 4287
 4288    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 4289    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 4290    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 4291    public StepStatus Stepper(Func<T, StepStatus> step, Axis1 axis1) =>
 4292      Stepper(step, _top, new Omnitree.Vector<Axis1>(axis1));
 4293
 4294    internal StepStatus Stepper(Func<T, StepStatus> step, Node node, Omnitree.Vector<Axis1> vector)
 4295    {
 4296      Node current = node;
 4297      while (current is not null)
 4298      {
 4299        if (current is Leaf)
 4300        {
 4301          for (Leaf.Node list = (current as Leaf).Head; list is not null; list = list.Next)
 4302          {
 4303            StepStatus status = StepStatus.Continue;
 4304            if (EqualsCheck(vector, LocateVector(list.Value)) &&
 4305              (status = step(list.Value)) != StepStatus.Continue)
 4306              return status;
 4307          }
 4308        }
 4309        else
 4310        {
 4311          Branch branch = current as Branch;
 4312          int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 4313          current = branch[child_index];
 4314        }
 4315      }
 4316      return StepStatus.Continue;
 4317    }
 4318
 4319    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 4320
 4321    public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 4322    {
 4323      // Note: this can be optimized.
 4324      IList<T> list = new ListLinked<T>();
 4325      Stepper(x => list.Add(x));
 4326      return list.GetEnumerator();
 4327    }
 4328
 4329    #endregion
 4330
 4331    /// <inheritdoc/>
 4332    public T[] ToArray() => throw new NotImplementedException();
 4333
 4334    #region Helpers
 4335
 4336    internal bool StraddlesLines(Omnitree.Bounds<Axis1> bounds, Omnitree.Vector<Axis1> vector) =>
 4337      Omnitree.StraddlesLines(bounds, vector
 4338        , _compare1
 4339        );
 4340
 4341    /// <summary>Computes the child index that contains the desired dimensions.</summary>
 4342    /// <param name="pointOfDivision">The point of division to compare against.</param>
 4343    /// <param name="vector">The dimensions to determine the child index.</param>
 4344    /// <returns>The computed child index based on the coordinates relative to the center of the node.</returns>
 4345    internal int DetermineChildIndex(Omnitree.Vector<Axis1> pointOfDivision, Omnitree.Vector<Axis1> vector)
 4346    {
 4347      int child = 0;
 4348      if (!(this._compare1(vector.Axis1, pointOfDivision.Axis1) is Less))
 4349        child += 1 << 0;
 4350      return child;
 4351    }
 4352
 4353    /// <summary>Converts a branch back into a leaf when the count is reduced.</summary>
 4354    /// <param name="parent">The parent to shrink a child of.</param>
 4355    /// <param name="child_index">The index of the child to shrink.</param>
 4356    internal void ShrinkChild(Branch parent, int child_index)
 4357    {
 4358      Leaf leaf;
 4359      Node removal = null;
 4360      if (parent is null) // top of tree
 4361      {
 4362        removal = this._top;
 4363        leaf = new Leaf(Omnitree.Bounds<Axis1>.None, null, -1);
 4364        this._top = leaf;
 4365      }
 4366      else // non-top branch
 4367      {
 4368        removal = parent[child_index];
 4369        leaf = new Leaf(removal.Bounds, removal.Parent, removal.Index);
 4370        parent[child_index] = leaf;
 4371      }
 4372
 4373      this.Stepper((T step) => { leaf.Add(step); }, removal);
 4374    }
 4375
 4376    /// <summary>Reduces the counts of all the parents of a given node by a given amount.</summary>
 4377    /// <param name="parent">The starting parent of the reduction.</param>
 4378    /// <param name="reduction">The amount to reduce the parent counts by.</param>
 4379    internal void ReduceParentCounts(Node parent, int reduction)
 4380    {
 4381      IncreaseParentCounts(parent, -reduction);
 4382    }
 4383
 4384    /// <summary>Increases the counts of all the parents of a given node by a given amount.</summary>
 4385    /// <param name="parent">The starting parent of the increase.</param>
 4386    /// <param name="increase">The amount to increase the parent counts by.</param>
 4387    internal void IncreaseParentCounts(Node parent, int increase)
 4388    {
 4389      Node node = parent;
 4390      while (node is not null)
 4391      {
 4392        node.Count += increase;
 4393        node = node.Parent;
 4394      }
 4395    }
 4396
 4397    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 4398    /// <returns>True if the spaces overlap; False if not.</returns>
 4399    internal bool InclusionCheck(Omnitree.Bounds<Axis1> a, Omnitree.Bounds<Axis1> b) =>
 4400      Omnitree.InclusionCheck(a, b
 4401      , _compare1
 4402      );
 4403
 4404    /// <summary>Checks if a space encapsulates a point.</summary>
 4405    /// <returns>True if the space encapsulates the point; False if not.</returns>
 4406    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1> bounds, Omnitree.Vector<Axis1> vector) =>
 4407      Omnitree.EncapsulationCheck(bounds, vector
 4408      , _compare1
 4409      );
 4410
 4411    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 4412    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 4413    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1> a, Omnitree.Bounds<Axis1> b) =>
 4414      Omnitree.EncapsulationCheck(a, b
 4415      , _compare1
 4416      );
 4417
 4418    /// <summary>Checks for equality between two locations.</summary>
 4419    /// <returns>True if equal; False if not;</returns>
 4420    internal bool EqualsCheck(Omnitree.Vector<Axis1> a, Omnitree.Vector<Axis1> b) =>
 4421      Omnitree.EqualsCheck(a, b
 4422      , (a, b) => _compare1(a, b) is Equal
 4423      );
 4424
 4425    /// <summary>Gets the nearest parent that encapsulates a location.</summary>
 4426    /// <param name="node">The starting node to find the encapsulating parent of the location.</param>
 4427    /// <param name="vector">The coordinates of the value.</param>
 4428    /// <returns>The nearest node that encapsulates the given location.</returns>
 4429    internal Node GetEncapsulationParent(Node node, Omnitree.Vector<Axis1> vector)
 4430    {
 4431      while (node is not null && !EncapsulationCheck(node.Bounds, vector))
 4432      {
 4433        node = node.Parent;
 4434      }
 4435      return node;
 4436    }
 4437
 4438    internal Omnitree.Vector<Axis1> LocateVector(T value)
 4439    {
 4440      Axis1 axis1;
 4441      this._locate(value, out axis1
 4442);
 4443      return new Omnitree.Vector<Axis1>(axis1);
 4444    }
 4445
 4446    #endregion
 4447
 4448    #endregion
 4449  }
 4450
 4451  #endregion
 4452
 4453  #region 2 Dimensional
 4454
 4455  /// <summary>Inheritance base for 2D omnitrees that store points.</summary>
 4456  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 4457  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 4458  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 4459  public interface IOmnitreePoints<T, Axis1, Axis2> : IOmnitree<T, Axis1, Axis2>
 4460  {
 4461    #region Properties
 4462
 4463    /// <summary>Steps through the values at a given location.</summary>
 4464    /// <param name="axis1">The coordinate along the 1D axis.</param>
 4465    /// <param name="axis2">The coordinate along the 2D axis.</param>
 4466
 4467    /// <returns>A Stepper of the items at the given coordinates.</returns>
 4468    Action<Action<T>> this[Axis1 axis1, Axis2 axis2] { get; }
 4469
 4470    /// <summary>The number of dimensions in this tree.</summary>
 4471    int Dimensions { get; }
 4472
 4473    /// <summary>The delegate being used by the omnitree to locate items in 2D space.</summary>
 4474    Omnitree.Location<T, Axis1
 4475      , Axis2
 4476      > Locate { get; }
 4477
 4478    #endregion
 4479
 4480    #region Methods
 4481
 4482    /// <summary>Counts the number of items in a sub space.</summary>
 4483    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 4484    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 4485    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 4486    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 4487    /// <returns>The number of items in the provided sub space.</returns>
 4488    int CountSubSpace(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound
 4489
 4490    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 4491    void Update();
 4492    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 4493    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 4494    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 4495    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 4496    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 4497    void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound<Axis2
 4498
 4499    /// <summary>Removes all the items in a given space.</summary>
 4500    /// <param name="axis1">The coordinate along the 1D axis.</param>
 4501    /// <param name="axis2">The coordinate along the 2D axis.</param>
 4502    void Remove(Axis1 axis1, Axis2 axis2);
 4503    /// <summary>Removes all the items in a given space.</summary>
 4504    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 4505    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 4506    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 4507    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 4508    void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound<Axis2
 4509    /// <summary>Removes all the items in a given space where equality is met.</summary>
 4510    /// <param name="axis1">The coordinate along the 1D axis.</param>
 4511    /// <param name="axis2">The coordinate along the 2D axis.</param>
 4512    /// <param name="where">The equality constraint of the removal.</param>
 4513    void Remove(Axis1 axis1, Axis2 axis2, Predicate<T> where);
 4514    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 4515    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 4516    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 4517    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 4518    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 4519    /// <param name="where">The predicate constraint of the removal.</param>
 4520    void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound<Axis2
 4521
 4522    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 4523    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 4524    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 4525    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 4526    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 4527    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 4528    void Stepper(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omn
 4529    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 4530    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 4531    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 4532    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 4533    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 4534    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 4535    StepStatus Stepper(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<
 4536    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 4537    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 4538    /// <param name="axis1">The coordinate along the 1D axis.</param>
 4539    /// <param name="axis2">The coordinate along the 2D axis.</param>
 4540    void Stepper(Action<T> step, Axis1 axis1, Axis2 axis2);
 4541    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 4542    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 4543    /// <param name="axis1">The coordinate along the 1D axis.</param>
 4544    /// <param name="axis2">The coordinate along the 2D axis.</param>
 4545    StepStatus Stepper(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2);
 4546
 4547    #endregion
 4548  }
 4549
 4550  /// <summary>Omnitree that stores points along 2 dimensions implemented as a linked tree.</summary>
 4551  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 4552  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 4553  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 4554  public class OmnitreePointsLinked<T, Axis1, Axis2> : IOmnitreePoints<T, Axis1, Axis2>
 4555  {
 4556    internal const int _dimensions = 2;
 4557    internal static int _children_per_node = (int)BigInteger.Pow(2, 2);
 4558
 4559    internal Node _top;
 4560    internal int _naturalLogLower = 1; // caching the next time to calculate loads (lower count)
 4561    internal int _naturalLogUpper = -1; // caching the next time to calculate loads (upper count)
 4562    internal int _load; // ln(count); min = _defaultLoad
 4563    internal Omnitree.Location<T, Axis1
 4564      , Axis2
 4565      > _locate;
 4566    internal bool _defaultCompare1;
 4567    internal Func<Axis1, Axis1, CompareResult> _compare1;
 4568    internal bool _defaultCompare2;
 4569    internal Func<Axis2, Axis2, CompareResult> _compare2;
 4570    internal Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2>> _subdivisionOverride1;
 4571    internal Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2>> _subdivisionOverride2;
 4572
 4573    #region Nested Types
 4574
 4575    /// <summary>Can be a leaf or a branch.</summary>
 4576    internal abstract class Node
 4577    {
 4578      internal Omnitree.Bounds<Axis1, Axis2> Bounds;
 4579      internal Branch Parent;
 4580      internal int Index;
 4581      internal int Count;
 4582
 4583      /// <summary>The depth this node is located in the Omnitree.</summary>
 4584      internal int Depth
 4585      {
 4586        get
 4587        {
 4588          int depth = -1;
 4589          for (Node node = this; node is not null; node = node.Parent)
 4590            depth++;
 4591          return depth;
 4592        }
 4593      }
 4594
 4595      /// <summary>Constructs a node.</summary>
 4596      /// <param name="bounds">The bounds of this node.</param>
 4597      /// <param name="parent">The parent of this node.</param>
 4598      /// <param name="index">The number of values stored in this node and its children.</param>
 4599      internal Node(Omnitree.Bounds<Axis1, Axis2> bounds, Branch parent, int index)
 4600      {
 4601        Bounds = bounds;
 4602        Parent = parent;
 4603        Index = index;
 4604      }
 4605
 4606      internal Node(Node nodeToClone)
 4607      {
 4608        this.Bounds = nodeToClone.Bounds;
 4609        this.Parent = nodeToClone.Parent;
 4610        this.Index = nodeToClone.Index;
 4611        this.Count = nodeToClone.Count;
 4612      }
 4613
 4614      internal abstract Node Clone();
 4615    }
 4616
 4617    /// <summary>A branch in the tree. Only contains nodes.</summary>
 4618    internal class Branch : Node
 4619    {
 4620      internal Node[] Children;
 4621      internal Omnitree.Vector<Axis1, Axis2> PointOfDivision;
 4622
 4623      /// <summary>Gets child by index.</summary>
 4624      /// <param name="child_index">The index of the child to get.</param>
 4625      /// <returns>The child of the given index or null if non-existent.</returns>
 4626      internal Node this[int child_index]
 4627      {
 4628        get
 4629        {
 4630          if (Children is null)
 4631            return null;
 4632          if (Children.Length == OmnitreePointsLinked<T, Axis1, Axis2>._children_per_node)
 4633            return Children[(int)child_index];
 4634          foreach (Node node in Children)
 4635            if (node.Index == child_index)
 4636              return node;
 4637          return null;
 4638        }
 4639        set
 4640        {
 4641          // This error check should be unnecessary... but fuck it... might as well
 4642          if (value.Index != child_index)
 4643            throw new System.Exception("Bug in Omnitree (index/property mis-match when setting a child on a branch)");
 4644
 4645          // no children yet
 4646          if (Children is null)
 4647          {
 4648            Children = â±¯(value);
 4649            return;
 4650          }
 4651          // max children overwrite
 4652          else if (this.Children.Length == OmnitreePointsLinked<T, Axis1, Axis2>._children_per_node)
 4653          {
 4654            Children[(int)child_index] = value;
 4655            return;
 4656          }
 4657          // non-max child overwrite
 4658          for (int i = 0; i < Children.Length; i++)
 4659            if (Children[i].Index == child_index)
 4660            {
 4661              Children[i] = value;
 4662              return;
 4663            }
 4664          // new child
 4665          Node[] newArray = new Node[Children.Length + 1];
 4666          if (newArray.Length == OmnitreePointsLinked<T, Axis1, Axis2>._children_per_node)
 4667          {
 4668            // new child resulting in a max children branch (sorting required)
 4669            for (int i = 0; i < Children.Length; i++)
 4670            {
 4671              newArray[(int)Children[i].Index] = Children[i];
 4672            }
 4673            newArray[(int)value.Index] = value;
 4674          }
 4675          else
 4676          {
 4677            // new child resulting in a non-max children branch
 4678            Array.Copy(Children, newArray, Children.Length);
 4679            newArray[newArray.Length - 1] = value;
 4680          }
 4681          this.Children = newArray;
 4682        }
 4683      }
 4684
 4685      internal Branch(Omnitree.Vector<Axis1, Axis2> pointOfDivision, Omnitree.Bounds<Axis1, Axis2> bounds, Branch parent
 4686        : base(bounds, parent, index)
 4687      {
 4688        this.PointOfDivision = pointOfDivision;
 4689      }
 4690
 4691      internal Branch(Branch branchToClone) : base(branchToClone)
 4692      {
 4693        Children = branchToClone.Children.Clone() as Node[];
 4694        PointOfDivision = branchToClone.PointOfDivision;
 4695      }
 4696
 4697      internal override Node Clone() =>
 4698        new Branch(this);
 4699    }
 4700
 4701    /// <summary>A branch in the tree. Only contains items.</summary>
 4702    internal class Leaf : Node
 4703    {
 4704      internal class Node
 4705      {
 4706        internal T Value;
 4707        internal Leaf.Node Next;
 4708
 4709        internal Node(T value, Leaf.Node next)
 4710        {
 4711          Value = value;
 4712          Next = next;
 4713        }
 4714      }
 4715
 4716      internal Leaf.Node Head;
 4717
 4718      internal Leaf(Omnitree.Bounds<Axis1, Axis2> bounds, Branch parent, int index)
 4719        : base(bounds, parent, index)
 4720      { }
 4721
 4722      internal Leaf(Leaf leaf) : base(leaf)
 4723      {
 4724        Head = new Node(leaf.Head.Value, null);
 4725        Node a = Head;
 4726        Node b = leaf.Head;
 4727        while (b is not null)
 4728        {
 4729          a.Next = new Node(b.Next.Value, null);
 4730          a = a.Next;
 4731          b = b.Next;
 4732        }
 4733      }
 4734
 4735      internal void Add(T addition)
 4736      {
 4737        Head = new Leaf.Node(addition, Head);
 4738        this.Count++;
 4739      }
 4740
 4741      internal override OmnitreePointsLinked<T, Axis1, Axis2>.Node Clone() =>
 4742        new Leaf(this);
 4743    }
 4744
 4745    #endregion
 4746
 4747    #region Constructors
 4748
 4749    /// <summary>This constructor is for cloning purposes</summary>
 4750    internal OmnitreePointsLinked(OmnitreePointsLinked<T, Axis1, Axis2> omnitree)
 4751    {
 4752      this._top = omnitree._top.Clone();
 4753      this._load = omnitree._load;
 4754      this._locate = omnitree._locate;
 4755      this._defaultCompare1 = omnitree._defaultCompare1;
 4756      this._compare1 = omnitree._compare1;
 4757      this._defaultCompare2 = omnitree._defaultCompare2;
 4758      this._compare2 = omnitree._compare2;
 4759      this._subdivisionOverride1 = omnitree._subdivisionOverride1;
 4760      this._subdivisionOverride2 = omnitree._subdivisionOverride2;
 4761    }
 4762
 4763    internal OmnitreePointsLinked(
 4764      Omnitree.Location<T, Axis1, Axis2> locate,
 4765      bool defaultCompare1,
 4766      Func<Axis1, Axis1, CompareResult> compare1,
 4767      bool defaultCompare2,
 4768      Func<Axis2, Axis2, CompareResult> compare2,
 4769      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2>> subdivisionOverride1
 4770,
 4771      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2>> subdivisionOverride2
 4772      )
 4773    {
 4774      if (locate is null)
 4775      {
 4776        throw new ArgumentNullException(nameof(locate));
 4777      }
 4778      if (compare1 is null)
 4779      {
 4780        throw new ArgumentNullException(nameof(compare1));
 4781      }
 4782
 4783      if (compare2 is null)
 4784      {
 4785        throw new ArgumentNullException(nameof(compare2));
 4786      }
 4787
 4788      this._locate = locate;
 4789      this._defaultCompare1 = defaultCompare1;
 4790      this._compare1 = compare1;
 4791      this._defaultCompare2 = defaultCompare2;
 4792      this._compare2 = compare2;
 4793      this._subdivisionOverride1 = subdivisionOverride1;
 4794      this._subdivisionOverride2 = subdivisionOverride2;
 4795      this._top = new Leaf(Omnitree.Bounds<Axis1, Axis2>.None, null, -1);
 4796      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 4797    }
 4798
 4799    /// <summary>Constructs a new 2D omnitree that stores points.</summary>
 4800    /// <param name="locate">The delegate for locating items in 2D space.</param>
 4801
 4802    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 4803
 4804    /// <param name="compare2">The delegate for comparing values along the 2D axis.</param>
 4805
 4806    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 4807
 4808    /// <param name="subdivisionOverride2">The subdivision overide to be used when splitting the 2 dimension.</param>
 4809    public OmnitreePointsLinked(
 4810      Omnitree.Location<T, Axis1, Axis2> locate,
 4811      Func<Axis1, Axis1, CompareResult> compare1 = null,
 4812      Func<Axis2, Axis2, CompareResult> compare2 = null,
 4813      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2>> subdivisionOverride1 = null
 4814,
 4815      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2>> subdivisionOverride2 = null
 4816      )
 4817      : this(
 4818        locate,
 4819        compare1 is null ? true : false,
 4820        compare1 ?? Compare,
 4821        compare2 is null ? true : false,
 4822        compare2 ?? Compare,
 4823        subdivisionOverride1
 4824,
 4825        subdivisionOverride2
 4826        ) { }
 4827
 4828    #endregion
 4829
 4830    #region Properties
 4831
 4832    /// <summary>Steps through all the items at a given coordinate.</summary>
 4833    /// <param name="axis1">The coordinate along axis 1.</param>
 4834    /// <param name="axis2">The coordinate along axis 2.</param>
 4835    /// <returns>The stepper for the items at the given coordinate.</returns>
 4836    public Action<Action<T>> this[Axis1 axis1, Axis2 axis2] =>
 4837      step => Stepper(step, axis1, axis2);
 4838
 4839    /// <summary>The number of dimensions in this tree.</summary>
 4840    public int Dimensions { get { return _dimensions; } }
 4841
 4842    /// <summary>The location function the Omnitree is using.</summary>
 4843    public Omnitree.Location<T, Axis1, Axis2> Locate { get { return this._locate; } }
 4844
 4845    /// <summary>The comparison function the Omnitree is using along the 1D axis.</summary>
 4846    public Func<Axis1, Axis1, CompareResult> Compare1 { get { return this._compare1; } }
 4847    /// <summary>The comparison function the Omnitree is using along the 2D axis.</summary>
 4848    public Func<Axis2, Axis2, CompareResult> Compare2 { get { return this._compare2; } }
 4849
 4850    /// <summary>The current number of items in the tree.</summary>
 4851    public int Count { get { return this._top.Count; } }
 4852
 4853    internal delegate void MaxDepthFinder(Node node, int current_depth, ref int max_depth);
 4854    /// <summary>Finds the current maximum depth of the tree. NOT AN O(1) OPERATION. Intended for educational purposes o
 4855    public int MaxDepth
 4856    {
 4857      get
 4858      {
 4859        MaxDepthFinder maxDepthFinder = null;
 4860        maxDepthFinder =
 4861          (Node node, int current_depth, ref int max_depth) =>
 4862          {
 4863            if (current_depth > max_depth)
 4864              max_depth = current_depth;
 4865            if (node is Branch)
 4866              foreach (Node child in (node as Branch).Children)
 4867                maxDepthFinder(child, current_depth + 1, ref max_depth);
 4868          };
 4869        int _max_depth = -1;
 4870        maxDepthFinder(this._top, 0, ref _max_depth);
 4871        return _max_depth;
 4872      }
 4873    }
 4874
 4875    internal delegate void NodeCountFinder(Node node, ref int current_count);
 4876    /// <summary>Counts the current number of nodes in the tree. NOT AN O(1) OPERATION. Intended for educational purpose
 4877    public int NodeCount
 4878    {
 4879      get
 4880      {
 4881        NodeCountFinder nodeCountFinder = null;
 4882        nodeCountFinder =
 4883          (Node node, ref int current_count) =>
 4884          {
 4885            current_count++;
 4886            if (node is Branch)
 4887              foreach (Node child in (node as Branch).Children)
 4888                nodeCountFinder(child, ref current_count);
 4889          };
 4890
 4891        int _current_count = 0;
 4892        nodeCountFinder(this._top, ref _current_count);
 4893        return _current_count;
 4894      }
 4895    }
 4896
 4897    internal delegate void BranchCountFinder(Node node, ref int current_count);
 4898    /// <summary>Counts the current number of branches in the tree. NOT AN O(1) OPERATION. Intended for educational purp
 4899    public int BranchCount
 4900    {
 4901      get
 4902      {
 4903        BranchCountFinder branchCountFinder = null;
 4904        branchCountFinder =
 4905          (Node node, ref int current_count) =>
 4906          {
 4907            if (node is Branch)
 4908            {
 4909              current_count++;
 4910              foreach (Node child in (node as Branch).Children)
 4911                branchCountFinder(child, ref current_count);
 4912            }
 4913          };
 4914
 4915        int _current_count = 0;
 4916        branchCountFinder(this._top, ref _current_count);
 4917        return _current_count;
 4918      }
 4919    }
 4920
 4921    internal delegate void LeafCountFinder(Node node, ref int current_count);
 4922    /// <summary>Counts the current number of leaves in the tree. NOT AN O(1) OPERATION. Intended for educational purpos
 4923    public int LeafCount
 4924    {
 4925      get
 4926      {
 4927        LeafCountFinder leafCountFinder = null;
 4928        leafCountFinder =
 4929          (Node node, ref int current_count) =>
 4930          {
 4931            if (node is Leaf)
 4932              current_count++;
 4933            else
 4934              foreach (Node child in (node as Branch).Children)
 4935                leafCountFinder(child, ref current_count);
 4936          };
 4937
 4938        int _current_count = 0;
 4939        leafCountFinder(this._top, ref _current_count);
 4940        return _current_count;
 4941      }
 4942    }
 4943
 4944    #endregion
 4945
 4946    #region Methods
 4947
 4948    #region Add
 4949
 4950
 4951    #region single
 4952
 4953    /// <summary>Tries to add a value.</summary>
 4954    /// <param name="value">The value to be added.</param>
 4955    /// <returns>True if successful or false if not.</returns>
 4956    public (bool Success, Exception? Exception) TryAdd(T value)
 4957    {
 4958      Add(value);
 4959      return (true, null);
 4960    }
 4961
 4962    /// <summary>Adds an item to the tree.</summary>
 4963    /// <param name="addition">The item to be added.</param>
 4964    public void Add(T addition)
 4965    {
 4966      if (this._top.Count is int.MaxValue)
 4967        throw new System.InvalidOperationException("(Count is int.MaxValue) max Omnitree size reached (change ints to lo
 4968
 4969      // dynamic tree sizes
 4970      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 4971
 4972      Omnitree.Vector<Axis1, Axis2> location = LocateVector(addition);
 4973
 4974      // grow the first branch of the tree
 4975      if (this._top is Leaf && (this._top as Leaf).Count >= _load)
 4976      {
 4977        Leaf top = this._top as Leaf;
 4978
 4979        // create the new branch from the median values
 4980        this._top = new Branch(DetermineMedians(top), Omnitree.Bounds<Axis1, Axis2>.None, null, -1);
 4981
 4982        // iterate through the values and add them to the appropriate children
 4983        for (Leaf.Node list = top.Head; list is not null; list = list.Next)
 4984          Add(list.Value, this._top, LocateVector(list.Value), 0);
 4985      }
 4986
 4987      this.Add(addition, this._top, location, 0);
 4988    }
 4989
 4990    /// <summary>Recursive version of the add function.</summary>
 4991    /// <param name="addition">The item to be added.</param>
 4992    /// <param name="node">The current node for tree trversal.</param>
 4993    /// <param name="location">The location of the addition.</param>
 4994    /// <param name="depth">The current depth of iteration.</param>
 4995    internal void Add(T addition, Node node, Omnitree.Vector<Axis1, Axis2> location, int depth)
 4996    {
 4997      if (node is Leaf)
 4998      {
 4999        Leaf leaf = node as Leaf;
 5000        if (depth >= _load || !(leaf.Count >= _load))
 5001        {
 5002          leaf.Add(addition);
 5003          return;
 5004        }
 5005        else
 5006        {
 5007          Branch parent = node.Parent;
 5008          int child_index = this.DetermineChildIndex(parent.PointOfDivision, location);
 5009          Branch growth = new Branch(DetermineMedians(leaf), leaf.Bounds, parent, child_index);
 5010          parent[child_index] = growth;
 5011          for (Leaf.Node list = leaf.Head; list is not null; list = list.Next)
 5012          {
 5013            Omnitree.Vector<Axis1, Axis2> temp_location = LocateVector(list.Value);
 5014            if (EncapsulationCheck(growth.Bounds, temp_location))
 5015              Add(list.Value, growth, temp_location, depth);
 5016            else
 5017            {
 5018              ReduceParentCounts(parent, 1);
 5019              Add(list.Value, this._top, temp_location, depth);
 5020            }
 5021          }
 5022
 5023          Add(addition, growth, location, depth);
 5024          return;
 5025        }
 5026      }
 5027      else
 5028      {
 5029        Branch branch = node as Branch;
 5030        int child_index = this.DetermineChildIndex(branch.PointOfDivision, location); // determine the child "index" (0 
 5031        Node child_node = branch[child_index];
 5032
 5033        // null children in branches are just empty leaves
 5034        if (child_node is null)
 5035        {
 5036          Leaf new_leaf = new Leaf(DetermineChildBounds(branch, child_index), branch, child_index);
 5037          branch[child_index] = new_leaf;
 5038          new_leaf.Add(addition);
 5039        }
 5040        else
 5041          // child exists already, continue adding
 5042          Add(addition, child_node, location, depth + 1);
 5043
 5044        branch.Count++;
 5045        return;
 5046      }
 5047    }
 5048
 5049    internal Omnitree.Vector<Axis1, Axis2> DetermineMedians(Leaf leaf)
 5050    {
 5051
 5052      Axis1 division1;
 5053      if (!(_subdivisionOverride1 is null))
 5054      {
 5055        division1 = _subdivisionOverride1(leaf.Bounds, x =>
 5056          {
 5057            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 5058            {
 5059              x(node.Value);
 5060            }
 5061          });
 5062      }
 5063      else
 5064      {
 5065        Axis1[] values = new Axis1[leaf.Count];
 5066        Leaf.Node for_current = leaf.Head;
 5067        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 5068          this._locate(for_current.Value
 5069          , out values[i]
 5070          , out _
 5071          );
 5072        if (_defaultCompare1) Array.Sort(values);
 5073        else SortQuick<Axis1>(values, this._compare1);
 5074        int index = (leaf.Count - 1) / 2;
 5075        division1 = values[index];
 5076      }
 5077
 5078      Axis2 division2;
 5079      if (!(_subdivisionOverride2 is null))
 5080      {
 5081        division2 = _subdivisionOverride2(leaf.Bounds, x =>
 5082          {
 5083            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 5084            {
 5085              x(node.Value);
 5086            }
 5087          });
 5088      }
 5089      else
 5090      {
 5091        Axis2[] values = new Axis2[leaf.Count];
 5092        Leaf.Node for_current = leaf.Head;
 5093        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 5094          this._locate(for_current.Value
 5095          , out _
 5096          , out values[i]
 5097          );
 5098        if (_defaultCompare2) Array.Sort(values);
 5099        else SortQuick<Axis2>(values, this._compare2);
 5100        int index = (leaf.Count - 1) / 2;
 5101        division2 = values[index];
 5102      }
 5103
 5104      return new Omnitree.Vector<Axis1, Axis2>(
 5105        division1
 5106
 5107        , division2
 5108
 5109        );
 5110    }
 5111
 5112    #endregion
 5113
 5114    #region Add Helpers
 5115
 5116    internal Omnitree.Bounds<Axis1, Axis2> DetermineChildBounds(Branch branch, int child_index)
 5117    {
 5118
 5119      Omnitree.Bound<Axis2> min2, max2;
 5120      if (child_index >= 2)
 5121      {
 5122        min2 = branch.PointOfDivision.Axis2;
 5123        max2 = branch.Bounds.Max2;
 5124        child_index -= 2;
 5125      }
 5126      else
 5127      {
 5128        min2 = branch.Bounds.Min2;
 5129        max2 = branch.PointOfDivision.Axis2;
 5130      }
 5131
 5132      Omnitree.Bound<Axis1> min1, max1;
 5133      if (child_index >= 1)
 5134      {
 5135        min1 = branch.PointOfDivision.Axis1;
 5136        max1 = branch.Bounds.Max1;
 5137        child_index -= 1;
 5138      }
 5139      else
 5140      {
 5141        min1 = branch.Bounds.Min1;
 5142        max1 = branch.PointOfDivision.Axis1;
 5143      }
 5144
 5145      return new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2);
 5146    }
 5147
 5148    #endregion
 5149
 5150    #endregion
 5151
 5152    #region Clear
 5153
 5154    /// <summary>Returns the tree to an empty state.</summary>
 5155    public void Clear()
 5156    {
 5157      this._top = new Leaf(Omnitree.Bounds<Axis1, Axis2>.None, null, -1);
 5158      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 5159    }
 5160
 5161    #endregion
 5162
 5163    #region Clone
 5164
 5165    /// <summary>Creates a shallow clone of this data structure.</summary>
 5166    /// <returns>A shallow clone of this data structure.</returns>
 5167    public OmnitreePointsLinked<T, Axis1, Axis2> Clone()
 5168    {
 5169      return new OmnitreePointsLinked<T, Axis1, Axis2>(this);
 5170    }
 5171
 5172    #endregion
 5173
 5174    #region Count
 5175
 5176    /// <summary>Counts the number of items in a sub space.</summary>
 5177    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 5178    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 5179    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 5180    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 5181    /// <returns>The number of items in the provided sub space.</returns>
 5182    public int CountSubSpace(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2)
 5183    {
 5184      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 5185    }
 5186    /// <summary>Counts the number of items in a sub space.</summary>
 5187    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 5188    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 5189    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 5190    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 5191    /// <returns>The number of items in the provided sub space.</returns>
 5192    public int CountSubSpace(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitre
 5193    {
 5194      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 5195    }
 5196    /// <summary>Counts the number of items in a sub space.</summary>
 5197    /// <param name="axis1">The coordinate along the 1D axis.</param>
 5198    /// <param name="axis2">The coordinate along the 2D axis.</param>
 5199    /// <returns>The number of items in the provided sub space.</returns>
 5200    public int CountSubSpace(Axis1 axis1, Axis2 axis2)
 5201    {
 5202      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2>(axis1, axis1, axis2, axis2));
 5203    }
 5204    /// <summary>Counts the number of items in a sub space.</summary>
 5205    /// <param name="axis1">The coordinate along the 1D axis.</param>
 5206    /// <param name="axis2">The coordinate along the 2D axis.</param>
 5207    /// <returns>The number of items in the provided sub space.</returns>
 5208    public int CountSubSpace(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2)
 5209    {
 5210      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2>(axis1, axis1, axis2, axis2));
 5211    }
 5212    /// <summary>Counts the number of items in a sub space.</summary>
 5213    /// <param name="node">The current traversal node.</param>
 5214    /// <param name="bounds">The bounds of the sub space being counted.</param>
 5215    /// <returns>The number of items in the provided sub space.</returns>
 5216    internal int CountSubSpace(Node node, Omnitree.Bounds<Axis1, Axis2> bounds)
 5217    {
 5218      // adjust min/max values
 5219      int count = 0;
 5220      if (EncapsulationCheck(bounds, node.Bounds))
 5221        count += node.Count;
 5222      else if (node is Leaf)
 5223      {
 5224        for (Leaf.Node list = (node as Leaf).Head; list is null; list = list.Next)
 5225          if (EncapsulationCheck(bounds, LocateVector(list.Value)))
 5226            count++;
 5227      }
 5228      else
 5229      {
 5230        Branch branch = node as Branch;
 5231        if (!StraddlesLines(branch.Bounds, branch.PointOfDivision))
 5232        {
 5233          int child_index = DetermineChildIndex(branch.PointOfDivision, new Omnitree.Vector<Axis1, Axis2>(bounds.Min1.Va
 5234            , bounds.Min2.Value
 5235            ));
 5236          Node child = branch[child_index];
 5237          if (child is not null)
 5238          {
 5239            count += this.CountSubSpace(child, bounds);
 5240          }
 5241        }
 5242        else
 5243        {
 5244          foreach (Node child in (node as Branch).Children)
 5245            count += this.CountSubSpace(child, bounds);
 5246        }
 5247      }
 5248      return count;
 5249    }
 5250
 5251    #endregion
 5252
 5253    #region Update
 5254
 5255    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 5256    public void Update()
 5257    {
 5258      this.Update(this._top, 0);
 5259    }
 5260
 5261    /// <summary>Recursive version of the Update method.</summary>
 5262    /// <param name="node">The current node of iteration.</param>
 5263    /// <param name="depth">The current depth of iteration.</param>
 5264    internal int Update(Node node, int depth)
 5265    {
 5266      int removals = 0;
 5267
 5268      if (node is Leaf)
 5269      {
 5270        Leaf leaf = node as Leaf;
 5271        Leaf.Node current = leaf.Head;
 5272        Leaf.Node previous = null;
 5273        while (current is not null)
 5274        {
 5275          Omnitree.Vector<Axis1, Axis2> location = LocateVector(current.Value);
 5276          if (!this.EncapsulationCheck(node.Bounds, location))
 5277          {
 5278            removals++;
 5279            T updated = current.Value;
 5280            if (previous is null)
 5281            {
 5282              leaf.Head = current.Next;
 5283              goto HeadRemoved;
 5284            }
 5285            else
 5286              previous.Next = current.Next;
 5287
 5288            Node whereToAdd = GetEncapsulationParent(node.Parent, location);
 5289
 5290            if (whereToAdd is null)
 5291              throw new System.Exception("an item was updated outside the range of the omnitree");
 5292
 5293            this.Add(updated, whereToAdd, location, whereToAdd.Depth);
 5294          }
 5295          previous = current;
 5296        HeadRemoved:
 5297          current = current.Next;
 5298        }
 5299        leaf.Count -= removals;
 5300        return removals;
 5301      }
 5302      else
 5303      {
 5304        Branch branch = node as Branch;
 5305        int skipped = 0;
 5306        for (int i = 0; i + skipped < branch.Children.Length; )
 5307        {
 5308          removals += this.Update(branch.Children[i], depth + 1);
 5309          if (branch.Children[i].Count is 0)
 5310            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 5311          else
 5312            i++;
 5313        }
 5314        Node[] newArray = new Node[branch.Children.Length - skipped];
 5315        Array.Copy(branch.Children, newArray, newArray.Length);
 5316        branch.Children = newArray;
 5317
 5318        branch.Count -= removals;
 5319
 5320        if (branch.Count < _load && branch.Count != 0)
 5321          ShrinkChild(branch.Parent, branch.Index);
 5322      }
 5323
 5324      return removals;
 5325    }
 5326
 5327    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 5328    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 5329    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 5330    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 5331    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 5332    public void Update(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2)
 5333    {
 5334      this.Update(new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2), this._top, 0);
 5335    }
 5336    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 5337    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 5338    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 5339    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 5340    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 5341    public void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 5342    {
 5343      this.Update(new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2), this._top, 0);
 5344    }
 5345    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 5346    /// <param name="axis1">The coordinate along the 1D axis.</param>
 5347    /// <param name="axis2">The coordinate along the 2D axis.</param>
 5348    public void Update(Axis1 axis1, Axis2 axis2)
 5349    {
 5350      this.Update(new Omnitree.Bounds<Axis1, Axis2>(axis1, axis1, axis2, axis2), this._top, 0);
 5351    }
 5352    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 5353    /// <param name="axis1">The coordinate along the 1D axis.</param>
 5354    /// <param name="axis2">The coordinate along the 2D axis.</param>
 5355    public void Update(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2)
 5356    {
 5357      this.Update(new Omnitree.Bounds<Axis1, Axis2>(axis1, axis1, axis2, axis2), this._top, 0);
 5358    }
 5359    internal int Update(Omnitree.Bounds<Axis1, Axis2> bounds, Node node, int depth)
 5360    {
 5361      if (!InclusionCheck(bounds, node.Bounds))
 5362        return 0;
 5363
 5364      int removals = 0;
 5365
 5366      if (node is Leaf)
 5367      {
 5368        Leaf leaf = node as Leaf;
 5369        Leaf.Node current = leaf.Head;
 5370        Leaf.Node previous = null;
 5371        while (current is not null)
 5372        {
 5373          Omnitree.Vector<Axis1, Axis2> location = LocateVector(current.Value);
 5374          if (!this.EncapsulationCheck(node.Bounds, location))
 5375          {
 5376            removals++;
 5377            T updated = current.Value;
 5378            if (previous is null)
 5379            {
 5380              leaf.Head = current.Next;
 5381              goto HeadRemoved;
 5382            }
 5383            else
 5384              previous.Next = current.Next;
 5385            Node whereToAdd = GetEncapsulationParent(node.Parent, location);
 5386            if (whereToAdd is null)
 5387              throw new System.Exception("an item was updates outside the range of the omnitree");
 5388            this.Add(updated, whereToAdd, location, whereToAdd.Depth);
 5389          }
 5390          previous = current;
 5391        HeadRemoved:
 5392          current = current.Next;
 5393        }
 5394        leaf.Count -= removals;
 5395        return removals;
 5396      }
 5397      else
 5398      {
 5399        Branch branch = node as Branch;
 5400        int skipped = 0;
 5401        for (int i = 0; i + skipped < branch.Children.Length; )
 5402        {
 5403          removals += this.Update(branch.Children[i], depth + 1);
 5404          if (branch.Children[i].Count is 0)
 5405            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 5406          else
 5407            i++;
 5408        }
 5409        Node[] newArray = new Node[branch.Children.Length - skipped];
 5410        Array.Copy(branch.Children, newArray, newArray.Length);
 5411        branch.Children = newArray;
 5412
 5413        branch.Count -= removals;
 5414
 5415        if (branch.Count < _load && branch.Count != 0)
 5416          ShrinkChild(branch.Parent, branch.Index);
 5417      }
 5418
 5419      return removals;
 5420    }
 5421
 5422    #endregion
 5423
 5424    #region Remove
 5425
 5426    /// <summary>Removes all the items qualified by the delegate.</summary>
 5427    /// <param name="where">The predicate to qualify removals.</param>
 5428    public void Remove(Predicate<T> where)
 5429    {
 5430      this.Remove(this._top, where);
 5431      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 5432    }
 5433
 5434    /// <summary>Recursive version of the remove method.</summary>
 5435    /// <param name="node">The current node of traversal.</param>
 5436    /// <param name="where">The predicate to qualify removals.</param>
 5437    internal int Remove(Node node, Predicate<T> where)
 5438    {
 5439      int removals = 0;
 5440      if (node is Leaf)
 5441      {
 5442        Leaf leaf = node as Leaf;
 5443        while (leaf.Head is not null && where(leaf.Head.Value))
 5444        {
 5445          leaf.Head = leaf.Head.Next;
 5446          removals++;
 5447        }
 5448        if (leaf.Head is not null)
 5449        {
 5450          Leaf.Node list = leaf.Head;
 5451          while (list.Next is not null)
 5452          {
 5453            if (where(list.Next.Value))
 5454            {
 5455              list.Next = list.Next.Next;
 5456              removals++;
 5457            }
 5458          }
 5459        }
 5460
 5461        leaf.Count -= removals;
 5462        return removals;
 5463      }
 5464      else
 5465      {
 5466        Branch branch = node as Branch;
 5467        int skipped = 0;
 5468        for (int i = 0; i + skipped < branch.Children.Length; )
 5469        {
 5470          removals += this.Remove(branch.Children[i], where);
 5471          if (branch.Children[i].Count is 0)
 5472            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 5473          else
 5474            i++;
 5475        }
 5476        Node[] newArray = new Node[branch.Children.Length - skipped];
 5477        Array.Copy(branch.Children, newArray, newArray.Length);
 5478        branch.Children = newArray;
 5479
 5480        branch.Count -= removals;
 5481
 5482        if (branch.Count < _load && branch.Count != 0)
 5483          ShrinkChild(branch.Parent, branch.Index);
 5484
 5485        return removals;
 5486      }
 5487    }
 5488
 5489    /// <summary>Removes all the items in a given space.</summary>
 5490    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 5491    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 5492    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 5493    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 5494    /// <returns>The number of items that were removed.</returns>
 5495    public void Remove(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2)
 5496    {
 5497      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 5498      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 5499    }
 5500    /// <summary>Removes all the items in a given space.</summary>
 5501    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 5502    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 5503    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 5504    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 5505    /// <returns>The number of items that were removed.</returns>
 5506    public void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 5507    {
 5508      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 5509      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 5510    }
 5511    internal int Remove(Node node, Omnitree.Bounds<Axis1, Axis2> bounds)
 5512    {
 5513      int removals = 0;
 5514      if (InclusionCheck(bounds, node.Bounds))
 5515      {
 5516        if (node is Leaf)
 5517        {
 5518          Leaf leaf = node as Leaf;
 5519          Leaf.Node current_node = leaf.Head;
 5520          Leaf.Node previous_node = null;
 5521          while (!(current_node is null))
 5522          {
 5523            Leaf.Node temp_previous = current_node;
 5524            if (EncapsulationCheck(bounds, LocateVector(current_node.Value)))
 5525            {
 5526              removals++;
 5527              if (current_node == leaf.Head)
 5528                leaf.Head = leaf.Head.Next;
 5529              else
 5530              {
 5531                previous_node.Next = current_node.Next;
 5532                temp_previous = previous_node;
 5533              }
 5534            }
 5535            previous_node = temp_previous;
 5536            current_node = current_node.Next;
 5537          }
 5538          leaf.Count -= removals;
 5539        }
 5540        else
 5541        {
 5542          Branch branch = node as Branch;
 5543          int skipped = 0;
 5544          for (int i = 0; i + skipped < branch.Children.Length; )
 5545          {
 5546            removals += this.Remove(branch.Children[i], bounds);
 5547            if (branch.Children[i].Count is 0)
 5548              branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 5549            else
 5550              i++;
 5551          }
 5552          Node[] newArray = new Node[branch.Children.Length - skipped];
 5553          Array.Copy(branch.Children, newArray, newArray.Length);
 5554          branch.Children = newArray;
 5555
 5556          branch.Count -= removals;
 5557          // convert this branch back into a leaf
 5558          // Note: if count is zero, it will be chopped off
 5559          if (branch.Count < _load && branch.Count > 0)
 5560            ShrinkChild(branch.Parent, branch.Index);
 5561        }
 5562      }
 5563
 5564      return removals;
 5565    }
 5566
 5567    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 5568    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 5569    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 5570    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 5571    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 5572    /// <param name="where">The equality constraint of the removal.</param>
 5573    public void Remove(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Predicate<T> where)
 5574    {
 5575      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2), where);
 5576      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 5577    }
 5578    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 5579    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 5580    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 5581    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 5582    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 5583    /// <param name="where">The equality constraint of the removal.</param>
 5584    public void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 5585    {
 5586      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2), where);
 5587      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 5588    }
 5589    internal int Remove(Node node, Omnitree.Bounds<Axis1, Axis2> bounds, Predicate<T> where)
 5590    {
 5591      if (!InclusionCheck(node.Bounds, bounds))
 5592        return 0;
 5593      int removals = 0;
 5594      if (node is Leaf)
 5595      {
 5596        Leaf leaf = node as Leaf;
 5597        Leaf.Node current = leaf.Head;
 5598        Leaf.Node previous = null;
 5599        while (current is not null)
 5600        {
 5601          if (this.EncapsulationCheck(bounds, LocateVector(current.Value)) && where(current.Value))
 5602          {
 5603            removals++;
 5604            if (previous is null)
 5605            {
 5606              leaf.Head = current.Next;
 5607              goto HeadRemoved;
 5608            }
 5609            else
 5610              previous.Next = current.Next;
 5611          }
 5612          previous = current;
 5613        HeadRemoved:
 5614          current = current.Next;
 5615        }
 5616
 5617        leaf.Count -= removals;
 5618        return removals;
 5619      }
 5620      else
 5621      {
 5622        Branch branch = node as Branch;
 5623        int skipped = 0;
 5624        for (int i = 0; i + skipped < branch.Children.Length; )
 5625        {
 5626          removals += this.Remove(branch.Children[i], bounds, where);
 5627          if (branch.Children[i].Count is 0)
 5628            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 5629          else
 5630            i++;
 5631        }
 5632        Node[] newArray = new Node[branch.Children.Length - skipped];
 5633        Array.Copy(branch.Children, newArray, newArray.Length);
 5634        branch.Children = newArray;
 5635
 5636        node.Count -= removals;
 5637
 5638        if (node.Count < _load && node.Count != 0)
 5639          ShrinkChild(node.Parent, node.Index);
 5640
 5641        return removals;
 5642      }
 5643    }
 5644
 5645    /// <summary>Tries to remove a value.</summary>
 5646    /// <param name="value">The value to remove.</param>
 5647    /// <returns>True if successful or false if not.</returns>
 5648    public (bool Success, Exception? Exception) TryRemove(T value)
 5649    {
 5650      Remove(value);
 5651      return (true, null);
 5652    }
 5653
 5654    /// <summary>Removes all instances of a given value.</summary>
 5655    public void Remove(T removal) => Omnitree.Remove(this, removal);
 5656
 5657    /// <summary>Removes all instances of a given value.</summary>
 5658    public void Remove(T removal, Func<T, T, bool> equate) => Omnitree.Remove(this, removal, equate);
 5659
 5660    /// <summary>Removes all the items in a given space.</summary>
 5661    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 5662    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 5663    /// <returns>The number of items that were removed.</returns>
 5664    public void Remove(Axis1 axis1
 5665      , Axis2 axis2
 5666      )
 5667    {
 5668      this.Remove(this._top, new Omnitree.Vector<Axis1, Axis2>(axis1
 5669        , axis2
 5670        ));
 5671      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 5672    }
 5673    internal int Remove(Node node, Omnitree.Vector<Axis1, Axis2> vector)
 5674    {
 5675      int removals = 0;
 5676      if (node is Leaf)
 5677      {
 5678        Leaf leaf = node as Leaf;
 5679        Leaf.Node current_node = leaf.Head;
 5680        Leaf.Node previous_node = null;
 5681        while (!(current_node is null))
 5682        {
 5683          Leaf.Node temp_previous = current_node;
 5684          if (EqualsCheck(vector, LocateVector(current_node.Value)))
 5685          {
 5686            removals++;
 5687            if (current_node == leaf.Head)
 5688              leaf.Head = leaf.Head.Next;
 5689            else
 5690            {
 5691              previous_node.Next = current_node.Next;
 5692              temp_previous = previous_node;
 5693            }
 5694          }
 5695          previous_node = temp_previous;
 5696          current_node = current_node.Next;
 5697        }
 5698        leaf.Count -= removals;
 5699      }
 5700      else
 5701      {
 5702        Branch branch = node as Branch;
 5703        int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 5704        removals += Remove(branch[child_index], vector);
 5705        branch.Count -= removals;
 5706        // convert this branch back into a leaf
 5707        // Note: if count is zero, it will be chopped off
 5708        if (branch.Count < _load && branch.Count > 0)
 5709          ShrinkChild(branch.Parent, branch.Index);
 5710      }
 5711
 5712      return removals;
 5713    }
 5714
 5715    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 5716    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 5717    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 5718    /// <param name="where">The equality constraint of the removal.</param>
 5719    public void Remove(Axis1 axis1, Axis2 axis2, Predicate<T> where)
 5720    {
 5721      this.Remove(this._top, new Omnitree.Vector<Axis1, Axis2>(axis1, axis2), where);
 5722      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 5723    }
 5724    internal int Remove(Node node, Omnitree.Vector<Axis1, Axis2> vector, Predicate<T> where)
 5725    {
 5726      int removals = 0;
 5727      if (node is Leaf)
 5728      {
 5729        Leaf leaf = node as Leaf;
 5730        Leaf.Node current_node = leaf.Head;
 5731        Leaf.Node previous_node = null;
 5732        while (!(current_node is null))
 5733        {
 5734          Leaf.Node temp_previous = current_node;
 5735          if (EqualsCheck(vector, LocateVector(current_node.Value)) && where(current_node.Value))
 5736          {
 5737            removals++;
 5738            if (current_node == leaf.Head)
 5739              leaf.Head = leaf.Head.Next;
 5740            else
 5741            {
 5742              previous_node.Next = current_node.Next;
 5743              temp_previous = previous_node;
 5744            }
 5745          }
 5746          previous_node = temp_previous;
 5747          current_node = current_node.Next;
 5748        }
 5749        leaf.Count -= removals;
 5750      }
 5751      else
 5752      {
 5753        Branch branch = node as Branch;
 5754        int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 5755        removals += Remove(branch[child_index], vector, where);
 5756        branch.Count -= removals;
 5757        // convert this branch back into a leaf
 5758        // Note: if count is zero, it will be chopped off
 5759        if (branch.Count < _load && branch.Count > 0)
 5760          ShrinkChild(branch.Parent, branch.Index);
 5761      }
 5762      return removals;
 5763    }
 5764
 5765    #endregion
 5766
 5767    #region Stepper And IEnumerable
 5768
 5769    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 5770    /// <param name="step">The delegate to perform on every item in the tree.</param>
 5771    public void Stepper(Action<T> step) =>
 5772      this.Stepper(step, this._top);
 5773
 5774    internal void Stepper(Action<T> step, Node node)
 5775    {
 5776      if (node is Leaf)
 5777      {
 5778        Leaf.Node list = (node as Leaf).Head;
 5779        while (list is not null)
 5780        {
 5781          step(list.Value);
 5782          list = list.Next;
 5783        }
 5784      }
 5785      else
 5786      {
 5787        foreach (Node child in (node as Branch).Children)
 5788          this.Stepper(step, child);
 5789      }
 5790    }
 5791
 5792    public StepStatus StepperBreak<TStep>(TStep step = default)
 5793      where TStep : struct, IFunc<T, StepStatus> =>
 5794      StepperBreak(_top, step);
 5795
 5796    internal StepStatus StepperBreak<TStep>(Node node, TStep step)
 5797      where TStep : struct, IFunc<T, StepStatus>
 5798    {
 5799      StepStatus status = StepStatus.Continue;
 5800      if (node is Leaf leaf)
 5801      {
 5802        for (Leaf.Node list = leaf.Head; list is not null; list = list.Next)
 5803        {
 5804          if (step.Invoke(list.Value) is Break) return Break;
 5805        }
 5806      }
 5807      else if (node is Branch branch)
 5808      {
 5809        foreach (Node child in branch.Children)
 5810        {
 5811          if (StepperBreak(child, step) is Break) return Break;
 5812        }
 5813      }
 5814      return Continue;
 5815    }
 5816
 5817    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 5818    /// <param name="step">The delegate to perform on every item in the tree.</param>
 5819    public StepStatus Stepper(Func<T, StepStatus> step) =>
 5820      Stepper(step, _top);
 5821
 5822    internal StepStatus Stepper(Func<T, StepStatus> step, Node node)
 5823    {
 5824      StepStatus status = StepStatus.Continue;
 5825      if (node is Leaf)
 5826      {
 5827        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 5828          if ((status = step(list.Value)) != StepStatus.Continue)
 5829            break;
 5830      }
 5831      else
 5832      {
 5833        foreach (Node child in (node as Branch).Children)
 5834          if ((status = Stepper(step, child)) != StepStatus.Continue)
 5835            break;
 5836      }
 5837      return status;
 5838    }
 5839
 5840    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 5841    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 5842    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 5843    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 5844    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 5845    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 5846    public void Stepper(Action<T> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2) =>
 5847      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 5848
 5849    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 5850    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 5851    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 5852    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 5853    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 5854    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 5855    public void Stepper(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> mi
 5856      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 5857
 5858    internal void Stepper(Action<T> step, Node node, Omnitree.Bounds<Axis1, Axis2> bounds)
 5859    {
 5860      if (node is Leaf)
 5861      {
 5862        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 5863          if (EncapsulationCheck(bounds, LocateVector(list.Value)))
 5864            step(list.Value);
 5865      }
 5866      else
 5867      {
 5868        foreach (Node child in (node as Branch).Children)
 5869          // optimization: stop bounds checking if space encapsulates node
 5870          if (EncapsulationCheck(bounds, child.Bounds))
 5871            this.Stepper(step, child);
 5872          else if (InclusionCheck(child.Bounds, bounds))
 5873            this.Stepper(step, child, bounds);
 5874      }
 5875    }
 5876
 5877    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 5878    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 5879    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 5880    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 5881    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 5882    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 5883    public StepStatus Stepper(Func<T, StepStatus> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2) =>
 5884      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 5885
 5886    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 5887    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 5888    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 5889    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 5890    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 5891    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 5892    public StepStatus Stepper(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree
 5893      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 5894
 5895    internal StepStatus Stepper(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1, Axis2> bounds)
 5896    {
 5897      StepStatus status = StepStatus.Continue;
 5898      if (node is Leaf)
 5899      {
 5900        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 5901          if (EncapsulationCheck(bounds, LocateVector(list.Value)) &&
 5902            (status = step(list.Value)) != StepStatus.Continue)
 5903            break;
 5904      }
 5905      else
 5906      {
 5907        foreach (Node child in (node as Branch).Children)
 5908          // optimization: stop bounds checking if space encapsulates node
 5909          if (EncapsulationCheck(bounds, child.Bounds) &&
 5910            (status = this.Stepper(step, child)) != StepStatus.Continue)
 5911            break;
 5912          else if (InclusionCheck(child.Bounds, bounds) &&
 5913            (status = this.Stepper(step, child, bounds)) != StepStatus.Continue)
 5914            break;
 5915      }
 5916      return status;
 5917    }
 5918
 5919    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 5920    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 5921    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 5922    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 5923    public void Stepper(Action<T> step, Axis1 axis1, Axis2 axis2) =>
 5924      Stepper(step, _top, new Omnitree.Vector<Axis1, Axis2>(axis1, axis2));
 5925
 5926    internal void Stepper(Action<T> step, Node node, Omnitree.Vector<Axis1, Axis2> vector)
 5927    {
 5928      Node current = node;
 5929      while (current is not null)
 5930      {
 5931        if (current is Leaf)
 5932        {
 5933          for (Leaf.Node leaf_node = (current as Leaf).Head; leaf_node is not null; leaf_node = leaf_node.Next)
 5934            if (EqualsCheck(vector, LocateVector(leaf_node.Value)))
 5935              step(leaf_node.Value);
 5936          break;
 5937        }
 5938        else
 5939        {
 5940          Branch branch = current as Branch;
 5941          int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 5942          current = branch[child_index];
 5943        }
 5944      }
 5945    }
 5946
 5947    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 5948    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 5949    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 5950    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 5951    public StepStatus Stepper(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2) =>
 5952      Stepper(step, _top, new Omnitree.Vector<Axis1, Axis2>(axis1, axis2));
 5953
 5954    internal StepStatus Stepper(Func<T, StepStatus> step, Node node, Omnitree.Vector<Axis1, Axis2> vector)
 5955    {
 5956      Node current = node;
 5957      while (current is not null)
 5958      {
 5959        if (current is Leaf)
 5960        {
 5961          for (Leaf.Node list = (current as Leaf).Head; list is not null; list = list.Next)
 5962          {
 5963            StepStatus status = StepStatus.Continue;
 5964            if (EqualsCheck(vector, LocateVector(list.Value)) &&
 5965              (status = step(list.Value)) != StepStatus.Continue)
 5966              return status;
 5967          }
 5968        }
 5969        else
 5970        {
 5971          Branch branch = current as Branch;
 5972          int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 5973          current = branch[child_index];
 5974        }
 5975      }
 5976      return StepStatus.Continue;
 5977    }
 5978
 5979    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 5980
 5981    public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 5982    {
 5983      // Note: this can be optimized.
 5984      IList<T> list = new ListLinked<T>();
 5985      Stepper(x => list.Add(x));
 5986      return list.GetEnumerator();
 5987    }
 5988
 5989    #endregion
 5990
 5991    /// <inheritdoc/>
 5992    public T[] ToArray() => throw new NotImplementedException();
 5993
 5994    #region Helpers
 5995
 5996    internal bool StraddlesLines(Omnitree.Bounds<Axis1, Axis2> bounds, Omnitree.Vector<Axis1, Axis2> vector) =>
 5997      Omnitree.StraddlesLines(bounds, vector
 5998        , _compare1
 5999        , _compare2
 6000        );
 6001
 6002    /// <summary>Computes the child index that contains the desired dimensions.</summary>
 6003    /// <param name="pointOfDivision">The point of division to compare against.</param>
 6004    /// <param name="vector">The dimensions to determine the child index.</param>
 6005    /// <returns>The computed child index based on the coordinates relative to the center of the node.</returns>
 6006    internal int DetermineChildIndex(Omnitree.Vector<Axis1, Axis2> pointOfDivision, Omnitree.Vector<Axis1, Axis2> vector
 6007    {
 6008      int child = 0;
 6009      if (!(this._compare1(vector.Axis1, pointOfDivision.Axis1) is Less))
 6010        child += 1 << 0;
 6011      if (!(this._compare2(vector.Axis2, pointOfDivision.Axis2) is Less))
 6012        child += 1 << 1;
 6013      return child;
 6014    }
 6015
 6016    /// <summary>Converts a branch back into a leaf when the count is reduced.</summary>
 6017    /// <param name="parent">The parent to shrink a child of.</param>
 6018    /// <param name="child_index">The index of the child to shrink.</param>
 6019    internal void ShrinkChild(Branch parent, int child_index)
 6020    {
 6021      Leaf leaf;
 6022      Node removal = null;
 6023      if (parent is null) // top of tree
 6024      {
 6025        removal = this._top;
 6026        leaf = new Leaf(Omnitree.Bounds<Axis1, Axis2>.None, null, -1);
 6027        this._top = leaf;
 6028      }
 6029      else // non-top branch
 6030      {
 6031        removal = parent[child_index];
 6032        leaf = new Leaf(removal.Bounds, removal.Parent, removal.Index);
 6033        parent[child_index] = leaf;
 6034      }
 6035
 6036      this.Stepper((T step) => { leaf.Add(step); }, removal);
 6037    }
 6038
 6039    /// <summary>Reduces the counts of all the parents of a given node by a given amount.</summary>
 6040    /// <param name="parent">The starting parent of the reduction.</param>
 6041    /// <param name="reduction">The amount to reduce the parent counts by.</param>
 6042    internal void ReduceParentCounts(Node parent, int reduction)
 6043    {
 6044      IncreaseParentCounts(parent, -reduction);
 6045    }
 6046
 6047    /// <summary>Increases the counts of all the parents of a given node by a given amount.</summary>
 6048    /// <param name="parent">The starting parent of the increase.</param>
 6049    /// <param name="increase">The amount to increase the parent counts by.</param>
 6050    internal void IncreaseParentCounts(Node parent, int increase)
 6051    {
 6052      Node node = parent;
 6053      while (node is not null)
 6054      {
 6055        node.Count += increase;
 6056        node = node.Parent;
 6057      }
 6058    }
 6059
 6060    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 6061    /// <returns>True if the spaces overlap; False if not.</returns>
 6062    internal bool InclusionCheck(Omnitree.Bounds<Axis1, Axis2> a, Omnitree.Bounds<Axis1, Axis2> b) =>
 6063      Omnitree.InclusionCheck(a, b
 6064      , _compare1
 6065      , _compare2
 6066      );
 6067
 6068    /// <summary>Checks if a space encapsulates a point.</summary>
 6069    /// <returns>True if the space encapsulates the point; False if not.</returns>
 6070    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2> bounds, Omnitree.Vector<Axis1, Axis2> vector) =>
 6071      Omnitree.EncapsulationCheck(bounds, vector
 6072      , _compare1
 6073      , _compare2
 6074      );
 6075
 6076    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 6077    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 6078    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2> a, Omnitree.Bounds<Axis1, Axis2> b) =>
 6079      Omnitree.EncapsulationCheck(a, b
 6080      , _compare1
 6081      , _compare2
 6082      );
 6083
 6084    /// <summary>Checks for equality between two locations.</summary>
 6085    /// <returns>True if equal; False if not;</returns>
 6086    internal bool EqualsCheck(Omnitree.Vector<Axis1, Axis2> a, Omnitree.Vector<Axis1, Axis2> b) =>
 6087      Omnitree.EqualsCheck(a, b
 6088      , (a, b) => _compare1(a, b) is Equal
 6089      , (a, b) => _compare2(a, b) is Equal
 6090      );
 6091
 6092    /// <summary>Gets the nearest parent that encapsulates a location.</summary>
 6093    /// <param name="node">The starting node to find the encapsulating parent of the location.</param>
 6094    /// <param name="vector">The coordinates of the value.</param>
 6095    /// <returns>The nearest node that encapsulates the given location.</returns>
 6096    internal Node GetEncapsulationParent(Node node, Omnitree.Vector<Axis1, Axis2> vector)
 6097    {
 6098      while (node is not null && !EncapsulationCheck(node.Bounds, vector))
 6099      {
 6100        node = node.Parent;
 6101      }
 6102      return node;
 6103    }
 6104
 6105    internal Omnitree.Vector<Axis1, Axis2> LocateVector(T value)
 6106    {
 6107      Axis1 axis1;
 6108      Axis2 axis2;
 6109      this._locate(value, out axis1
 6110, out axis2
 6111);
 6112      return new Omnitree.Vector<Axis1, Axis2>(axis1, axis2);
 6113    }
 6114
 6115    #endregion
 6116
 6117    #endregion
 6118  }
 6119
 6120  #endregion
 6121
 6122  #region 3 Dimensional
 6123
 6124  /// <summary>Inheritance base for 3D omnitrees that store points.</summary>
 6125  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 6126  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 6127  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 6128  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 6129  public interface IOmnitreePoints<T, Axis1, Axis2, Axis3> : IOmnitree<T, Axis1, Axis2, Axis3>
 6130  {
 6131    #region Properties
 6132
 6133    /// <summary>Steps through the values at a given location.</summary>
 6134    /// <param name="axis1">The coordinate along the 1D axis.</param>
 6135    /// <param name="axis2">The coordinate along the 2D axis.</param>
 6136    /// <param name="axis3">The coordinate along the 3D axis.</param>
 6137
 6138    /// <returns>A Stepper of the items at the given coordinates.</returns>
 6139    Action<Action<T>> this[Axis1 axis1, Axis2 axis2, Axis3 axis3] { get; }
 6140
 6141    /// <summary>The number of dimensions in this tree.</summary>
 6142    int Dimensions { get; }
 6143
 6144    /// <summary>The delegate being used by the omnitree to locate items in 3D space.</summary>
 6145    Omnitree.Location<T, Axis1
 6146      , Axis2
 6147      , Axis3
 6148      > Locate { get; }
 6149
 6150    #endregion
 6151
 6152    #region Methods
 6153
 6154    /// <summary>Counts the number of items in a sub space.</summary>
 6155    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 6156    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 6157    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 6158    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 6159    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 6160    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 6161    /// <returns>The number of items in the provided sub space.</returns>
 6162    int CountSubSpace(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound
 6163
 6164    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 6165    void Update();
 6166    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 6167    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 6168    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 6169    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 6170    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 6171    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 6172    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 6173    void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound<Axis2
 6174
 6175    /// <summary>Removes all the items in a given space.</summary>
 6176    /// <param name="axis1">The coordinate along the 1D axis.</param>
 6177    /// <param name="axis2">The coordinate along the 2D axis.</param>
 6178    /// <param name="axis3">The coordinate along the 3D axis.</param>
 6179    void Remove(Axis1 axis1, Axis2 axis2, Axis3 axis3);
 6180    /// <summary>Removes all the items in a given space.</summary>
 6181    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 6182    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 6183    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 6184    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 6185    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 6186    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 6187    void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound<Axis2
 6188    /// <summary>Removes all the items in a given space where equality is met.</summary>
 6189    /// <param name="axis1">The coordinate along the 1D axis.</param>
 6190    /// <param name="axis2">The coordinate along the 2D axis.</param>
 6191    /// <param name="axis3">The coordinate along the 3D axis.</param>
 6192    /// <param name="where">The equality constraint of the removal.</param>
 6193    void Remove(Axis1 axis1, Axis2 axis2, Axis3 axis3, Predicate<T> where);
 6194    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 6195    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 6196    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 6197    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 6198    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 6199    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 6200    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 6201    /// <param name="where">The predicate constraint of the removal.</param>
 6202    void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound<Axis2
 6203
 6204    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 6205    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 6206    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 6207    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 6208    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 6209    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 6210    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 6211    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 6212    void Stepper(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omn
 6213    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 6214    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 6215    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 6216    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 6217    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 6218    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 6219    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 6220    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 6221    StepStatus Stepper(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<
 6222    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 6223    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 6224    /// <param name="axis1">The coordinate along the 1D axis.</param>
 6225    /// <param name="axis2">The coordinate along the 2D axis.</param>
 6226    /// <param name="axis3">The coordinate along the 3D axis.</param>
 6227    void Stepper(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3);
 6228    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 6229    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 6230    /// <param name="axis1">The coordinate along the 1D axis.</param>
 6231    /// <param name="axis2">The coordinate along the 2D axis.</param>
 6232    /// <param name="axis3">The coordinate along the 3D axis.</param>
 6233    StepStatus Stepper(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3);
 6234
 6235    #endregion
 6236  }
 6237
 6238  /// <summary>Omnitree that stores points along 3 dimensions implemented as a linked tree.</summary>
 6239  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 6240  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 6241  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 6242  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 6243  public class OmnitreePointsLinked<T, Axis1, Axis2, Axis3> : IOmnitreePoints<T, Axis1, Axis2, Axis3>
 6244  {
 6245    internal const int _dimensions = 3;
 6246    internal static int _children_per_node = (int)BigInteger.Pow(2, 3);
 6247
 6248    internal Node _top;
 6249    internal int _naturalLogLower = 1; // caching the next time to calculate loads (lower count)
 6250    internal int _naturalLogUpper = -1; // caching the next time to calculate loads (upper count)
 6251    internal int _load; // ln(count); min = _defaultLoad
 6252    internal Omnitree.Location<T, Axis1
 6253      , Axis2
 6254      , Axis3
 6255      > _locate;
 6256    internal bool _defaultCompare1;
 6257    internal Func<Axis1, Axis1, CompareResult> _compare1;
 6258    internal bool _defaultCompare2;
 6259    internal Func<Axis2, Axis2, CompareResult> _compare2;
 6260    internal bool _defaultCompare3;
 6261    internal Func<Axis3, Axis3, CompareResult> _compare3;
 6262    internal Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3>> _subdivisionOverride1;
 6263    internal Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3>> _subdivisionOverride2;
 6264    internal Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3>> _subdivisionOverride3;
 6265
 6266    #region Nested Types
 6267
 6268    /// <summary>Can be a leaf or a branch.</summary>
 6269    internal abstract class Node
 6270    {
 6271      internal Omnitree.Bounds<Axis1, Axis2, Axis3> Bounds;
 6272      internal Branch Parent;
 6273      internal int Index;
 6274      internal int Count;
 6275
 6276      /// <summary>The depth this node is located in the Omnitree.</summary>
 6277      internal int Depth
 6278      {
 6279        get
 6280        {
 6281          int depth = -1;
 6282          for (Node node = this; node is not null; node = node.Parent)
 6283            depth++;
 6284          return depth;
 6285        }
 6286      }
 6287
 6288      /// <summary>Constructs a node.</summary>
 6289      /// <param name="bounds">The bounds of this node.</param>
 6290      /// <param name="parent">The parent of this node.</param>
 6291      /// <param name="index">The number of values stored in this node and its children.</param>
 6292      internal Node(Omnitree.Bounds<Axis1, Axis2, Axis3> bounds, Branch parent, int index)
 6293      {
 6294        Bounds = bounds;
 6295        Parent = parent;
 6296        Index = index;
 6297      }
 6298
 6299      internal Node(Node nodeToClone)
 6300      {
 6301        this.Bounds = nodeToClone.Bounds;
 6302        this.Parent = nodeToClone.Parent;
 6303        this.Index = nodeToClone.Index;
 6304        this.Count = nodeToClone.Count;
 6305      }
 6306
 6307      internal abstract Node Clone();
 6308    }
 6309
 6310    /// <summary>A branch in the tree. Only contains nodes.</summary>
 6311    internal class Branch : Node
 6312    {
 6313      internal Node[] Children;
 6314      internal Omnitree.Vector<Axis1, Axis2, Axis3> PointOfDivision;
 6315
 6316      /// <summary>Gets child by index.</summary>
 6317      /// <param name="child_index">The index of the child to get.</param>
 6318      /// <returns>The child of the given index or null if non-existent.</returns>
 6319      internal Node this[int child_index]
 6320      {
 6321        get
 6322        {
 6323          if (Children is null)
 6324            return null;
 6325          if (Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3>._children_per_node)
 6326            return Children[(int)child_index];
 6327          foreach (Node node in Children)
 6328            if (node.Index == child_index)
 6329              return node;
 6330          return null;
 6331        }
 6332        set
 6333        {
 6334          // This error check should be unnecessary... but fuck it... might as well
 6335          if (value.Index != child_index)
 6336            throw new System.Exception("Bug in Omnitree (index/property mis-match when setting a child on a branch)");
 6337
 6338          // no children yet
 6339          if (Children is null)
 6340          {
 6341            Children = â±¯(value);
 6342            return;
 6343          }
 6344          // max children overwrite
 6345          else if (this.Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3>._children_per_node)
 6346          {
 6347            Children[(int)child_index] = value;
 6348            return;
 6349          }
 6350          // non-max child overwrite
 6351          for (int i = 0; i < Children.Length; i++)
 6352            if (Children[i].Index == child_index)
 6353            {
 6354              Children[i] = value;
 6355              return;
 6356            }
 6357          // new child
 6358          Node[] newArray = new Node[Children.Length + 1];
 6359          if (newArray.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3>._children_per_node)
 6360          {
 6361            // new child resulting in a max children branch (sorting required)
 6362            for (int i = 0; i < Children.Length; i++)
 6363            {
 6364              newArray[(int)Children[i].Index] = Children[i];
 6365            }
 6366            newArray[(int)value.Index] = value;
 6367          }
 6368          else
 6369          {
 6370            // new child resulting in a non-max children branch
 6371            Array.Copy(Children, newArray, Children.Length);
 6372            newArray[newArray.Length - 1] = value;
 6373          }
 6374          this.Children = newArray;
 6375        }
 6376      }
 6377
 6378      internal Branch(Omnitree.Vector<Axis1, Axis2, Axis3> pointOfDivision, Omnitree.Bounds<Axis1, Axis2, Axis3> bounds,
 6379        : base(bounds, parent, index)
 6380      {
 6381        this.PointOfDivision = pointOfDivision;
 6382      }
 6383
 6384      internal Branch(Branch branchToClone) : base(branchToClone)
 6385      {
 6386        Children = branchToClone.Children.Clone() as Node[];
 6387        PointOfDivision = branchToClone.PointOfDivision;
 6388      }
 6389
 6390      internal override Node Clone() =>
 6391        new Branch(this);
 6392    }
 6393
 6394    /// <summary>A branch in the tree. Only contains items.</summary>
 6395    internal class Leaf : Node
 6396    {
 6397      internal class Node
 6398      {
 6399        internal T Value;
 6400        internal Leaf.Node Next;
 6401
 6402        internal Node(T value, Leaf.Node next)
 6403        {
 6404          Value = value;
 6405          Next = next;
 6406        }
 6407      }
 6408
 6409      internal Leaf.Node Head;
 6410
 6411      internal Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3> bounds, Branch parent, int index)
 6412        : base(bounds, parent, index)
 6413      { }
 6414
 6415      internal Leaf(Leaf leaf) : base(leaf)
 6416      {
 6417        Head = new Node(leaf.Head.Value, null);
 6418        Node a = Head;
 6419        Node b = leaf.Head;
 6420        while (b is not null)
 6421        {
 6422          a.Next = new Node(b.Next.Value, null);
 6423          a = a.Next;
 6424          b = b.Next;
 6425        }
 6426      }
 6427
 6428      internal void Add(T addition)
 6429      {
 6430        Head = new Leaf.Node(addition, Head);
 6431        this.Count++;
 6432      }
 6433
 6434      internal override OmnitreePointsLinked<T, Axis1, Axis2, Axis3>.Node Clone() =>
 6435        new Leaf(this);
 6436    }
 6437
 6438    #endregion
 6439
 6440    #region Constructors
 6441
 6442    /// <summary>This constructor is for cloning purposes</summary>
 6443    internal OmnitreePointsLinked(OmnitreePointsLinked<T, Axis1, Axis2, Axis3> omnitree)
 6444    {
 6445      this._top = omnitree._top.Clone();
 6446      this._load = omnitree._load;
 6447      this._locate = omnitree._locate;
 6448      this._defaultCompare1 = omnitree._defaultCompare1;
 6449      this._compare1 = omnitree._compare1;
 6450      this._defaultCompare2 = omnitree._defaultCompare2;
 6451      this._compare2 = omnitree._compare2;
 6452      this._defaultCompare3 = omnitree._defaultCompare3;
 6453      this._compare3 = omnitree._compare3;
 6454      this._subdivisionOverride1 = omnitree._subdivisionOverride1;
 6455      this._subdivisionOverride2 = omnitree._subdivisionOverride2;
 6456      this._subdivisionOverride3 = omnitree._subdivisionOverride3;
 6457    }
 6458
 6459    internal OmnitreePointsLinked(
 6460      Omnitree.Location<T, Axis1, Axis2, Axis3> locate,
 6461      bool defaultCompare1,
 6462      Func<Axis1, Axis1, CompareResult> compare1,
 6463      bool defaultCompare2,
 6464      Func<Axis2, Axis2, CompareResult> compare2,
 6465      bool defaultCompare3,
 6466      Func<Axis3, Axis3, CompareResult> compare3,
 6467      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3>> subdivisionOverride1
 6468,
 6469      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3>> subdivisionOverride2
 6470,
 6471      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3>> subdivisionOverride3
 6472      )
 6473    {
 6474      if (locate is null)
 6475      {
 6476        throw new ArgumentNullException(nameof(locate));
 6477      }
 6478      if (compare1 is null)
 6479      {
 6480        throw new ArgumentNullException(nameof(compare1));
 6481      }
 6482
 6483      if (compare2 is null)
 6484      {
 6485        throw new ArgumentNullException(nameof(compare2));
 6486      }
 6487
 6488      if (compare3 is null)
 6489      {
 6490        throw new ArgumentNullException(nameof(compare3));
 6491      }
 6492
 6493      this._locate = locate;
 6494      this._defaultCompare1 = defaultCompare1;
 6495      this._compare1 = compare1;
 6496      this._defaultCompare2 = defaultCompare2;
 6497      this._compare2 = compare2;
 6498      this._defaultCompare3 = defaultCompare3;
 6499      this._compare3 = compare3;
 6500      this._subdivisionOverride1 = subdivisionOverride1;
 6501      this._subdivisionOverride2 = subdivisionOverride2;
 6502      this._subdivisionOverride3 = subdivisionOverride3;
 6503      this._top = new Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3>.None, null, -1);
 6504      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 6505    }
 6506
 6507    /// <summary>Constructs a new 3D omnitree that stores points.</summary>
 6508    /// <param name="locate">The delegate for locating items in 3D space.</param>
 6509
 6510    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 6511
 6512    /// <param name="compare2">The delegate for comparing values along the 2D axis.</param>
 6513
 6514    /// <param name="compare3">The delegate for comparing values along the 3D axis.</param>
 6515
 6516    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 6517
 6518    /// <param name="subdivisionOverride2">The subdivision overide to be used when splitting the 2 dimension.</param>
 6519
 6520    /// <param name="subdivisionOverride3">The subdivision overide to be used when splitting the 3 dimension.</param>
 6521    public OmnitreePointsLinked(
 6522      Omnitree.Location<T, Axis1, Axis2, Axis3> locate,
 6523      Func<Axis1, Axis1, CompareResult> compare1 = null,
 6524      Func<Axis2, Axis2, CompareResult> compare2 = null,
 6525      Func<Axis3, Axis3, CompareResult> compare3 = null,
 6526      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3>> subdivisionOverride1 = null
 6527,
 6528      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3>> subdivisionOverride2 = null
 6529,
 6530      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3>> subdivisionOverride3 = null
 6531      )
 6532      : this(
 6533        locate,
 6534        compare1 is null ? true : false,
 6535        compare1 ?? Compare,
 6536        compare2 is null ? true : false,
 6537        compare2 ?? Compare,
 6538        compare3 is null ? true : false,
 6539        compare3 ?? Compare,
 6540        subdivisionOverride1
 6541,
 6542        subdivisionOverride2
 6543,
 6544        subdivisionOverride3
 6545        ) { }
 6546
 6547    #endregion
 6548
 6549    #region Properties
 6550
 6551    /// <summary>Steps through all the items at a given coordinate.</summary>
 6552    /// <param name="axis1">The coordinate along axis 1.</param>
 6553    /// <param name="axis2">The coordinate along axis 2.</param>
 6554    /// <param name="axis3">The coordinate along axis 3.</param>
 6555    /// <returns>The stepper for the items at the given coordinate.</returns>
 6556    public Action<Action<T>> this[Axis1 axis1, Axis2 axis2, Axis3 axis3] =>
 6557      step => Stepper(step, axis1, axis2, axis3);
 6558
 6559    /// <summary>The number of dimensions in this tree.</summary>
 6560    public int Dimensions { get { return _dimensions; } }
 6561
 6562    /// <summary>The location function the Omnitree is using.</summary>
 6563    public Omnitree.Location<T, Axis1, Axis2, Axis3> Locate { get { return this._locate; } }
 6564
 6565    /// <summary>The comparison function the Omnitree is using along the 1D axis.</summary>
 6566    public Func<Axis1, Axis1, CompareResult> Compare1 { get { return this._compare1; } }
 6567    /// <summary>The comparison function the Omnitree is using along the 2D axis.</summary>
 6568    public Func<Axis2, Axis2, CompareResult> Compare2 { get { return this._compare2; } }
 6569    /// <summary>The comparison function the Omnitree is using along the 3D axis.</summary>
 6570    public Func<Axis3, Axis3, CompareResult> Compare3 { get { return this._compare3; } }
 6571
 6572    /// <summary>The current number of items in the tree.</summary>
 6573    public int Count { get { return this._top.Count; } }
 6574
 6575    internal delegate void MaxDepthFinder(Node node, int current_depth, ref int max_depth);
 6576    /// <summary>Finds the current maximum depth of the tree. NOT AN O(1) OPERATION. Intended for educational purposes o
 6577    public int MaxDepth
 6578    {
 6579      get
 6580      {
 6581        MaxDepthFinder maxDepthFinder = null;
 6582        maxDepthFinder =
 6583          (Node node, int current_depth, ref int max_depth) =>
 6584          {
 6585            if (current_depth > max_depth)
 6586              max_depth = current_depth;
 6587            if (node is Branch)
 6588              foreach (Node child in (node as Branch).Children)
 6589                maxDepthFinder(child, current_depth + 1, ref max_depth);
 6590          };
 6591        int _max_depth = -1;
 6592        maxDepthFinder(this._top, 0, ref _max_depth);
 6593        return _max_depth;
 6594      }
 6595    }
 6596
 6597    internal delegate void NodeCountFinder(Node node, ref int current_count);
 6598    /// <summary>Counts the current number of nodes in the tree. NOT AN O(1) OPERATION. Intended for educational purpose
 6599    public int NodeCount
 6600    {
 6601      get
 6602      {
 6603        NodeCountFinder nodeCountFinder = null;
 6604        nodeCountFinder =
 6605          (Node node, ref int current_count) =>
 6606          {
 6607            current_count++;
 6608            if (node is Branch)
 6609              foreach (Node child in (node as Branch).Children)
 6610                nodeCountFinder(child, ref current_count);
 6611          };
 6612
 6613        int _current_count = 0;
 6614        nodeCountFinder(this._top, ref _current_count);
 6615        return _current_count;
 6616      }
 6617    }
 6618
 6619    internal delegate void BranchCountFinder(Node node, ref int current_count);
 6620    /// <summary>Counts the current number of branches in the tree. NOT AN O(1) OPERATION. Intended for educational purp
 6621    public int BranchCount
 6622    {
 6623      get
 6624      {
 6625        BranchCountFinder branchCountFinder = null;
 6626        branchCountFinder =
 6627          (Node node, ref int current_count) =>
 6628          {
 6629            if (node is Branch)
 6630            {
 6631              current_count++;
 6632              foreach (Node child in (node as Branch).Children)
 6633                branchCountFinder(child, ref current_count);
 6634            }
 6635          };
 6636
 6637        int _current_count = 0;
 6638        branchCountFinder(this._top, ref _current_count);
 6639        return _current_count;
 6640      }
 6641    }
 6642
 6643    internal delegate void LeafCountFinder(Node node, ref int current_count);
 6644    /// <summary>Counts the current number of leaves in the tree. NOT AN O(1) OPERATION. Intended for educational purpos
 6645    public int LeafCount
 6646    {
 6647      get
 6648      {
 6649        LeafCountFinder leafCountFinder = null;
 6650        leafCountFinder =
 6651          (Node node, ref int current_count) =>
 6652          {
 6653            if (node is Leaf)
 6654              current_count++;
 6655            else
 6656              foreach (Node child in (node as Branch).Children)
 6657                leafCountFinder(child, ref current_count);
 6658          };
 6659
 6660        int _current_count = 0;
 6661        leafCountFinder(this._top, ref _current_count);
 6662        return _current_count;
 6663      }
 6664    }
 6665
 6666    #endregion
 6667
 6668    #region Methods
 6669
 6670    #region Add
 6671
 6672
 6673    #region single
 6674
 6675    /// <summary>Tries to add a value.</summary>
 6676    /// <param name="value">The value to be added.</param>
 6677    /// <returns>True if successful or false if not.</returns>
 6678    public (bool Success, Exception? Exception) TryAdd(T value)
 6679    {
 6680      Add(value);
 6681      return (true, null);
 6682    }
 6683
 6684    /// <summary>Adds an item to the tree.</summary>
 6685    /// <param name="addition">The item to be added.</param>
 6686    public void Add(T addition)
 6687    {
 6688      if (this._top.Count is int.MaxValue)
 6689        throw new System.InvalidOperationException("(Count is int.MaxValue) max Omnitree size reached (change ints to lo
 6690
 6691      // dynamic tree sizes
 6692      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 6693
 6694      Omnitree.Vector<Axis1, Axis2, Axis3> location = LocateVector(addition);
 6695
 6696      // grow the first branch of the tree
 6697      if (this._top is Leaf && (this._top as Leaf).Count >= _load)
 6698      {
 6699        Leaf top = this._top as Leaf;
 6700
 6701        // create the new branch from the median values
 6702        this._top = new Branch(DetermineMedians(top), Omnitree.Bounds<Axis1, Axis2, Axis3>.None, null, -1);
 6703
 6704        // iterate through the values and add them to the appropriate children
 6705        for (Leaf.Node list = top.Head; list is not null; list = list.Next)
 6706          Add(list.Value, this._top, LocateVector(list.Value), 0);
 6707      }
 6708
 6709      this.Add(addition, this._top, location, 0);
 6710    }
 6711
 6712    /// <summary>Recursive version of the add function.</summary>
 6713    /// <param name="addition">The item to be added.</param>
 6714    /// <param name="node">The current node for tree trversal.</param>
 6715    /// <param name="location">The location of the addition.</param>
 6716    /// <param name="depth">The current depth of iteration.</param>
 6717    internal void Add(T addition, Node node, Omnitree.Vector<Axis1, Axis2, Axis3> location, int depth)
 6718    {
 6719      if (node is Leaf)
 6720      {
 6721        Leaf leaf = node as Leaf;
 6722        if (depth >= _load || !(leaf.Count >= _load))
 6723        {
 6724          leaf.Add(addition);
 6725          return;
 6726        }
 6727        else
 6728        {
 6729          Branch parent = node.Parent;
 6730          int child_index = this.DetermineChildIndex(parent.PointOfDivision, location);
 6731          Branch growth = new Branch(DetermineMedians(leaf), leaf.Bounds, parent, child_index);
 6732          parent[child_index] = growth;
 6733          for (Leaf.Node list = leaf.Head; list is not null; list = list.Next)
 6734          {
 6735            Omnitree.Vector<Axis1, Axis2, Axis3> temp_location = LocateVector(list.Value);
 6736            if (EncapsulationCheck(growth.Bounds, temp_location))
 6737              Add(list.Value, growth, temp_location, depth);
 6738            else
 6739            {
 6740              ReduceParentCounts(parent, 1);
 6741              Add(list.Value, this._top, temp_location, depth);
 6742            }
 6743          }
 6744
 6745          Add(addition, growth, location, depth);
 6746          return;
 6747        }
 6748      }
 6749      else
 6750      {
 6751        Branch branch = node as Branch;
 6752        int child_index = this.DetermineChildIndex(branch.PointOfDivision, location); // determine the child "index" (0 
 6753        Node child_node = branch[child_index];
 6754
 6755        // null children in branches are just empty leaves
 6756        if (child_node is null)
 6757        {
 6758          Leaf new_leaf = new Leaf(DetermineChildBounds(branch, child_index), branch, child_index);
 6759          branch[child_index] = new_leaf;
 6760          new_leaf.Add(addition);
 6761        }
 6762        else
 6763          // child exists already, continue adding
 6764          Add(addition, child_node, location, depth + 1);
 6765
 6766        branch.Count++;
 6767        return;
 6768      }
 6769    }
 6770
 6771    internal Omnitree.Vector<Axis1, Axis2, Axis3> DetermineMedians(Leaf leaf)
 6772    {
 6773
 6774      Axis1 division1;
 6775      if (!(_subdivisionOverride1 is null))
 6776      {
 6777        division1 = _subdivisionOverride1(leaf.Bounds, x =>
 6778          {
 6779            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 6780            {
 6781              x(node.Value);
 6782            }
 6783          });
 6784      }
 6785      else
 6786      {
 6787        Axis1[] values = new Axis1[leaf.Count];
 6788        Leaf.Node for_current = leaf.Head;
 6789        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 6790          this._locate(for_current.Value
 6791          , out values[i]
 6792          , out _
 6793          , out _
 6794          );
 6795        if (_defaultCompare1) Array.Sort(values);
 6796        else SortQuick<Axis1>(values, this._compare1);
 6797        int index = (leaf.Count - 1) / 2;
 6798        division1 = values[index];
 6799      }
 6800
 6801      Axis2 division2;
 6802      if (!(_subdivisionOverride2 is null))
 6803      {
 6804        division2 = _subdivisionOverride2(leaf.Bounds, x =>
 6805          {
 6806            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 6807            {
 6808              x(node.Value);
 6809            }
 6810          });
 6811      }
 6812      else
 6813      {
 6814        Axis2[] values = new Axis2[leaf.Count];
 6815        Leaf.Node for_current = leaf.Head;
 6816        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 6817          this._locate(for_current.Value
 6818          , out _
 6819          , out values[i]
 6820          , out _
 6821          );
 6822        if (_defaultCompare2) Array.Sort(values);
 6823        else SortQuick<Axis2>(values, this._compare2);
 6824        int index = (leaf.Count - 1) / 2;
 6825        division2 = values[index];
 6826      }
 6827
 6828      Axis3 division3;
 6829      if (!(_subdivisionOverride3 is null))
 6830      {
 6831        division3 = _subdivisionOverride3(leaf.Bounds, x =>
 6832          {
 6833            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 6834            {
 6835              x(node.Value);
 6836            }
 6837          });
 6838      }
 6839      else
 6840      {
 6841        Axis3[] values = new Axis3[leaf.Count];
 6842        Leaf.Node for_current = leaf.Head;
 6843        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 6844          this._locate(for_current.Value
 6845          , out _
 6846          , out _
 6847          , out values[i]
 6848          );
 6849        if (_defaultCompare3) Array.Sort(values);
 6850        else SortQuick<Axis3>(values, this._compare3);
 6851        int index = (leaf.Count - 1) / 2;
 6852        division3 = values[index];
 6853      }
 6854
 6855      return new Omnitree.Vector<Axis1, Axis2, Axis3>(
 6856        division1
 6857
 6858        , division2
 6859
 6860        , division3
 6861
 6862        );
 6863    }
 6864
 6865    #endregion
 6866
 6867    #region Add Helpers
 6868
 6869    internal Omnitree.Bounds<Axis1, Axis2, Axis3> DetermineChildBounds(Branch branch, int child_index)
 6870    {
 6871
 6872      Omnitree.Bound<Axis3> min3, max3;
 6873      if (child_index >= 4)
 6874      {
 6875        min3 = branch.PointOfDivision.Axis3;
 6876        max3 = branch.Bounds.Max3;
 6877        child_index -= 4;
 6878      }
 6879      else
 6880      {
 6881        min3 = branch.Bounds.Min3;
 6882        max3 = branch.PointOfDivision.Axis3;
 6883      }
 6884
 6885      Omnitree.Bound<Axis2> min2, max2;
 6886      if (child_index >= 2)
 6887      {
 6888        min2 = branch.PointOfDivision.Axis2;
 6889        max2 = branch.Bounds.Max2;
 6890        child_index -= 2;
 6891      }
 6892      else
 6893      {
 6894        min2 = branch.Bounds.Min2;
 6895        max2 = branch.PointOfDivision.Axis2;
 6896      }
 6897
 6898      Omnitree.Bound<Axis1> min1, max1;
 6899      if (child_index >= 1)
 6900      {
 6901        min1 = branch.PointOfDivision.Axis1;
 6902        max1 = branch.Bounds.Max1;
 6903        child_index -= 1;
 6904      }
 6905      else
 6906      {
 6907        min1 = branch.Bounds.Min1;
 6908        max1 = branch.PointOfDivision.Axis1;
 6909      }
 6910
 6911      return new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3);
 6912    }
 6913
 6914    #endregion
 6915
 6916    #endregion
 6917
 6918    #region Clear
 6919
 6920    /// <summary>Returns the tree to an empty state.</summary>
 6921    public void Clear()
 6922    {
 6923      this._top = new Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3>.None, null, -1);
 6924      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 6925    }
 6926
 6927    #endregion
 6928
 6929    #region Clone
 6930
 6931    /// <summary>Creates a shallow clone of this data structure.</summary>
 6932    /// <returns>A shallow clone of this data structure.</returns>
 6933    public OmnitreePointsLinked<T, Axis1, Axis2, Axis3> Clone()
 6934    {
 6935      return new OmnitreePointsLinked<T, Axis1, Axis2, Axis3>(this);
 6936    }
 6937
 6938    #endregion
 6939
 6940    #region Count
 6941
 6942    /// <summary>Counts the number of items in a sub space.</summary>
 6943    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 6944    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 6945    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 6946    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 6947    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 6948    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 6949    /// <returns>The number of items in the provided sub space.</returns>
 6950    public int CountSubSpace(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3)
 6951    {
 6952      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 6953    }
 6954    /// <summary>Counts the number of items in a sub space.</summary>
 6955    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 6956    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 6957    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 6958    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 6959    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 6960    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 6961    /// <returns>The number of items in the provided sub space.</returns>
 6962    public int CountSubSpace(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitre
 6963    {
 6964      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 6965    }
 6966    /// <summary>Counts the number of items in a sub space.</summary>
 6967    /// <param name="axis1">The coordinate along the 1D axis.</param>
 6968    /// <param name="axis2">The coordinate along the 2D axis.</param>
 6969    /// <param name="axis3">The coordinate along the 3D axis.</param>
 6970    /// <returns>The number of items in the provided sub space.</returns>
 6971    public int CountSubSpace(Axis1 axis1, Axis2 axis2, Axis3 axis3)
 6972    {
 6973      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(axis1, axis1, axis2, axis2, axis3, axis3));
 6974    }
 6975    /// <summary>Counts the number of items in a sub space.</summary>
 6976    /// <param name="axis1">The coordinate along the 1D axis.</param>
 6977    /// <param name="axis2">The coordinate along the 2D axis.</param>
 6978    /// <param name="axis3">The coordinate along the 3D axis.</param>
 6979    /// <returns>The number of items in the provided sub space.</returns>
 6980    public int CountSubSpace(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3)
 6981    {
 6982      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(axis1, axis1, axis2, axis2, axis3, axis3));
 6983    }
 6984    /// <summary>Counts the number of items in a sub space.</summary>
 6985    /// <param name="node">The current traversal node.</param>
 6986    /// <param name="bounds">The bounds of the sub space being counted.</param>
 6987    /// <returns>The number of items in the provided sub space.</returns>
 6988    internal int CountSubSpace(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3> bounds)
 6989    {
 6990      // adjust min/max values
 6991      int count = 0;
 6992      if (EncapsulationCheck(bounds, node.Bounds))
 6993        count += node.Count;
 6994      else if (node is Leaf)
 6995      {
 6996        for (Leaf.Node list = (node as Leaf).Head; list is null; list = list.Next)
 6997          if (EncapsulationCheck(bounds, LocateVector(list.Value)))
 6998            count++;
 6999      }
 7000      else
 7001      {
 7002        Branch branch = node as Branch;
 7003        if (!StraddlesLines(branch.Bounds, branch.PointOfDivision))
 7004        {
 7005          int child_index = DetermineChildIndex(branch.PointOfDivision, new Omnitree.Vector<Axis1, Axis2, Axis3>(bounds.
 7006            , bounds.Min2.Value
 7007            , bounds.Min3.Value
 7008            ));
 7009          Node child = branch[child_index];
 7010          if (child is not null)
 7011          {
 7012            count += this.CountSubSpace(child, bounds);
 7013          }
 7014        }
 7015        else
 7016        {
 7017          foreach (Node child in (node as Branch).Children)
 7018            count += this.CountSubSpace(child, bounds);
 7019        }
 7020      }
 7021      return count;
 7022    }
 7023
 7024    #endregion
 7025
 7026    #region Update
 7027
 7028    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 7029    public void Update()
 7030    {
 7031      this.Update(this._top, 0);
 7032    }
 7033
 7034    /// <summary>Recursive version of the Update method.</summary>
 7035    /// <param name="node">The current node of iteration.</param>
 7036    /// <param name="depth">The current depth of iteration.</param>
 7037    internal int Update(Node node, int depth)
 7038    {
 7039      int removals = 0;
 7040
 7041      if (node is Leaf)
 7042      {
 7043        Leaf leaf = node as Leaf;
 7044        Leaf.Node current = leaf.Head;
 7045        Leaf.Node previous = null;
 7046        while (current is not null)
 7047        {
 7048          Omnitree.Vector<Axis1, Axis2, Axis3> location = LocateVector(current.Value);
 7049          if (!this.EncapsulationCheck(node.Bounds, location))
 7050          {
 7051            removals++;
 7052            T updated = current.Value;
 7053            if (previous is null)
 7054            {
 7055              leaf.Head = current.Next;
 7056              goto HeadRemoved;
 7057            }
 7058            else
 7059              previous.Next = current.Next;
 7060
 7061            Node whereToAdd = GetEncapsulationParent(node.Parent, location);
 7062
 7063            if (whereToAdd is null)
 7064              throw new System.Exception("an item was updated outside the range of the omnitree");
 7065
 7066            this.Add(updated, whereToAdd, location, whereToAdd.Depth);
 7067          }
 7068          previous = current;
 7069        HeadRemoved:
 7070          current = current.Next;
 7071        }
 7072        leaf.Count -= removals;
 7073        return removals;
 7074      }
 7075      else
 7076      {
 7077        Branch branch = node as Branch;
 7078        int skipped = 0;
 7079        for (int i = 0; i + skipped < branch.Children.Length; )
 7080        {
 7081          removals += this.Update(branch.Children[i], depth + 1);
 7082          if (branch.Children[i].Count is 0)
 7083            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 7084          else
 7085            i++;
 7086        }
 7087        Node[] newArray = new Node[branch.Children.Length - skipped];
 7088        Array.Copy(branch.Children, newArray, newArray.Length);
 7089        branch.Children = newArray;
 7090
 7091        branch.Count -= removals;
 7092
 7093        if (branch.Count < _load && branch.Count != 0)
 7094          ShrinkChild(branch.Parent, branch.Index);
 7095      }
 7096
 7097      return removals;
 7098    }
 7099
 7100    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 7101    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 7102    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 7103    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 7104    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 7105    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 7106    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 7107    public void Update(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3)
 7108    {
 7109      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3), this._top, 0);
 7110    }
 7111    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 7112    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 7113    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 7114    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 7115    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 7116    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 7117    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 7118    public void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 7119    {
 7120      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3), this._top, 0);
 7121    }
 7122    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 7123    /// <param name="axis1">The coordinate along the 1D axis.</param>
 7124    /// <param name="axis2">The coordinate along the 2D axis.</param>
 7125    /// <param name="axis3">The coordinate along the 3D axis.</param>
 7126    public void Update(Axis1 axis1, Axis2 axis2, Axis3 axis3)
 7127    {
 7128      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3>(axis1, axis1, axis2, axis2, axis3, axis3), this._top, 0);
 7129    }
 7130    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 7131    /// <param name="axis1">The coordinate along the 1D axis.</param>
 7132    /// <param name="axis2">The coordinate along the 2D axis.</param>
 7133    /// <param name="axis3">The coordinate along the 3D axis.</param>
 7134    public void Update(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3)
 7135    {
 7136      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3>(axis1, axis1, axis2, axis2, axis3, axis3), this._top, 0);
 7137    }
 7138    internal int Update(Omnitree.Bounds<Axis1, Axis2, Axis3> bounds, Node node, int depth)
 7139    {
 7140      if (!InclusionCheck(bounds, node.Bounds))
 7141        return 0;
 7142
 7143      int removals = 0;
 7144
 7145      if (node is Leaf)
 7146      {
 7147        Leaf leaf = node as Leaf;
 7148        Leaf.Node current = leaf.Head;
 7149        Leaf.Node previous = null;
 7150        while (current is not null)
 7151        {
 7152          Omnitree.Vector<Axis1, Axis2, Axis3> location = LocateVector(current.Value);
 7153          if (!this.EncapsulationCheck(node.Bounds, location))
 7154          {
 7155            removals++;
 7156            T updated = current.Value;
 7157            if (previous is null)
 7158            {
 7159              leaf.Head = current.Next;
 7160              goto HeadRemoved;
 7161            }
 7162            else
 7163              previous.Next = current.Next;
 7164            Node whereToAdd = GetEncapsulationParent(node.Parent, location);
 7165            if (whereToAdd is null)
 7166              throw new System.Exception("an item was updates outside the range of the omnitree");
 7167            this.Add(updated, whereToAdd, location, whereToAdd.Depth);
 7168          }
 7169          previous = current;
 7170        HeadRemoved:
 7171          current = current.Next;
 7172        }
 7173        leaf.Count -= removals;
 7174        return removals;
 7175      }
 7176      else
 7177      {
 7178        Branch branch = node as Branch;
 7179        int skipped = 0;
 7180        for (int i = 0; i + skipped < branch.Children.Length; )
 7181        {
 7182          removals += this.Update(branch.Children[i], depth + 1);
 7183          if (branch.Children[i].Count is 0)
 7184            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 7185          else
 7186            i++;
 7187        }
 7188        Node[] newArray = new Node[branch.Children.Length - skipped];
 7189        Array.Copy(branch.Children, newArray, newArray.Length);
 7190        branch.Children = newArray;
 7191
 7192        branch.Count -= removals;
 7193
 7194        if (branch.Count < _load && branch.Count != 0)
 7195          ShrinkChild(branch.Parent, branch.Index);
 7196      }
 7197
 7198      return removals;
 7199    }
 7200
 7201    #endregion
 7202
 7203    #region Remove
 7204
 7205    /// <summary>Removes all the items qualified by the delegate.</summary>
 7206    /// <param name="where">The predicate to qualify removals.</param>
 7207    public void Remove(Predicate<T> where)
 7208    {
 7209      this.Remove(this._top, where);
 7210      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 7211    }
 7212
 7213    /// <summary>Recursive version of the remove method.</summary>
 7214    /// <param name="node">The current node of traversal.</param>
 7215    /// <param name="where">The predicate to qualify removals.</param>
 7216    internal int Remove(Node node, Predicate<T> where)
 7217    {
 7218      int removals = 0;
 7219      if (node is Leaf)
 7220      {
 7221        Leaf leaf = node as Leaf;
 7222        while (leaf.Head is not null && where(leaf.Head.Value))
 7223        {
 7224          leaf.Head = leaf.Head.Next;
 7225          removals++;
 7226        }
 7227        if (leaf.Head is not null)
 7228        {
 7229          Leaf.Node list = leaf.Head;
 7230          while (list.Next is not null)
 7231          {
 7232            if (where(list.Next.Value))
 7233            {
 7234              list.Next = list.Next.Next;
 7235              removals++;
 7236            }
 7237          }
 7238        }
 7239
 7240        leaf.Count -= removals;
 7241        return removals;
 7242      }
 7243      else
 7244      {
 7245        Branch branch = node as Branch;
 7246        int skipped = 0;
 7247        for (int i = 0; i + skipped < branch.Children.Length; )
 7248        {
 7249          removals += this.Remove(branch.Children[i], where);
 7250          if (branch.Children[i].Count is 0)
 7251            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 7252          else
 7253            i++;
 7254        }
 7255        Node[] newArray = new Node[branch.Children.Length - skipped];
 7256        Array.Copy(branch.Children, newArray, newArray.Length);
 7257        branch.Children = newArray;
 7258
 7259        branch.Count -= removals;
 7260
 7261        if (branch.Count < _load && branch.Count != 0)
 7262          ShrinkChild(branch.Parent, branch.Index);
 7263
 7264        return removals;
 7265      }
 7266    }
 7267
 7268    /// <summary>Removes all the items in a given space.</summary>
 7269    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 7270    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 7271    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 7272    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 7273    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 7274    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 7275    /// <returns>The number of items that were removed.</returns>
 7276    public void Remove(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3)
 7277    {
 7278      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 7279      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 7280    }
 7281    /// <summary>Removes all the items in a given space.</summary>
 7282    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 7283    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 7284    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 7285    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 7286    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 7287    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 7288    /// <returns>The number of items that were removed.</returns>
 7289    public void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 7290    {
 7291      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 7292      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 7293    }
 7294    internal int Remove(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3> bounds)
 7295    {
 7296      int removals = 0;
 7297      if (InclusionCheck(bounds, node.Bounds))
 7298      {
 7299        if (node is Leaf)
 7300        {
 7301          Leaf leaf = node as Leaf;
 7302          Leaf.Node current_node = leaf.Head;
 7303          Leaf.Node previous_node = null;
 7304          while (!(current_node is null))
 7305          {
 7306            Leaf.Node temp_previous = current_node;
 7307            if (EncapsulationCheck(bounds, LocateVector(current_node.Value)))
 7308            {
 7309              removals++;
 7310              if (current_node == leaf.Head)
 7311                leaf.Head = leaf.Head.Next;
 7312              else
 7313              {
 7314                previous_node.Next = current_node.Next;
 7315                temp_previous = previous_node;
 7316              }
 7317            }
 7318            previous_node = temp_previous;
 7319            current_node = current_node.Next;
 7320          }
 7321          leaf.Count -= removals;
 7322        }
 7323        else
 7324        {
 7325          Branch branch = node as Branch;
 7326          int skipped = 0;
 7327          for (int i = 0; i + skipped < branch.Children.Length; )
 7328          {
 7329            removals += this.Remove(branch.Children[i], bounds);
 7330            if (branch.Children[i].Count is 0)
 7331              branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 7332            else
 7333              i++;
 7334          }
 7335          Node[] newArray = new Node[branch.Children.Length - skipped];
 7336          Array.Copy(branch.Children, newArray, newArray.Length);
 7337          branch.Children = newArray;
 7338
 7339          branch.Count -= removals;
 7340          // convert this branch back into a leaf
 7341          // Note: if count is zero, it will be chopped off
 7342          if (branch.Count < _load && branch.Count > 0)
 7343            ShrinkChild(branch.Parent, branch.Index);
 7344        }
 7345      }
 7346
 7347      return removals;
 7348    }
 7349
 7350    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 7351    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 7352    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 7353    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 7354    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 7355    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 7356    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 7357    /// <param name="where">The equality constraint of the removal.</param>
 7358    public void Remove(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Predicate<T> where)
 7359    {
 7360      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3), where);
 7361      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 7362    }
 7363    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 7364    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 7365    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 7366    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 7367    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 7368    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 7369    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 7370    /// <param name="where">The equality constraint of the removal.</param>
 7371    public void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 7372    {
 7373      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3), where);
 7374      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 7375    }
 7376    internal int Remove(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3> bounds, Predicate<T> where)
 7377    {
 7378      if (!InclusionCheck(node.Bounds, bounds))
 7379        return 0;
 7380      int removals = 0;
 7381      if (node is Leaf)
 7382      {
 7383        Leaf leaf = node as Leaf;
 7384        Leaf.Node current = leaf.Head;
 7385        Leaf.Node previous = null;
 7386        while (current is not null)
 7387        {
 7388          if (this.EncapsulationCheck(bounds, LocateVector(current.Value)) && where(current.Value))
 7389          {
 7390            removals++;
 7391            if (previous is null)
 7392            {
 7393              leaf.Head = current.Next;
 7394              goto HeadRemoved;
 7395            }
 7396            else
 7397              previous.Next = current.Next;
 7398          }
 7399          previous = current;
 7400        HeadRemoved:
 7401          current = current.Next;
 7402        }
 7403
 7404        leaf.Count -= removals;
 7405        return removals;
 7406      }
 7407      else
 7408      {
 7409        Branch branch = node as Branch;
 7410        int skipped = 0;
 7411        for (int i = 0; i + skipped < branch.Children.Length; )
 7412        {
 7413          removals += this.Remove(branch.Children[i], bounds, where);
 7414          if (branch.Children[i].Count is 0)
 7415            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 7416          else
 7417            i++;
 7418        }
 7419        Node[] newArray = new Node[branch.Children.Length - skipped];
 7420        Array.Copy(branch.Children, newArray, newArray.Length);
 7421        branch.Children = newArray;
 7422
 7423        node.Count -= removals;
 7424
 7425        if (node.Count < _load && node.Count != 0)
 7426          ShrinkChild(node.Parent, node.Index);
 7427
 7428        return removals;
 7429      }
 7430    }
 7431
 7432    /// <summary>Tries to remove a value.</summary>
 7433    /// <param name="value">The value to remove.</param>
 7434    /// <returns>True if successful or false if not.</returns>
 7435    public (bool Success, Exception? Exception) TryRemove(T value)
 7436    {
 7437      Remove(value);
 7438      return (true, null);
 7439    }
 7440
 7441    /// <summary>Removes all instances of a given value.</summary>
 7442    public void Remove(T removal) => Omnitree.Remove(this, removal);
 7443
 7444    /// <summary>Removes all instances of a given value.</summary>
 7445    public void Remove(T removal, Func<T, T, bool> equate) => Omnitree.Remove(this, removal, equate);
 7446
 7447    /// <summary>Removes all the items in a given space.</summary>
 7448    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 7449    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 7450    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 7451    /// <returns>The number of items that were removed.</returns>
 7452    public void Remove(Axis1 axis1
 7453      , Axis2 axis2
 7454      , Axis3 axis3
 7455      )
 7456    {
 7457      this.Remove(this._top, new Omnitree.Vector<Axis1, Axis2, Axis3>(axis1
 7458        , axis2
 7459        , axis3
 7460        ));
 7461      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 7462    }
 7463    internal int Remove(Node node, Omnitree.Vector<Axis1, Axis2, Axis3> vector)
 7464    {
 7465      int removals = 0;
 7466      if (node is Leaf)
 7467      {
 7468        Leaf leaf = node as Leaf;
 7469        Leaf.Node current_node = leaf.Head;
 7470        Leaf.Node previous_node = null;
 7471        while (!(current_node is null))
 7472        {
 7473          Leaf.Node temp_previous = current_node;
 7474          if (EqualsCheck(vector, LocateVector(current_node.Value)))
 7475          {
 7476            removals++;
 7477            if (current_node == leaf.Head)
 7478              leaf.Head = leaf.Head.Next;
 7479            else
 7480            {
 7481              previous_node.Next = current_node.Next;
 7482              temp_previous = previous_node;
 7483            }
 7484          }
 7485          previous_node = temp_previous;
 7486          current_node = current_node.Next;
 7487        }
 7488        leaf.Count -= removals;
 7489      }
 7490      else
 7491      {
 7492        Branch branch = node as Branch;
 7493        int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 7494        removals += Remove(branch[child_index], vector);
 7495        branch.Count -= removals;
 7496        // convert this branch back into a leaf
 7497        // Note: if count is zero, it will be chopped off
 7498        if (branch.Count < _load && branch.Count > 0)
 7499          ShrinkChild(branch.Parent, branch.Index);
 7500      }
 7501
 7502      return removals;
 7503    }
 7504
 7505    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 7506    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 7507    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 7508    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 7509    /// <param name="where">The equality constraint of the removal.</param>
 7510    public void Remove(Axis1 axis1, Axis2 axis2, Axis3 axis3, Predicate<T> where)
 7511    {
 7512      this.Remove(this._top, new Omnitree.Vector<Axis1, Axis2, Axis3>(axis1, axis2, axis3), where);
 7513      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 7514    }
 7515    internal int Remove(Node node, Omnitree.Vector<Axis1, Axis2, Axis3> vector, Predicate<T> where)
 7516    {
 7517      int removals = 0;
 7518      if (node is Leaf)
 7519      {
 7520        Leaf leaf = node as Leaf;
 7521        Leaf.Node current_node = leaf.Head;
 7522        Leaf.Node previous_node = null;
 7523        while (!(current_node is null))
 7524        {
 7525          Leaf.Node temp_previous = current_node;
 7526          if (EqualsCheck(vector, LocateVector(current_node.Value)) && where(current_node.Value))
 7527          {
 7528            removals++;
 7529            if (current_node == leaf.Head)
 7530              leaf.Head = leaf.Head.Next;
 7531            else
 7532            {
 7533              previous_node.Next = current_node.Next;
 7534              temp_previous = previous_node;
 7535            }
 7536          }
 7537          previous_node = temp_previous;
 7538          current_node = current_node.Next;
 7539        }
 7540        leaf.Count -= removals;
 7541      }
 7542      else
 7543      {
 7544        Branch branch = node as Branch;
 7545        int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 7546        removals += Remove(branch[child_index], vector, where);
 7547        branch.Count -= removals;
 7548        // convert this branch back into a leaf
 7549        // Note: if count is zero, it will be chopped off
 7550        if (branch.Count < _load && branch.Count > 0)
 7551          ShrinkChild(branch.Parent, branch.Index);
 7552      }
 7553      return removals;
 7554    }
 7555
 7556    #endregion
 7557
 7558    #region Stepper And IEnumerable
 7559
 7560    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 7561    /// <param name="step">The delegate to perform on every item in the tree.</param>
 7562    public void Stepper(Action<T> step) =>
 7563      this.Stepper(step, this._top);
 7564
 7565    internal void Stepper(Action<T> step, Node node)
 7566    {
 7567      if (node is Leaf)
 7568      {
 7569        Leaf.Node list = (node as Leaf).Head;
 7570        while (list is not null)
 7571        {
 7572          step(list.Value);
 7573          list = list.Next;
 7574        }
 7575      }
 7576      else
 7577      {
 7578        foreach (Node child in (node as Branch).Children)
 7579          this.Stepper(step, child);
 7580      }
 7581    }
 7582
 7583    public StepStatus StepperBreak<TStep>(TStep step = default)
 7584      where TStep : struct, IFunc<T, StepStatus> =>
 7585      StepperBreak(_top, step);
 7586
 7587    internal StepStatus StepperBreak<TStep>(Node node, TStep step)
 7588      where TStep : struct, IFunc<T, StepStatus>
 7589    {
 7590      StepStatus status = StepStatus.Continue;
 7591      if (node is Leaf leaf)
 7592      {
 7593        for (Leaf.Node list = leaf.Head; list is not null; list = list.Next)
 7594        {
 7595          if (step.Invoke(list.Value) is Break) return Break;
 7596        }
 7597      }
 7598      else if (node is Branch branch)
 7599      {
 7600        foreach (Node child in branch.Children)
 7601        {
 7602          if (StepperBreak(child, step) is Break) return Break;
 7603        }
 7604      }
 7605      return Continue;
 7606    }
 7607
 7608    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 7609    /// <param name="step">The delegate to perform on every item in the tree.</param>
 7610    public StepStatus Stepper(Func<T, StepStatus> step) =>
 7611      Stepper(step, _top);
 7612
 7613    internal StepStatus Stepper(Func<T, StepStatus> step, Node node)
 7614    {
 7615      StepStatus status = StepStatus.Continue;
 7616      if (node is Leaf)
 7617      {
 7618        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 7619          if ((status = step(list.Value)) != StepStatus.Continue)
 7620            break;
 7621      }
 7622      else
 7623      {
 7624        foreach (Node child in (node as Branch).Children)
 7625          if ((status = Stepper(step, child)) != StepStatus.Continue)
 7626            break;
 7627      }
 7628      return status;
 7629    }
 7630
 7631    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 7632    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 7633    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 7634    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 7635    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 7636    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 7637    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 7638    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 7639    public void Stepper(Action<T> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3) =>
 7640      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 7641
 7642    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 7643    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 7644    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 7645    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 7646    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 7647    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 7648    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 7649    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 7650    public void Stepper(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> mi
 7651      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 7652
 7653    internal void Stepper(Action<T> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3> bounds)
 7654    {
 7655      if (node is Leaf)
 7656      {
 7657        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 7658          if (EncapsulationCheck(bounds, LocateVector(list.Value)))
 7659            step(list.Value);
 7660      }
 7661      else
 7662      {
 7663        foreach (Node child in (node as Branch).Children)
 7664          // optimization: stop bounds checking if space encapsulates node
 7665          if (EncapsulationCheck(bounds, child.Bounds))
 7666            this.Stepper(step, child);
 7667          else if (InclusionCheck(child.Bounds, bounds))
 7668            this.Stepper(step, child, bounds);
 7669      }
 7670    }
 7671
 7672    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 7673    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 7674    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 7675    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 7676    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 7677    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 7678    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 7679    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 7680    public StepStatus Stepper(Func<T, StepStatus> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis
 7681      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 7682
 7683    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 7684    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 7685    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 7686    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 7687    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 7688    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 7689    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 7690    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 7691    public StepStatus Stepper(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree
 7692      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 7693
 7694    internal StepStatus Stepper(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3> bounds)
 7695    {
 7696      StepStatus status = StepStatus.Continue;
 7697      if (node is Leaf)
 7698      {
 7699        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 7700          if (EncapsulationCheck(bounds, LocateVector(list.Value)) &&
 7701            (status = step(list.Value)) != StepStatus.Continue)
 7702            break;
 7703      }
 7704      else
 7705      {
 7706        foreach (Node child in (node as Branch).Children)
 7707          // optimization: stop bounds checking if space encapsulates node
 7708          if (EncapsulationCheck(bounds, child.Bounds) &&
 7709            (status = this.Stepper(step, child)) != StepStatus.Continue)
 7710            break;
 7711          else if (InclusionCheck(child.Bounds, bounds) &&
 7712            (status = this.Stepper(step, child, bounds)) != StepStatus.Continue)
 7713            break;
 7714      }
 7715      return status;
 7716    }
 7717
 7718    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 7719    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 7720    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 7721    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 7722    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 7723    public void Stepper(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3) =>
 7724      Stepper(step, _top, new Omnitree.Vector<Axis1, Axis2, Axis3>(axis1, axis2, axis3));
 7725
 7726    internal void Stepper(Action<T> step, Node node, Omnitree.Vector<Axis1, Axis2, Axis3> vector)
 7727    {
 7728      Node current = node;
 7729      while (current is not null)
 7730      {
 7731        if (current is Leaf)
 7732        {
 7733          for (Leaf.Node leaf_node = (current as Leaf).Head; leaf_node is not null; leaf_node = leaf_node.Next)
 7734            if (EqualsCheck(vector, LocateVector(leaf_node.Value)))
 7735              step(leaf_node.Value);
 7736          break;
 7737        }
 7738        else
 7739        {
 7740          Branch branch = current as Branch;
 7741          int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 7742          current = branch[child_index];
 7743        }
 7744      }
 7745    }
 7746
 7747    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 7748    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 7749    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 7750    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 7751    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 7752    public StepStatus Stepper(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3) =>
 7753      Stepper(step, _top, new Omnitree.Vector<Axis1, Axis2, Axis3>(axis1, axis2, axis3));
 7754
 7755    internal StepStatus Stepper(Func<T, StepStatus> step, Node node, Omnitree.Vector<Axis1, Axis2, Axis3> vector)
 7756    {
 7757      Node current = node;
 7758      while (current is not null)
 7759      {
 7760        if (current is Leaf)
 7761        {
 7762          for (Leaf.Node list = (current as Leaf).Head; list is not null; list = list.Next)
 7763          {
 7764            StepStatus status = StepStatus.Continue;
 7765            if (EqualsCheck(vector, LocateVector(list.Value)) &&
 7766              (status = step(list.Value)) != StepStatus.Continue)
 7767              return status;
 7768          }
 7769        }
 7770        else
 7771        {
 7772          Branch branch = current as Branch;
 7773          int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 7774          current = branch[child_index];
 7775        }
 7776      }
 7777      return StepStatus.Continue;
 7778    }
 7779
 7780    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 7781
 7782    public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 7783    {
 7784      // Note: this can be optimized.
 7785      IList<T> list = new ListLinked<T>();
 7786      Stepper(x => list.Add(x));
 7787      return list.GetEnumerator();
 7788    }
 7789
 7790    #endregion
 7791
 7792    /// <inheritdoc/>
 7793    public T[] ToArray() => throw new NotImplementedException();
 7794
 7795    #region Helpers
 7796
 7797    internal bool StraddlesLines(Omnitree.Bounds<Axis1, Axis2, Axis3> bounds, Omnitree.Vector<Axis1, Axis2, Axis3> vecto
 7798      Omnitree.StraddlesLines(bounds, vector
 7799        , _compare1
 7800        , _compare2
 7801        , _compare3
 7802        );
 7803
 7804    /// <summary>Computes the child index that contains the desired dimensions.</summary>
 7805    /// <param name="pointOfDivision">The point of division to compare against.</param>
 7806    /// <param name="vector">The dimensions to determine the child index.</param>
 7807    /// <returns>The computed child index based on the coordinates relative to the center of the node.</returns>
 7808    internal int DetermineChildIndex(Omnitree.Vector<Axis1, Axis2, Axis3> pointOfDivision, Omnitree.Vector<Axis1, Axis2,
 7809    {
 7810      int child = 0;
 7811      if (!(this._compare1(vector.Axis1, pointOfDivision.Axis1) is Less))
 7812        child += 1 << 0;
 7813      if (!(this._compare2(vector.Axis2, pointOfDivision.Axis2) is Less))
 7814        child += 1 << 1;
 7815      if (!(this._compare3(vector.Axis3, pointOfDivision.Axis3) is Less))
 7816        child += 1 << 2;
 7817      return child;
 7818    }
 7819
 7820    /// <summary>Converts a branch back into a leaf when the count is reduced.</summary>
 7821    /// <param name="parent">The parent to shrink a child of.</param>
 7822    /// <param name="child_index">The index of the child to shrink.</param>
 7823    internal void ShrinkChild(Branch parent, int child_index)
 7824    {
 7825      Leaf leaf;
 7826      Node removal = null;
 7827      if (parent is null) // top of tree
 7828      {
 7829        removal = this._top;
 7830        leaf = new Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3>.None, null, -1);
 7831        this._top = leaf;
 7832      }
 7833      else // non-top branch
 7834      {
 7835        removal = parent[child_index];
 7836        leaf = new Leaf(removal.Bounds, removal.Parent, removal.Index);
 7837        parent[child_index] = leaf;
 7838      }
 7839
 7840      this.Stepper((T step) => { leaf.Add(step); }, removal);
 7841    }
 7842
 7843    /// <summary>Reduces the counts of all the parents of a given node by a given amount.</summary>
 7844    /// <param name="parent">The starting parent of the reduction.</param>
 7845    /// <param name="reduction">The amount to reduce the parent counts by.</param>
 7846    internal void ReduceParentCounts(Node parent, int reduction)
 7847    {
 7848      IncreaseParentCounts(parent, -reduction);
 7849    }
 7850
 7851    /// <summary>Increases the counts of all the parents of a given node by a given amount.</summary>
 7852    /// <param name="parent">The starting parent of the increase.</param>
 7853    /// <param name="increase">The amount to increase the parent counts by.</param>
 7854    internal void IncreaseParentCounts(Node parent, int increase)
 7855    {
 7856      Node node = parent;
 7857      while (node is not null)
 7858      {
 7859        node.Count += increase;
 7860        node = node.Parent;
 7861      }
 7862    }
 7863
 7864    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 7865    /// <returns>True if the spaces overlap; False if not.</returns>
 7866    internal bool InclusionCheck(Omnitree.Bounds<Axis1, Axis2, Axis3> a, Omnitree.Bounds<Axis1, Axis2, Axis3> b) =>
 7867      Omnitree.InclusionCheck(a, b
 7868      , _compare1
 7869      , _compare2
 7870      , _compare3
 7871      );
 7872
 7873    /// <summary>Checks if a space encapsulates a point.</summary>
 7874    /// <returns>True if the space encapsulates the point; False if not.</returns>
 7875    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3> bounds, Omnitree.Vector<Axis1, Axis2, Axis3> v
 7876      Omnitree.EncapsulationCheck(bounds, vector
 7877      , _compare1
 7878      , _compare2
 7879      , _compare3
 7880      );
 7881
 7882    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 7883    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 7884    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3> a, Omnitree.Bounds<Axis1, Axis2, Axis3> b) =>
 7885      Omnitree.EncapsulationCheck(a, b
 7886      , _compare1
 7887      , _compare2
 7888      , _compare3
 7889      );
 7890
 7891    /// <summary>Checks for equality between two locations.</summary>
 7892    /// <returns>True if equal; False if not;</returns>
 7893    internal bool EqualsCheck(Omnitree.Vector<Axis1, Axis2, Axis3> a, Omnitree.Vector<Axis1, Axis2, Axis3> b) =>
 7894      Omnitree.EqualsCheck(a, b
 7895      , (a, b) => _compare1(a, b) is Equal
 7896      , (a, b) => _compare2(a, b) is Equal
 7897      , (a, b) => _compare3(a, b) is Equal
 7898      );
 7899
 7900    /// <summary>Gets the nearest parent that encapsulates a location.</summary>
 7901    /// <param name="node">The starting node to find the encapsulating parent of the location.</param>
 7902    /// <param name="vector">The coordinates of the value.</param>
 7903    /// <returns>The nearest node that encapsulates the given location.</returns>
 7904    internal Node GetEncapsulationParent(Node node, Omnitree.Vector<Axis1, Axis2, Axis3> vector)
 7905    {
 7906      while (node is not null && !EncapsulationCheck(node.Bounds, vector))
 7907      {
 7908        node = node.Parent;
 7909      }
 7910      return node;
 7911    }
 7912
 7913    internal Omnitree.Vector<Axis1, Axis2, Axis3> LocateVector(T value)
 7914    {
 7915      Axis1 axis1;
 7916      Axis2 axis2;
 7917      Axis3 axis3;
 7918      this._locate(value, out axis1
 7919, out axis2
 7920, out axis3
 7921);
 7922      return new Omnitree.Vector<Axis1, Axis2, Axis3>(axis1, axis2, axis3);
 7923    }
 7924
 7925    #endregion
 7926
 7927    #endregion
 7928  }
 7929
 7930  #endregion
 7931
 7932  #region 4 Dimensional
 7933
 7934  /// <summary>Inheritance base for 4D omnitrees that store points.</summary>
 7935  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 7936  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 7937  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 7938  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 7939  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 7940  public interface IOmnitreePoints<T, Axis1, Axis2, Axis3, Axis4> : IOmnitree<T, Axis1, Axis2, Axis3, Axis4>
 7941  {
 7942    #region Properties
 7943
 7944    /// <summary>Steps through the values at a given location.</summary>
 7945    /// <param name="axis1">The coordinate along the 1D axis.</param>
 7946    /// <param name="axis2">The coordinate along the 2D axis.</param>
 7947    /// <param name="axis3">The coordinate along the 3D axis.</param>
 7948    /// <param name="axis4">The coordinate along the 4D axis.</param>
 7949
 7950    /// <returns>A Stepper of the items at the given coordinates.</returns>
 7951    Action<Action<T>> this[Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4] { get; }
 7952
 7953    /// <summary>The number of dimensions in this tree.</summary>
 7954    int Dimensions { get; }
 7955
 7956    /// <summary>The delegate being used by the omnitree to locate items in 4D space.</summary>
 7957    Omnitree.Location<T, Axis1
 7958      , Axis2
 7959      , Axis3
 7960      , Axis4
 7961      > Locate { get; }
 7962
 7963    #endregion
 7964
 7965    #region Methods
 7966
 7967    /// <summary>Counts the number of items in a sub space.</summary>
 7968    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 7969    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 7970    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 7971    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 7972    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 7973    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 7974    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 7975    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 7976    /// <returns>The number of items in the provided sub space.</returns>
 7977    int CountSubSpace(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound
 7978
 7979    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 7980    void Update();
 7981    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 7982    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 7983    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 7984    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 7985    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 7986    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 7987    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 7988    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 7989    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 7990    void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound<Axis2
 7991
 7992    /// <summary>Removes all the items in a given space.</summary>
 7993    /// <param name="axis1">The coordinate along the 1D axis.</param>
 7994    /// <param name="axis2">The coordinate along the 2D axis.</param>
 7995    /// <param name="axis3">The coordinate along the 3D axis.</param>
 7996    /// <param name="axis4">The coordinate along the 4D axis.</param>
 7997    void Remove(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4);
 7998    /// <summary>Removes all the items in a given space.</summary>
 7999    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 8000    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 8001    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 8002    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 8003    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 8004    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 8005    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 8006    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 8007    void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound<Axis2
 8008    /// <summary>Removes all the items in a given space where equality is met.</summary>
 8009    /// <param name="axis1">The coordinate along the 1D axis.</param>
 8010    /// <param name="axis2">The coordinate along the 2D axis.</param>
 8011    /// <param name="axis3">The coordinate along the 3D axis.</param>
 8012    /// <param name="axis4">The coordinate along the 4D axis.</param>
 8013    /// <param name="where">The equality constraint of the removal.</param>
 8014    void Remove(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Predicate<T> where);
 8015    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 8016    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 8017    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 8018    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 8019    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 8020    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 8021    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 8022    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 8023    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 8024    /// <param name="where">The predicate constraint of the removal.</param>
 8025    void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound<Axis2
 8026
 8027    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 8028    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 8029    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 8030    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 8031    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 8032    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 8033    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 8034    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 8035    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 8036    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 8037    void Stepper(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omn
 8038    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 8039    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 8040    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 8041    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 8042    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 8043    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 8044    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 8045    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 8046    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 8047    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 8048    StepStatus Stepper(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<
 8049    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 8050    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 8051    /// <param name="axis1">The coordinate along the 1D axis.</param>
 8052    /// <param name="axis2">The coordinate along the 2D axis.</param>
 8053    /// <param name="axis3">The coordinate along the 3D axis.</param>
 8054    /// <param name="axis4">The coordinate along the 4D axis.</param>
 8055    void Stepper(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4);
 8056    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 8057    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 8058    /// <param name="axis1">The coordinate along the 1D axis.</param>
 8059    /// <param name="axis2">The coordinate along the 2D axis.</param>
 8060    /// <param name="axis3">The coordinate along the 3D axis.</param>
 8061    /// <param name="axis4">The coordinate along the 4D axis.</param>
 8062    StepStatus Stepper(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4);
 8063
 8064    #endregion
 8065  }
 8066
 8067  /// <summary>Omnitree that stores points along 4 dimensions implemented as a linked tree.</summary>
 8068  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 8069  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 8070  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 8071  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 8072  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 8073  public class OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4> : IOmnitreePoints<T, Axis1, Axis2, Axis3, Axis4>
 8074  {
 8075    internal const int _dimensions = 4;
 8076    internal static int _children_per_node = (int)BigInteger.Pow(2, 4);
 8077
 8078    internal Node _top;
 8079    internal int _naturalLogLower = 1; // caching the next time to calculate loads (lower count)
 8080    internal int _naturalLogUpper = -1; // caching the next time to calculate loads (upper count)
 8081    internal int _load; // ln(count); min = _defaultLoad
 8082    internal Omnitree.Location<T, Axis1
 8083      , Axis2
 8084      , Axis3
 8085      , Axis4
 8086      > _locate;
 8087    internal bool _defaultCompare1;
 8088    internal Func<Axis1, Axis1, CompareResult> _compare1;
 8089    internal bool _defaultCompare2;
 8090    internal Func<Axis2, Axis2, CompareResult> _compare2;
 8091    internal bool _defaultCompare3;
 8092    internal Func<Axis3, Axis3, CompareResult> _compare3;
 8093    internal bool _defaultCompare4;
 8094    internal Func<Axis4, Axis4, CompareResult> _compare4;
 8095    internal Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> _subdivisionOverride1;
 8096    internal Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> _subdivisionOverride2;
 8097    internal Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> _subdivisionOverride3;
 8098    internal Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> _subdivisionOverride4;
 8099
 8100    #region Nested Types
 8101
 8102    /// <summary>Can be a leaf or a branch.</summary>
 8103    internal abstract class Node
 8104    {
 8105      internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> Bounds;
 8106      internal Branch Parent;
 8107      internal int Index;
 8108      internal int Count;
 8109
 8110      /// <summary>The depth this node is located in the Omnitree.</summary>
 8111      internal int Depth
 8112      {
 8113        get
 8114        {
 8115          int depth = -1;
 8116          for (Node node = this; node is not null; node = node.Parent)
 8117            depth++;
 8118          return depth;
 8119        }
 8120      }
 8121
 8122      /// <summary>Constructs a node.</summary>
 8123      /// <param name="bounds">The bounds of this node.</param>
 8124      /// <param name="parent">The parent of this node.</param>
 8125      /// <param name="index">The number of values stored in this node and its children.</param>
 8126      internal Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds, Branch parent, int index)
 8127      {
 8128        Bounds = bounds;
 8129        Parent = parent;
 8130        Index = index;
 8131      }
 8132
 8133      internal Node(Node nodeToClone)
 8134      {
 8135        this.Bounds = nodeToClone.Bounds;
 8136        this.Parent = nodeToClone.Parent;
 8137        this.Index = nodeToClone.Index;
 8138        this.Count = nodeToClone.Count;
 8139      }
 8140
 8141      internal abstract Node Clone();
 8142    }
 8143
 8144    /// <summary>A branch in the tree. Only contains nodes.</summary>
 8145    internal class Branch : Node
 8146    {
 8147      internal Node[] Children;
 8148      internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> PointOfDivision;
 8149
 8150      /// <summary>Gets child by index.</summary>
 8151      /// <param name="child_index">The index of the child to get.</param>
 8152      /// <returns>The child of the given index or null if non-existent.</returns>
 8153      internal Node this[int child_index]
 8154      {
 8155        get
 8156        {
 8157          if (Children is null)
 8158            return null;
 8159          if (Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4>._children_per_node)
 8160            return Children[(int)child_index];
 8161          foreach (Node node in Children)
 8162            if (node.Index == child_index)
 8163              return node;
 8164          return null;
 8165        }
 8166        set
 8167        {
 8168          // This error check should be unnecessary... but fuck it... might as well
 8169          if (value.Index != child_index)
 8170            throw new System.Exception("Bug in Omnitree (index/property mis-match when setting a child on a branch)");
 8171
 8172          // no children yet
 8173          if (Children is null)
 8174          {
 8175            Children = â±¯(value);
 8176            return;
 8177          }
 8178          // max children overwrite
 8179          else if (this.Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4>._children_per_node)
 8180          {
 8181            Children[(int)child_index] = value;
 8182            return;
 8183          }
 8184          // non-max child overwrite
 8185          for (int i = 0; i < Children.Length; i++)
 8186            if (Children[i].Index == child_index)
 8187            {
 8188              Children[i] = value;
 8189              return;
 8190            }
 8191          // new child
 8192          Node[] newArray = new Node[Children.Length + 1];
 8193          if (newArray.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4>._children_per_node)
 8194          {
 8195            // new child resulting in a max children branch (sorting required)
 8196            for (int i = 0; i < Children.Length; i++)
 8197            {
 8198              newArray[(int)Children[i].Index] = Children[i];
 8199            }
 8200            newArray[(int)value.Index] = value;
 8201          }
 8202          else
 8203          {
 8204            // new child resulting in a non-max children branch
 8205            Array.Copy(Children, newArray, Children.Length);
 8206            newArray[newArray.Length - 1] = value;
 8207          }
 8208          this.Children = newArray;
 8209        }
 8210      }
 8211
 8212      internal Branch(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> pointOfDivision, Omnitree.Bounds<Axis1, Axis2, Axis3, 
 8213        : base(bounds, parent, index)
 8214      {
 8215        this.PointOfDivision = pointOfDivision;
 8216      }
 8217
 8218      internal Branch(Branch branchToClone) : base(branchToClone)
 8219      {
 8220        Children = branchToClone.Children.Clone() as Node[];
 8221        PointOfDivision = branchToClone.PointOfDivision;
 8222      }
 8223
 8224      internal override Node Clone() =>
 8225        new Branch(this);
 8226    }
 8227
 8228    /// <summary>A branch in the tree. Only contains items.</summary>
 8229    internal class Leaf : Node
 8230    {
 8231      internal class Node
 8232      {
 8233        internal T Value;
 8234        internal Leaf.Node Next;
 8235
 8236        internal Node(T value, Leaf.Node next)
 8237        {
 8238          Value = value;
 8239          Next = next;
 8240        }
 8241      }
 8242
 8243      internal Leaf.Node Head;
 8244
 8245      internal Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds, Branch parent, int index)
 8246        : base(bounds, parent, index)
 8247      { }
 8248
 8249      internal Leaf(Leaf leaf) : base(leaf)
 8250      {
 8251        Head = new Node(leaf.Head.Value, null);
 8252        Node a = Head;
 8253        Node b = leaf.Head;
 8254        while (b is not null)
 8255        {
 8256          a.Next = new Node(b.Next.Value, null);
 8257          a = a.Next;
 8258          b = b.Next;
 8259        }
 8260      }
 8261
 8262      internal void Add(T addition)
 8263      {
 8264        Head = new Leaf.Node(addition, Head);
 8265        this.Count++;
 8266      }
 8267
 8268      internal override OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4>.Node Clone() =>
 8269        new Leaf(this);
 8270    }
 8271
 8272    #endregion
 8273
 8274    #region Constructors
 8275
 8276    /// <summary>This constructor is for cloning purposes</summary>
 8277    internal OmnitreePointsLinked(OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4> omnitree)
 8278    {
 8279      this._top = omnitree._top.Clone();
 8280      this._load = omnitree._load;
 8281      this._locate = omnitree._locate;
 8282      this._defaultCompare1 = omnitree._defaultCompare1;
 8283      this._compare1 = omnitree._compare1;
 8284      this._defaultCompare2 = omnitree._defaultCompare2;
 8285      this._compare2 = omnitree._compare2;
 8286      this._defaultCompare3 = omnitree._defaultCompare3;
 8287      this._compare3 = omnitree._compare3;
 8288      this._defaultCompare4 = omnitree._defaultCompare4;
 8289      this._compare4 = omnitree._compare4;
 8290      this._subdivisionOverride1 = omnitree._subdivisionOverride1;
 8291      this._subdivisionOverride2 = omnitree._subdivisionOverride2;
 8292      this._subdivisionOverride3 = omnitree._subdivisionOverride3;
 8293      this._subdivisionOverride4 = omnitree._subdivisionOverride4;
 8294    }
 8295
 8296    internal OmnitreePointsLinked(
 8297      Omnitree.Location<T, Axis1, Axis2, Axis3, Axis4> locate,
 8298      bool defaultCompare1,
 8299      Func<Axis1, Axis1, CompareResult> compare1,
 8300      bool defaultCompare2,
 8301      Func<Axis2, Axis2, CompareResult> compare2,
 8302      bool defaultCompare3,
 8303      Func<Axis3, Axis3, CompareResult> compare3,
 8304      bool defaultCompare4,
 8305      Func<Axis4, Axis4, CompareResult> compare4,
 8306      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride1
 8307,
 8308      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride2
 8309,
 8310      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride3
 8311,
 8312      Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride4
 8313      )
 8314    {
 8315      if (locate is null)
 8316      {
 8317        throw new ArgumentNullException(nameof(locate));
 8318      }
 8319      if (compare1 is null)
 8320      {
 8321        throw new ArgumentNullException(nameof(compare1));
 8322      }
 8323
 8324      if (compare2 is null)
 8325      {
 8326        throw new ArgumentNullException(nameof(compare2));
 8327      }
 8328
 8329      if (compare3 is null)
 8330      {
 8331        throw new ArgumentNullException(nameof(compare3));
 8332      }
 8333
 8334      if (compare4 is null)
 8335      {
 8336        throw new ArgumentNullException(nameof(compare4));
 8337      }
 8338
 8339      this._locate = locate;
 8340      this._defaultCompare1 = defaultCompare1;
 8341      this._compare1 = compare1;
 8342      this._defaultCompare2 = defaultCompare2;
 8343      this._compare2 = compare2;
 8344      this._defaultCompare3 = defaultCompare3;
 8345      this._compare3 = compare3;
 8346      this._defaultCompare4 = defaultCompare4;
 8347      this._compare4 = compare4;
 8348      this._subdivisionOverride1 = subdivisionOverride1;
 8349      this._subdivisionOverride2 = subdivisionOverride2;
 8350      this._subdivisionOverride3 = subdivisionOverride3;
 8351      this._subdivisionOverride4 = subdivisionOverride4;
 8352      this._top = new Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>.None, null, -1);
 8353      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 8354    }
 8355
 8356    /// <summary>Constructs a new 4D omnitree that stores points.</summary>
 8357    /// <param name="locate">The delegate for locating items in 4D space.</param>
 8358
 8359    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 8360
 8361    /// <param name="compare2">The delegate for comparing values along the 2D axis.</param>
 8362
 8363    /// <param name="compare3">The delegate for comparing values along the 3D axis.</param>
 8364
 8365    /// <param name="compare4">The delegate for comparing values along the 4D axis.</param>
 8366
 8367    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 8368
 8369    /// <param name="subdivisionOverride2">The subdivision overide to be used when splitting the 2 dimension.</param>
 8370
 8371    /// <param name="subdivisionOverride3">The subdivision overide to be used when splitting the 3 dimension.</param>
 8372
 8373    /// <param name="subdivisionOverride4">The subdivision overide to be used when splitting the 4 dimension.</param>
 8374    public OmnitreePointsLinked(
 8375      Omnitree.Location<T, Axis1, Axis2, Axis3, Axis4> locate,
 8376      Func<Axis1, Axis1, CompareResult> compare1 = null,
 8377      Func<Axis2, Axis2, CompareResult> compare2 = null,
 8378      Func<Axis3, Axis3, CompareResult> compare3 = null,
 8379      Func<Axis4, Axis4, CompareResult> compare4 = null,
 8380      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride1 = null
 8381,
 8382      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride2 = null
 8383,
 8384      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride3 = null
 8385,
 8386      Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride4 = null
 8387      )
 8388      : this(
 8389        locate,
 8390        compare1 is null ? true : false,
 8391        compare1 ?? Compare,
 8392        compare2 is null ? true : false,
 8393        compare2 ?? Compare,
 8394        compare3 is null ? true : false,
 8395        compare3 ?? Compare,
 8396        compare4 is null ? true : false,
 8397        compare4 ?? Compare,
 8398        subdivisionOverride1
 8399,
 8400        subdivisionOverride2
 8401,
 8402        subdivisionOverride3
 8403,
 8404        subdivisionOverride4
 8405        ) { }
 8406
 8407    #endregion
 8408
 8409    #region Properties
 8410
 8411    /// <summary>Steps through all the items at a given coordinate.</summary>
 8412    /// <param name="axis1">The coordinate along axis 1.</param>
 8413    /// <param name="axis2">The coordinate along axis 2.</param>
 8414    /// <param name="axis3">The coordinate along axis 3.</param>
 8415    /// <param name="axis4">The coordinate along axis 4.</param>
 8416    /// <returns>The stepper for the items at the given coordinate.</returns>
 8417    public Action<Action<T>> this[Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4] =>
 8418      step => Stepper(step, axis1, axis2, axis3, axis4);
 8419
 8420    /// <summary>The number of dimensions in this tree.</summary>
 8421    public int Dimensions { get { return _dimensions; } }
 8422
 8423    /// <summary>The location function the Omnitree is using.</summary>
 8424    public Omnitree.Location<T, Axis1, Axis2, Axis3, Axis4> Locate { get { return this._locate; } }
 8425
 8426    /// <summary>The comparison function the Omnitree is using along the 1D axis.</summary>
 8427    public Func<Axis1, Axis1, CompareResult> Compare1 { get { return this._compare1; } }
 8428    /// <summary>The comparison function the Omnitree is using along the 2D axis.</summary>
 8429    public Func<Axis2, Axis2, CompareResult> Compare2 { get { return this._compare2; } }
 8430    /// <summary>The comparison function the Omnitree is using along the 3D axis.</summary>
 8431    public Func<Axis3, Axis3, CompareResult> Compare3 { get { return this._compare3; } }
 8432    /// <summary>The comparison function the Omnitree is using along the 4D axis.</summary>
 8433    public Func<Axis4, Axis4, CompareResult> Compare4 { get { return this._compare4; } }
 8434
 8435    /// <summary>The current number of items in the tree.</summary>
 8436    public int Count { get { return this._top.Count; } }
 8437
 8438    internal delegate void MaxDepthFinder(Node node, int current_depth, ref int max_depth);
 8439    /// <summary>Finds the current maximum depth of the tree. NOT AN O(1) OPERATION. Intended for educational purposes o
 8440    public int MaxDepth
 8441    {
 8442      get
 8443      {
 8444        MaxDepthFinder maxDepthFinder = null;
 8445        maxDepthFinder =
 8446          (Node node, int current_depth, ref int max_depth) =>
 8447          {
 8448            if (current_depth > max_depth)
 8449              max_depth = current_depth;
 8450            if (node is Branch)
 8451              foreach (Node child in (node as Branch).Children)
 8452                maxDepthFinder(child, current_depth + 1, ref max_depth);
 8453          };
 8454        int _max_depth = -1;
 8455        maxDepthFinder(this._top, 0, ref _max_depth);
 8456        return _max_depth;
 8457      }
 8458    }
 8459
 8460    internal delegate void NodeCountFinder(Node node, ref int current_count);
 8461    /// <summary>Counts the current number of nodes in the tree. NOT AN O(1) OPERATION. Intended for educational purpose
 8462    public int NodeCount
 8463    {
 8464      get
 8465      {
 8466        NodeCountFinder nodeCountFinder = null;
 8467        nodeCountFinder =
 8468          (Node node, ref int current_count) =>
 8469          {
 8470            current_count++;
 8471            if (node is Branch)
 8472              foreach (Node child in (node as Branch).Children)
 8473                nodeCountFinder(child, ref current_count);
 8474          };
 8475
 8476        int _current_count = 0;
 8477        nodeCountFinder(this._top, ref _current_count);
 8478        return _current_count;
 8479      }
 8480    }
 8481
 8482    internal delegate void BranchCountFinder(Node node, ref int current_count);
 8483    /// <summary>Counts the current number of branches in the tree. NOT AN O(1) OPERATION. Intended for educational purp
 8484    public int BranchCount
 8485    {
 8486      get
 8487      {
 8488        BranchCountFinder branchCountFinder = null;
 8489        branchCountFinder =
 8490          (Node node, ref int current_count) =>
 8491          {
 8492            if (node is Branch)
 8493            {
 8494              current_count++;
 8495              foreach (Node child in (node as Branch).Children)
 8496                branchCountFinder(child, ref current_count);
 8497            }
 8498          };
 8499
 8500        int _current_count = 0;
 8501        branchCountFinder(this._top, ref _current_count);
 8502        return _current_count;
 8503      }
 8504    }
 8505
 8506    internal delegate void LeafCountFinder(Node node, ref int current_count);
 8507    /// <summary>Counts the current number of leaves in the tree. NOT AN O(1) OPERATION. Intended for educational purpos
 8508    public int LeafCount
 8509    {
 8510      get
 8511      {
 8512        LeafCountFinder leafCountFinder = null;
 8513        leafCountFinder =
 8514          (Node node, ref int current_count) =>
 8515          {
 8516            if (node is Leaf)
 8517              current_count++;
 8518            else
 8519              foreach (Node child in (node as Branch).Children)
 8520                leafCountFinder(child, ref current_count);
 8521          };
 8522
 8523        int _current_count = 0;
 8524        leafCountFinder(this._top, ref _current_count);
 8525        return _current_count;
 8526      }
 8527    }
 8528
 8529    #endregion
 8530
 8531    #region Methods
 8532
 8533    #region Add
 8534
 8535
 8536    #region single
 8537
 8538    /// <summary>Tries to add a value.</summary>
 8539    /// <param name="value">The value to be added.</param>
 8540    /// <returns>True if successful or false if not.</returns>
 8541    public (bool Success, Exception? Exception) TryAdd(T value)
 8542    {
 8543      Add(value);
 8544      return (true, null);
 8545    }
 8546
 8547    /// <summary>Adds an item to the tree.</summary>
 8548    /// <param name="addition">The item to be added.</param>
 8549    public void Add(T addition)
 8550    {
 8551      if (this._top.Count is int.MaxValue)
 8552        throw new System.InvalidOperationException("(Count is int.MaxValue) max Omnitree size reached (change ints to lo
 8553
 8554      // dynamic tree sizes
 8555      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 8556
 8557      Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> location = LocateVector(addition);
 8558
 8559      // grow the first branch of the tree
 8560      if (this._top is Leaf && (this._top as Leaf).Count >= _load)
 8561      {
 8562        Leaf top = this._top as Leaf;
 8563
 8564        // create the new branch from the median values
 8565        this._top = new Branch(DetermineMedians(top), Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>.None, null, -1);
 8566
 8567        // iterate through the values and add them to the appropriate children
 8568        for (Leaf.Node list = top.Head; list is not null; list = list.Next)
 8569          Add(list.Value, this._top, LocateVector(list.Value), 0);
 8570      }
 8571
 8572      this.Add(addition, this._top, location, 0);
 8573    }
 8574
 8575    /// <summary>Recursive version of the add function.</summary>
 8576    /// <param name="addition">The item to be added.</param>
 8577    /// <param name="node">The current node for tree trversal.</param>
 8578    /// <param name="location">The location of the addition.</param>
 8579    /// <param name="depth">The current depth of iteration.</param>
 8580    internal void Add(T addition, Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> location, int depth)
 8581    {
 8582      if (node is Leaf)
 8583      {
 8584        Leaf leaf = node as Leaf;
 8585        if (depth >= _load || !(leaf.Count >= _load))
 8586        {
 8587          leaf.Add(addition);
 8588          return;
 8589        }
 8590        else
 8591        {
 8592          Branch parent = node.Parent;
 8593          int child_index = this.DetermineChildIndex(parent.PointOfDivision, location);
 8594          Branch growth = new Branch(DetermineMedians(leaf), leaf.Bounds, parent, child_index);
 8595          parent[child_index] = growth;
 8596          for (Leaf.Node list = leaf.Head; list is not null; list = list.Next)
 8597          {
 8598            Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> temp_location = LocateVector(list.Value);
 8599            if (EncapsulationCheck(growth.Bounds, temp_location))
 8600              Add(list.Value, growth, temp_location, depth);
 8601            else
 8602            {
 8603              ReduceParentCounts(parent, 1);
 8604              Add(list.Value, this._top, temp_location, depth);
 8605            }
 8606          }
 8607
 8608          Add(addition, growth, location, depth);
 8609          return;
 8610        }
 8611      }
 8612      else
 8613      {
 8614        Branch branch = node as Branch;
 8615        int child_index = this.DetermineChildIndex(branch.PointOfDivision, location); // determine the child "index" (0 
 8616        Node child_node = branch[child_index];
 8617
 8618        // null children in branches are just empty leaves
 8619        if (child_node is null)
 8620        {
 8621          Leaf new_leaf = new Leaf(DetermineChildBounds(branch, child_index), branch, child_index);
 8622          branch[child_index] = new_leaf;
 8623          new_leaf.Add(addition);
 8624        }
 8625        else
 8626          // child exists already, continue adding
 8627          Add(addition, child_node, location, depth + 1);
 8628
 8629        branch.Count++;
 8630        return;
 8631      }
 8632    }
 8633
 8634    internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> DetermineMedians(Leaf leaf)
 8635    {
 8636
 8637      Axis1 division1;
 8638      if (!(_subdivisionOverride1 is null))
 8639      {
 8640        division1 = _subdivisionOverride1(leaf.Bounds, x =>
 8641          {
 8642            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 8643            {
 8644              x(node.Value);
 8645            }
 8646          });
 8647      }
 8648      else
 8649      {
 8650        Axis1[] values = new Axis1[leaf.Count];
 8651        Leaf.Node for_current = leaf.Head;
 8652        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 8653          this._locate(for_current.Value
 8654          , out values[i]
 8655          , out _
 8656          , out _
 8657          , out _
 8658          );
 8659        if (_defaultCompare1) Array.Sort(values);
 8660        else SortQuick<Axis1>(values, this._compare1);
 8661        int index = (leaf.Count - 1) / 2;
 8662        division1 = values[index];
 8663      }
 8664
 8665      Axis2 division2;
 8666      if (!(_subdivisionOverride2 is null))
 8667      {
 8668        division2 = _subdivisionOverride2(leaf.Bounds, x =>
 8669          {
 8670            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 8671            {
 8672              x(node.Value);
 8673            }
 8674          });
 8675      }
 8676      else
 8677      {
 8678        Axis2[] values = new Axis2[leaf.Count];
 8679        Leaf.Node for_current = leaf.Head;
 8680        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 8681          this._locate(for_current.Value
 8682          , out _
 8683          , out values[i]
 8684          , out _
 8685          , out _
 8686          );
 8687        if (_defaultCompare2) Array.Sort(values);
 8688        else SortQuick<Axis2>(values, this._compare2);
 8689        int index = (leaf.Count - 1) / 2;
 8690        division2 = values[index];
 8691      }
 8692
 8693      Axis3 division3;
 8694      if (!(_subdivisionOverride3 is null))
 8695      {
 8696        division3 = _subdivisionOverride3(leaf.Bounds, x =>
 8697          {
 8698            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 8699            {
 8700              x(node.Value);
 8701            }
 8702          });
 8703      }
 8704      else
 8705      {
 8706        Axis3[] values = new Axis3[leaf.Count];
 8707        Leaf.Node for_current = leaf.Head;
 8708        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 8709          this._locate(for_current.Value
 8710          , out _
 8711          , out _
 8712          , out values[i]
 8713          , out _
 8714          );
 8715        if (_defaultCompare3) Array.Sort(values);
 8716        else SortQuick<Axis3>(values, this._compare3);
 8717        int index = (leaf.Count - 1) / 2;
 8718        division3 = values[index];
 8719      }
 8720
 8721      Axis4 division4;
 8722      if (!(_subdivisionOverride4 is null))
 8723      {
 8724        division4 = _subdivisionOverride4(leaf.Bounds, x =>
 8725          {
 8726            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 8727            {
 8728              x(node.Value);
 8729            }
 8730          });
 8731      }
 8732      else
 8733      {
 8734        Axis4[] values = new Axis4[leaf.Count];
 8735        Leaf.Node for_current = leaf.Head;
 8736        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 8737          this._locate(for_current.Value
 8738          , out _
 8739          , out _
 8740          , out _
 8741          , out values[i]
 8742          );
 8743        if (_defaultCompare4) Array.Sort(values);
 8744        else SortQuick<Axis4>(values, this._compare4);
 8745        int index = (leaf.Count - 1) / 2;
 8746        division4 = values[index];
 8747      }
 8748
 8749      return new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4>(
 8750        division1
 8751
 8752        , division2
 8753
 8754        , division3
 8755
 8756        , division4
 8757
 8758        );
 8759    }
 8760
 8761    #endregion
 8762
 8763    #region Add Helpers
 8764
 8765    internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> DetermineChildBounds(Branch branch, int child_index)
 8766    {
 8767
 8768      Omnitree.Bound<Axis4> min4, max4;
 8769      if (child_index >= 8)
 8770      {
 8771        min4 = branch.PointOfDivision.Axis4;
 8772        max4 = branch.Bounds.Max4;
 8773        child_index -= 8;
 8774      }
 8775      else
 8776      {
 8777        min4 = branch.Bounds.Min4;
 8778        max4 = branch.PointOfDivision.Axis4;
 8779      }
 8780
 8781      Omnitree.Bound<Axis3> min3, max3;
 8782      if (child_index >= 4)
 8783      {
 8784        min3 = branch.PointOfDivision.Axis3;
 8785        max3 = branch.Bounds.Max3;
 8786        child_index -= 4;
 8787      }
 8788      else
 8789      {
 8790        min3 = branch.Bounds.Min3;
 8791        max3 = branch.PointOfDivision.Axis3;
 8792      }
 8793
 8794      Omnitree.Bound<Axis2> min2, max2;
 8795      if (child_index >= 2)
 8796      {
 8797        min2 = branch.PointOfDivision.Axis2;
 8798        max2 = branch.Bounds.Max2;
 8799        child_index -= 2;
 8800      }
 8801      else
 8802      {
 8803        min2 = branch.Bounds.Min2;
 8804        max2 = branch.PointOfDivision.Axis2;
 8805      }
 8806
 8807      Omnitree.Bound<Axis1> min1, max1;
 8808      if (child_index >= 1)
 8809      {
 8810        min1 = branch.PointOfDivision.Axis1;
 8811        max1 = branch.Bounds.Max1;
 8812        child_index -= 1;
 8813      }
 8814      else
 8815      {
 8816        min1 = branch.Bounds.Min1;
 8817        max1 = branch.PointOfDivision.Axis1;
 8818      }
 8819
 8820      return new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, min4, max4);
 8821    }
 8822
 8823    #endregion
 8824
 8825    #endregion
 8826
 8827    #region Clear
 8828
 8829    /// <summary>Returns the tree to an empty state.</summary>
 8830    public void Clear()
 8831    {
 8832      this._top = new Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>.None, null, -1);
 8833      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 8834    }
 8835
 8836    #endregion
 8837
 8838    #region Clone
 8839
 8840    /// <summary>Creates a shallow clone of this data structure.</summary>
 8841    /// <returns>A shallow clone of this data structure.</returns>
 8842    public OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4> Clone()
 8843    {
 8844      return new OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4>(this);
 8845    }
 8846
 8847    #endregion
 8848
 8849    #region Count
 8850
 8851    /// <summary>Counts the number of items in a sub space.</summary>
 8852    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 8853    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 8854    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 8855    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 8856    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 8857    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 8858    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 8859    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 8860    /// <returns>The number of items in the provided sub space.</returns>
 8861    public int CountSubSpace(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 m
 8862    {
 8863      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, min
 8864    }
 8865    /// <summary>Counts the number of items in a sub space.</summary>
 8866    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 8867    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 8868    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 8869    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 8870    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 8871    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 8872    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 8873    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 8874    /// <returns>The number of items in the provided sub space.</returns>
 8875    public int CountSubSpace(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitre
 8876    {
 8877      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, min
 8878    }
 8879    /// <summary>Counts the number of items in a sub space.</summary>
 8880    /// <param name="axis1">The coordinate along the 1D axis.</param>
 8881    /// <param name="axis2">The coordinate along the 2D axis.</param>
 8882    /// <param name="axis3">The coordinate along the 3D axis.</param>
 8883    /// <param name="axis4">The coordinate along the 4D axis.</param>
 8884    /// <returns>The number of items in the provided sub space.</returns>
 8885    public int CountSubSpace(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4)
 8886    {
 8887      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(axis1, axis1, axis2, axis2, axis3, axis
 8888    }
 8889    /// <summary>Counts the number of items in a sub space.</summary>
 8890    /// <param name="axis1">The coordinate along the 1D axis.</param>
 8891    /// <param name="axis2">The coordinate along the 2D axis.</param>
 8892    /// <param name="axis3">The coordinate along the 3D axis.</param>
 8893    /// <param name="axis4">The coordinate along the 4D axis.</param>
 8894    /// <returns>The number of items in the provided sub space.</returns>
 8895    public int CountSubSpace(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3, Omni
 8896    {
 8897      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(axis1, axis1, axis2, axis2, axis3, axis
 8898    }
 8899    /// <summary>Counts the number of items in a sub space.</summary>
 8900    /// <param name="node">The current traversal node.</param>
 8901    /// <param name="bounds">The bounds of the sub space being counted.</param>
 8902    /// <returns>The number of items in the provided sub space.</returns>
 8903    internal int CountSubSpace(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds)
 8904    {
 8905      // adjust min/max values
 8906      int count = 0;
 8907      if (EncapsulationCheck(bounds, node.Bounds))
 8908        count += node.Count;
 8909      else if (node is Leaf)
 8910      {
 8911        for (Leaf.Node list = (node as Leaf).Head; list is null; list = list.Next)
 8912          if (EncapsulationCheck(bounds, LocateVector(list.Value)))
 8913            count++;
 8914      }
 8915      else
 8916      {
 8917        Branch branch = node as Branch;
 8918        if (!StraddlesLines(branch.Bounds, branch.PointOfDivision))
 8919        {
 8920          int child_index = DetermineChildIndex(branch.PointOfDivision, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4>(
 8921            , bounds.Min2.Value
 8922            , bounds.Min3.Value
 8923            , bounds.Min4.Value
 8924            ));
 8925          Node child = branch[child_index];
 8926          if (child is not null)
 8927          {
 8928            count += this.CountSubSpace(child, bounds);
 8929          }
 8930        }
 8931        else
 8932        {
 8933          foreach (Node child in (node as Branch).Children)
 8934            count += this.CountSubSpace(child, bounds);
 8935        }
 8936      }
 8937      return count;
 8938    }
 8939
 8940    #endregion
 8941
 8942    #region Update
 8943
 8944    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 8945    public void Update()
 8946    {
 8947      this.Update(this._top, 0);
 8948    }
 8949
 8950    /// <summary>Recursive version of the Update method.</summary>
 8951    /// <param name="node">The current node of iteration.</param>
 8952    /// <param name="depth">The current depth of iteration.</param>
 8953    internal int Update(Node node, int depth)
 8954    {
 8955      int removals = 0;
 8956
 8957      if (node is Leaf)
 8958      {
 8959        Leaf leaf = node as Leaf;
 8960        Leaf.Node current = leaf.Head;
 8961        Leaf.Node previous = null;
 8962        while (current is not null)
 8963        {
 8964          Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> location = LocateVector(current.Value);
 8965          if (!this.EncapsulationCheck(node.Bounds, location))
 8966          {
 8967            removals++;
 8968            T updated = current.Value;
 8969            if (previous is null)
 8970            {
 8971              leaf.Head = current.Next;
 8972              goto HeadRemoved;
 8973            }
 8974            else
 8975              previous.Next = current.Next;
 8976
 8977            Node whereToAdd = GetEncapsulationParent(node.Parent, location);
 8978
 8979            if (whereToAdd is null)
 8980              throw new System.Exception("an item was updated outside the range of the omnitree");
 8981
 8982            this.Add(updated, whereToAdd, location, whereToAdd.Depth);
 8983          }
 8984          previous = current;
 8985        HeadRemoved:
 8986          current = current.Next;
 8987        }
 8988        leaf.Count -= removals;
 8989        return removals;
 8990      }
 8991      else
 8992      {
 8993        Branch branch = node as Branch;
 8994        int skipped = 0;
 8995        for (int i = 0; i + skipped < branch.Children.Length; )
 8996        {
 8997          removals += this.Update(branch.Children[i], depth + 1);
 8998          if (branch.Children[i].Count is 0)
 8999            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 9000          else
 9001            i++;
 9002        }
 9003        Node[] newArray = new Node[branch.Children.Length - skipped];
 9004        Array.Copy(branch.Children, newArray, newArray.Length);
 9005        branch.Children = newArray;
 9006
 9007        branch.Count -= removals;
 9008
 9009        if (branch.Count < _load && branch.Count != 0)
 9010          ShrinkChild(branch.Parent, branch.Index);
 9011      }
 9012
 9013      return removals;
 9014    }
 9015
 9016    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 9017    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 9018    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 9019    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 9020    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 9021    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 9022    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 9023    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 9024    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 9025    public void Update(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4)
 9026    {
 9027      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, min4, max4), this.
 9028    }
 9029    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 9030    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 9031    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 9032    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 9033    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 9034    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 9035    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 9036    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 9037    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 9038    public void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 9039    {
 9040      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, min4, max4), this.
 9041    }
 9042    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 9043    /// <param name="axis1">The coordinate along the 1D axis.</param>
 9044    /// <param name="axis2">The coordinate along the 2D axis.</param>
 9045    /// <param name="axis3">The coordinate along the 3D axis.</param>
 9046    /// <param name="axis4">The coordinate along the 4D axis.</param>
 9047    public void Update(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4)
 9048    {
 9049      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(axis1, axis1, axis2, axis2, axis3, axis3, axis4, axis4
 9050    }
 9051    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 9052    /// <param name="axis1">The coordinate along the 1D axis.</param>
 9053    /// <param name="axis2">The coordinate along the 2D axis.</param>
 9054    /// <param name="axis3">The coordinate along the 3D axis.</param>
 9055    /// <param name="axis4">The coordinate along the 4D axis.</param>
 9056    public void Update(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3, Omnitree.B
 9057    {
 9058      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(axis1, axis1, axis2, axis2, axis3, axis3, axis4, axis4
 9059    }
 9060    internal int Update(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds, Node node, int depth)
 9061    {
 9062      if (!InclusionCheck(bounds, node.Bounds))
 9063        return 0;
 9064
 9065      int removals = 0;
 9066
 9067      if (node is Leaf)
 9068      {
 9069        Leaf leaf = node as Leaf;
 9070        Leaf.Node current = leaf.Head;
 9071        Leaf.Node previous = null;
 9072        while (current is not null)
 9073        {
 9074          Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> location = LocateVector(current.Value);
 9075          if (!this.EncapsulationCheck(node.Bounds, location))
 9076          {
 9077            removals++;
 9078            T updated = current.Value;
 9079            if (previous is null)
 9080            {
 9081              leaf.Head = current.Next;
 9082              goto HeadRemoved;
 9083            }
 9084            else
 9085              previous.Next = current.Next;
 9086            Node whereToAdd = GetEncapsulationParent(node.Parent, location);
 9087            if (whereToAdd is null)
 9088              throw new System.Exception("an item was updates outside the range of the omnitree");
 9089            this.Add(updated, whereToAdd, location, whereToAdd.Depth);
 9090          }
 9091          previous = current;
 9092        HeadRemoved:
 9093          current = current.Next;
 9094        }
 9095        leaf.Count -= removals;
 9096        return removals;
 9097      }
 9098      else
 9099      {
 9100        Branch branch = node as Branch;
 9101        int skipped = 0;
 9102        for (int i = 0; i + skipped < branch.Children.Length; )
 9103        {
 9104          removals += this.Update(branch.Children[i], depth + 1);
 9105          if (branch.Children[i].Count is 0)
 9106            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 9107          else
 9108            i++;
 9109        }
 9110        Node[] newArray = new Node[branch.Children.Length - skipped];
 9111        Array.Copy(branch.Children, newArray, newArray.Length);
 9112        branch.Children = newArray;
 9113
 9114        branch.Count -= removals;
 9115
 9116        if (branch.Count < _load && branch.Count != 0)
 9117          ShrinkChild(branch.Parent, branch.Index);
 9118      }
 9119
 9120      return removals;
 9121    }
 9122
 9123    #endregion
 9124
 9125    #region Remove
 9126
 9127    /// <summary>Removes all the items qualified by the delegate.</summary>
 9128    /// <param name="where">The predicate to qualify removals.</param>
 9129    public void Remove(Predicate<T> where)
 9130    {
 9131      this.Remove(this._top, where);
 9132      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 9133    }
 9134
 9135    /// <summary>Recursive version of the remove method.</summary>
 9136    /// <param name="node">The current node of traversal.</param>
 9137    /// <param name="where">The predicate to qualify removals.</param>
 9138    internal int Remove(Node node, Predicate<T> where)
 9139    {
 9140      int removals = 0;
 9141      if (node is Leaf)
 9142      {
 9143        Leaf leaf = node as Leaf;
 9144        while (leaf.Head is not null && where(leaf.Head.Value))
 9145        {
 9146          leaf.Head = leaf.Head.Next;
 9147          removals++;
 9148        }
 9149        if (leaf.Head is not null)
 9150        {
 9151          Leaf.Node list = leaf.Head;
 9152          while (list.Next is not null)
 9153          {
 9154            if (where(list.Next.Value))
 9155            {
 9156              list.Next = list.Next.Next;
 9157              removals++;
 9158            }
 9159          }
 9160        }
 9161
 9162        leaf.Count -= removals;
 9163        return removals;
 9164      }
 9165      else
 9166      {
 9167        Branch branch = node as Branch;
 9168        int skipped = 0;
 9169        for (int i = 0; i + skipped < branch.Children.Length; )
 9170        {
 9171          removals += this.Remove(branch.Children[i], where);
 9172          if (branch.Children[i].Count is 0)
 9173            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 9174          else
 9175            i++;
 9176        }
 9177        Node[] newArray = new Node[branch.Children.Length - skipped];
 9178        Array.Copy(branch.Children, newArray, newArray.Length);
 9179        branch.Children = newArray;
 9180
 9181        branch.Count -= removals;
 9182
 9183        if (branch.Count < _load && branch.Count != 0)
 9184          ShrinkChild(branch.Parent, branch.Index);
 9185
 9186        return removals;
 9187      }
 9188    }
 9189
 9190    /// <summary>Removes all the items in a given space.</summary>
 9191    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 9192    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 9193    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 9194    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 9195    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 9196    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 9197    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 9198    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 9199    /// <returns>The number of items that were removed.</returns>
 9200    public void Remove(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4)
 9201    {
 9202      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, min4, m
 9203      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 9204    }
 9205    /// <summary>Removes all the items in a given space.</summary>
 9206    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 9207    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 9208    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 9209    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 9210    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 9211    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 9212    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 9213    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 9214    /// <returns>The number of items that were removed.</returns>
 9215    public void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 9216    {
 9217      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, min4, m
 9218      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 9219    }
 9220    internal int Remove(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds)
 9221    {
 9222      int removals = 0;
 9223      if (InclusionCheck(bounds, node.Bounds))
 9224      {
 9225        if (node is Leaf)
 9226        {
 9227          Leaf leaf = node as Leaf;
 9228          Leaf.Node current_node = leaf.Head;
 9229          Leaf.Node previous_node = null;
 9230          while (!(current_node is null))
 9231          {
 9232            Leaf.Node temp_previous = current_node;
 9233            if (EncapsulationCheck(bounds, LocateVector(current_node.Value)))
 9234            {
 9235              removals++;
 9236              if (current_node == leaf.Head)
 9237                leaf.Head = leaf.Head.Next;
 9238              else
 9239              {
 9240                previous_node.Next = current_node.Next;
 9241                temp_previous = previous_node;
 9242              }
 9243            }
 9244            previous_node = temp_previous;
 9245            current_node = current_node.Next;
 9246          }
 9247          leaf.Count -= removals;
 9248        }
 9249        else
 9250        {
 9251          Branch branch = node as Branch;
 9252          int skipped = 0;
 9253          for (int i = 0; i + skipped < branch.Children.Length; )
 9254          {
 9255            removals += this.Remove(branch.Children[i], bounds);
 9256            if (branch.Children[i].Count is 0)
 9257              branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 9258            else
 9259              i++;
 9260          }
 9261          Node[] newArray = new Node[branch.Children.Length - skipped];
 9262          Array.Copy(branch.Children, newArray, newArray.Length);
 9263          branch.Children = newArray;
 9264
 9265          branch.Count -= removals;
 9266          // convert this branch back into a leaf
 9267          // Note: if count is zero, it will be chopped off
 9268          if (branch.Count < _load && branch.Count > 0)
 9269            ShrinkChild(branch.Parent, branch.Index);
 9270        }
 9271      }
 9272
 9273      return removals;
 9274    }
 9275
 9276    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 9277    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 9278    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 9279    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 9280    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 9281    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 9282    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 9283    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 9284    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 9285    /// <param name="where">The equality constraint of the removal.</param>
 9286    public void Remove(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4, P
 9287    {
 9288      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, min4, m
 9289      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 9290    }
 9291    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 9292    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 9293    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 9294    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 9295    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 9296    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 9297    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 9298    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 9299    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 9300    /// <param name="where">The equality constraint of the removal.</param>
 9301    public void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 9302    {
 9303      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, min4, m
 9304      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 9305    }
 9306    internal int Remove(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds, Predicate<T> where)
 9307    {
 9308      if (!InclusionCheck(node.Bounds, bounds))
 9309        return 0;
 9310      int removals = 0;
 9311      if (node is Leaf)
 9312      {
 9313        Leaf leaf = node as Leaf;
 9314        Leaf.Node current = leaf.Head;
 9315        Leaf.Node previous = null;
 9316        while (current is not null)
 9317        {
 9318          if (this.EncapsulationCheck(bounds, LocateVector(current.Value)) && where(current.Value))
 9319          {
 9320            removals++;
 9321            if (previous is null)
 9322            {
 9323              leaf.Head = current.Next;
 9324              goto HeadRemoved;
 9325            }
 9326            else
 9327              previous.Next = current.Next;
 9328          }
 9329          previous = current;
 9330        HeadRemoved:
 9331          current = current.Next;
 9332        }
 9333
 9334        leaf.Count -= removals;
 9335        return removals;
 9336      }
 9337      else
 9338      {
 9339        Branch branch = node as Branch;
 9340        int skipped = 0;
 9341        for (int i = 0; i + skipped < branch.Children.Length; )
 9342        {
 9343          removals += this.Remove(branch.Children[i], bounds, where);
 9344          if (branch.Children[i].Count is 0)
 9345            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 9346          else
 9347            i++;
 9348        }
 9349        Node[] newArray = new Node[branch.Children.Length - skipped];
 9350        Array.Copy(branch.Children, newArray, newArray.Length);
 9351        branch.Children = newArray;
 9352
 9353        node.Count -= removals;
 9354
 9355        if (node.Count < _load && node.Count != 0)
 9356          ShrinkChild(node.Parent, node.Index);
 9357
 9358        return removals;
 9359      }
 9360    }
 9361
 9362    /// <summary>Tries to remove a value.</summary>
 9363    /// <param name="value">The value to remove.</param>
 9364    /// <returns>True if successful or false if not.</returns>
 9365    public (bool Success, Exception? Exception) TryRemove(T value)
 9366    {
 9367      Remove(value);
 9368      return (true, null);
 9369    }
 9370
 9371    /// <summary>Removes all instances of a given value.</summary>
 9372    public void Remove(T removal) => Omnitree.Remove(this, removal);
 9373
 9374    /// <summary>Removes all instances of a given value.</summary>
 9375    public void Remove(T removal, Func<T, T, bool> equate) => Omnitree.Remove(this, removal, equate);
 9376
 9377    /// <summary>Removes all the items in a given space.</summary>
 9378    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 9379    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 9380    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 9381    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 9382    /// <returns>The number of items that were removed.</returns>
 9383    public void Remove(Axis1 axis1
 9384      , Axis2 axis2
 9385      , Axis3 axis3
 9386      , Axis4 axis4
 9387      )
 9388    {
 9389      this.Remove(this._top, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4>(axis1
 9390        , axis2
 9391        , axis3
 9392        , axis4
 9393        ));
 9394      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 9395    }
 9396    internal int Remove(Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> vector)
 9397    {
 9398      int removals = 0;
 9399      if (node is Leaf)
 9400      {
 9401        Leaf leaf = node as Leaf;
 9402        Leaf.Node current_node = leaf.Head;
 9403        Leaf.Node previous_node = null;
 9404        while (!(current_node is null))
 9405        {
 9406          Leaf.Node temp_previous = current_node;
 9407          if (EqualsCheck(vector, LocateVector(current_node.Value)))
 9408          {
 9409            removals++;
 9410            if (current_node == leaf.Head)
 9411              leaf.Head = leaf.Head.Next;
 9412            else
 9413            {
 9414              previous_node.Next = current_node.Next;
 9415              temp_previous = previous_node;
 9416            }
 9417          }
 9418          previous_node = temp_previous;
 9419          current_node = current_node.Next;
 9420        }
 9421        leaf.Count -= removals;
 9422      }
 9423      else
 9424      {
 9425        Branch branch = node as Branch;
 9426        int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 9427        removals += Remove(branch[child_index], vector);
 9428        branch.Count -= removals;
 9429        // convert this branch back into a leaf
 9430        // Note: if count is zero, it will be chopped off
 9431        if (branch.Count < _load && branch.Count > 0)
 9432          ShrinkChild(branch.Parent, branch.Index);
 9433      }
 9434
 9435      return removals;
 9436    }
 9437
 9438    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 9439    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 9440    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 9441    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 9442    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 9443    /// <param name="where">The equality constraint of the removal.</param>
 9444    public void Remove(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Predicate<T> where)
 9445    {
 9446      this.Remove(this._top, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4>(axis1, axis2, axis3, axis4), where);
 9447      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 9448    }
 9449    internal int Remove(Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> vector, Predicate<T> where)
 9450    {
 9451      int removals = 0;
 9452      if (node is Leaf)
 9453      {
 9454        Leaf leaf = node as Leaf;
 9455        Leaf.Node current_node = leaf.Head;
 9456        Leaf.Node previous_node = null;
 9457        while (!(current_node is null))
 9458        {
 9459          Leaf.Node temp_previous = current_node;
 9460          if (EqualsCheck(vector, LocateVector(current_node.Value)) && where(current_node.Value))
 9461          {
 9462            removals++;
 9463            if (current_node == leaf.Head)
 9464              leaf.Head = leaf.Head.Next;
 9465            else
 9466            {
 9467              previous_node.Next = current_node.Next;
 9468              temp_previous = previous_node;
 9469            }
 9470          }
 9471          previous_node = temp_previous;
 9472          current_node = current_node.Next;
 9473        }
 9474        leaf.Count -= removals;
 9475      }
 9476      else
 9477      {
 9478        Branch branch = node as Branch;
 9479        int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 9480        removals += Remove(branch[child_index], vector, where);
 9481        branch.Count -= removals;
 9482        // convert this branch back into a leaf
 9483        // Note: if count is zero, it will be chopped off
 9484        if (branch.Count < _load && branch.Count > 0)
 9485          ShrinkChild(branch.Parent, branch.Index);
 9486      }
 9487      return removals;
 9488    }
 9489
 9490    #endregion
 9491
 9492    #region Stepper And IEnumerable
 9493
 9494    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 9495    /// <param name="step">The delegate to perform on every item in the tree.</param>
 9496    public void Stepper(Action<T> step) =>
 9497      this.Stepper(step, this._top);
 9498
 9499    internal void Stepper(Action<T> step, Node node)
 9500    {
 9501      if (node is Leaf)
 9502      {
 9503        Leaf.Node list = (node as Leaf).Head;
 9504        while (list is not null)
 9505        {
 9506          step(list.Value);
 9507          list = list.Next;
 9508        }
 9509      }
 9510      else
 9511      {
 9512        foreach (Node child in (node as Branch).Children)
 9513          this.Stepper(step, child);
 9514      }
 9515    }
 9516
 9517    public StepStatus StepperBreak<TStep>(TStep step = default)
 9518      where TStep : struct, IFunc<T, StepStatus> =>
 9519      StepperBreak(_top, step);
 9520
 9521    internal StepStatus StepperBreak<TStep>(Node node, TStep step)
 9522      where TStep : struct, IFunc<T, StepStatus>
 9523    {
 9524      StepStatus status = StepStatus.Continue;
 9525      if (node is Leaf leaf)
 9526      {
 9527        for (Leaf.Node list = leaf.Head; list is not null; list = list.Next)
 9528        {
 9529          if (step.Invoke(list.Value) is Break) return Break;
 9530        }
 9531      }
 9532      else if (node is Branch branch)
 9533      {
 9534        foreach (Node child in branch.Children)
 9535        {
 9536          if (StepperBreak(child, step) is Break) return Break;
 9537        }
 9538      }
 9539      return Continue;
 9540    }
 9541
 9542    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 9543    /// <param name="step">The delegate to perform on every item in the tree.</param>
 9544    public StepStatus Stepper(Func<T, StepStatus> step) =>
 9545      Stepper(step, _top);
 9546
 9547    internal StepStatus Stepper(Func<T, StepStatus> step, Node node)
 9548    {
 9549      StepStatus status = StepStatus.Continue;
 9550      if (node is Leaf)
 9551      {
 9552        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 9553          if ((status = step(list.Value)) != StepStatus.Continue)
 9554            break;
 9555      }
 9556      else
 9557      {
 9558        foreach (Node child in (node as Branch).Children)
 9559          if ((status = Stepper(step, child)) != StepStatus.Continue)
 9560            break;
 9561      }
 9562      return status;
 9563    }
 9564
 9565    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 9566    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 9567    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 9568    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 9569    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 9570    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 9571    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 9572    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 9573    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 9574    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 9575    public void Stepper(Action<T> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 mi
 9576      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, min4, max4
 9577
 9578    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 9579    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 9580    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 9581    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 9582    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 9583    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 9584    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 9585    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 9586    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 9587    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 9588    public void Stepper(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> mi
 9589      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, min4, max4
 9590
 9591    internal void Stepper(Action<T> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds)
 9592    {
 9593      if (node is Leaf)
 9594      {
 9595        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 9596          if (EncapsulationCheck(bounds, LocateVector(list.Value)))
 9597            step(list.Value);
 9598      }
 9599      else
 9600      {
 9601        foreach (Node child in (node as Branch).Children)
 9602          // optimization: stop bounds checking if space encapsulates node
 9603          if (EncapsulationCheck(bounds, child.Bounds))
 9604            this.Stepper(step, child);
 9605          else if (InclusionCheck(child.Bounds, bounds))
 9606            this.Stepper(step, child, bounds);
 9607      }
 9608    }
 9609
 9610    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 9611    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 9612    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 9613    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 9614    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 9615    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 9616    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 9617    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 9618    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 9619    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 9620    public StepStatus Stepper(Func<T, StepStatus> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis
 9621      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, min4, max4
 9622
 9623    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 9624    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 9625    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 9626    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 9627    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 9628    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 9629    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 9630    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 9631    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 9632    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 9633    public StepStatus Stepper(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree
 9634      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, min4, max4
 9635
 9636    internal StepStatus Stepper(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds)
 9637    {
 9638      StepStatus status = StepStatus.Continue;
 9639      if (node is Leaf)
 9640      {
 9641        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 9642          if (EncapsulationCheck(bounds, LocateVector(list.Value)) &&
 9643            (status = step(list.Value)) != StepStatus.Continue)
 9644            break;
 9645      }
 9646      else
 9647      {
 9648        foreach (Node child in (node as Branch).Children)
 9649          // optimization: stop bounds checking if space encapsulates node
 9650          if (EncapsulationCheck(bounds, child.Bounds) &&
 9651            (status = this.Stepper(step, child)) != StepStatus.Continue)
 9652            break;
 9653          else if (InclusionCheck(child.Bounds, bounds) &&
 9654            (status = this.Stepper(step, child, bounds)) != StepStatus.Continue)
 9655            break;
 9656      }
 9657      return status;
 9658    }
 9659
 9660    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 9661    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 9662    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 9663    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 9664    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 9665    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 9666    public void Stepper(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4) =>
 9667      Stepper(step, _top, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4>(axis1, axis2, axis3, axis4));
 9668
 9669    internal void Stepper(Action<T> step, Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> vector)
 9670    {
 9671      Node current = node;
 9672      while (current is not null)
 9673      {
 9674        if (current is Leaf)
 9675        {
 9676          for (Leaf.Node leaf_node = (current as Leaf).Head; leaf_node is not null; leaf_node = leaf_node.Next)
 9677            if (EqualsCheck(vector, LocateVector(leaf_node.Value)))
 9678              step(leaf_node.Value);
 9679          break;
 9680        }
 9681        else
 9682        {
 9683          Branch branch = current as Branch;
 9684          int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 9685          current = branch[child_index];
 9686        }
 9687      }
 9688    }
 9689
 9690    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 9691    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 9692    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 9693    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 9694    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 9695    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 9696    public StepStatus Stepper(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4) =>
 9697      Stepper(step, _top, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4>(axis1, axis2, axis3, axis4));
 9698
 9699    internal StepStatus Stepper(Func<T, StepStatus> step, Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> vector)
 9700    {
 9701      Node current = node;
 9702      while (current is not null)
 9703      {
 9704        if (current is Leaf)
 9705        {
 9706          for (Leaf.Node list = (current as Leaf).Head; list is not null; list = list.Next)
 9707          {
 9708            StepStatus status = StepStatus.Continue;
 9709            if (EqualsCheck(vector, LocateVector(list.Value)) &&
 9710              (status = step(list.Value)) != StepStatus.Continue)
 9711              return status;
 9712          }
 9713        }
 9714        else
 9715        {
 9716          Branch branch = current as Branch;
 9717          int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 9718          current = branch[child_index];
 9719        }
 9720      }
 9721      return StepStatus.Continue;
 9722    }
 9723
 9724    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 9725
 9726    public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 9727    {
 9728      // Note: this can be optimized.
 9729      IList<T> list = new ListLinked<T>();
 9730      Stepper(x => list.Add(x));
 9731      return list.GetEnumerator();
 9732    }
 9733
 9734    #endregion
 9735
 9736    /// <inheritdoc/>
 9737    public T[] ToArray() => throw new NotImplementedException();
 9738
 9739    #region Helpers
 9740
 9741    internal bool StraddlesLines(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds, Omnitree.Vector<Axis1, Axis2, Axis3
 9742      Omnitree.StraddlesLines(bounds, vector
 9743        , _compare1
 9744        , _compare2
 9745        , _compare3
 9746        , _compare4
 9747        );
 9748
 9749    /// <summary>Computes the child index that contains the desired dimensions.</summary>
 9750    /// <param name="pointOfDivision">The point of division to compare against.</param>
 9751    /// <param name="vector">The dimensions to determine the child index.</param>
 9752    /// <returns>The computed child index based on the coordinates relative to the center of the node.</returns>
 9753    internal int DetermineChildIndex(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> pointOfDivision, Omnitree.Vector<Axis1,
 9754    {
 9755      int child = 0;
 9756      if (!(this._compare1(vector.Axis1, pointOfDivision.Axis1) is Less))
 9757        child += 1 << 0;
 9758      if (!(this._compare2(vector.Axis2, pointOfDivision.Axis2) is Less))
 9759        child += 1 << 1;
 9760      if (!(this._compare3(vector.Axis3, pointOfDivision.Axis3) is Less))
 9761        child += 1 << 2;
 9762      if (!(this._compare4(vector.Axis4, pointOfDivision.Axis4) is Less))
 9763        child += 1 << 3;
 9764      return child;
 9765    }
 9766
 9767    /// <summary>Converts a branch back into a leaf when the count is reduced.</summary>
 9768    /// <param name="parent">The parent to shrink a child of.</param>
 9769    /// <param name="child_index">The index of the child to shrink.</param>
 9770    internal void ShrinkChild(Branch parent, int child_index)
 9771    {
 9772      Leaf leaf;
 9773      Node removal = null;
 9774      if (parent is null) // top of tree
 9775      {
 9776        removal = this._top;
 9777        leaf = new Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>.None, null, -1);
 9778        this._top = leaf;
 9779      }
 9780      else // non-top branch
 9781      {
 9782        removal = parent[child_index];
 9783        leaf = new Leaf(removal.Bounds, removal.Parent, removal.Index);
 9784        parent[child_index] = leaf;
 9785      }
 9786
 9787      this.Stepper((T step) => { leaf.Add(step); }, removal);
 9788    }
 9789
 9790    /// <summary>Reduces the counts of all the parents of a given node by a given amount.</summary>
 9791    /// <param name="parent">The starting parent of the reduction.</param>
 9792    /// <param name="reduction">The amount to reduce the parent counts by.</param>
 9793    internal void ReduceParentCounts(Node parent, int reduction)
 9794    {
 9795      IncreaseParentCounts(parent, -reduction);
 9796    }
 9797
 9798    /// <summary>Increases the counts of all the parents of a given node by a given amount.</summary>
 9799    /// <param name="parent">The starting parent of the increase.</param>
 9800    /// <param name="increase">The amount to increase the parent counts by.</param>
 9801    internal void IncreaseParentCounts(Node parent, int increase)
 9802    {
 9803      Node node = parent;
 9804      while (node is not null)
 9805      {
 9806        node.Count += increase;
 9807        node = node.Parent;
 9808      }
 9809    }
 9810
 9811    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 9812    /// <returns>True if the spaces overlap; False if not.</returns>
 9813    internal bool InclusionCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> a, Omnitree.Bounds<Axis1, Axis2, Axis3, Axi
 9814      Omnitree.InclusionCheck(a, b
 9815      , _compare1
 9816      , _compare2
 9817      , _compare3
 9818      , _compare4
 9819      );
 9820
 9821    /// <summary>Checks if a space encapsulates a point.</summary>
 9822    /// <returns>True if the space encapsulates the point; False if not.</returns>
 9823    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds, Omnitree.Vector<Axis1, Axis2, A
 9824      Omnitree.EncapsulationCheck(bounds, vector
 9825      , _compare1
 9826      , _compare2
 9827      , _compare3
 9828      , _compare4
 9829      );
 9830
 9831    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 9832    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 9833    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> a, Omnitree.Bounds<Axis1, Axis2, Axis3,
 9834      Omnitree.EncapsulationCheck(a, b
 9835      , _compare1
 9836      , _compare2
 9837      , _compare3
 9838      , _compare4
 9839      );
 9840
 9841    /// <summary>Checks for equality between two locations.</summary>
 9842    /// <returns>True if equal; False if not;</returns>
 9843    internal bool EqualsCheck(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> a, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4>
 9844      Omnitree.EqualsCheck(a, b
 9845      , (a, b) => _compare1(a, b) is Equal
 9846      , (a, b) => _compare2(a, b) is Equal
 9847      , (a, b) => _compare3(a, b) is Equal
 9848      , (a, b) => _compare4(a, b) is Equal
 9849      );
 9850
 9851    /// <summary>Gets the nearest parent that encapsulates a location.</summary>
 9852    /// <param name="node">The starting node to find the encapsulating parent of the location.</param>
 9853    /// <param name="vector">The coordinates of the value.</param>
 9854    /// <returns>The nearest node that encapsulates the given location.</returns>
 9855    internal Node GetEncapsulationParent(Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> vector)
 9856    {
 9857      while (node is not null && !EncapsulationCheck(node.Bounds, vector))
 9858      {
 9859        node = node.Parent;
 9860      }
 9861      return node;
 9862    }
 9863
 9864    internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> LocateVector(T value)
 9865    {
 9866      Axis1 axis1;
 9867      Axis2 axis2;
 9868      Axis3 axis3;
 9869      Axis4 axis4;
 9870      this._locate(value, out axis1
 9871, out axis2
 9872, out axis3
 9873, out axis4
 9874);
 9875      return new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4>(axis1, axis2, axis3, axis4);
 9876    }
 9877
 9878    #endregion
 9879
 9880    #endregion
 9881  }
 9882
 9883  #endregion
 9884
 9885  #region 5 Dimensional
 9886
 9887  /// <summary>Inheritance base for 5D omnitrees that store points.</summary>
 9888  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 9889  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 9890  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 9891  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 9892  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 9893  /// <typeparam name="Axis5">The type 5D axis.</typeparam>
 9894  public interface IOmnitreePoints<T, Axis1, Axis2, Axis3, Axis4, Axis5> : IOmnitree<T, Axis1, Axis2, Axis3, Axis4, Axis
 9895  {
 9896    #region Properties
 9897
 9898    /// <summary>Steps through the values at a given location.</summary>
 9899    /// <param name="axis1">The coordinate along the 1D axis.</param>
 9900    /// <param name="axis2">The coordinate along the 2D axis.</param>
 9901    /// <param name="axis3">The coordinate along the 3D axis.</param>
 9902    /// <param name="axis4">The coordinate along the 4D axis.</param>
 9903    /// <param name="axis5">The coordinate along the 5D axis.</param>
 9904
 9905    /// <returns>A Stepper of the items at the given coordinates.</returns>
 9906    Action<Action<T>> this[Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5] { get; }
 9907
 9908    /// <summary>The number of dimensions in this tree.</summary>
 9909    int Dimensions { get; }
 9910
 9911    /// <summary>The delegate being used by the omnitree to locate items in 5D space.</summary>
 9912    Omnitree.Location<T, Axis1
 9913      , Axis2
 9914      , Axis3
 9915      , Axis4
 9916      , Axis5
 9917      > Locate { get; }
 9918
 9919    #endregion
 9920
 9921    #region Methods
 9922
 9923    /// <summary>Counts the number of items in a sub space.</summary>
 9924    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 9925    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 9926    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 9927    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 9928    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 9929    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 9930    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 9931    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 9932    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 9933    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 9934    /// <returns>The number of items in the provided sub space.</returns>
 9935    int CountSubSpace(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound
 9936
 9937    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 9938    void Update();
 9939    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 9940    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 9941    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 9942    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 9943    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 9944    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 9945    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 9946    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 9947    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 9948    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 9949    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 9950    void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound<Axis2
 9951
 9952    /// <summary>Removes all the items in a given space.</summary>
 9953    /// <param name="axis1">The coordinate along the 1D axis.</param>
 9954    /// <param name="axis2">The coordinate along the 2D axis.</param>
 9955    /// <param name="axis3">The coordinate along the 3D axis.</param>
 9956    /// <param name="axis4">The coordinate along the 4D axis.</param>
 9957    /// <param name="axis5">The coordinate along the 5D axis.</param>
 9958    void Remove(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5);
 9959    /// <summary>Removes all the items in a given space.</summary>
 9960    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 9961    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 9962    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 9963    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 9964    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 9965    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 9966    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 9967    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 9968    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 9969    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 9970    void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound<Axis2
 9971    /// <summary>Removes all the items in a given space where equality is met.</summary>
 9972    /// <param name="axis1">The coordinate along the 1D axis.</param>
 9973    /// <param name="axis2">The coordinate along the 2D axis.</param>
 9974    /// <param name="axis3">The coordinate along the 3D axis.</param>
 9975    /// <param name="axis4">The coordinate along the 4D axis.</param>
 9976    /// <param name="axis5">The coordinate along the 5D axis.</param>
 9977    /// <param name="where">The equality constraint of the removal.</param>
 9978    void Remove(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Predicate<T> where);
 9979    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 9980    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 9981    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 9982    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 9983    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 9984    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 9985    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 9986    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 9987    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 9988    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 9989    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 9990    /// <param name="where">The predicate constraint of the removal.</param>
 9991    void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound<Axis2
 9992
 9993    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 9994    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 9995    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 9996    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 9997    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 9998    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 9999    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 10000    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 10001    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 10002    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 10003    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 10004    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 10005    void Stepper(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omn
 10006    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 10007    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 10008    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 10009    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 10010    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 10011    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 10012    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 10013    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 10014    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 10015    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 10016    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 10017    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 10018    StepStatus Stepper(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<
 10019    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 10020    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 10021    /// <param name="axis1">The coordinate along the 1D axis.</param>
 10022    /// <param name="axis2">The coordinate along the 2D axis.</param>
 10023    /// <param name="axis3">The coordinate along the 3D axis.</param>
 10024    /// <param name="axis4">The coordinate along the 4D axis.</param>
 10025    /// <param name="axis5">The coordinate along the 5D axis.</param>
 10026    void Stepper(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5);
 10027    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 10028    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 10029    /// <param name="axis1">The coordinate along the 1D axis.</param>
 10030    /// <param name="axis2">The coordinate along the 2D axis.</param>
 10031    /// <param name="axis3">The coordinate along the 3D axis.</param>
 10032    /// <param name="axis4">The coordinate along the 4D axis.</param>
 10033    /// <param name="axis5">The coordinate along the 5D axis.</param>
 10034    StepStatus Stepper(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5);
 10035
 10036    #endregion
 10037  }
 10038
 10039  /// <summary>Omnitree that stores points along 5 dimensions implemented as a linked tree.</summary>
 10040  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 10041  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 10042  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 10043  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 10044  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 10045  /// <typeparam name="Axis5">The type 5D axis.</typeparam>
 10046  public class OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5> : IOmnitreePoints<T, Axis1, Axis2, Axis3, Axis
 10047  {
 10048    internal const int _dimensions = 5;
 10049    internal static int _children_per_node = (int)BigInteger.Pow(2, 5);
 10050
 10051    internal Node _top;
 10052    internal int _naturalLogLower = 1; // caching the next time to calculate loads (lower count)
 10053    internal int _naturalLogUpper = -1; // caching the next time to calculate loads (upper count)
 10054    internal int _load; // ln(count); min = _defaultLoad
 10055    internal Omnitree.Location<T, Axis1
 10056      , Axis2
 10057      , Axis3
 10058      , Axis4
 10059      , Axis5
 10060      > _locate;
 10061    internal bool _defaultCompare1;
 10062    internal Func<Axis1, Axis1, CompareResult> _compare1;
 10063    internal bool _defaultCompare2;
 10064    internal Func<Axis2, Axis2, CompareResult> _compare2;
 10065    internal bool _defaultCompare3;
 10066    internal Func<Axis3, Axis3, CompareResult> _compare3;
 10067    internal bool _defaultCompare4;
 10068    internal Func<Axis4, Axis4, CompareResult> _compare4;
 10069    internal bool _defaultCompare5;
 10070    internal Func<Axis5, Axis5, CompareResult> _compare5;
 10071    internal Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> _subdivisionOver
 10072    internal Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> _subdivisionOver
 10073    internal Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> _subdivisionOver
 10074    internal Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> _subdivisionOver
 10075    internal Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> _subdivisionOver
 10076
 10077    #region Nested Types
 10078
 10079    /// <summary>Can be a leaf or a branch.</summary>
 10080    internal abstract class Node
 10081    {
 10082      internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> Bounds;
 10083      internal Branch Parent;
 10084      internal int Index;
 10085      internal int Count;
 10086
 10087      /// <summary>The depth this node is located in the Omnitree.</summary>
 10088      internal int Depth
 10089      {
 10090        get
 10091        {
 10092          int depth = -1;
 10093          for (Node node = this; node is not null; node = node.Parent)
 10094            depth++;
 10095          return depth;
 10096        }
 10097      }
 10098
 10099      /// <summary>Constructs a node.</summary>
 10100      /// <param name="bounds">The bounds of this node.</param>
 10101      /// <param name="parent">The parent of this node.</param>
 10102      /// <param name="index">The number of values stored in this node and its children.</param>
 10103      internal Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds, Branch parent, int index)
 10104      {
 10105        Bounds = bounds;
 10106        Parent = parent;
 10107        Index = index;
 10108      }
 10109
 10110      internal Node(Node nodeToClone)
 10111      {
 10112        this.Bounds = nodeToClone.Bounds;
 10113        this.Parent = nodeToClone.Parent;
 10114        this.Index = nodeToClone.Index;
 10115        this.Count = nodeToClone.Count;
 10116      }
 10117
 10118      internal abstract Node Clone();
 10119    }
 10120
 10121    /// <summary>A branch in the tree. Only contains nodes.</summary>
 10122    internal class Branch : Node
 10123    {
 10124      internal Node[] Children;
 10125      internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> PointOfDivision;
 10126
 10127      /// <summary>Gets child by index.</summary>
 10128      /// <param name="child_index">The index of the child to get.</param>
 10129      /// <returns>The child of the given index or null if non-existent.</returns>
 10130      internal Node this[int child_index]
 10131      {
 10132        get
 10133        {
 10134          if (Children is null)
 10135            return null;
 10136          if (Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5>._children_per_node)
 10137            return Children[(int)child_index];
 10138          foreach (Node node in Children)
 10139            if (node.Index == child_index)
 10140              return node;
 10141          return null;
 10142        }
 10143        set
 10144        {
 10145          // This error check should be unnecessary... but fuck it... might as well
 10146          if (value.Index != child_index)
 10147            throw new System.Exception("Bug in Omnitree (index/property mis-match when setting a child on a branch)");
 10148
 10149          // no children yet
 10150          if (Children is null)
 10151          {
 10152            Children = â±¯(value);
 10153            return;
 10154          }
 10155          // max children overwrite
 10156          else if (this.Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5>._children_per_node
 10157          {
 10158            Children[(int)child_index] = value;
 10159            return;
 10160          }
 10161          // non-max child overwrite
 10162          for (int i = 0; i < Children.Length; i++)
 10163            if (Children[i].Index == child_index)
 10164            {
 10165              Children[i] = value;
 10166              return;
 10167            }
 10168          // new child
 10169          Node[] newArray = new Node[Children.Length + 1];
 10170          if (newArray.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5>._children_per_node)
 10171          {
 10172            // new child resulting in a max children branch (sorting required)
 10173            for (int i = 0; i < Children.Length; i++)
 10174            {
 10175              newArray[(int)Children[i].Index] = Children[i];
 10176            }
 10177            newArray[(int)value.Index] = value;
 10178          }
 10179          else
 10180          {
 10181            // new child resulting in a non-max children branch
 10182            Array.Copy(Children, newArray, Children.Length);
 10183            newArray[newArray.Length - 1] = value;
 10184          }
 10185          this.Children = newArray;
 10186        }
 10187      }
 10188
 10189      internal Branch(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> pointOfDivision, Omnitree.Bounds<Axis1, Axis2, 
 10190        : base(bounds, parent, index)
 10191      {
 10192        this.PointOfDivision = pointOfDivision;
 10193      }
 10194
 10195      internal Branch(Branch branchToClone) : base(branchToClone)
 10196      {
 10197        Children = branchToClone.Children.Clone() as Node[];
 10198        PointOfDivision = branchToClone.PointOfDivision;
 10199      }
 10200
 10201      internal override Node Clone() =>
 10202        new Branch(this);
 10203    }
 10204
 10205    /// <summary>A branch in the tree. Only contains items.</summary>
 10206    internal class Leaf : Node
 10207    {
 10208      internal class Node
 10209      {
 10210        internal T Value;
 10211        internal Leaf.Node Next;
 10212
 10213        internal Node(T value, Leaf.Node next)
 10214        {
 10215          Value = value;
 10216          Next = next;
 10217        }
 10218      }
 10219
 10220      internal Leaf.Node Head;
 10221
 10222      internal Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds, Branch parent, int index)
 10223        : base(bounds, parent, index)
 10224      { }
 10225
 10226      internal Leaf(Leaf leaf) : base(leaf)
 10227      {
 10228        Head = new Node(leaf.Head.Value, null);
 10229        Node a = Head;
 10230        Node b = leaf.Head;
 10231        while (b is not null)
 10232        {
 10233          a.Next = new Node(b.Next.Value, null);
 10234          a = a.Next;
 10235          b = b.Next;
 10236        }
 10237      }
 10238
 10239      internal void Add(T addition)
 10240      {
 10241        Head = new Leaf.Node(addition, Head);
 10242        this.Count++;
 10243      }
 10244
 10245      internal override OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5>.Node Clone() =>
 10246        new Leaf(this);
 10247    }
 10248
 10249    #endregion
 10250
 10251    #region Constructors
 10252
 10253    /// <summary>This constructor is for cloning purposes</summary>
 10254    internal OmnitreePointsLinked(OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5> omnitree)
 10255    {
 10256      this._top = omnitree._top.Clone();
 10257      this._load = omnitree._load;
 10258      this._locate = omnitree._locate;
 10259      this._defaultCompare1 = omnitree._defaultCompare1;
 10260      this._compare1 = omnitree._compare1;
 10261      this._defaultCompare2 = omnitree._defaultCompare2;
 10262      this._compare2 = omnitree._compare2;
 10263      this._defaultCompare3 = omnitree._defaultCompare3;
 10264      this._compare3 = omnitree._compare3;
 10265      this._defaultCompare4 = omnitree._defaultCompare4;
 10266      this._compare4 = omnitree._compare4;
 10267      this._defaultCompare5 = omnitree._defaultCompare5;
 10268      this._compare5 = omnitree._compare5;
 10269      this._subdivisionOverride1 = omnitree._subdivisionOverride1;
 10270      this._subdivisionOverride2 = omnitree._subdivisionOverride2;
 10271      this._subdivisionOverride3 = omnitree._subdivisionOverride3;
 10272      this._subdivisionOverride4 = omnitree._subdivisionOverride4;
 10273      this._subdivisionOverride5 = omnitree._subdivisionOverride5;
 10274    }
 10275
 10276    internal OmnitreePointsLinked(
 10277      Omnitree.Location<T, Axis1, Axis2, Axis3, Axis4, Axis5> locate,
 10278      bool defaultCompare1,
 10279      Func<Axis1, Axis1, CompareResult> compare1,
 10280      bool defaultCompare2,
 10281      Func<Axis2, Axis2, CompareResult> compare2,
 10282      bool defaultCompare3,
 10283      Func<Axis3, Axis3, CompareResult> compare3,
 10284      bool defaultCompare4,
 10285      Func<Axis4, Axis4, CompareResult> compare4,
 10286      bool defaultCompare5,
 10287      Func<Axis5, Axis5, CompareResult> compare5,
 10288      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride1
 10289,
 10290      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride2
 10291,
 10292      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride3
 10293,
 10294      Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride4
 10295,
 10296      Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride5
 10297      )
 10298    {
 10299      if (locate is null)
 10300      {
 10301        throw new ArgumentNullException(nameof(locate));
 10302      }
 10303      if (compare1 is null)
 10304      {
 10305        throw new ArgumentNullException(nameof(compare1));
 10306      }
 10307
 10308      if (compare2 is null)
 10309      {
 10310        throw new ArgumentNullException(nameof(compare2));
 10311      }
 10312
 10313      if (compare3 is null)
 10314      {
 10315        throw new ArgumentNullException(nameof(compare3));
 10316      }
 10317
 10318      if (compare4 is null)
 10319      {
 10320        throw new ArgumentNullException(nameof(compare4));
 10321      }
 10322
 10323      if (compare5 is null)
 10324      {
 10325        throw new ArgumentNullException(nameof(compare5));
 10326      }
 10327
 10328      this._locate = locate;
 10329      this._defaultCompare1 = defaultCompare1;
 10330      this._compare1 = compare1;
 10331      this._defaultCompare2 = defaultCompare2;
 10332      this._compare2 = compare2;
 10333      this._defaultCompare3 = defaultCompare3;
 10334      this._compare3 = compare3;
 10335      this._defaultCompare4 = defaultCompare4;
 10336      this._compare4 = compare4;
 10337      this._defaultCompare5 = defaultCompare5;
 10338      this._compare5 = compare5;
 10339      this._subdivisionOverride1 = subdivisionOverride1;
 10340      this._subdivisionOverride2 = subdivisionOverride2;
 10341      this._subdivisionOverride3 = subdivisionOverride3;
 10342      this._subdivisionOverride4 = subdivisionOverride4;
 10343      this._subdivisionOverride5 = subdivisionOverride5;
 10344      this._top = new Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>.None, null, -1);
 10345      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 10346    }
 10347
 10348    /// <summary>Constructs a new 5D omnitree that stores points.</summary>
 10349    /// <param name="locate">The delegate for locating items in 5D space.</param>
 10350
 10351    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 10352
 10353    /// <param name="compare2">The delegate for comparing values along the 2D axis.</param>
 10354
 10355    /// <param name="compare3">The delegate for comparing values along the 3D axis.</param>
 10356
 10357    /// <param name="compare4">The delegate for comparing values along the 4D axis.</param>
 10358
 10359    /// <param name="compare5">The delegate for comparing values along the 5D axis.</param>
 10360
 10361    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 10362
 10363    /// <param name="subdivisionOverride2">The subdivision overide to be used when splitting the 2 dimension.</param>
 10364
 10365    /// <param name="subdivisionOverride3">The subdivision overide to be used when splitting the 3 dimension.</param>
 10366
 10367    /// <param name="subdivisionOverride4">The subdivision overide to be used when splitting the 4 dimension.</param>
 10368
 10369    /// <param name="subdivisionOverride5">The subdivision overide to be used when splitting the 5 dimension.</param>
 10370    public OmnitreePointsLinked(
 10371      Omnitree.Location<T, Axis1, Axis2, Axis3, Axis4, Axis5> locate,
 10372      Func<Axis1, Axis1, CompareResult> compare1 = null,
 10373      Func<Axis2, Axis2, CompareResult> compare2 = null,
 10374      Func<Axis3, Axis3, CompareResult> compare3 = null,
 10375      Func<Axis4, Axis4, CompareResult> compare4 = null,
 10376      Func<Axis5, Axis5, CompareResult> compare5 = null,
 10377      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride1 = 
 10378,
 10379      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride2 = 
 10380,
 10381      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride3 = 
 10382,
 10383      Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride4 = 
 10384,
 10385      Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride5 = 
 10386      )
 10387      : this(
 10388        locate,
 10389        compare1 is null ? true : false,
 10390        compare1 ?? Compare,
 10391        compare2 is null ? true : false,
 10392        compare2 ?? Compare,
 10393        compare3 is null ? true : false,
 10394        compare3 ?? Compare,
 10395        compare4 is null ? true : false,
 10396        compare4 ?? Compare,
 10397        compare5 is null ? true : false,
 10398        compare5 ?? Compare,
 10399        subdivisionOverride1
 10400,
 10401        subdivisionOverride2
 10402,
 10403        subdivisionOverride3
 10404,
 10405        subdivisionOverride4
 10406,
 10407        subdivisionOverride5
 10408        ) { }
 10409
 10410    #endregion
 10411
 10412    #region Properties
 10413
 10414    /// <summary>Steps through all the items at a given coordinate.</summary>
 10415    /// <param name="axis1">The coordinate along axis 1.</param>
 10416    /// <param name="axis2">The coordinate along axis 2.</param>
 10417    /// <param name="axis3">The coordinate along axis 3.</param>
 10418    /// <param name="axis4">The coordinate along axis 4.</param>
 10419    /// <param name="axis5">The coordinate along axis 5.</param>
 10420    /// <returns>The stepper for the items at the given coordinate.</returns>
 10421    public Action<Action<T>> this[Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5] =>
 10422      step => Stepper(step, axis1, axis2, axis3, axis4, axis5);
 10423
 10424    /// <summary>The number of dimensions in this tree.</summary>
 10425    public int Dimensions { get { return _dimensions; } }
 10426
 10427    /// <summary>The location function the Omnitree is using.</summary>
 10428    public Omnitree.Location<T, Axis1, Axis2, Axis3, Axis4, Axis5> Locate { get { return this._locate; } }
 10429
 10430    /// <summary>The comparison function the Omnitree is using along the 1D axis.</summary>
 10431    public Func<Axis1, Axis1, CompareResult> Compare1 { get { return this._compare1; } }
 10432    /// <summary>The comparison function the Omnitree is using along the 2D axis.</summary>
 10433    public Func<Axis2, Axis2, CompareResult> Compare2 { get { return this._compare2; } }
 10434    /// <summary>The comparison function the Omnitree is using along the 3D axis.</summary>
 10435    public Func<Axis3, Axis3, CompareResult> Compare3 { get { return this._compare3; } }
 10436    /// <summary>The comparison function the Omnitree is using along the 4D axis.</summary>
 10437    public Func<Axis4, Axis4, CompareResult> Compare4 { get { return this._compare4; } }
 10438    /// <summary>The comparison function the Omnitree is using along the 5D axis.</summary>
 10439    public Func<Axis5, Axis5, CompareResult> Compare5 { get { return this._compare5; } }
 10440
 10441    /// <summary>The current number of items in the tree.</summary>
 10442    public int Count { get { return this._top.Count; } }
 10443
 10444    internal delegate void MaxDepthFinder(Node node, int current_depth, ref int max_depth);
 10445    /// <summary>Finds the current maximum depth of the tree. NOT AN O(1) OPERATION. Intended for educational purposes o
 10446    public int MaxDepth
 10447    {
 10448      get
 10449      {
 10450        MaxDepthFinder maxDepthFinder = null;
 10451        maxDepthFinder =
 10452          (Node node, int current_depth, ref int max_depth) =>
 10453          {
 10454            if (current_depth > max_depth)
 10455              max_depth = current_depth;
 10456            if (node is Branch)
 10457              foreach (Node child in (node as Branch).Children)
 10458                maxDepthFinder(child, current_depth + 1, ref max_depth);
 10459          };
 10460        int _max_depth = -1;
 10461        maxDepthFinder(this._top, 0, ref _max_depth);
 10462        return _max_depth;
 10463      }
 10464    }
 10465
 10466    internal delegate void NodeCountFinder(Node node, ref int current_count);
 10467    /// <summary>Counts the current number of nodes in the tree. NOT AN O(1) OPERATION. Intended for educational purpose
 10468    public int NodeCount
 10469    {
 10470      get
 10471      {
 10472        NodeCountFinder nodeCountFinder = null;
 10473        nodeCountFinder =
 10474          (Node node, ref int current_count) =>
 10475          {
 10476            current_count++;
 10477            if (node is Branch)
 10478              foreach (Node child in (node as Branch).Children)
 10479                nodeCountFinder(child, ref current_count);
 10480          };
 10481
 10482        int _current_count = 0;
 10483        nodeCountFinder(this._top, ref _current_count);
 10484        return _current_count;
 10485      }
 10486    }
 10487
 10488    internal delegate void BranchCountFinder(Node node, ref int current_count);
 10489    /// <summary>Counts the current number of branches in the tree. NOT AN O(1) OPERATION. Intended for educational purp
 10490    public int BranchCount
 10491    {
 10492      get
 10493      {
 10494        BranchCountFinder branchCountFinder = null;
 10495        branchCountFinder =
 10496          (Node node, ref int current_count) =>
 10497          {
 10498            if (node is Branch)
 10499            {
 10500              current_count++;
 10501              foreach (Node child in (node as Branch).Children)
 10502                branchCountFinder(child, ref current_count);
 10503            }
 10504          };
 10505
 10506        int _current_count = 0;
 10507        branchCountFinder(this._top, ref _current_count);
 10508        return _current_count;
 10509      }
 10510    }
 10511
 10512    internal delegate void LeafCountFinder(Node node, ref int current_count);
 10513    /// <summary>Counts the current number of leaves in the tree. NOT AN O(1) OPERATION. Intended for educational purpos
 10514    public int LeafCount
 10515    {
 10516      get
 10517      {
 10518        LeafCountFinder leafCountFinder = null;
 10519        leafCountFinder =
 10520          (Node node, ref int current_count) =>
 10521          {
 10522            if (node is Leaf)
 10523              current_count++;
 10524            else
 10525              foreach (Node child in (node as Branch).Children)
 10526                leafCountFinder(child, ref current_count);
 10527          };
 10528
 10529        int _current_count = 0;
 10530        leafCountFinder(this._top, ref _current_count);
 10531        return _current_count;
 10532      }
 10533    }
 10534
 10535    #endregion
 10536
 10537    #region Methods
 10538
 10539    #region Add
 10540
 10541
 10542    #region single
 10543
 10544    /// <summary>Tries to add a value.</summary>
 10545    /// <param name="value">The value to be added.</param>
 10546    /// <returns>True if successful or false if not.</returns>
 10547    public (bool Success, Exception? Exception) TryAdd(T value)
 10548    {
 10549      Add(value);
 10550      return (true, null);
 10551    }
 10552
 10553    /// <summary>Adds an item to the tree.</summary>
 10554    /// <param name="addition">The item to be added.</param>
 10555    public void Add(T addition)
 10556    {
 10557      if (this._top.Count is int.MaxValue)
 10558        throw new System.InvalidOperationException("(Count is int.MaxValue) max Omnitree size reached (change ints to lo
 10559
 10560      // dynamic tree sizes
 10561      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 10562
 10563      Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> location = LocateVector(addition);
 10564
 10565      // grow the first branch of the tree
 10566      if (this._top is Leaf && (this._top as Leaf).Count >= _load)
 10567      {
 10568        Leaf top = this._top as Leaf;
 10569
 10570        // create the new branch from the median values
 10571        this._top = new Branch(DetermineMedians(top), Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>.None, null, -1)
 10572
 10573        // iterate through the values and add them to the appropriate children
 10574        for (Leaf.Node list = top.Head; list is not null; list = list.Next)
 10575          Add(list.Value, this._top, LocateVector(list.Value), 0);
 10576      }
 10577
 10578      this.Add(addition, this._top, location, 0);
 10579    }
 10580
 10581    /// <summary>Recursive version of the add function.</summary>
 10582    /// <param name="addition">The item to be added.</param>
 10583    /// <param name="node">The current node for tree trversal.</param>
 10584    /// <param name="location">The location of the addition.</param>
 10585    /// <param name="depth">The current depth of iteration.</param>
 10586    internal void Add(T addition, Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> location, int depth)
 10587    {
 10588      if (node is Leaf)
 10589      {
 10590        Leaf leaf = node as Leaf;
 10591        if (depth >= _load || !(leaf.Count >= _load))
 10592        {
 10593          leaf.Add(addition);
 10594          return;
 10595        }
 10596        else
 10597        {
 10598          Branch parent = node.Parent;
 10599          int child_index = this.DetermineChildIndex(parent.PointOfDivision, location);
 10600          Branch growth = new Branch(DetermineMedians(leaf), leaf.Bounds, parent, child_index);
 10601          parent[child_index] = growth;
 10602          for (Leaf.Node list = leaf.Head; list is not null; list = list.Next)
 10603          {
 10604            Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> temp_location = LocateVector(list.Value);
 10605            if (EncapsulationCheck(growth.Bounds, temp_location))
 10606              Add(list.Value, growth, temp_location, depth);
 10607            else
 10608            {
 10609              ReduceParentCounts(parent, 1);
 10610              Add(list.Value, this._top, temp_location, depth);
 10611            }
 10612          }
 10613
 10614          Add(addition, growth, location, depth);
 10615          return;
 10616        }
 10617      }
 10618      else
 10619      {
 10620        Branch branch = node as Branch;
 10621        int child_index = this.DetermineChildIndex(branch.PointOfDivision, location); // determine the child "index" (0 
 10622        Node child_node = branch[child_index];
 10623
 10624        // null children in branches are just empty leaves
 10625        if (child_node is null)
 10626        {
 10627          Leaf new_leaf = new Leaf(DetermineChildBounds(branch, child_index), branch, child_index);
 10628          branch[child_index] = new_leaf;
 10629          new_leaf.Add(addition);
 10630        }
 10631        else
 10632          // child exists already, continue adding
 10633          Add(addition, child_node, location, depth + 1);
 10634
 10635        branch.Count++;
 10636        return;
 10637      }
 10638    }
 10639
 10640    internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> DetermineMedians(Leaf leaf)
 10641    {
 10642
 10643      Axis1 division1;
 10644      if (!(_subdivisionOverride1 is null))
 10645      {
 10646        division1 = _subdivisionOverride1(leaf.Bounds, x =>
 10647          {
 10648            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 10649            {
 10650              x(node.Value);
 10651            }
 10652          });
 10653      }
 10654      else
 10655      {
 10656        Axis1[] values = new Axis1[leaf.Count];
 10657        Leaf.Node for_current = leaf.Head;
 10658        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 10659          this._locate(for_current.Value
 10660          , out values[i]
 10661          , out _
 10662          , out _
 10663          , out _
 10664          , out _
 10665          );
 10666        if (_defaultCompare1) Array.Sort(values);
 10667        else SortQuick<Axis1>(values, this._compare1);
 10668        int index = (leaf.Count - 1) / 2;
 10669        division1 = values[index];
 10670      }
 10671
 10672      Axis2 division2;
 10673      if (!(_subdivisionOverride2 is null))
 10674      {
 10675        division2 = _subdivisionOverride2(leaf.Bounds, x =>
 10676          {
 10677            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 10678            {
 10679              x(node.Value);
 10680            }
 10681          });
 10682      }
 10683      else
 10684      {
 10685        Axis2[] values = new Axis2[leaf.Count];
 10686        Leaf.Node for_current = leaf.Head;
 10687        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 10688          this._locate(for_current.Value
 10689          , out _
 10690          , out values[i]
 10691          , out _
 10692          , out _
 10693          , out _
 10694          );
 10695        if (_defaultCompare2) Array.Sort(values);
 10696        else SortQuick<Axis2>(values, this._compare2);
 10697        int index = (leaf.Count - 1) / 2;
 10698        division2 = values[index];
 10699      }
 10700
 10701      Axis3 division3;
 10702      if (!(_subdivisionOverride3 is null))
 10703      {
 10704        division3 = _subdivisionOverride3(leaf.Bounds, x =>
 10705          {
 10706            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 10707            {
 10708              x(node.Value);
 10709            }
 10710          });
 10711      }
 10712      else
 10713      {
 10714        Axis3[] values = new Axis3[leaf.Count];
 10715        Leaf.Node for_current = leaf.Head;
 10716        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 10717          this._locate(for_current.Value
 10718          , out _
 10719          , out _
 10720          , out values[i]
 10721          , out _
 10722          , out _
 10723          );
 10724        if (_defaultCompare3) Array.Sort(values);
 10725        else SortQuick<Axis3>(values, this._compare3);
 10726        int index = (leaf.Count - 1) / 2;
 10727        division3 = values[index];
 10728      }
 10729
 10730      Axis4 division4;
 10731      if (!(_subdivisionOverride4 is null))
 10732      {
 10733        division4 = _subdivisionOverride4(leaf.Bounds, x =>
 10734          {
 10735            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 10736            {
 10737              x(node.Value);
 10738            }
 10739          });
 10740      }
 10741      else
 10742      {
 10743        Axis4[] values = new Axis4[leaf.Count];
 10744        Leaf.Node for_current = leaf.Head;
 10745        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 10746          this._locate(for_current.Value
 10747          , out _
 10748          , out _
 10749          , out _
 10750          , out values[i]
 10751          , out _
 10752          );
 10753        if (_defaultCompare4) Array.Sort(values);
 10754        else SortQuick<Axis4>(values, this._compare4);
 10755        int index = (leaf.Count - 1) / 2;
 10756        division4 = values[index];
 10757      }
 10758
 10759      Axis5 division5;
 10760      if (!(_subdivisionOverride5 is null))
 10761      {
 10762        division5 = _subdivisionOverride5(leaf.Bounds, x =>
 10763          {
 10764            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 10765            {
 10766              x(node.Value);
 10767            }
 10768          });
 10769      }
 10770      else
 10771      {
 10772        Axis5[] values = new Axis5[leaf.Count];
 10773        Leaf.Node for_current = leaf.Head;
 10774        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 10775          this._locate(for_current.Value
 10776          , out _
 10777          , out _
 10778          , out _
 10779          , out _
 10780          , out values[i]
 10781          );
 10782        if (_defaultCompare5) Array.Sort(values);
 10783        else SortQuick<Axis5>(values, this._compare5);
 10784        int index = (leaf.Count - 1) / 2;
 10785        division5 = values[index];
 10786      }
 10787
 10788      return new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5>(
 10789        division1
 10790
 10791        , division2
 10792
 10793        , division3
 10794
 10795        , division4
 10796
 10797        , division5
 10798
 10799        );
 10800    }
 10801
 10802    #endregion
 10803
 10804    #region Add Helpers
 10805
 10806    internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> DetermineChildBounds(Branch branch, int child_index)
 10807    {
 10808
 10809      Omnitree.Bound<Axis5> min5, max5;
 10810      if (child_index >= 16)
 10811      {
 10812        min5 = branch.PointOfDivision.Axis5;
 10813        max5 = branch.Bounds.Max5;
 10814        child_index -= 16;
 10815      }
 10816      else
 10817      {
 10818        min5 = branch.Bounds.Min5;
 10819        max5 = branch.PointOfDivision.Axis5;
 10820      }
 10821
 10822      Omnitree.Bound<Axis4> min4, max4;
 10823      if (child_index >= 8)
 10824      {
 10825        min4 = branch.PointOfDivision.Axis4;
 10826        max4 = branch.Bounds.Max4;
 10827        child_index -= 8;
 10828      }
 10829      else
 10830      {
 10831        min4 = branch.Bounds.Min4;
 10832        max4 = branch.PointOfDivision.Axis4;
 10833      }
 10834
 10835      Omnitree.Bound<Axis3> min3, max3;
 10836      if (child_index >= 4)
 10837      {
 10838        min3 = branch.PointOfDivision.Axis3;
 10839        max3 = branch.Bounds.Max3;
 10840        child_index -= 4;
 10841      }
 10842      else
 10843      {
 10844        min3 = branch.Bounds.Min3;
 10845        max3 = branch.PointOfDivision.Axis3;
 10846      }
 10847
 10848      Omnitree.Bound<Axis2> min2, max2;
 10849      if (child_index >= 2)
 10850      {
 10851        min2 = branch.PointOfDivision.Axis2;
 10852        max2 = branch.Bounds.Max2;
 10853        child_index -= 2;
 10854      }
 10855      else
 10856      {
 10857        min2 = branch.Bounds.Min2;
 10858        max2 = branch.PointOfDivision.Axis2;
 10859      }
 10860
 10861      Omnitree.Bound<Axis1> min1, max1;
 10862      if (child_index >= 1)
 10863      {
 10864        min1 = branch.PointOfDivision.Axis1;
 10865        max1 = branch.Bounds.Max1;
 10866        child_index -= 1;
 10867      }
 10868      else
 10869      {
 10870        min1 = branch.Bounds.Min1;
 10871        max1 = branch.PointOfDivision.Axis1;
 10872      }
 10873
 10874      return new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3, max3, min4, max4, min5
 10875    }
 10876
 10877    #endregion
 10878
 10879    #endregion
 10880
 10881    #region Clear
 10882
 10883    /// <summary>Returns the tree to an empty state.</summary>
 10884    public void Clear()
 10885    {
 10886      this._top = new Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>.None, null, -1);
 10887      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 10888    }
 10889
 10890    #endregion
 10891
 10892    #region Clone
 10893
 10894    /// <summary>Creates a shallow clone of this data structure.</summary>
 10895    /// <returns>A shallow clone of this data structure.</returns>
 10896    public OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5> Clone()
 10897    {
 10898      return new OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5>(this);
 10899    }
 10900
 10901    #endregion
 10902
 10903    #region Count
 10904
 10905    /// <summary>Counts the number of items in a sub space.</summary>
 10906    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 10907    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 10908    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 10909    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 10910    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 10911    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 10912    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 10913    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 10914    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 10915    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 10916    /// <returns>The number of items in the provided sub space.</returns>
 10917    public int CountSubSpace(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 m
 10918    {
 10919      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3, ma
 10920    }
 10921    /// <summary>Counts the number of items in a sub space.</summary>
 10922    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 10923    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 10924    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 10925    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 10926    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 10927    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 10928    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 10929    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 10930    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 10931    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 10932    /// <returns>The number of items in the provided sub space.</returns>
 10933    public int CountSubSpace(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitre
 10934    {
 10935      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3, ma
 10936    }
 10937    /// <summary>Counts the number of items in a sub space.</summary>
 10938    /// <param name="axis1">The coordinate along the 1D axis.</param>
 10939    /// <param name="axis2">The coordinate along the 2D axis.</param>
 10940    /// <param name="axis3">The coordinate along the 3D axis.</param>
 10941    /// <param name="axis4">The coordinate along the 4D axis.</param>
 10942    /// <param name="axis5">The coordinate along the 5D axis.</param>
 10943    /// <returns>The number of items in the provided sub space.</returns>
 10944    public int CountSubSpace(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5)
 10945    {
 10946      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(axis1, axis1, axis2, axis2, axis
 10947    }
 10948    /// <summary>Counts the number of items in a sub space.</summary>
 10949    /// <param name="axis1">The coordinate along the 1D axis.</param>
 10950    /// <param name="axis2">The coordinate along the 2D axis.</param>
 10951    /// <param name="axis3">The coordinate along the 3D axis.</param>
 10952    /// <param name="axis4">The coordinate along the 4D axis.</param>
 10953    /// <param name="axis5">The coordinate along the 5D axis.</param>
 10954    /// <returns>The number of items in the provided sub space.</returns>
 10955    public int CountSubSpace(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3, Omni
 10956    {
 10957      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(axis1, axis1, axis2, axis2, axis
 10958    }
 10959    /// <summary>Counts the number of items in a sub space.</summary>
 10960    /// <param name="node">The current traversal node.</param>
 10961    /// <param name="bounds">The bounds of the sub space being counted.</param>
 10962    /// <returns>The number of items in the provided sub space.</returns>
 10963    internal int CountSubSpace(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds)
 10964    {
 10965      // adjust min/max values
 10966      int count = 0;
 10967      if (EncapsulationCheck(bounds, node.Bounds))
 10968        count += node.Count;
 10969      else if (node is Leaf)
 10970      {
 10971        for (Leaf.Node list = (node as Leaf).Head; list is null; list = list.Next)
 10972          if (EncapsulationCheck(bounds, LocateVector(list.Value)))
 10973            count++;
 10974      }
 10975      else
 10976      {
 10977        Branch branch = node as Branch;
 10978        if (!StraddlesLines(branch.Bounds, branch.PointOfDivision))
 10979        {
 10980          int child_index = DetermineChildIndex(branch.PointOfDivision, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, 
 10981            , bounds.Min2.Value
 10982            , bounds.Min3.Value
 10983            , bounds.Min4.Value
 10984            , bounds.Min5.Value
 10985            ));
 10986          Node child = branch[child_index];
 10987          if (child is not null)
 10988          {
 10989            count += this.CountSubSpace(child, bounds);
 10990          }
 10991        }
 10992        else
 10993        {
 10994          foreach (Node child in (node as Branch).Children)
 10995            count += this.CountSubSpace(child, bounds);
 10996        }
 10997      }
 10998      return count;
 10999    }
 11000
 11001    #endregion
 11002
 11003    #region Update
 11004
 11005    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 11006    public void Update()
 11007    {
 11008      this.Update(this._top, 0);
 11009    }
 11010
 11011    /// <summary>Recursive version of the Update method.</summary>
 11012    /// <param name="node">The current node of iteration.</param>
 11013    /// <param name="depth">The current depth of iteration.</param>
 11014    internal int Update(Node node, int depth)
 11015    {
 11016      int removals = 0;
 11017
 11018      if (node is Leaf)
 11019      {
 11020        Leaf leaf = node as Leaf;
 11021        Leaf.Node current = leaf.Head;
 11022        Leaf.Node previous = null;
 11023        while (current is not null)
 11024        {
 11025          Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> location = LocateVector(current.Value);
 11026          if (!this.EncapsulationCheck(node.Bounds, location))
 11027          {
 11028            removals++;
 11029            T updated = current.Value;
 11030            if (previous is null)
 11031            {
 11032              leaf.Head = current.Next;
 11033              goto HeadRemoved;
 11034            }
 11035            else
 11036              previous.Next = current.Next;
 11037
 11038            Node whereToAdd = GetEncapsulationParent(node.Parent, location);
 11039
 11040            if (whereToAdd is null)
 11041              throw new System.Exception("an item was updated outside the range of the omnitree");
 11042
 11043            this.Add(updated, whereToAdd, location, whereToAdd.Depth);
 11044          }
 11045          previous = current;
 11046        HeadRemoved:
 11047          current = current.Next;
 11048        }
 11049        leaf.Count -= removals;
 11050        return removals;
 11051      }
 11052      else
 11053      {
 11054        Branch branch = node as Branch;
 11055        int skipped = 0;
 11056        for (int i = 0; i + skipped < branch.Children.Length; )
 11057        {
 11058          removals += this.Update(branch.Children[i], depth + 1);
 11059          if (branch.Children[i].Count is 0)
 11060            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 11061          else
 11062            i++;
 11063        }
 11064        Node[] newArray = new Node[branch.Children.Length - skipped];
 11065        Array.Copy(branch.Children, newArray, newArray.Length);
 11066        branch.Children = newArray;
 11067
 11068        branch.Count -= removals;
 11069
 11070        if (branch.Count < _load && branch.Count != 0)
 11071          ShrinkChild(branch.Parent, branch.Index);
 11072      }
 11073
 11074      return removals;
 11075    }
 11076
 11077    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 11078    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 11079    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 11080    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 11081    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 11082    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 11083    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 11084    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 11085    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 11086    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 11087    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 11088    public void Update(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4, A
 11089    {
 11090      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3, max3, min4, max4,
 11091    }
 11092    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 11093    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 11094    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 11095    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 11096    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 11097    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 11098    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 11099    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 11100    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 11101    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 11102    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 11103    public void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 11104    {
 11105      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3, max3, min4, max4,
 11106    }
 11107    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 11108    /// <param name="axis1">The coordinate along the 1D axis.</param>
 11109    /// <param name="axis2">The coordinate along the 2D axis.</param>
 11110    /// <param name="axis3">The coordinate along the 3D axis.</param>
 11111    /// <param name="axis4">The coordinate along the 4D axis.</param>
 11112    /// <param name="axis5">The coordinate along the 5D axis.</param>
 11113    public void Update(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5)
 11114    {
 11115      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(axis1, axis1, axis2, axis2, axis3, axis3, axis4
 11116    }
 11117    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 11118    /// <param name="axis1">The coordinate along the 1D axis.</param>
 11119    /// <param name="axis2">The coordinate along the 2D axis.</param>
 11120    /// <param name="axis3">The coordinate along the 3D axis.</param>
 11121    /// <param name="axis4">The coordinate along the 4D axis.</param>
 11122    /// <param name="axis5">The coordinate along the 5D axis.</param>
 11123    public void Update(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3, Omnitree.B
 11124    {
 11125      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(axis1, axis1, axis2, axis2, axis3, axis3, axis4
 11126    }
 11127    internal int Update(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds, Node node, int depth)
 11128    {
 11129      if (!InclusionCheck(bounds, node.Bounds))
 11130        return 0;
 11131
 11132      int removals = 0;
 11133
 11134      if (node is Leaf)
 11135      {
 11136        Leaf leaf = node as Leaf;
 11137        Leaf.Node current = leaf.Head;
 11138        Leaf.Node previous = null;
 11139        while (current is not null)
 11140        {
 11141          Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> location = LocateVector(current.Value);
 11142          if (!this.EncapsulationCheck(node.Bounds, location))
 11143          {
 11144            removals++;
 11145            T updated = current.Value;
 11146            if (previous is null)
 11147            {
 11148              leaf.Head = current.Next;
 11149              goto HeadRemoved;
 11150            }
 11151            else
 11152              previous.Next = current.Next;
 11153            Node whereToAdd = GetEncapsulationParent(node.Parent, location);
 11154            if (whereToAdd is null)
 11155              throw new System.Exception("an item was updates outside the range of the omnitree");
 11156            this.Add(updated, whereToAdd, location, whereToAdd.Depth);
 11157          }
 11158          previous = current;
 11159        HeadRemoved:
 11160          current = current.Next;
 11161        }
 11162        leaf.Count -= removals;
 11163        return removals;
 11164      }
 11165      else
 11166      {
 11167        Branch branch = node as Branch;
 11168        int skipped = 0;
 11169        for (int i = 0; i + skipped < branch.Children.Length; )
 11170        {
 11171          removals += this.Update(branch.Children[i], depth + 1);
 11172          if (branch.Children[i].Count is 0)
 11173            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 11174          else
 11175            i++;
 11176        }
 11177        Node[] newArray = new Node[branch.Children.Length - skipped];
 11178        Array.Copy(branch.Children, newArray, newArray.Length);
 11179        branch.Children = newArray;
 11180
 11181        branch.Count -= removals;
 11182
 11183        if (branch.Count < _load && branch.Count != 0)
 11184          ShrinkChild(branch.Parent, branch.Index);
 11185      }
 11186
 11187      return removals;
 11188    }
 11189
 11190    #endregion
 11191
 11192    #region Remove
 11193
 11194    /// <summary>Removes all the items qualified by the delegate.</summary>
 11195    /// <param name="where">The predicate to qualify removals.</param>
 11196    public void Remove(Predicate<T> where)
 11197    {
 11198      this.Remove(this._top, where);
 11199      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 11200    }
 11201
 11202    /// <summary>Recursive version of the remove method.</summary>
 11203    /// <param name="node">The current node of traversal.</param>
 11204    /// <param name="where">The predicate to qualify removals.</param>
 11205    internal int Remove(Node node, Predicate<T> where)
 11206    {
 11207      int removals = 0;
 11208      if (node is Leaf)
 11209      {
 11210        Leaf leaf = node as Leaf;
 11211        while (leaf.Head is not null && where(leaf.Head.Value))
 11212        {
 11213          leaf.Head = leaf.Head.Next;
 11214          removals++;
 11215        }
 11216        if (leaf.Head is not null)
 11217        {
 11218          Leaf.Node list = leaf.Head;
 11219          while (list.Next is not null)
 11220          {
 11221            if (where(list.Next.Value))
 11222            {
 11223              list.Next = list.Next.Next;
 11224              removals++;
 11225            }
 11226          }
 11227        }
 11228
 11229        leaf.Count -= removals;
 11230        return removals;
 11231      }
 11232      else
 11233      {
 11234        Branch branch = node as Branch;
 11235        int skipped = 0;
 11236        for (int i = 0; i + skipped < branch.Children.Length; )
 11237        {
 11238          removals += this.Remove(branch.Children[i], where);
 11239          if (branch.Children[i].Count is 0)
 11240            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 11241          else
 11242            i++;
 11243        }
 11244        Node[] newArray = new Node[branch.Children.Length - skipped];
 11245        Array.Copy(branch.Children, newArray, newArray.Length);
 11246        branch.Children = newArray;
 11247
 11248        branch.Count -= removals;
 11249
 11250        if (branch.Count < _load && branch.Count != 0)
 11251          ShrinkChild(branch.Parent, branch.Index);
 11252
 11253        return removals;
 11254      }
 11255    }
 11256
 11257    /// <summary>Removes all the items in a given space.</summary>
 11258    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 11259    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 11260    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 11261    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 11262    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 11263    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 11264    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 11265    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 11266    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 11267    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 11268    /// <returns>The number of items that were removed.</returns>
 11269    public void Remove(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4, A
 11270    {
 11271      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3, max3, 
 11272      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 11273    }
 11274    /// <summary>Removes all the items in a given space.</summary>
 11275    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 11276    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 11277    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 11278    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 11279    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 11280    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 11281    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 11282    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 11283    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 11284    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 11285    /// <returns>The number of items that were removed.</returns>
 11286    public void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 11287    {
 11288      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3, max3, 
 11289      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 11290    }
 11291    internal int Remove(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds)
 11292    {
 11293      int removals = 0;
 11294      if (InclusionCheck(bounds, node.Bounds))
 11295      {
 11296        if (node is Leaf)
 11297        {
 11298          Leaf leaf = node as Leaf;
 11299          Leaf.Node current_node = leaf.Head;
 11300          Leaf.Node previous_node = null;
 11301          while (!(current_node is null))
 11302          {
 11303            Leaf.Node temp_previous = current_node;
 11304            if (EncapsulationCheck(bounds, LocateVector(current_node.Value)))
 11305            {
 11306              removals++;
 11307              if (current_node == leaf.Head)
 11308                leaf.Head = leaf.Head.Next;
 11309              else
 11310              {
 11311                previous_node.Next = current_node.Next;
 11312                temp_previous = previous_node;
 11313              }
 11314            }
 11315            previous_node = temp_previous;
 11316            current_node = current_node.Next;
 11317          }
 11318          leaf.Count -= removals;
 11319        }
 11320        else
 11321        {
 11322          Branch branch = node as Branch;
 11323          int skipped = 0;
 11324          for (int i = 0; i + skipped < branch.Children.Length; )
 11325          {
 11326            removals += this.Remove(branch.Children[i], bounds);
 11327            if (branch.Children[i].Count is 0)
 11328              branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 11329            else
 11330              i++;
 11331          }
 11332          Node[] newArray = new Node[branch.Children.Length - skipped];
 11333          Array.Copy(branch.Children, newArray, newArray.Length);
 11334          branch.Children = newArray;
 11335
 11336          branch.Count -= removals;
 11337          // convert this branch back into a leaf
 11338          // Note: if count is zero, it will be chopped off
 11339          if (branch.Count < _load && branch.Count > 0)
 11340            ShrinkChild(branch.Parent, branch.Index);
 11341        }
 11342      }
 11343
 11344      return removals;
 11345    }
 11346
 11347    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 11348    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 11349    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 11350    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 11351    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 11352    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 11353    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 11354    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 11355    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 11356    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 11357    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 11358    /// <param name="where">The equality constraint of the removal.</param>
 11359    public void Remove(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4, A
 11360    {
 11361      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3, max3, 
 11362      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 11363    }
 11364    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 11365    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 11366    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 11367    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 11368    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 11369    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 11370    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 11371    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 11372    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 11373    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 11374    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 11375    /// <param name="where">The equality constraint of the removal.</param>
 11376    public void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 11377    {
 11378      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3, max3, 
 11379      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 11380    }
 11381    internal int Remove(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds, Predicate<T> where)
 11382    {
 11383      if (!InclusionCheck(node.Bounds, bounds))
 11384        return 0;
 11385      int removals = 0;
 11386      if (node is Leaf)
 11387      {
 11388        Leaf leaf = node as Leaf;
 11389        Leaf.Node current = leaf.Head;
 11390        Leaf.Node previous = null;
 11391        while (current is not null)
 11392        {
 11393          if (this.EncapsulationCheck(bounds, LocateVector(current.Value)) && where(current.Value))
 11394          {
 11395            removals++;
 11396            if (previous is null)
 11397            {
 11398              leaf.Head = current.Next;
 11399              goto HeadRemoved;
 11400            }
 11401            else
 11402              previous.Next = current.Next;
 11403          }
 11404          previous = current;
 11405        HeadRemoved:
 11406          current = current.Next;
 11407        }
 11408
 11409        leaf.Count -= removals;
 11410        return removals;
 11411      }
 11412      else
 11413      {
 11414        Branch branch = node as Branch;
 11415        int skipped = 0;
 11416        for (int i = 0; i + skipped < branch.Children.Length; )
 11417        {
 11418          removals += this.Remove(branch.Children[i], bounds, where);
 11419          if (branch.Children[i].Count is 0)
 11420            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 11421          else
 11422            i++;
 11423        }
 11424        Node[] newArray = new Node[branch.Children.Length - skipped];
 11425        Array.Copy(branch.Children, newArray, newArray.Length);
 11426        branch.Children = newArray;
 11427
 11428        node.Count -= removals;
 11429
 11430        if (node.Count < _load && node.Count != 0)
 11431          ShrinkChild(node.Parent, node.Index);
 11432
 11433        return removals;
 11434      }
 11435    }
 11436
 11437    /// <summary>Tries to remove a value.</summary>
 11438    /// <param name="value">The value to remove.</param>
 11439    /// <returns>True if successful or false if not.</returns>
 11440    public (bool Success, Exception? Exception) TryRemove(T value)
 11441    {
 11442      Remove(value);
 11443      return (true, null);
 11444    }
 11445
 11446    /// <summary>Removes all instances of a given value.</summary>
 11447    public void Remove(T removal) => Omnitree.Remove(this, removal);
 11448
 11449    /// <summary>Removes all instances of a given value.</summary>
 11450    public void Remove(T removal, Func<T, T, bool> equate) => Omnitree.Remove(this, removal, equate);
 11451
 11452    /// <summary>Removes all the items in a given space.</summary>
 11453    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 11454    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 11455    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 11456    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 11457    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 11458    /// <returns>The number of items that were removed.</returns>
 11459    public void Remove(Axis1 axis1
 11460      , Axis2 axis2
 11461      , Axis3 axis3
 11462      , Axis4 axis4
 11463      , Axis5 axis5
 11464      )
 11465    {
 11466      this.Remove(this._top, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5>(axis1
 11467        , axis2
 11468        , axis3
 11469        , axis4
 11470        , axis5
 11471        ));
 11472      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 11473    }
 11474    internal int Remove(Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> vector)
 11475    {
 11476      int removals = 0;
 11477      if (node is Leaf)
 11478      {
 11479        Leaf leaf = node as Leaf;
 11480        Leaf.Node current_node = leaf.Head;
 11481        Leaf.Node previous_node = null;
 11482        while (!(current_node is null))
 11483        {
 11484          Leaf.Node temp_previous = current_node;
 11485          if (EqualsCheck(vector, LocateVector(current_node.Value)))
 11486          {
 11487            removals++;
 11488            if (current_node == leaf.Head)
 11489              leaf.Head = leaf.Head.Next;
 11490            else
 11491            {
 11492              previous_node.Next = current_node.Next;
 11493              temp_previous = previous_node;
 11494            }
 11495          }
 11496          previous_node = temp_previous;
 11497          current_node = current_node.Next;
 11498        }
 11499        leaf.Count -= removals;
 11500      }
 11501      else
 11502      {
 11503        Branch branch = node as Branch;
 11504        int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 11505        removals += Remove(branch[child_index], vector);
 11506        branch.Count -= removals;
 11507        // convert this branch back into a leaf
 11508        // Note: if count is zero, it will be chopped off
 11509        if (branch.Count < _load && branch.Count > 0)
 11510          ShrinkChild(branch.Parent, branch.Index);
 11511      }
 11512
 11513      return removals;
 11514    }
 11515
 11516    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 11517    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 11518    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 11519    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 11520    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 11521    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 11522    /// <param name="where">The equality constraint of the removal.</param>
 11523    public void Remove(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Predicate<T> where)
 11524    {
 11525      this.Remove(this._top, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5>(axis1, axis2, axis3, axis4, axis5), 
 11526      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 11527    }
 11528    internal int Remove(Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> vector, Predicate<T> where)
 11529    {
 11530      int removals = 0;
 11531      if (node is Leaf)
 11532      {
 11533        Leaf leaf = node as Leaf;
 11534        Leaf.Node current_node = leaf.Head;
 11535        Leaf.Node previous_node = null;
 11536        while (!(current_node is null))
 11537        {
 11538          Leaf.Node temp_previous = current_node;
 11539          if (EqualsCheck(vector, LocateVector(current_node.Value)) && where(current_node.Value))
 11540          {
 11541            removals++;
 11542            if (current_node == leaf.Head)
 11543              leaf.Head = leaf.Head.Next;
 11544            else
 11545            {
 11546              previous_node.Next = current_node.Next;
 11547              temp_previous = previous_node;
 11548            }
 11549          }
 11550          previous_node = temp_previous;
 11551          current_node = current_node.Next;
 11552        }
 11553        leaf.Count -= removals;
 11554      }
 11555      else
 11556      {
 11557        Branch branch = node as Branch;
 11558        int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 11559        removals += Remove(branch[child_index], vector, where);
 11560        branch.Count -= removals;
 11561        // convert this branch back into a leaf
 11562        // Note: if count is zero, it will be chopped off
 11563        if (branch.Count < _load && branch.Count > 0)
 11564          ShrinkChild(branch.Parent, branch.Index);
 11565      }
 11566      return removals;
 11567    }
 11568
 11569    #endregion
 11570
 11571    #region Stepper And IEnumerable
 11572
 11573    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 11574    /// <param name="step">The delegate to perform on every item in the tree.</param>
 11575    public void Stepper(Action<T> step) =>
 11576      this.Stepper(step, this._top);
 11577
 11578    internal void Stepper(Action<T> step, Node node)
 11579    {
 11580      if (node is Leaf)
 11581      {
 11582        Leaf.Node list = (node as Leaf).Head;
 11583        while (list is not null)
 11584        {
 11585          step(list.Value);
 11586          list = list.Next;
 11587        }
 11588      }
 11589      else
 11590      {
 11591        foreach (Node child in (node as Branch).Children)
 11592          this.Stepper(step, child);
 11593      }
 11594    }
 11595
 11596    public StepStatus StepperBreak<TStep>(TStep step = default)
 11597      where TStep : struct, IFunc<T, StepStatus> =>
 11598      StepperBreak(_top, step);
 11599
 11600    internal StepStatus StepperBreak<TStep>(Node node, TStep step)
 11601      where TStep : struct, IFunc<T, StepStatus>
 11602    {
 11603      StepStatus status = StepStatus.Continue;
 11604      if (node is Leaf leaf)
 11605      {
 11606        for (Leaf.Node list = leaf.Head; list is not null; list = list.Next)
 11607        {
 11608          if (step.Invoke(list.Value) is Break) return Break;
 11609        }
 11610      }
 11611      else if (node is Branch branch)
 11612      {
 11613        foreach (Node child in branch.Children)
 11614        {
 11615          if (StepperBreak(child, step) is Break) return Break;
 11616        }
 11617      }
 11618      return Continue;
 11619    }
 11620
 11621    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 11622    /// <param name="step">The delegate to perform on every item in the tree.</param>
 11623    public StepStatus Stepper(Func<T, StepStatus> step) =>
 11624      Stepper(step, _top);
 11625
 11626    internal StepStatus Stepper(Func<T, StepStatus> step, Node node)
 11627    {
 11628      StepStatus status = StepStatus.Continue;
 11629      if (node is Leaf)
 11630      {
 11631        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 11632          if ((status = step(list.Value)) != StepStatus.Continue)
 11633            break;
 11634      }
 11635      else
 11636      {
 11637        foreach (Node child in (node as Branch).Children)
 11638          if ((status = Stepper(step, child)) != StepStatus.Continue)
 11639            break;
 11640      }
 11641      return status;
 11642    }
 11643
 11644    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 11645    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 11646    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 11647    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 11648    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 11649    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 11650    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 11651    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 11652    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 11653    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 11654    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 11655    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 11656    public void Stepper(Action<T> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 mi
 11657      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3, max3, min
 11658
 11659    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 11660    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 11661    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 11662    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 11663    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 11664    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 11665    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 11666    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 11667    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 11668    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 11669    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 11670    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 11671    public void Stepper(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> mi
 11672      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3, max3, min
 11673
 11674    internal void Stepper(Action<T> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds)
 11675    {
 11676      if (node is Leaf)
 11677      {
 11678        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 11679          if (EncapsulationCheck(bounds, LocateVector(list.Value)))
 11680            step(list.Value);
 11681      }
 11682      else
 11683      {
 11684        foreach (Node child in (node as Branch).Children)
 11685          // optimization: stop bounds checking if space encapsulates node
 11686          if (EncapsulationCheck(bounds, child.Bounds))
 11687            this.Stepper(step, child);
 11688          else if (InclusionCheck(child.Bounds, bounds))
 11689            this.Stepper(step, child, bounds);
 11690      }
 11691    }
 11692
 11693    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 11694    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 11695    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 11696    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 11697    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 11698    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 11699    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 11700    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 11701    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 11702    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 11703    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 11704    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 11705    public StepStatus Stepper(Func<T, StepStatus> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis
 11706      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3, max3, min
 11707
 11708    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 11709    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 11710    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 11711    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 11712    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 11713    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 11714    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 11715    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 11716    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 11717    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 11718    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 11719    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 11720    public StepStatus Stepper(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree
 11721      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3, max3, min
 11722
 11723    internal StepStatus Stepper(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> 
 11724    {
 11725      StepStatus status = StepStatus.Continue;
 11726      if (node is Leaf)
 11727      {
 11728        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 11729          if (EncapsulationCheck(bounds, LocateVector(list.Value)) &&
 11730            (status = step(list.Value)) != StepStatus.Continue)
 11731            break;
 11732      }
 11733      else
 11734      {
 11735        foreach (Node child in (node as Branch).Children)
 11736          // optimization: stop bounds checking if space encapsulates node
 11737          if (EncapsulationCheck(bounds, child.Bounds) &&
 11738            (status = this.Stepper(step, child)) != StepStatus.Continue)
 11739            break;
 11740          else if (InclusionCheck(child.Bounds, bounds) &&
 11741            (status = this.Stepper(step, child, bounds)) != StepStatus.Continue)
 11742            break;
 11743      }
 11744      return status;
 11745    }
 11746
 11747    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 11748    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 11749    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 11750    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 11751    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 11752    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 11753    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 11754    public void Stepper(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5) =>
 11755      Stepper(step, _top, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5>(axis1, axis2, axis3, axis4, axis5));
 11756
 11757    internal void Stepper(Action<T> step, Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> vector)
 11758    {
 11759      Node current = node;
 11760      while (current is not null)
 11761      {
 11762        if (current is Leaf)
 11763        {
 11764          for (Leaf.Node leaf_node = (current as Leaf).Head; leaf_node is not null; leaf_node = leaf_node.Next)
 11765            if (EqualsCheck(vector, LocateVector(leaf_node.Value)))
 11766              step(leaf_node.Value);
 11767          break;
 11768        }
 11769        else
 11770        {
 11771          Branch branch = current as Branch;
 11772          int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 11773          current = branch[child_index];
 11774        }
 11775      }
 11776    }
 11777
 11778    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 11779    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 11780    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 11781    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 11782    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 11783    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 11784    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 11785    public StepStatus Stepper(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5)
 11786      Stepper(step, _top, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5>(axis1, axis2, axis3, axis4, axis5));
 11787
 11788    internal StepStatus Stepper(Func<T, StepStatus> step, Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> 
 11789    {
 11790      Node current = node;
 11791      while (current is not null)
 11792      {
 11793        if (current is Leaf)
 11794        {
 11795          for (Leaf.Node list = (current as Leaf).Head; list is not null; list = list.Next)
 11796          {
 11797            StepStatus status = StepStatus.Continue;
 11798            if (EqualsCheck(vector, LocateVector(list.Value)) &&
 11799              (status = step(list.Value)) != StepStatus.Continue)
 11800              return status;
 11801          }
 11802        }
 11803        else
 11804        {
 11805          Branch branch = current as Branch;
 11806          int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 11807          current = branch[child_index];
 11808        }
 11809      }
 11810      return StepStatus.Continue;
 11811    }
 11812
 11813    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 11814
 11815    public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 11816    {
 11817      // Note: this can be optimized.
 11818      IList<T> list = new ListLinked<T>();
 11819      Stepper(x => list.Add(x));
 11820      return list.GetEnumerator();
 11821    }
 11822
 11823    #endregion
 11824
 11825    /// <inheritdoc/>
 11826    public T[] ToArray() => throw new NotImplementedException();
 11827
 11828    #region Helpers
 11829
 11830    internal bool StraddlesLines(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds, Omnitree.Vector<Axis1, Axis2
 11831      Omnitree.StraddlesLines(bounds, vector
 11832        , _compare1
 11833        , _compare2
 11834        , _compare3
 11835        , _compare4
 11836        , _compare5
 11837        );
 11838
 11839    /// <summary>Computes the child index that contains the desired dimensions.</summary>
 11840    /// <param name="pointOfDivision">The point of division to compare against.</param>
 11841    /// <param name="vector">The dimensions to determine the child index.</param>
 11842    /// <returns>The computed child index based on the coordinates relative to the center of the node.</returns>
 11843    internal int DetermineChildIndex(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> pointOfDivision, Omnitree.Vector
 11844    {
 11845      int child = 0;
 11846      if (!(this._compare1(vector.Axis1, pointOfDivision.Axis1) is Less))
 11847        child += 1 << 0;
 11848      if (!(this._compare2(vector.Axis2, pointOfDivision.Axis2) is Less))
 11849        child += 1 << 1;
 11850      if (!(this._compare3(vector.Axis3, pointOfDivision.Axis3) is Less))
 11851        child += 1 << 2;
 11852      if (!(this._compare4(vector.Axis4, pointOfDivision.Axis4) is Less))
 11853        child += 1 << 3;
 11854      if (!(this._compare5(vector.Axis5, pointOfDivision.Axis5) is Less))
 11855        child += 1 << 4;
 11856      return child;
 11857    }
 11858
 11859    /// <summary>Converts a branch back into a leaf when the count is reduced.</summary>
 11860    /// <param name="parent">The parent to shrink a child of.</param>
 11861    /// <param name="child_index">The index of the child to shrink.</param>
 11862    internal void ShrinkChild(Branch parent, int child_index)
 11863    {
 11864      Leaf leaf;
 11865      Node removal = null;
 11866      if (parent is null) // top of tree
 11867      {
 11868        removal = this._top;
 11869        leaf = new Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>.None, null, -1);
 11870        this._top = leaf;
 11871      }
 11872      else // non-top branch
 11873      {
 11874        removal = parent[child_index];
 11875        leaf = new Leaf(removal.Bounds, removal.Parent, removal.Index);
 11876        parent[child_index] = leaf;
 11877      }
 11878
 11879      this.Stepper((T step) => { leaf.Add(step); }, removal);
 11880    }
 11881
 11882    /// <summary>Reduces the counts of all the parents of a given node by a given amount.</summary>
 11883    /// <param name="parent">The starting parent of the reduction.</param>
 11884    /// <param name="reduction">The amount to reduce the parent counts by.</param>
 11885    internal void ReduceParentCounts(Node parent, int reduction)
 11886    {
 11887      IncreaseParentCounts(parent, -reduction);
 11888    }
 11889
 11890    /// <summary>Increases the counts of all the parents of a given node by a given amount.</summary>
 11891    /// <param name="parent">The starting parent of the increase.</param>
 11892    /// <param name="increase">The amount to increase the parent counts by.</param>
 11893    internal void IncreaseParentCounts(Node parent, int increase)
 11894    {
 11895      Node node = parent;
 11896      while (node is not null)
 11897      {
 11898        node.Count += increase;
 11899        node = node.Parent;
 11900      }
 11901    }
 11902
 11903    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 11904    /// <returns>True if the spaces overlap; False if not.</returns>
 11905    internal bool InclusionCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> a, Omnitree.Bounds<Axis1, Axis2, Axi
 11906      Omnitree.InclusionCheck(a, b
 11907      , _compare1
 11908      , _compare2
 11909      , _compare3
 11910      , _compare4
 11911      , _compare5
 11912      );
 11913
 11914    /// <summary>Checks if a space encapsulates a point.</summary>
 11915    /// <returns>True if the space encapsulates the point; False if not.</returns>
 11916    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds, Omnitree.Vector<Axis1, A
 11917      Omnitree.EncapsulationCheck(bounds, vector
 11918      , _compare1
 11919      , _compare2
 11920      , _compare3
 11921      , _compare4
 11922      , _compare5
 11923      );
 11924
 11925    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 11926    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 11927    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> a, Omnitree.Bounds<Axis1, Axis2,
 11928      Omnitree.EncapsulationCheck(a, b
 11929      , _compare1
 11930      , _compare2
 11931      , _compare3
 11932      , _compare4
 11933      , _compare5
 11934      );
 11935
 11936    /// <summary>Checks for equality between two locations.</summary>
 11937    /// <returns>True if equal; False if not;</returns>
 11938    internal bool EqualsCheck(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> a, Omnitree.Vector<Axis1, Axis2, Axis3,
 11939      Omnitree.EqualsCheck(a, b
 11940      , (a, b) => _compare1(a, b) is Equal
 11941      , (a, b) => _compare2(a, b) is Equal
 11942      , (a, b) => _compare3(a, b) is Equal
 11943      , (a, b) => _compare4(a, b) is Equal
 11944      , (a, b) => _compare5(a, b) is Equal
 11945      );
 11946
 11947    /// <summary>Gets the nearest parent that encapsulates a location.</summary>
 11948    /// <param name="node">The starting node to find the encapsulating parent of the location.</param>
 11949    /// <param name="vector">The coordinates of the value.</param>
 11950    /// <returns>The nearest node that encapsulates the given location.</returns>
 11951    internal Node GetEncapsulationParent(Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> vector)
 11952    {
 11953      while (node is not null && !EncapsulationCheck(node.Bounds, vector))
 11954      {
 11955        node = node.Parent;
 11956      }
 11957      return node;
 11958    }
 11959
 11960    internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> LocateVector(T value)
 11961    {
 11962      Axis1 axis1;
 11963      Axis2 axis2;
 11964      Axis3 axis3;
 11965      Axis4 axis4;
 11966      Axis5 axis5;
 11967      this._locate(value, out axis1
 11968, out axis2
 11969, out axis3
 11970, out axis4
 11971, out axis5
 11972);
 11973      return new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5>(axis1, axis2, axis3, axis4, axis5);
 11974    }
 11975
 11976    #endregion
 11977
 11978    #endregion
 11979  }
 11980
 11981  #endregion
 11982
 11983  #region 6 Dimensional
 11984
 11985  /// <summary>Inheritance base for 6D omnitrees that store points.</summary>
 11986  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 11987  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 11988  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 11989  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 11990  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 11991  /// <typeparam name="Axis5">The type 5D axis.</typeparam>
 11992  /// <typeparam name="Axis6">The type 6D axis.</typeparam>
 11993  public interface IOmnitreePoints<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> : IOmnitree<T, Axis1, Axis2, Axis3, Axis
 11994  {
 11995    #region Properties
 11996
 11997    /// <summary>Steps through the values at a given location.</summary>
 11998    /// <param name="axis1">The coordinate along the 1D axis.</param>
 11999    /// <param name="axis2">The coordinate along the 2D axis.</param>
 12000    /// <param name="axis3">The coordinate along the 3D axis.</param>
 12001    /// <param name="axis4">The coordinate along the 4D axis.</param>
 12002    /// <param name="axis5">The coordinate along the 5D axis.</param>
 12003    /// <param name="axis6">The coordinate along the 6D axis.</param>
 12004
 12005    /// <returns>A Stepper of the items at the given coordinates.</returns>
 12006    Action<Action<T>> this[Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6] { get; }
 12007
 12008    /// <summary>The number of dimensions in this tree.</summary>
 12009    int Dimensions { get; }
 12010
 12011    /// <summary>The delegate being used by the omnitree to locate items in 6D space.</summary>
 12012    Omnitree.Location<T, Axis1
 12013      , Axis2
 12014      , Axis3
 12015      , Axis4
 12016      , Axis5
 12017      , Axis6
 12018      > Locate { get; }
 12019
 12020    #endregion
 12021
 12022    #region Methods
 12023
 12024    /// <summary>Counts the number of items in a sub space.</summary>
 12025    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 12026    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 12027    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 12028    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 12029    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 12030    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 12031    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 12032    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 12033    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 12034    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 12035    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 12036    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 12037    /// <returns>The number of items in the provided sub space.</returns>
 12038    int CountSubSpace(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound
 12039
 12040    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 12041    void Update();
 12042    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 12043    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 12044    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 12045    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 12046    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 12047    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 12048    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 12049    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 12050    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 12051    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 12052    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 12053    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 12054    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 12055    void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound<Axis2
 12056
 12057    /// <summary>Removes all the items in a given space.</summary>
 12058    /// <param name="axis1">The coordinate along the 1D axis.</param>
 12059    /// <param name="axis2">The coordinate along the 2D axis.</param>
 12060    /// <param name="axis3">The coordinate along the 3D axis.</param>
 12061    /// <param name="axis4">The coordinate along the 4D axis.</param>
 12062    /// <param name="axis5">The coordinate along the 5D axis.</param>
 12063    /// <param name="axis6">The coordinate along the 6D axis.</param>
 12064    void Remove(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6);
 12065    /// <summary>Removes all the items in a given space.</summary>
 12066    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 12067    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 12068    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 12069    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 12070    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 12071    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 12072    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 12073    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 12074    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 12075    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 12076    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 12077    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 12078    void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound<Axis2
 12079    /// <summary>Removes all the items in a given space where equality is met.</summary>
 12080    /// <param name="axis1">The coordinate along the 1D axis.</param>
 12081    /// <param name="axis2">The coordinate along the 2D axis.</param>
 12082    /// <param name="axis3">The coordinate along the 3D axis.</param>
 12083    /// <param name="axis4">The coordinate along the 4D axis.</param>
 12084    /// <param name="axis5">The coordinate along the 5D axis.</param>
 12085    /// <param name="axis6">The coordinate along the 6D axis.</param>
 12086    /// <param name="where">The equality constraint of the removal.</param>
 12087    void Remove(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6, Predicate<T> where);
 12088    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 12089    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 12090    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 12091    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 12092    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 12093    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 12094    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 12095    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 12096    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 12097    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 12098    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 12099    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 12100    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 12101    /// <param name="where">The predicate constraint of the removal.</param>
 12102    void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound<Axis2
 12103
 12104    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 12105    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 12106    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 12107    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 12108    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 12109    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 12110    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 12111    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 12112    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 12113    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 12114    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 12115    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 12116    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 12117    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 12118    void Stepper(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omn
 12119    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 12120    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 12121    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 12122    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 12123    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 12124    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 12125    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 12126    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 12127    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 12128    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 12129    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 12130    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 12131    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 12132    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 12133    StepStatus Stepper(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<
 12134    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 12135    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 12136    /// <param name="axis1">The coordinate along the 1D axis.</param>
 12137    /// <param name="axis2">The coordinate along the 2D axis.</param>
 12138    /// <param name="axis3">The coordinate along the 3D axis.</param>
 12139    /// <param name="axis4">The coordinate along the 4D axis.</param>
 12140    /// <param name="axis5">The coordinate along the 5D axis.</param>
 12141    /// <param name="axis6">The coordinate along the 6D axis.</param>
 12142    void Stepper(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6);
 12143    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 12144    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 12145    /// <param name="axis1">The coordinate along the 1D axis.</param>
 12146    /// <param name="axis2">The coordinate along the 2D axis.</param>
 12147    /// <param name="axis3">The coordinate along the 3D axis.</param>
 12148    /// <param name="axis4">The coordinate along the 4D axis.</param>
 12149    /// <param name="axis5">The coordinate along the 5D axis.</param>
 12150    /// <param name="axis6">The coordinate along the 6D axis.</param>
 12151    StepStatus Stepper(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 
 12152
 12153    #endregion
 12154  }
 12155
 12156  /// <summary>Omnitree that stores points along 6 dimensions implemented as a linked tree.</summary>
 12157  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 12158  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 12159  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 12160  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 12161  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 12162  /// <typeparam name="Axis5">The type 5D axis.</typeparam>
 12163  /// <typeparam name="Axis6">The type 6D axis.</typeparam>
 12164  public class OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> : IOmnitreePoints<T, Axis1, Axis2, Axis
 12165  {
 12166    internal const int _dimensions = 6;
 12167    internal static int _children_per_node = (int)BigInteger.Pow(2, 6);
 12168
 12169    internal Node _top;
 12170    internal int _naturalLogLower = 1; // caching the next time to calculate loads (lower count)
 12171    internal int _naturalLogUpper = -1; // caching the next time to calculate loads (upper count)
 12172    internal int _load; // ln(count); min = _defaultLoad
 12173    internal Omnitree.Location<T, Axis1
 12174      , Axis2
 12175      , Axis3
 12176      , Axis4
 12177      , Axis5
 12178      , Axis6
 12179      > _locate;
 12180    internal bool _defaultCompare1;
 12181    internal Func<Axis1, Axis1, CompareResult> _compare1;
 12182    internal bool _defaultCompare2;
 12183    internal Func<Axis2, Axis2, CompareResult> _compare2;
 12184    internal bool _defaultCompare3;
 12185    internal Func<Axis3, Axis3, CompareResult> _compare3;
 12186    internal bool _defaultCompare4;
 12187    internal Func<Axis4, Axis4, CompareResult> _compare4;
 12188    internal bool _defaultCompare5;
 12189    internal Func<Axis5, Axis5, CompareResult> _compare5;
 12190    internal bool _defaultCompare6;
 12191    internal Func<Axis6, Axis6, CompareResult> _compare6;
 12192    internal Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> _subdivis
 12193    internal Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> _subdivis
 12194    internal Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> _subdivis
 12195    internal Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> _subdivis
 12196    internal Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> _subdivis
 12197    internal Omnitree.SubdivisionOverride<T, Axis6, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> _subdivis
 12198
 12199    #region Nested Types
 12200
 12201    /// <summary>Can be a leaf or a branch.</summary>
 12202    internal abstract class Node
 12203    {
 12204      internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> Bounds;
 12205      internal Branch Parent;
 12206      internal int Index;
 12207      internal int Count;
 12208
 12209      /// <summary>The depth this node is located in the Omnitree.</summary>
 12210      internal int Depth
 12211      {
 12212        get
 12213        {
 12214          int depth = -1;
 12215          for (Node node = this; node is not null; node = node.Parent)
 12216            depth++;
 12217          return depth;
 12218        }
 12219      }
 12220
 12221      /// <summary>Constructs a node.</summary>
 12222      /// <param name="bounds">The bounds of this node.</param>
 12223      /// <param name="parent">The parent of this node.</param>
 12224      /// <param name="index">The number of values stored in this node and its children.</param>
 12225      internal Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds, Branch parent, int index)
 12226      {
 12227        Bounds = bounds;
 12228        Parent = parent;
 12229        Index = index;
 12230      }
 12231
 12232      internal Node(Node nodeToClone)
 12233      {
 12234        this.Bounds = nodeToClone.Bounds;
 12235        this.Parent = nodeToClone.Parent;
 12236        this.Index = nodeToClone.Index;
 12237        this.Count = nodeToClone.Count;
 12238      }
 12239
 12240      internal abstract Node Clone();
 12241    }
 12242
 12243    /// <summary>A branch in the tree. Only contains nodes.</summary>
 12244    internal class Branch : Node
 12245    {
 12246      internal Node[] Children;
 12247      internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> PointOfDivision;
 12248
 12249      /// <summary>Gets child by index.</summary>
 12250      /// <param name="child_index">The index of the child to get.</param>
 12251      /// <returns>The child of the given index or null if non-existent.</returns>
 12252      internal Node this[int child_index]
 12253      {
 12254        get
 12255        {
 12256          if (Children is null)
 12257            return null;
 12258          if (Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>._children_per_node)
 12259            return Children[(int)child_index];
 12260          foreach (Node node in Children)
 12261            if (node.Index == child_index)
 12262              return node;
 12263          return null;
 12264        }
 12265        set
 12266        {
 12267          // This error check should be unnecessary... but fuck it... might as well
 12268          if (value.Index != child_index)
 12269            throw new System.Exception("Bug in Omnitree (index/property mis-match when setting a child on a branch)");
 12270
 12271          // no children yet
 12272          if (Children is null)
 12273          {
 12274            Children = â±¯(value);
 12275            return;
 12276          }
 12277          // max children overwrite
 12278          else if (this.Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>._children_p
 12279          {
 12280            Children[(int)child_index] = value;
 12281            return;
 12282          }
 12283          // non-max child overwrite
 12284          for (int i = 0; i < Children.Length; i++)
 12285            if (Children[i].Index == child_index)
 12286            {
 12287              Children[i] = value;
 12288              return;
 12289            }
 12290          // new child
 12291          Node[] newArray = new Node[Children.Length + 1];
 12292          if (newArray.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>._children_per_node)
 12293          {
 12294            // new child resulting in a max children branch (sorting required)
 12295            for (int i = 0; i < Children.Length; i++)
 12296            {
 12297              newArray[(int)Children[i].Index] = Children[i];
 12298            }
 12299            newArray[(int)value.Index] = value;
 12300          }
 12301          else
 12302          {
 12303            // new child resulting in a non-max children branch
 12304            Array.Copy(Children, newArray, Children.Length);
 12305            newArray[newArray.Length - 1] = value;
 12306          }
 12307          this.Children = newArray;
 12308        }
 12309      }
 12310
 12311      internal Branch(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> pointOfDivision, Omnitree.Bounds<Axis1, 
 12312        : base(bounds, parent, index)
 12313      {
 12314        this.PointOfDivision = pointOfDivision;
 12315      }
 12316
 12317      internal Branch(Branch branchToClone) : base(branchToClone)
 12318      {
 12319        Children = branchToClone.Children.Clone() as Node[];
 12320        PointOfDivision = branchToClone.PointOfDivision;
 12321      }
 12322
 12323      internal override Node Clone() =>
 12324        new Branch(this);
 12325    }
 12326
 12327    /// <summary>A branch in the tree. Only contains items.</summary>
 12328    internal class Leaf : Node
 12329    {
 12330      internal class Node
 12331      {
 12332        internal T Value;
 12333        internal Leaf.Node Next;
 12334
 12335        internal Node(T value, Leaf.Node next)
 12336        {
 12337          Value = value;
 12338          Next = next;
 12339        }
 12340      }
 12341
 12342      internal Leaf.Node Head;
 12343
 12344      internal Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds, Branch parent, int index)
 12345        : base(bounds, parent, index)
 12346      { }
 12347
 12348      internal Leaf(Leaf leaf) : base(leaf)
 12349      {
 12350        Head = new Node(leaf.Head.Value, null);
 12351        Node a = Head;
 12352        Node b = leaf.Head;
 12353        while (b is not null)
 12354        {
 12355          a.Next = new Node(b.Next.Value, null);
 12356          a = a.Next;
 12357          b = b.Next;
 12358        }
 12359      }
 12360
 12361      internal void Add(T addition)
 12362      {
 12363        Head = new Leaf.Node(addition, Head);
 12364        this.Count++;
 12365      }
 12366
 12367      internal override OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>.Node Clone() =>
 12368        new Leaf(this);
 12369    }
 12370
 12371    #endregion
 12372
 12373    #region Constructors
 12374
 12375    /// <summary>This constructor is for cloning purposes</summary>
 12376    internal OmnitreePointsLinked(OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> omnitree)
 12377    {
 12378      this._top = omnitree._top.Clone();
 12379      this._load = omnitree._load;
 12380      this._locate = omnitree._locate;
 12381      this._defaultCompare1 = omnitree._defaultCompare1;
 12382      this._compare1 = omnitree._compare1;
 12383      this._defaultCompare2 = omnitree._defaultCompare2;
 12384      this._compare2 = omnitree._compare2;
 12385      this._defaultCompare3 = omnitree._defaultCompare3;
 12386      this._compare3 = omnitree._compare3;
 12387      this._defaultCompare4 = omnitree._defaultCompare4;
 12388      this._compare4 = omnitree._compare4;
 12389      this._defaultCompare5 = omnitree._defaultCompare5;
 12390      this._compare5 = omnitree._compare5;
 12391      this._defaultCompare6 = omnitree._defaultCompare6;
 12392      this._compare6 = omnitree._compare6;
 12393      this._subdivisionOverride1 = omnitree._subdivisionOverride1;
 12394      this._subdivisionOverride2 = omnitree._subdivisionOverride2;
 12395      this._subdivisionOverride3 = omnitree._subdivisionOverride3;
 12396      this._subdivisionOverride4 = omnitree._subdivisionOverride4;
 12397      this._subdivisionOverride5 = omnitree._subdivisionOverride5;
 12398      this._subdivisionOverride6 = omnitree._subdivisionOverride6;
 12399    }
 12400
 12401    internal OmnitreePointsLinked(
 12402      Omnitree.Location<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> locate,
 12403      bool defaultCompare1,
 12404      Func<Axis1, Axis1, CompareResult> compare1,
 12405      bool defaultCompare2,
 12406      Func<Axis2, Axis2, CompareResult> compare2,
 12407      bool defaultCompare3,
 12408      Func<Axis3, Axis3, CompareResult> compare3,
 12409      bool defaultCompare4,
 12410      Func<Axis4, Axis4, CompareResult> compare4,
 12411      bool defaultCompare5,
 12412      Func<Axis5, Axis5, CompareResult> compare5,
 12413      bool defaultCompare6,
 12414      Func<Axis6, Axis6, CompareResult> compare6,
 12415      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 12416,
 12417      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 12418,
 12419      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 12420,
 12421      Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 12422,
 12423      Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 12424,
 12425      Omnitree.SubdivisionOverride<T, Axis6, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 12426      )
 12427    {
 12428      if (locate is null)
 12429      {
 12430        throw new ArgumentNullException(nameof(locate));
 12431      }
 12432      if (compare1 is null)
 12433      {
 12434        throw new ArgumentNullException(nameof(compare1));
 12435      }
 12436
 12437      if (compare2 is null)
 12438      {
 12439        throw new ArgumentNullException(nameof(compare2));
 12440      }
 12441
 12442      if (compare3 is null)
 12443      {
 12444        throw new ArgumentNullException(nameof(compare3));
 12445      }
 12446
 12447      if (compare4 is null)
 12448      {
 12449        throw new ArgumentNullException(nameof(compare4));
 12450      }
 12451
 12452      if (compare5 is null)
 12453      {
 12454        throw new ArgumentNullException(nameof(compare5));
 12455      }
 12456
 12457      if (compare6 is null)
 12458      {
 12459        throw new ArgumentNullException(nameof(compare6));
 12460      }
 12461
 12462      this._locate = locate;
 12463      this._defaultCompare1 = defaultCompare1;
 12464      this._compare1 = compare1;
 12465      this._defaultCompare2 = defaultCompare2;
 12466      this._compare2 = compare2;
 12467      this._defaultCompare3 = defaultCompare3;
 12468      this._compare3 = compare3;
 12469      this._defaultCompare4 = defaultCompare4;
 12470      this._compare4 = compare4;
 12471      this._defaultCompare5 = defaultCompare5;
 12472      this._compare5 = compare5;
 12473      this._defaultCompare6 = defaultCompare6;
 12474      this._compare6 = compare6;
 12475      this._subdivisionOverride1 = subdivisionOverride1;
 12476      this._subdivisionOverride2 = subdivisionOverride2;
 12477      this._subdivisionOverride3 = subdivisionOverride3;
 12478      this._subdivisionOverride4 = subdivisionOverride4;
 12479      this._subdivisionOverride5 = subdivisionOverride5;
 12480      this._subdivisionOverride6 = subdivisionOverride6;
 12481      this._top = new Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>.None, null, -1);
 12482      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 12483    }
 12484
 12485    /// <summary>Constructs a new 6D omnitree that stores points.</summary>
 12486    /// <param name="locate">The delegate for locating items in 6D space.</param>
 12487
 12488    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 12489
 12490    /// <param name="compare2">The delegate for comparing values along the 2D axis.</param>
 12491
 12492    /// <param name="compare3">The delegate for comparing values along the 3D axis.</param>
 12493
 12494    /// <param name="compare4">The delegate for comparing values along the 4D axis.</param>
 12495
 12496    /// <param name="compare5">The delegate for comparing values along the 5D axis.</param>
 12497
 12498    /// <param name="compare6">The delegate for comparing values along the 6D axis.</param>
 12499
 12500    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 12501
 12502    /// <param name="subdivisionOverride2">The subdivision overide to be used when splitting the 2 dimension.</param>
 12503
 12504    /// <param name="subdivisionOverride3">The subdivision overide to be used when splitting the 3 dimension.</param>
 12505
 12506    /// <param name="subdivisionOverride4">The subdivision overide to be used when splitting the 4 dimension.</param>
 12507
 12508    /// <param name="subdivisionOverride5">The subdivision overide to be used when splitting the 5 dimension.</param>
 12509
 12510    /// <param name="subdivisionOverride6">The subdivision overide to be used when splitting the 6 dimension.</param>
 12511    public OmnitreePointsLinked(
 12512      Omnitree.Location<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> locate,
 12513      Func<Axis1, Axis1, CompareResult> compare1 = null,
 12514      Func<Axis2, Axis2, CompareResult> compare2 = null,
 12515      Func<Axis3, Axis3, CompareResult> compare3 = null,
 12516      Func<Axis4, Axis4, CompareResult> compare4 = null,
 12517      Func<Axis5, Axis5, CompareResult> compare5 = null,
 12518      Func<Axis6, Axis6, CompareResult> compare6 = null,
 12519      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 12520,
 12521      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 12522,
 12523      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 12524,
 12525      Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 12526,
 12527      Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 12528,
 12529      Omnitree.SubdivisionOverride<T, Axis6, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 12530      )
 12531      : this(
 12532        locate,
 12533        compare1 is null ? true : false,
 12534        compare1 ?? Compare,
 12535        compare2 is null ? true : false,
 12536        compare2 ?? Compare,
 12537        compare3 is null ? true : false,
 12538        compare3 ?? Compare,
 12539        compare4 is null ? true : false,
 12540        compare4 ?? Compare,
 12541        compare5 is null ? true : false,
 12542        compare5 ?? Compare,
 12543        compare6 is null ? true : false,
 12544        compare6 ?? Compare,
 12545        subdivisionOverride1
 12546,
 12547        subdivisionOverride2
 12548,
 12549        subdivisionOverride3
 12550,
 12551        subdivisionOverride4
 12552,
 12553        subdivisionOverride5
 12554,
 12555        subdivisionOverride6
 12556        ) { }
 12557
 12558    #endregion
 12559
 12560    #region Properties
 12561
 12562    /// <summary>Steps through all the items at a given coordinate.</summary>
 12563    /// <param name="axis1">The coordinate along axis 1.</param>
 12564    /// <param name="axis2">The coordinate along axis 2.</param>
 12565    /// <param name="axis3">The coordinate along axis 3.</param>
 12566    /// <param name="axis4">The coordinate along axis 4.</param>
 12567    /// <param name="axis5">The coordinate along axis 5.</param>
 12568    /// <param name="axis6">The coordinate along axis 6.</param>
 12569    /// <returns>The stepper for the items at the given coordinate.</returns>
 12570    public Action<Action<T>> this[Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6] =>
 12571      step => Stepper(step, axis1, axis2, axis3, axis4, axis5, axis6);
 12572
 12573    /// <summary>The number of dimensions in this tree.</summary>
 12574    public int Dimensions { get { return _dimensions; } }
 12575
 12576    /// <summary>The location function the Omnitree is using.</summary>
 12577    public Omnitree.Location<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> Locate { get { return this._locate; } }
 12578
 12579    /// <summary>The comparison function the Omnitree is using along the 1D axis.</summary>
 12580    public Func<Axis1, Axis1, CompareResult> Compare1 { get { return this._compare1; } }
 12581    /// <summary>The comparison function the Omnitree is using along the 2D axis.</summary>
 12582    public Func<Axis2, Axis2, CompareResult> Compare2 { get { return this._compare2; } }
 12583    /// <summary>The comparison function the Omnitree is using along the 3D axis.</summary>
 12584    public Func<Axis3, Axis3, CompareResult> Compare3 { get { return this._compare3; } }
 12585    /// <summary>The comparison function the Omnitree is using along the 4D axis.</summary>
 12586    public Func<Axis4, Axis4, CompareResult> Compare4 { get { return this._compare4; } }
 12587    /// <summary>The comparison function the Omnitree is using along the 5D axis.</summary>
 12588    public Func<Axis5, Axis5, CompareResult> Compare5 { get { return this._compare5; } }
 12589    /// <summary>The comparison function the Omnitree is using along the 6D axis.</summary>
 12590    public Func<Axis6, Axis6, CompareResult> Compare6 { get { return this._compare6; } }
 12591
 12592    /// <summary>The current number of items in the tree.</summary>
 12593    public int Count { get { return this._top.Count; } }
 12594
 12595    internal delegate void MaxDepthFinder(Node node, int current_depth, ref int max_depth);
 12596    /// <summary>Finds the current maximum depth of the tree. NOT AN O(1) OPERATION. Intended for educational purposes o
 12597    public int MaxDepth
 12598    {
 12599      get
 12600      {
 12601        MaxDepthFinder maxDepthFinder = null;
 12602        maxDepthFinder =
 12603          (Node node, int current_depth, ref int max_depth) =>
 12604          {
 12605            if (current_depth > max_depth)
 12606              max_depth = current_depth;
 12607            if (node is Branch)
 12608              foreach (Node child in (node as Branch).Children)
 12609                maxDepthFinder(child, current_depth + 1, ref max_depth);
 12610          };
 12611        int _max_depth = -1;
 12612        maxDepthFinder(this._top, 0, ref _max_depth);
 12613        return _max_depth;
 12614      }
 12615    }
 12616
 12617    internal delegate void NodeCountFinder(Node node, ref int current_count);
 12618    /// <summary>Counts the current number of nodes in the tree. NOT AN O(1) OPERATION. Intended for educational purpose
 12619    public int NodeCount
 12620    {
 12621      get
 12622      {
 12623        NodeCountFinder nodeCountFinder = null;
 12624        nodeCountFinder =
 12625          (Node node, ref int current_count) =>
 12626          {
 12627            current_count++;
 12628            if (node is Branch)
 12629              foreach (Node child in (node as Branch).Children)
 12630                nodeCountFinder(child, ref current_count);
 12631          };
 12632
 12633        int _current_count = 0;
 12634        nodeCountFinder(this._top, ref _current_count);
 12635        return _current_count;
 12636      }
 12637    }
 12638
 12639    internal delegate void BranchCountFinder(Node node, ref int current_count);
 12640    /// <summary>Counts the current number of branches in the tree. NOT AN O(1) OPERATION. Intended for educational purp
 12641    public int BranchCount
 12642    {
 12643      get
 12644      {
 12645        BranchCountFinder branchCountFinder = null;
 12646        branchCountFinder =
 12647          (Node node, ref int current_count) =>
 12648          {
 12649            if (node is Branch)
 12650            {
 12651              current_count++;
 12652              foreach (Node child in (node as Branch).Children)
 12653                branchCountFinder(child, ref current_count);
 12654            }
 12655          };
 12656
 12657        int _current_count = 0;
 12658        branchCountFinder(this._top, ref _current_count);
 12659        return _current_count;
 12660      }
 12661    }
 12662
 12663    internal delegate void LeafCountFinder(Node node, ref int current_count);
 12664    /// <summary>Counts the current number of leaves in the tree. NOT AN O(1) OPERATION. Intended for educational purpos
 12665    public int LeafCount
 12666    {
 12667      get
 12668      {
 12669        LeafCountFinder leafCountFinder = null;
 12670        leafCountFinder =
 12671          (Node node, ref int current_count) =>
 12672          {
 12673            if (node is Leaf)
 12674              current_count++;
 12675            else
 12676              foreach (Node child in (node as Branch).Children)
 12677                leafCountFinder(child, ref current_count);
 12678          };
 12679
 12680        int _current_count = 0;
 12681        leafCountFinder(this._top, ref _current_count);
 12682        return _current_count;
 12683      }
 12684    }
 12685
 12686    #endregion
 12687
 12688    #region Methods
 12689
 12690    #region Add
 12691
 12692
 12693    #region single
 12694
 12695    /// <summary>Tries to add a value.</summary>
 12696    /// <param name="value">The value to be added.</param>
 12697    /// <returns>True if successful or false if not.</returns>
 12698    public (bool Success, Exception? Exception) TryAdd(T value)
 12699    {
 12700      Add(value);
 12701      return (true, null);
 12702    }
 12703
 12704    /// <summary>Adds an item to the tree.</summary>
 12705    /// <param name="addition">The item to be added.</param>
 12706    public void Add(T addition)
 12707    {
 12708      if (this._top.Count is int.MaxValue)
 12709        throw new System.InvalidOperationException("(Count is int.MaxValue) max Omnitree size reached (change ints to lo
 12710
 12711      // dynamic tree sizes
 12712      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 12713
 12714      Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> location = LocateVector(addition);
 12715
 12716      // grow the first branch of the tree
 12717      if (this._top is Leaf && (this._top as Leaf).Count >= _load)
 12718      {
 12719        Leaf top = this._top as Leaf;
 12720
 12721        // create the new branch from the median values
 12722        this._top = new Branch(DetermineMedians(top), Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>.None, nu
 12723
 12724        // iterate through the values and add them to the appropriate children
 12725        for (Leaf.Node list = top.Head; list is not null; list = list.Next)
 12726          Add(list.Value, this._top, LocateVector(list.Value), 0);
 12727      }
 12728
 12729      this.Add(addition, this._top, location, 0);
 12730    }
 12731
 12732    /// <summary>Recursive version of the add function.</summary>
 12733    /// <param name="addition">The item to be added.</param>
 12734    /// <param name="node">The current node for tree trversal.</param>
 12735    /// <param name="location">The location of the addition.</param>
 12736    /// <param name="depth">The current depth of iteration.</param>
 12737    internal void Add(T addition, Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> location, int dep
 12738    {
 12739      if (node is Leaf)
 12740      {
 12741        Leaf leaf = node as Leaf;
 12742        if (depth >= _load || !(leaf.Count >= _load))
 12743        {
 12744          leaf.Add(addition);
 12745          return;
 12746        }
 12747        else
 12748        {
 12749          Branch parent = node.Parent;
 12750          int child_index = this.DetermineChildIndex(parent.PointOfDivision, location);
 12751          Branch growth = new Branch(DetermineMedians(leaf), leaf.Bounds, parent, child_index);
 12752          parent[child_index] = growth;
 12753          for (Leaf.Node list = leaf.Head; list is not null; list = list.Next)
 12754          {
 12755            Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> temp_location = LocateVector(list.Value);
 12756            if (EncapsulationCheck(growth.Bounds, temp_location))
 12757              Add(list.Value, growth, temp_location, depth);
 12758            else
 12759            {
 12760              ReduceParentCounts(parent, 1);
 12761              Add(list.Value, this._top, temp_location, depth);
 12762            }
 12763          }
 12764
 12765          Add(addition, growth, location, depth);
 12766          return;
 12767        }
 12768      }
 12769      else
 12770      {
 12771        Branch branch = node as Branch;
 12772        int child_index = this.DetermineChildIndex(branch.PointOfDivision, location); // determine the child "index" (0 
 12773        Node child_node = branch[child_index];
 12774
 12775        // null children in branches are just empty leaves
 12776        if (child_node is null)
 12777        {
 12778          Leaf new_leaf = new Leaf(DetermineChildBounds(branch, child_index), branch, child_index);
 12779          branch[child_index] = new_leaf;
 12780          new_leaf.Add(addition);
 12781        }
 12782        else
 12783          // child exists already, continue adding
 12784          Add(addition, child_node, location, depth + 1);
 12785
 12786        branch.Count++;
 12787        return;
 12788      }
 12789    }
 12790
 12791    internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> DetermineMedians(Leaf leaf)
 12792    {
 12793
 12794      Axis1 division1;
 12795      if (!(_subdivisionOverride1 is null))
 12796      {
 12797        division1 = _subdivisionOverride1(leaf.Bounds, x =>
 12798          {
 12799            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 12800            {
 12801              x(node.Value);
 12802            }
 12803          });
 12804      }
 12805      else
 12806      {
 12807        Axis1[] values = new Axis1[leaf.Count];
 12808        Leaf.Node for_current = leaf.Head;
 12809        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 12810          this._locate(for_current.Value
 12811          , out values[i]
 12812          , out _
 12813          , out _
 12814          , out _
 12815          , out _
 12816          , out _
 12817          );
 12818        if (_defaultCompare1) Array.Sort(values);
 12819        else SortQuick<Axis1>(values, this._compare1);
 12820        int index = (leaf.Count - 1) / 2;
 12821        division1 = values[index];
 12822      }
 12823
 12824      Axis2 division2;
 12825      if (!(_subdivisionOverride2 is null))
 12826      {
 12827        division2 = _subdivisionOverride2(leaf.Bounds, x =>
 12828          {
 12829            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 12830            {
 12831              x(node.Value);
 12832            }
 12833          });
 12834      }
 12835      else
 12836      {
 12837        Axis2[] values = new Axis2[leaf.Count];
 12838        Leaf.Node for_current = leaf.Head;
 12839        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 12840          this._locate(for_current.Value
 12841          , out _
 12842          , out values[i]
 12843          , out _
 12844          , out _
 12845          , out _
 12846          , out _
 12847          );
 12848        if (_defaultCompare2) Array.Sort(values);
 12849        else SortQuick<Axis2>(values, this._compare2);
 12850        int index = (leaf.Count - 1) / 2;
 12851        division2 = values[index];
 12852      }
 12853
 12854      Axis3 division3;
 12855      if (!(_subdivisionOverride3 is null))
 12856      {
 12857        division3 = _subdivisionOverride3(leaf.Bounds, x =>
 12858          {
 12859            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 12860            {
 12861              x(node.Value);
 12862            }
 12863          });
 12864      }
 12865      else
 12866      {
 12867        Axis3[] values = new Axis3[leaf.Count];
 12868        Leaf.Node for_current = leaf.Head;
 12869        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 12870          this._locate(for_current.Value
 12871          , out _
 12872          , out _
 12873          , out values[i]
 12874          , out _
 12875          , out _
 12876          , out _
 12877          );
 12878        if (_defaultCompare3) Array.Sort(values);
 12879        else SortQuick<Axis3>(values, this._compare3);
 12880        int index = (leaf.Count - 1) / 2;
 12881        division3 = values[index];
 12882      }
 12883
 12884      Axis4 division4;
 12885      if (!(_subdivisionOverride4 is null))
 12886      {
 12887        division4 = _subdivisionOverride4(leaf.Bounds, x =>
 12888          {
 12889            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 12890            {
 12891              x(node.Value);
 12892            }
 12893          });
 12894      }
 12895      else
 12896      {
 12897        Axis4[] values = new Axis4[leaf.Count];
 12898        Leaf.Node for_current = leaf.Head;
 12899        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 12900          this._locate(for_current.Value
 12901          , out _
 12902          , out _
 12903          , out _
 12904          , out values[i]
 12905          , out _
 12906          , out _
 12907          );
 12908        if (_defaultCompare4) Array.Sort(values);
 12909        else SortQuick<Axis4>(values, this._compare4);
 12910        int index = (leaf.Count - 1) / 2;
 12911        division4 = values[index];
 12912      }
 12913
 12914      Axis5 division5;
 12915      if (!(_subdivisionOverride5 is null))
 12916      {
 12917        division5 = _subdivisionOverride5(leaf.Bounds, x =>
 12918          {
 12919            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 12920            {
 12921              x(node.Value);
 12922            }
 12923          });
 12924      }
 12925      else
 12926      {
 12927        Axis5[] values = new Axis5[leaf.Count];
 12928        Leaf.Node for_current = leaf.Head;
 12929        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 12930          this._locate(for_current.Value
 12931          , out _
 12932          , out _
 12933          , out _
 12934          , out _
 12935          , out values[i]
 12936          , out _
 12937          );
 12938        if (_defaultCompare5) Array.Sort(values);
 12939        else SortQuick<Axis5>(values, this._compare5);
 12940        int index = (leaf.Count - 1) / 2;
 12941        division5 = values[index];
 12942      }
 12943
 12944      Axis6 division6;
 12945      if (!(_subdivisionOverride6 is null))
 12946      {
 12947        division6 = _subdivisionOverride6(leaf.Bounds, x =>
 12948          {
 12949            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 12950            {
 12951              x(node.Value);
 12952            }
 12953          });
 12954      }
 12955      else
 12956      {
 12957        Axis6[] values = new Axis6[leaf.Count];
 12958        Leaf.Node for_current = leaf.Head;
 12959        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 12960          this._locate(for_current.Value
 12961          , out _
 12962          , out _
 12963          , out _
 12964          , out _
 12965          , out _
 12966          , out values[i]
 12967          );
 12968        if (_defaultCompare6) Array.Sort(values);
 12969        else SortQuick<Axis6>(values, this._compare6);
 12970        int index = (leaf.Count - 1) / 2;
 12971        division6 = values[index];
 12972      }
 12973
 12974      return new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(
 12975        division1
 12976
 12977        , division2
 12978
 12979        , division3
 12980
 12981        , division4
 12982
 12983        , division5
 12984
 12985        , division6
 12986
 12987        );
 12988    }
 12989
 12990    #endregion
 12991
 12992    #region Add Helpers
 12993
 12994    internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> DetermineChildBounds(Branch branch, int child_ind
 12995    {
 12996
 12997      Omnitree.Bound<Axis6> min6, max6;
 12998      if (child_index >= 32)
 12999      {
 13000        min6 = branch.PointOfDivision.Axis6;
 13001        max6 = branch.Bounds.Max6;
 13002        child_index -= 32;
 13003      }
 13004      else
 13005      {
 13006        min6 = branch.Bounds.Min6;
 13007        max6 = branch.PointOfDivision.Axis6;
 13008      }
 13009
 13010      Omnitree.Bound<Axis5> min5, max5;
 13011      if (child_index >= 16)
 13012      {
 13013        min5 = branch.PointOfDivision.Axis5;
 13014        max5 = branch.Bounds.Max5;
 13015        child_index -= 16;
 13016      }
 13017      else
 13018      {
 13019        min5 = branch.Bounds.Min5;
 13020        max5 = branch.PointOfDivision.Axis5;
 13021      }
 13022
 13023      Omnitree.Bound<Axis4> min4, max4;
 13024      if (child_index >= 8)
 13025      {
 13026        min4 = branch.PointOfDivision.Axis4;
 13027        max4 = branch.Bounds.Max4;
 13028        child_index -= 8;
 13029      }
 13030      else
 13031      {
 13032        min4 = branch.Bounds.Min4;
 13033        max4 = branch.PointOfDivision.Axis4;
 13034      }
 13035
 13036      Omnitree.Bound<Axis3> min3, max3;
 13037      if (child_index >= 4)
 13038      {
 13039        min3 = branch.PointOfDivision.Axis3;
 13040        max3 = branch.Bounds.Max3;
 13041        child_index -= 4;
 13042      }
 13043      else
 13044      {
 13045        min3 = branch.Bounds.Min3;
 13046        max3 = branch.PointOfDivision.Axis3;
 13047      }
 13048
 13049      Omnitree.Bound<Axis2> min2, max2;
 13050      if (child_index >= 2)
 13051      {
 13052        min2 = branch.PointOfDivision.Axis2;
 13053        max2 = branch.Bounds.Max2;
 13054        child_index -= 2;
 13055      }
 13056      else
 13057      {
 13058        min2 = branch.Bounds.Min2;
 13059        max2 = branch.PointOfDivision.Axis2;
 13060      }
 13061
 13062      Omnitree.Bound<Axis1> min1, max1;
 13063      if (child_index >= 1)
 13064      {
 13065        min1 = branch.PointOfDivision.Axis1;
 13066        max1 = branch.Bounds.Max1;
 13067        child_index -= 1;
 13068      }
 13069      else
 13070      {
 13071        min1 = branch.Bounds.Min1;
 13072        max1 = branch.PointOfDivision.Axis1;
 13073      }
 13074
 13075      return new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2, min3, max3, min4, max
 13076    }
 13077
 13078    #endregion
 13079
 13080    #endregion
 13081
 13082    #region Clear
 13083
 13084    /// <summary>Returns the tree to an empty state.</summary>
 13085    public void Clear()
 13086    {
 13087      this._top = new Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>.None, null, -1);
 13088      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 13089    }
 13090
 13091    #endregion
 13092
 13093    #region Clone
 13094
 13095    /// <summary>Creates a shallow clone of this data structure.</summary>
 13096    /// <returns>A shallow clone of this data structure.</returns>
 13097    public OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> Clone()
 13098    {
 13099      return new OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(this);
 13100    }
 13101
 13102    #endregion
 13103
 13104    #region Count
 13105
 13106    /// <summary>Counts the number of items in a sub space.</summary>
 13107    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 13108    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 13109    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 13110    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 13111    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 13112    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 13113    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 13114    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 13115    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 13116    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 13117    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 13118    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 13119    /// <returns>The number of items in the provided sub space.</returns>
 13120    public int CountSubSpace(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 m
 13121    {
 13122      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2, m
 13123    }
 13124    /// <summary>Counts the number of items in a sub space.</summary>
 13125    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 13126    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 13127    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 13128    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 13129    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 13130    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 13131    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 13132    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 13133    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 13134    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 13135    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 13136    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 13137    /// <returns>The number of items in the provided sub space.</returns>
 13138    public int CountSubSpace(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitre
 13139    {
 13140      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2, m
 13141    }
 13142    /// <summary>Counts the number of items in a sub space.</summary>
 13143    /// <param name="axis1">The coordinate along the 1D axis.</param>
 13144    /// <param name="axis2">The coordinate along the 2D axis.</param>
 13145    /// <param name="axis3">The coordinate along the 3D axis.</param>
 13146    /// <param name="axis4">The coordinate along the 4D axis.</param>
 13147    /// <param name="axis5">The coordinate along the 5D axis.</param>
 13148    /// <param name="axis6">The coordinate along the 6D axis.</param>
 13149    /// <returns>The number of items in the provided sub space.</returns>
 13150    public int CountSubSpace(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6)
 13151    {
 13152      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(axis1, axis1, axis2, axis
 13153    }
 13154    /// <summary>Counts the number of items in a sub space.</summary>
 13155    /// <param name="axis1">The coordinate along the 1D axis.</param>
 13156    /// <param name="axis2">The coordinate along the 2D axis.</param>
 13157    /// <param name="axis3">The coordinate along the 3D axis.</param>
 13158    /// <param name="axis4">The coordinate along the 4D axis.</param>
 13159    /// <param name="axis5">The coordinate along the 5D axis.</param>
 13160    /// <param name="axis6">The coordinate along the 6D axis.</param>
 13161    /// <returns>The number of items in the provided sub space.</returns>
 13162    public int CountSubSpace(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3, Omni
 13163    {
 13164      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(axis1, axis1, axis2, axis
 13165    }
 13166    /// <summary>Counts the number of items in a sub space.</summary>
 13167    /// <param name="node">The current traversal node.</param>
 13168    /// <param name="bounds">The bounds of the sub space being counted.</param>
 13169    /// <returns>The number of items in the provided sub space.</returns>
 13170    internal int CountSubSpace(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds)
 13171    {
 13172      // adjust min/max values
 13173      int count = 0;
 13174      if (EncapsulationCheck(bounds, node.Bounds))
 13175        count += node.Count;
 13176      else if (node is Leaf)
 13177      {
 13178        for (Leaf.Node list = (node as Leaf).Head; list is null; list = list.Next)
 13179          if (EncapsulationCheck(bounds, LocateVector(list.Value)))
 13180            count++;
 13181      }
 13182      else
 13183      {
 13184        Branch branch = node as Branch;
 13185        if (!StraddlesLines(branch.Bounds, branch.PointOfDivision))
 13186        {
 13187          int child_index = DetermineChildIndex(branch.PointOfDivision, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, 
 13188            , bounds.Min2.Value
 13189            , bounds.Min3.Value
 13190            , bounds.Min4.Value
 13191            , bounds.Min5.Value
 13192            , bounds.Min6.Value
 13193            ));
 13194          Node child = branch[child_index];
 13195          if (child is not null)
 13196          {
 13197            count += this.CountSubSpace(child, bounds);
 13198          }
 13199        }
 13200        else
 13201        {
 13202          foreach (Node child in (node as Branch).Children)
 13203            count += this.CountSubSpace(child, bounds);
 13204        }
 13205      }
 13206      return count;
 13207    }
 13208
 13209    #endregion
 13210
 13211    #region Update
 13212
 13213    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 13214    public void Update()
 13215    {
 13216      this.Update(this._top, 0);
 13217    }
 13218
 13219    /// <summary>Recursive version of the Update method.</summary>
 13220    /// <param name="node">The current node of iteration.</param>
 13221    /// <param name="depth">The current depth of iteration.</param>
 13222    internal int Update(Node node, int depth)
 13223    {
 13224      int removals = 0;
 13225
 13226      if (node is Leaf)
 13227      {
 13228        Leaf leaf = node as Leaf;
 13229        Leaf.Node current = leaf.Head;
 13230        Leaf.Node previous = null;
 13231        while (current is not null)
 13232        {
 13233          Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> location = LocateVector(current.Value);
 13234          if (!this.EncapsulationCheck(node.Bounds, location))
 13235          {
 13236            removals++;
 13237            T updated = current.Value;
 13238            if (previous is null)
 13239            {
 13240              leaf.Head = current.Next;
 13241              goto HeadRemoved;
 13242            }
 13243            else
 13244              previous.Next = current.Next;
 13245
 13246            Node whereToAdd = GetEncapsulationParent(node.Parent, location);
 13247
 13248            if (whereToAdd is null)
 13249              throw new System.Exception("an item was updated outside the range of the omnitree");
 13250
 13251            this.Add(updated, whereToAdd, location, whereToAdd.Depth);
 13252          }
 13253          previous = current;
 13254        HeadRemoved:
 13255          current = current.Next;
 13256        }
 13257        leaf.Count -= removals;
 13258        return removals;
 13259      }
 13260      else
 13261      {
 13262        Branch branch = node as Branch;
 13263        int skipped = 0;
 13264        for (int i = 0; i + skipped < branch.Children.Length; )
 13265        {
 13266          removals += this.Update(branch.Children[i], depth + 1);
 13267          if (branch.Children[i].Count is 0)
 13268            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 13269          else
 13270            i++;
 13271        }
 13272        Node[] newArray = new Node[branch.Children.Length - skipped];
 13273        Array.Copy(branch.Children, newArray, newArray.Length);
 13274        branch.Children = newArray;
 13275
 13276        branch.Count -= removals;
 13277
 13278        if (branch.Count < _load && branch.Count != 0)
 13279          ShrinkChild(branch.Parent, branch.Index);
 13280      }
 13281
 13282      return removals;
 13283    }
 13284
 13285    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 13286    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 13287    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 13288    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 13289    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 13290    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 13291    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 13292    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 13293    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 13294    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 13295    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 13296    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 13297    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 13298    public void Update(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4, A
 13299    {
 13300      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2, min3, max3, min4
 13301    }
 13302    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 13303    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 13304    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 13305    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 13306    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 13307    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 13308    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 13309    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 13310    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 13311    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 13312    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 13313    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 13314    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 13315    public void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 13316    {
 13317      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2, min3, max3, min4
 13318    }
 13319    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 13320    /// <param name="axis1">The coordinate along the 1D axis.</param>
 13321    /// <param name="axis2">The coordinate along the 2D axis.</param>
 13322    /// <param name="axis3">The coordinate along the 3D axis.</param>
 13323    /// <param name="axis4">The coordinate along the 4D axis.</param>
 13324    /// <param name="axis5">The coordinate along the 5D axis.</param>
 13325    /// <param name="axis6">The coordinate along the 6D axis.</param>
 13326    public void Update(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6)
 13327    {
 13328      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(axis1, axis1, axis2, axis2, axis3, axis3
 13329    }
 13330    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 13331    /// <param name="axis1">The coordinate along the 1D axis.</param>
 13332    /// <param name="axis2">The coordinate along the 2D axis.</param>
 13333    /// <param name="axis3">The coordinate along the 3D axis.</param>
 13334    /// <param name="axis4">The coordinate along the 4D axis.</param>
 13335    /// <param name="axis5">The coordinate along the 5D axis.</param>
 13336    /// <param name="axis6">The coordinate along the 6D axis.</param>
 13337    public void Update(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3, Omnitree.B
 13338    {
 13339      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(axis1, axis1, axis2, axis2, axis3, axis3
 13340    }
 13341    internal int Update(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds, Node node, int depth)
 13342    {
 13343      if (!InclusionCheck(bounds, node.Bounds))
 13344        return 0;
 13345
 13346      int removals = 0;
 13347
 13348      if (node is Leaf)
 13349      {
 13350        Leaf leaf = node as Leaf;
 13351        Leaf.Node current = leaf.Head;
 13352        Leaf.Node previous = null;
 13353        while (current is not null)
 13354        {
 13355          Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> location = LocateVector(current.Value);
 13356          if (!this.EncapsulationCheck(node.Bounds, location))
 13357          {
 13358            removals++;
 13359            T updated = current.Value;
 13360            if (previous is null)
 13361            {
 13362              leaf.Head = current.Next;
 13363              goto HeadRemoved;
 13364            }
 13365            else
 13366              previous.Next = current.Next;
 13367            Node whereToAdd = GetEncapsulationParent(node.Parent, location);
 13368            if (whereToAdd is null)
 13369              throw new System.Exception("an item was updates outside the range of the omnitree");
 13370            this.Add(updated, whereToAdd, location, whereToAdd.Depth);
 13371          }
 13372          previous = current;
 13373        HeadRemoved:
 13374          current = current.Next;
 13375        }
 13376        leaf.Count -= removals;
 13377        return removals;
 13378      }
 13379      else
 13380      {
 13381        Branch branch = node as Branch;
 13382        int skipped = 0;
 13383        for (int i = 0; i + skipped < branch.Children.Length; )
 13384        {
 13385          removals += this.Update(branch.Children[i], depth + 1);
 13386          if (branch.Children[i].Count is 0)
 13387            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 13388          else
 13389            i++;
 13390        }
 13391        Node[] newArray = new Node[branch.Children.Length - skipped];
 13392        Array.Copy(branch.Children, newArray, newArray.Length);
 13393        branch.Children = newArray;
 13394
 13395        branch.Count -= removals;
 13396
 13397        if (branch.Count < _load && branch.Count != 0)
 13398          ShrinkChild(branch.Parent, branch.Index);
 13399      }
 13400
 13401      return removals;
 13402    }
 13403
 13404    #endregion
 13405
 13406    #region Remove
 13407
 13408    /// <summary>Removes all the items qualified by the delegate.</summary>
 13409    /// <param name="where">The predicate to qualify removals.</param>
 13410    public void Remove(Predicate<T> where)
 13411    {
 13412      this.Remove(this._top, where);
 13413      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 13414    }
 13415
 13416    /// <summary>Recursive version of the remove method.</summary>
 13417    /// <param name="node">The current node of traversal.</param>
 13418    /// <param name="where">The predicate to qualify removals.</param>
 13419    internal int Remove(Node node, Predicate<T> where)
 13420    {
 13421      int removals = 0;
 13422      if (node is Leaf)
 13423      {
 13424        Leaf leaf = node as Leaf;
 13425        while (leaf.Head is not null && where(leaf.Head.Value))
 13426        {
 13427          leaf.Head = leaf.Head.Next;
 13428          removals++;
 13429        }
 13430        if (leaf.Head is not null)
 13431        {
 13432          Leaf.Node list = leaf.Head;
 13433          while (list.Next is not null)
 13434          {
 13435            if (where(list.Next.Value))
 13436            {
 13437              list.Next = list.Next.Next;
 13438              removals++;
 13439            }
 13440          }
 13441        }
 13442
 13443        leaf.Count -= removals;
 13444        return removals;
 13445      }
 13446      else
 13447      {
 13448        Branch branch = node as Branch;
 13449        int skipped = 0;
 13450        for (int i = 0; i + skipped < branch.Children.Length; )
 13451        {
 13452          removals += this.Remove(branch.Children[i], where);
 13453          if (branch.Children[i].Count is 0)
 13454            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 13455          else
 13456            i++;
 13457        }
 13458        Node[] newArray = new Node[branch.Children.Length - skipped];
 13459        Array.Copy(branch.Children, newArray, newArray.Length);
 13460        branch.Children = newArray;
 13461
 13462        branch.Count -= removals;
 13463
 13464        if (branch.Count < _load && branch.Count != 0)
 13465          ShrinkChild(branch.Parent, branch.Index);
 13466
 13467        return removals;
 13468      }
 13469    }
 13470
 13471    /// <summary>Removes all the items in a given space.</summary>
 13472    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 13473    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 13474    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 13475    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 13476    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 13477    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 13478    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 13479    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 13480    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 13481    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 13482    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 13483    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 13484    /// <returns>The number of items that were removed.</returns>
 13485    public void Remove(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4, A
 13486    {
 13487      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2, min3,
 13488      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 13489    }
 13490    /// <summary>Removes all the items in a given space.</summary>
 13491    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 13492    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 13493    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 13494    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 13495    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 13496    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 13497    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 13498    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 13499    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 13500    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 13501    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 13502    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 13503    /// <returns>The number of items that were removed.</returns>
 13504    public void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 13505    {
 13506      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2, min3,
 13507      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 13508    }
 13509    internal int Remove(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds)
 13510    {
 13511      int removals = 0;
 13512      if (InclusionCheck(bounds, node.Bounds))
 13513      {
 13514        if (node is Leaf)
 13515        {
 13516          Leaf leaf = node as Leaf;
 13517          Leaf.Node current_node = leaf.Head;
 13518          Leaf.Node previous_node = null;
 13519          while (!(current_node is null))
 13520          {
 13521            Leaf.Node temp_previous = current_node;
 13522            if (EncapsulationCheck(bounds, LocateVector(current_node.Value)))
 13523            {
 13524              removals++;
 13525              if (current_node == leaf.Head)
 13526                leaf.Head = leaf.Head.Next;
 13527              else
 13528              {
 13529                previous_node.Next = current_node.Next;
 13530                temp_previous = previous_node;
 13531              }
 13532            }
 13533            previous_node = temp_previous;
 13534            current_node = current_node.Next;
 13535          }
 13536          leaf.Count -= removals;
 13537        }
 13538        else
 13539        {
 13540          Branch branch = node as Branch;
 13541          int skipped = 0;
 13542          for (int i = 0; i + skipped < branch.Children.Length; )
 13543          {
 13544            removals += this.Remove(branch.Children[i], bounds);
 13545            if (branch.Children[i].Count is 0)
 13546              branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 13547            else
 13548              i++;
 13549          }
 13550          Node[] newArray = new Node[branch.Children.Length - skipped];
 13551          Array.Copy(branch.Children, newArray, newArray.Length);
 13552          branch.Children = newArray;
 13553
 13554          branch.Count -= removals;
 13555          // convert this branch back into a leaf
 13556          // Note: if count is zero, it will be chopped off
 13557          if (branch.Count < _load && branch.Count > 0)
 13558            ShrinkChild(branch.Parent, branch.Index);
 13559        }
 13560      }
 13561
 13562      return removals;
 13563    }
 13564
 13565    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 13566    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 13567    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 13568    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 13569    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 13570    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 13571    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 13572    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 13573    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 13574    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 13575    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 13576    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 13577    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 13578    /// <param name="where">The equality constraint of the removal.</param>
 13579    public void Remove(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4, A
 13580    {
 13581      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2, min3,
 13582      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 13583    }
 13584    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 13585    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 13586    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 13587    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 13588    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 13589    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 13590    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 13591    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 13592    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 13593    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 13594    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 13595    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 13596    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 13597    /// <param name="where">The equality constraint of the removal.</param>
 13598    public void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 13599    {
 13600      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2, min3,
 13601      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 13602    }
 13603    internal int Remove(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds, Predicate<T> where)
 13604    {
 13605      if (!InclusionCheck(node.Bounds, bounds))
 13606        return 0;
 13607      int removals = 0;
 13608      if (node is Leaf)
 13609      {
 13610        Leaf leaf = node as Leaf;
 13611        Leaf.Node current = leaf.Head;
 13612        Leaf.Node previous = null;
 13613        while (current is not null)
 13614        {
 13615          if (this.EncapsulationCheck(bounds, LocateVector(current.Value)) && where(current.Value))
 13616          {
 13617            removals++;
 13618            if (previous is null)
 13619            {
 13620              leaf.Head = current.Next;
 13621              goto HeadRemoved;
 13622            }
 13623            else
 13624              previous.Next = current.Next;
 13625          }
 13626          previous = current;
 13627        HeadRemoved:
 13628          current = current.Next;
 13629        }
 13630
 13631        leaf.Count -= removals;
 13632        return removals;
 13633      }
 13634      else
 13635      {
 13636        Branch branch = node as Branch;
 13637        int skipped = 0;
 13638        for (int i = 0; i + skipped < branch.Children.Length; )
 13639        {
 13640          removals += this.Remove(branch.Children[i], bounds, where);
 13641          if (branch.Children[i].Count is 0)
 13642            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 13643          else
 13644            i++;
 13645        }
 13646        Node[] newArray = new Node[branch.Children.Length - skipped];
 13647        Array.Copy(branch.Children, newArray, newArray.Length);
 13648        branch.Children = newArray;
 13649
 13650        node.Count -= removals;
 13651
 13652        if (node.Count < _load && node.Count != 0)
 13653          ShrinkChild(node.Parent, node.Index);
 13654
 13655        return removals;
 13656      }
 13657    }
 13658
 13659    /// <summary>Tries to remove a value.</summary>
 13660    /// <param name="value">The value to remove.</param>
 13661    /// <returns>True if successful or false if not.</returns>
 13662    public (bool Success, Exception? Exception) TryRemove(T value)
 13663    {
 13664      Remove(value);
 13665      return (true, null);
 13666    }
 13667
 13668    /// <summary>Removes all instances of a given value.</summary>
 13669    public void Remove(T removal) => Omnitree.Remove(this, removal);
 13670
 13671    /// <summary>Removes all instances of a given value.</summary>
 13672    public void Remove(T removal, Func<T, T, bool> equate) => Omnitree.Remove(this, removal, equate);
 13673
 13674    /// <summary>Removes all the items in a given space.</summary>
 13675    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 13676    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 13677    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 13678    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 13679    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 13680    /// <param name="axis6">The axis of the removal along the  6D axis.</param>
 13681    /// <returns>The number of items that were removed.</returns>
 13682    public void Remove(Axis1 axis1
 13683      , Axis2 axis2
 13684      , Axis3 axis3
 13685      , Axis4 axis4
 13686      , Axis5 axis5
 13687      , Axis6 axis6
 13688      )
 13689    {
 13690      this.Remove(this._top, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(axis1
 13691        , axis2
 13692        , axis3
 13693        , axis4
 13694        , axis5
 13695        , axis6
 13696        ));
 13697      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 13698    }
 13699    internal int Remove(Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> vector)
 13700    {
 13701      int removals = 0;
 13702      if (node is Leaf)
 13703      {
 13704        Leaf leaf = node as Leaf;
 13705        Leaf.Node current_node = leaf.Head;
 13706        Leaf.Node previous_node = null;
 13707        while (!(current_node is null))
 13708        {
 13709          Leaf.Node temp_previous = current_node;
 13710          if (EqualsCheck(vector, LocateVector(current_node.Value)))
 13711          {
 13712            removals++;
 13713            if (current_node == leaf.Head)
 13714              leaf.Head = leaf.Head.Next;
 13715            else
 13716            {
 13717              previous_node.Next = current_node.Next;
 13718              temp_previous = previous_node;
 13719            }
 13720          }
 13721          previous_node = temp_previous;
 13722          current_node = current_node.Next;
 13723        }
 13724        leaf.Count -= removals;
 13725      }
 13726      else
 13727      {
 13728        Branch branch = node as Branch;
 13729        int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 13730        removals += Remove(branch[child_index], vector);
 13731        branch.Count -= removals;
 13732        // convert this branch back into a leaf
 13733        // Note: if count is zero, it will be chopped off
 13734        if (branch.Count < _load && branch.Count > 0)
 13735          ShrinkChild(branch.Parent, branch.Index);
 13736      }
 13737
 13738      return removals;
 13739    }
 13740
 13741    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 13742    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 13743    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 13744    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 13745    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 13746    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 13747    /// <param name="axis6">The axis of the removal along the  6D axis.</param>
 13748    /// <param name="where">The equality constraint of the removal.</param>
 13749    public void Remove(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6, Predicate<T> where)
 13750    {
 13751      this.Remove(this._top, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(axis1, axis2, axis3, axis4, a
 13752      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 13753    }
 13754    internal int Remove(Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> vector, Predicate<T> where)
 13755    {
 13756      int removals = 0;
 13757      if (node is Leaf)
 13758      {
 13759        Leaf leaf = node as Leaf;
 13760        Leaf.Node current_node = leaf.Head;
 13761        Leaf.Node previous_node = null;
 13762        while (!(current_node is null))
 13763        {
 13764          Leaf.Node temp_previous = current_node;
 13765          if (EqualsCheck(vector, LocateVector(current_node.Value)) && where(current_node.Value))
 13766          {
 13767            removals++;
 13768            if (current_node == leaf.Head)
 13769              leaf.Head = leaf.Head.Next;
 13770            else
 13771            {
 13772              previous_node.Next = current_node.Next;
 13773              temp_previous = previous_node;
 13774            }
 13775          }
 13776          previous_node = temp_previous;
 13777          current_node = current_node.Next;
 13778        }
 13779        leaf.Count -= removals;
 13780      }
 13781      else
 13782      {
 13783        Branch branch = node as Branch;
 13784        int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 13785        removals += Remove(branch[child_index], vector, where);
 13786        branch.Count -= removals;
 13787        // convert this branch back into a leaf
 13788        // Note: if count is zero, it will be chopped off
 13789        if (branch.Count < _load && branch.Count > 0)
 13790          ShrinkChild(branch.Parent, branch.Index);
 13791      }
 13792      return removals;
 13793    }
 13794
 13795    #endregion
 13796
 13797    #region Stepper And IEnumerable
 13798
 13799    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 13800    /// <param name="step">The delegate to perform on every item in the tree.</param>
 13801    public void Stepper(Action<T> step) =>
 13802      this.Stepper(step, this._top);
 13803
 13804    internal void Stepper(Action<T> step, Node node)
 13805    {
 13806      if (node is Leaf)
 13807      {
 13808        Leaf.Node list = (node as Leaf).Head;
 13809        while (list is not null)
 13810        {
 13811          step(list.Value);
 13812          list = list.Next;
 13813        }
 13814      }
 13815      else
 13816      {
 13817        foreach (Node child in (node as Branch).Children)
 13818          this.Stepper(step, child);
 13819      }
 13820    }
 13821
 13822    public StepStatus StepperBreak<TStep>(TStep step = default)
 13823      where TStep : struct, IFunc<T, StepStatus> =>
 13824      StepperBreak(_top, step);
 13825
 13826    internal StepStatus StepperBreak<TStep>(Node node, TStep step)
 13827      where TStep : struct, IFunc<T, StepStatus>
 13828    {
 13829      StepStatus status = StepStatus.Continue;
 13830      if (node is Leaf leaf)
 13831      {
 13832        for (Leaf.Node list = leaf.Head; list is not null; list = list.Next)
 13833        {
 13834          if (step.Invoke(list.Value) is Break) return Break;
 13835        }
 13836      }
 13837      else if (node is Branch branch)
 13838      {
 13839        foreach (Node child in branch.Children)
 13840        {
 13841          if (StepperBreak(child, step) is Break) return Break;
 13842        }
 13843      }
 13844      return Continue;
 13845    }
 13846
 13847    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 13848    /// <param name="step">The delegate to perform on every item in the tree.</param>
 13849    public StepStatus Stepper(Func<T, StepStatus> step) =>
 13850      Stepper(step, _top);
 13851
 13852    internal StepStatus Stepper(Func<T, StepStatus> step, Node node)
 13853    {
 13854      StepStatus status = StepStatus.Continue;
 13855      if (node is Leaf)
 13856      {
 13857        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 13858          if ((status = step(list.Value)) != StepStatus.Continue)
 13859            break;
 13860      }
 13861      else
 13862      {
 13863        foreach (Node child in (node as Branch).Children)
 13864          if ((status = Stepper(step, child)) != StepStatus.Continue)
 13865            break;
 13866      }
 13867      return status;
 13868    }
 13869
 13870    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 13871    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 13872    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 13873    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 13874    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 13875    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 13876    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 13877    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 13878    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 13879    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 13880    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 13881    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 13882    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 13883    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 13884    public void Stepper(Action<T> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 mi
 13885      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2, min3, ma
 13886
 13887    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 13888    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 13889    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 13890    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 13891    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 13892    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 13893    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 13894    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 13895    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 13896    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 13897    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 13898    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 13899    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 13900    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 13901    public void Stepper(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> mi
 13902      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2, min3, ma
 13903
 13904    internal void Stepper(Action<T> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds)
 13905    {
 13906      if (node is Leaf)
 13907      {
 13908        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 13909          if (EncapsulationCheck(bounds, LocateVector(list.Value)))
 13910            step(list.Value);
 13911      }
 13912      else
 13913      {
 13914        foreach (Node child in (node as Branch).Children)
 13915          // optimization: stop bounds checking if space encapsulates node
 13916          if (EncapsulationCheck(bounds, child.Bounds))
 13917            this.Stepper(step, child);
 13918          else if (InclusionCheck(child.Bounds, bounds))
 13919            this.Stepper(step, child, bounds);
 13920      }
 13921    }
 13922
 13923    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 13924    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 13925    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 13926    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 13927    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 13928    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 13929    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 13930    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 13931    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 13932    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 13933    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 13934    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 13935    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 13936    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 13937    public StepStatus Stepper(Func<T, StepStatus> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis
 13938      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2, min3, ma
 13939
 13940    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 13941    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 13942    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 13943    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 13944    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 13945    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 13946    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 13947    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 13948    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 13949    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 13950    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 13951    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 13952    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 13953    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 13954    public StepStatus Stepper(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree
 13955      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2, min3, ma
 13956
 13957    internal StepStatus Stepper(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, 
 13958    {
 13959      StepStatus status = StepStatus.Continue;
 13960      if (node is Leaf)
 13961      {
 13962        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 13963          if (EncapsulationCheck(bounds, LocateVector(list.Value)) &&
 13964            (status = step(list.Value)) != StepStatus.Continue)
 13965            break;
 13966      }
 13967      else
 13968      {
 13969        foreach (Node child in (node as Branch).Children)
 13970          // optimization: stop bounds checking if space encapsulates node
 13971          if (EncapsulationCheck(bounds, child.Bounds) &&
 13972            (status = this.Stepper(step, child)) != StepStatus.Continue)
 13973            break;
 13974          else if (InclusionCheck(child.Bounds, bounds) &&
 13975            (status = this.Stepper(step, child, bounds)) != StepStatus.Continue)
 13976            break;
 13977      }
 13978      return status;
 13979    }
 13980
 13981    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 13982    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 13983    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 13984    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 13985    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 13986    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 13987    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 13988    /// <param name="axis6">The axis of the removal along the  6D axis.</param>
 13989    public void Stepper(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6) =>
 13990      Stepper(step, _top, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(axis1, axis2, axis3, axis4, axis
 13991
 13992    internal void Stepper(Action<T> step, Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> vector)
 13993    {
 13994      Node current = node;
 13995      while (current is not null)
 13996      {
 13997        if (current is Leaf)
 13998        {
 13999          for (Leaf.Node leaf_node = (current as Leaf).Head; leaf_node is not null; leaf_node = leaf_node.Next)
 14000            if (EqualsCheck(vector, LocateVector(leaf_node.Value)))
 14001              step(leaf_node.Value);
 14002          break;
 14003        }
 14004        else
 14005        {
 14006          Branch branch = current as Branch;
 14007          int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 14008          current = branch[child_index];
 14009        }
 14010      }
 14011    }
 14012
 14013    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 14014    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 14015    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 14016    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 14017    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 14018    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 14019    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 14020    /// <param name="axis6">The axis of the removal along the  6D axis.</param>
 14021    public StepStatus Stepper(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5,
 14022      Stepper(step, _top, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(axis1, axis2, axis3, axis4, axis
 14023
 14024    internal StepStatus Stepper(Func<T, StepStatus> step, Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, 
 14025    {
 14026      Node current = node;
 14027      while (current is not null)
 14028      {
 14029        if (current is Leaf)
 14030        {
 14031          for (Leaf.Node list = (current as Leaf).Head; list is not null; list = list.Next)
 14032          {
 14033            StepStatus status = StepStatus.Continue;
 14034            if (EqualsCheck(vector, LocateVector(list.Value)) &&
 14035              (status = step(list.Value)) != StepStatus.Continue)
 14036              return status;
 14037          }
 14038        }
 14039        else
 14040        {
 14041          Branch branch = current as Branch;
 14042          int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 14043          current = branch[child_index];
 14044        }
 14045      }
 14046      return StepStatus.Continue;
 14047    }
 14048
 14049    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 14050
 14051    public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 14052    {
 14053      // Note: this can be optimized.
 14054      IList<T> list = new ListLinked<T>();
 14055      Stepper(x => list.Add(x));
 14056      return list.GetEnumerator();
 14057    }
 14058
 14059    #endregion
 14060
 14061    /// <inheritdoc/>
 14062    public T[] ToArray() => throw new NotImplementedException();
 14063
 14064    #region Helpers
 14065
 14066    internal bool StraddlesLines(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds, Omnitree.Vector<Axis1
 14067      Omnitree.StraddlesLines(bounds, vector
 14068        , _compare1
 14069        , _compare2
 14070        , _compare3
 14071        , _compare4
 14072        , _compare5
 14073        , _compare6
 14074        );
 14075
 14076    /// <summary>Computes the child index that contains the desired dimensions.</summary>
 14077    /// <param name="pointOfDivision">The point of division to compare against.</param>
 14078    /// <param name="vector">The dimensions to determine the child index.</param>
 14079    /// <returns>The computed child index based on the coordinates relative to the center of the node.</returns>
 14080    internal int DetermineChildIndex(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> pointOfDivision, Omnitree
 14081    {
 14082      int child = 0;
 14083      if (!(this._compare1(vector.Axis1, pointOfDivision.Axis1) is Less))
 14084        child += 1 << 0;
 14085      if (!(this._compare2(vector.Axis2, pointOfDivision.Axis2) is Less))
 14086        child += 1 << 1;
 14087      if (!(this._compare3(vector.Axis3, pointOfDivision.Axis3) is Less))
 14088        child += 1 << 2;
 14089      if (!(this._compare4(vector.Axis4, pointOfDivision.Axis4) is Less))
 14090        child += 1 << 3;
 14091      if (!(this._compare5(vector.Axis5, pointOfDivision.Axis5) is Less))
 14092        child += 1 << 4;
 14093      if (!(this._compare6(vector.Axis6, pointOfDivision.Axis6) is Less))
 14094        child += 1 << 5;
 14095      return child;
 14096    }
 14097
 14098    /// <summary>Converts a branch back into a leaf when the count is reduced.</summary>
 14099    /// <param name="parent">The parent to shrink a child of.</param>
 14100    /// <param name="child_index">The index of the child to shrink.</param>
 14101    internal void ShrinkChild(Branch parent, int child_index)
 14102    {
 14103      Leaf leaf;
 14104      Node removal = null;
 14105      if (parent is null) // top of tree
 14106      {
 14107        removal = this._top;
 14108        leaf = new Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>.None, null, -1);
 14109        this._top = leaf;
 14110      }
 14111      else // non-top branch
 14112      {
 14113        removal = parent[child_index];
 14114        leaf = new Leaf(removal.Bounds, removal.Parent, removal.Index);
 14115        parent[child_index] = leaf;
 14116      }
 14117
 14118      this.Stepper((T step) => { leaf.Add(step); }, removal);
 14119    }
 14120
 14121    /// <summary>Reduces the counts of all the parents of a given node by a given amount.</summary>
 14122    /// <param name="parent">The starting parent of the reduction.</param>
 14123    /// <param name="reduction">The amount to reduce the parent counts by.</param>
 14124    internal void ReduceParentCounts(Node parent, int reduction)
 14125    {
 14126      IncreaseParentCounts(parent, -reduction);
 14127    }
 14128
 14129    /// <summary>Increases the counts of all the parents of a given node by a given amount.</summary>
 14130    /// <param name="parent">The starting parent of the increase.</param>
 14131    /// <param name="increase">The amount to increase the parent counts by.</param>
 14132    internal void IncreaseParentCounts(Node parent, int increase)
 14133    {
 14134      Node node = parent;
 14135      while (node is not null)
 14136      {
 14137        node.Count += increase;
 14138        node = node.Parent;
 14139      }
 14140    }
 14141
 14142    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 14143    /// <returns>True if the spaces overlap; False if not.</returns>
 14144    internal bool InclusionCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> a, Omnitree.Bounds<Axis1, Axi
 14145      Omnitree.InclusionCheck(a, b
 14146      , _compare1
 14147      , _compare2
 14148      , _compare3
 14149      , _compare4
 14150      , _compare5
 14151      , _compare6
 14152      );
 14153
 14154    /// <summary>Checks if a space encapsulates a point.</summary>
 14155    /// <returns>True if the space encapsulates the point; False if not.</returns>
 14156    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds, Omnitree.Vector<A
 14157      Omnitree.EncapsulationCheck(bounds, vector
 14158      , _compare1
 14159      , _compare2
 14160      , _compare3
 14161      , _compare4
 14162      , _compare5
 14163      , _compare6
 14164      );
 14165
 14166    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 14167    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 14168    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> a, Omnitree.Bounds<Axis1,
 14169      Omnitree.EncapsulationCheck(a, b
 14170      , _compare1
 14171      , _compare2
 14172      , _compare3
 14173      , _compare4
 14174      , _compare5
 14175      , _compare6
 14176      );
 14177
 14178    /// <summary>Checks for equality between two locations.</summary>
 14179    /// <returns>True if equal; False if not;</returns>
 14180    internal bool EqualsCheck(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> a, Omnitree.Vector<Axis1, Axis2,
 14181      Omnitree.EqualsCheck(a, b
 14182      , (a, b) => _compare1(a, b) is Equal
 14183      , (a, b) => _compare2(a, b) is Equal
 14184      , (a, b) => _compare3(a, b) is Equal
 14185      , (a, b) => _compare4(a, b) is Equal
 14186      , (a, b) => _compare5(a, b) is Equal
 14187      , (a, b) => _compare6(a, b) is Equal
 14188      );
 14189
 14190    /// <summary>Gets the nearest parent that encapsulates a location.</summary>
 14191    /// <param name="node">The starting node to find the encapsulating parent of the location.</param>
 14192    /// <param name="vector">The coordinates of the value.</param>
 14193    /// <returns>The nearest node that encapsulates the given location.</returns>
 14194    internal Node GetEncapsulationParent(Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> vector)
 14195    {
 14196      while (node is not null && !EncapsulationCheck(node.Bounds, vector))
 14197      {
 14198        node = node.Parent;
 14199      }
 14200      return node;
 14201    }
 14202
 14203    internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> LocateVector(T value)
 14204    {
 14205      Axis1 axis1;
 14206      Axis2 axis2;
 14207      Axis3 axis3;
 14208      Axis4 axis4;
 14209      Axis5 axis5;
 14210      Axis6 axis6;
 14211      this._locate(value, out axis1
 14212, out axis2
 14213, out axis3
 14214, out axis4
 14215, out axis5
 14216, out axis6
 14217);
 14218      return new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(axis1, axis2, axis3, axis4, axis5, axis6);
 14219    }
 14220
 14221    #endregion
 14222
 14223    #endregion
 14224  }
 14225
 14226  #endregion
 14227
 14228  #region 7 Dimensional
 14229
 14230  /// <summary>Inheritance base for 7D omnitrees that store points.</summary>
 14231  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 14232  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 14233  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 14234  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 14235  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 14236  /// <typeparam name="Axis5">The type 5D axis.</typeparam>
 14237  /// <typeparam name="Axis6">The type 6D axis.</typeparam>
 14238  /// <typeparam name="Axis7">The type 7D axis.</typeparam>
 14239  public interface IOmnitreePoints<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> : IOmnitree<T, Axis1, Axis2, Axis
 14240  {
 14241    #region Properties
 14242
 14243    /// <summary>Steps through the values at a given location.</summary>
 14244    /// <param name="axis1">The coordinate along the 1D axis.</param>
 14245    /// <param name="axis2">The coordinate along the 2D axis.</param>
 14246    /// <param name="axis3">The coordinate along the 3D axis.</param>
 14247    /// <param name="axis4">The coordinate along the 4D axis.</param>
 14248    /// <param name="axis5">The coordinate along the 5D axis.</param>
 14249    /// <param name="axis6">The coordinate along the 6D axis.</param>
 14250    /// <param name="axis7">The coordinate along the 7D axis.</param>
 14251
 14252    /// <returns>A Stepper of the items at the given coordinates.</returns>
 14253    Action<Action<T>> this[Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6, Axis7 axis7] { 
 14254
 14255    /// <summary>The number of dimensions in this tree.</summary>
 14256    int Dimensions { get; }
 14257
 14258    /// <summary>The delegate being used by the omnitree to locate items in 7D space.</summary>
 14259    Omnitree.Location<T, Axis1
 14260      , Axis2
 14261      , Axis3
 14262      , Axis4
 14263      , Axis5
 14264      , Axis6
 14265      , Axis7
 14266      > Locate { get; }
 14267
 14268    #endregion
 14269
 14270    #region Methods
 14271
 14272    /// <summary>Counts the number of items in a sub space.</summary>
 14273    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 14274    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 14275    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 14276    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 14277    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 14278    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 14279    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 14280    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 14281    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 14282    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 14283    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 14284    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 14285    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 14286    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 14287    /// <returns>The number of items in the provided sub space.</returns>
 14288    int CountSubSpace(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound
 14289
 14290    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 14291    void Update();
 14292    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 14293    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 14294    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 14295    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 14296    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 14297    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 14298    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 14299    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 14300    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 14301    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 14302    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 14303    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 14304    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 14305    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 14306    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 14307    void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound<Axis2
 14308
 14309    /// <summary>Removes all the items in a given space.</summary>
 14310    /// <param name="axis1">The coordinate along the 1D axis.</param>
 14311    /// <param name="axis2">The coordinate along the 2D axis.</param>
 14312    /// <param name="axis3">The coordinate along the 3D axis.</param>
 14313    /// <param name="axis4">The coordinate along the 4D axis.</param>
 14314    /// <param name="axis5">The coordinate along the 5D axis.</param>
 14315    /// <param name="axis6">The coordinate along the 6D axis.</param>
 14316    /// <param name="axis7">The coordinate along the 7D axis.</param>
 14317    void Remove(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6, Axis7 axis7);
 14318    /// <summary>Removes all the items in a given space.</summary>
 14319    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 14320    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 14321    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 14322    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 14323    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 14324    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 14325    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 14326    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 14327    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 14328    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 14329    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 14330    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 14331    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 14332    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 14333    void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound<Axis2
 14334    /// <summary>Removes all the items in a given space where equality is met.</summary>
 14335    /// <param name="axis1">The coordinate along the 1D axis.</param>
 14336    /// <param name="axis2">The coordinate along the 2D axis.</param>
 14337    /// <param name="axis3">The coordinate along the 3D axis.</param>
 14338    /// <param name="axis4">The coordinate along the 4D axis.</param>
 14339    /// <param name="axis5">The coordinate along the 5D axis.</param>
 14340    /// <param name="axis6">The coordinate along the 6D axis.</param>
 14341    /// <param name="axis7">The coordinate along the 7D axis.</param>
 14342    /// <param name="where">The equality constraint of the removal.</param>
 14343    void Remove(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6, Axis7 axis7, Predicate<T> 
 14344    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 14345    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 14346    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 14347    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 14348    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 14349    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 14350    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 14351    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 14352    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 14353    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 14354    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 14355    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 14356    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 14357    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 14358    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 14359    /// <param name="where">The predicate constraint of the removal.</param>
 14360    void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Bound<Axis2
 14361
 14362    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 14363    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 14364    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 14365    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 14366    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 14367    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 14368    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 14369    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 14370    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 14371    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 14372    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 14373    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 14374    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 14375    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 14376    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 14377    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 14378    void Stepper(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omn
 14379    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 14380    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 14381    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 14382    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 14383    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 14384    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 14385    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 14386    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 14387    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 14388    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 14389    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 14390    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 14391    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 14392    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 14393    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 14394    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 14395    StepStatus Stepper(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<
 14396    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 14397    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 14398    /// <param name="axis1">The coordinate along the 1D axis.</param>
 14399    /// <param name="axis2">The coordinate along the 2D axis.</param>
 14400    /// <param name="axis3">The coordinate along the 3D axis.</param>
 14401    /// <param name="axis4">The coordinate along the 4D axis.</param>
 14402    /// <param name="axis5">The coordinate along the 5D axis.</param>
 14403    /// <param name="axis6">The coordinate along the 6D axis.</param>
 14404    /// <param name="axis7">The coordinate along the 7D axis.</param>
 14405    void Stepper(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6, Axis7 axi
 14406    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 14407    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 14408    /// <param name="axis1">The coordinate along the 1D axis.</param>
 14409    /// <param name="axis2">The coordinate along the 2D axis.</param>
 14410    /// <param name="axis3">The coordinate along the 3D axis.</param>
 14411    /// <param name="axis4">The coordinate along the 4D axis.</param>
 14412    /// <param name="axis5">The coordinate along the 5D axis.</param>
 14413    /// <param name="axis6">The coordinate along the 6D axis.</param>
 14414    /// <param name="axis7">The coordinate along the 7D axis.</param>
 14415    StepStatus Stepper(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 
 14416
 14417    #endregion
 14418  }
 14419
 14420  /// <summary>Omnitree that stores points along 7 dimensions implemented as a linked tree.</summary>
 14421  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 14422  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 14423  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 14424  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 14425  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 14426  /// <typeparam name="Axis5">The type 5D axis.</typeparam>
 14427  /// <typeparam name="Axis6">The type 6D axis.</typeparam>
 14428  /// <typeparam name="Axis7">The type 7D axis.</typeparam>
 14429  public class OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> : IOmnitreePoints<T, Axis1, Axis
 14430  {
 14431    internal const int _dimensions = 7;
 14432    internal static int _children_per_node = (int)BigInteger.Pow(2, 7);
 14433
 14434    internal Node _top;
 14435    internal int _naturalLogLower = 1; // caching the next time to calculate loads (lower count)
 14436    internal int _naturalLogUpper = -1; // caching the next time to calculate loads (upper count)
 14437    internal int _load; // ln(count); min = _defaultLoad
 14438    internal Omnitree.Location<T, Axis1
 14439      , Axis2
 14440      , Axis3
 14441      , Axis4
 14442      , Axis5
 14443      , Axis6
 14444      , Axis7
 14445      > _locate;
 14446    internal bool _defaultCompare1;
 14447    internal Func<Axis1, Axis1, CompareResult> _compare1;
 14448    internal bool _defaultCompare2;
 14449    internal Func<Axis2, Axis2, CompareResult> _compare2;
 14450    internal bool _defaultCompare3;
 14451    internal Func<Axis3, Axis3, CompareResult> _compare3;
 14452    internal bool _defaultCompare4;
 14453    internal Func<Axis4, Axis4, CompareResult> _compare4;
 14454    internal bool _defaultCompare5;
 14455    internal Func<Axis5, Axis5, CompareResult> _compare5;
 14456    internal bool _defaultCompare6;
 14457    internal Func<Axis6, Axis6, CompareResult> _compare6;
 14458    internal bool _defaultCompare7;
 14459    internal Func<Axis7, Axis7, CompareResult> _compare7;
 14460    internal Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> _s
 14461    internal Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> _s
 14462    internal Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> _s
 14463    internal Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> _s
 14464    internal Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> _s
 14465    internal Omnitree.SubdivisionOverride<T, Axis6, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> _s
 14466    internal Omnitree.SubdivisionOverride<T, Axis7, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> _s
 14467
 14468    #region Nested Types
 14469
 14470    /// <summary>Can be a leaf or a branch.</summary>
 14471    internal abstract class Node
 14472    {
 14473      internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> Bounds;
 14474      internal Branch Parent;
 14475      internal int Index;
 14476      internal int Count;
 14477
 14478      /// <summary>The depth this node is located in the Omnitree.</summary>
 14479      internal int Depth
 14480      {
 14481        get
 14482        {
 14483          int depth = -1;
 14484          for (Node node = this; node is not null; node = node.Parent)
 14485            depth++;
 14486          return depth;
 14487        }
 14488      }
 14489
 14490      /// <summary>Constructs a node.</summary>
 14491      /// <param name="bounds">The bounds of this node.</param>
 14492      /// <param name="parent">The parent of this node.</param>
 14493      /// <param name="index">The number of values stored in this node and its children.</param>
 14494      internal Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds, Branch parent, int index)
 14495      {
 14496        Bounds = bounds;
 14497        Parent = parent;
 14498        Index = index;
 14499      }
 14500
 14501      internal Node(Node nodeToClone)
 14502      {
 14503        this.Bounds = nodeToClone.Bounds;
 14504        this.Parent = nodeToClone.Parent;
 14505        this.Index = nodeToClone.Index;
 14506        this.Count = nodeToClone.Count;
 14507      }
 14508
 14509      internal abstract Node Clone();
 14510    }
 14511
 14512    /// <summary>A branch in the tree. Only contains nodes.</summary>
 14513    internal class Branch : Node
 14514    {
 14515      internal Node[] Children;
 14516      internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> PointOfDivision;
 14517
 14518      /// <summary>Gets child by index.</summary>
 14519      /// <param name="child_index">The index of the child to get.</param>
 14520      /// <returns>The child of the given index or null if non-existent.</returns>
 14521      internal Node this[int child_index]
 14522      {
 14523        get
 14524        {
 14525          if (Children is null)
 14526            return null;
 14527          if (Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>._children_per_
 14528            return Children[(int)child_index];
 14529          foreach (Node node in Children)
 14530            if (node.Index == child_index)
 14531              return node;
 14532          return null;
 14533        }
 14534        set
 14535        {
 14536          // This error check should be unnecessary... but fuck it... might as well
 14537          if (value.Index != child_index)
 14538            throw new System.Exception("Bug in Omnitree (index/property mis-match when setting a child on a branch)");
 14539
 14540          // no children yet
 14541          if (Children is null)
 14542          {
 14543            Children = â±¯(value);
 14544            return;
 14545          }
 14546          // max children overwrite
 14547          else if (this.Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>._chi
 14548          {
 14549            Children[(int)child_index] = value;
 14550            return;
 14551          }
 14552          // non-max child overwrite
 14553          for (int i = 0; i < Children.Length; i++)
 14554            if (Children[i].Index == child_index)
 14555            {
 14556              Children[i] = value;
 14557              return;
 14558            }
 14559          // new child
 14560          Node[] newArray = new Node[Children.Length + 1];
 14561          if (newArray.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>._children_per_
 14562          {
 14563            // new child resulting in a max children branch (sorting required)
 14564            for (int i = 0; i < Children.Length; i++)
 14565            {
 14566              newArray[(int)Children[i].Index] = Children[i];
 14567            }
 14568            newArray[(int)value.Index] = value;
 14569          }
 14570          else
 14571          {
 14572            // new child resulting in a non-max children branch
 14573            Array.Copy(Children, newArray, Children.Length);
 14574            newArray[newArray.Length - 1] = value;
 14575          }
 14576          this.Children = newArray;
 14577        }
 14578      }
 14579
 14580      internal Branch(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> pointOfDivision, Omnitree.Bounds<
 14581        : base(bounds, parent, index)
 14582      {
 14583        this.PointOfDivision = pointOfDivision;
 14584      }
 14585
 14586      internal Branch(Branch branchToClone) : base(branchToClone)
 14587      {
 14588        Children = branchToClone.Children.Clone() as Node[];
 14589        PointOfDivision = branchToClone.PointOfDivision;
 14590      }
 14591
 14592      internal override Node Clone() =>
 14593        new Branch(this);
 14594    }
 14595
 14596    /// <summary>A branch in the tree. Only contains items.</summary>
 14597    internal class Leaf : Node
 14598    {
 14599      internal class Node
 14600      {
 14601        internal T Value;
 14602        internal Leaf.Node Next;
 14603
 14604        internal Node(T value, Leaf.Node next)
 14605        {
 14606          Value = value;
 14607          Next = next;
 14608        }
 14609      }
 14610
 14611      internal Leaf.Node Head;
 14612
 14613      internal Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds, Branch parent, int index)
 14614        : base(bounds, parent, index)
 14615      { }
 14616
 14617      internal Leaf(Leaf leaf) : base(leaf)
 14618      {
 14619        Head = new Node(leaf.Head.Value, null);
 14620        Node a = Head;
 14621        Node b = leaf.Head;
 14622        while (b is not null)
 14623        {
 14624          a.Next = new Node(b.Next.Value, null);
 14625          a = a.Next;
 14626          b = b.Next;
 14627        }
 14628      }
 14629
 14630      internal void Add(T addition)
 14631      {
 14632        Head = new Leaf.Node(addition, Head);
 14633        this.Count++;
 14634      }
 14635
 14636      internal override OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>.Node Clone() =>
 14637        new Leaf(this);
 14638    }
 14639
 14640    #endregion
 14641
 14642    #region Constructors
 14643
 14644    /// <summary>This constructor is for cloning purposes</summary>
 14645    internal OmnitreePointsLinked(OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> omnitree)
 14646    {
 14647      this._top = omnitree._top.Clone();
 14648      this._load = omnitree._load;
 14649      this._locate = omnitree._locate;
 14650      this._defaultCompare1 = omnitree._defaultCompare1;
 14651      this._compare1 = omnitree._compare1;
 14652      this._defaultCompare2 = omnitree._defaultCompare2;
 14653      this._compare2 = omnitree._compare2;
 14654      this._defaultCompare3 = omnitree._defaultCompare3;
 14655      this._compare3 = omnitree._compare3;
 14656      this._defaultCompare4 = omnitree._defaultCompare4;
 14657      this._compare4 = omnitree._compare4;
 14658      this._defaultCompare5 = omnitree._defaultCompare5;
 14659      this._compare5 = omnitree._compare5;
 14660      this._defaultCompare6 = omnitree._defaultCompare6;
 14661      this._compare6 = omnitree._compare6;
 14662      this._defaultCompare7 = omnitree._defaultCompare7;
 14663      this._compare7 = omnitree._compare7;
 14664      this._subdivisionOverride1 = omnitree._subdivisionOverride1;
 14665      this._subdivisionOverride2 = omnitree._subdivisionOverride2;
 14666      this._subdivisionOverride3 = omnitree._subdivisionOverride3;
 14667      this._subdivisionOverride4 = omnitree._subdivisionOverride4;
 14668      this._subdivisionOverride5 = omnitree._subdivisionOverride5;
 14669      this._subdivisionOverride6 = omnitree._subdivisionOverride6;
 14670      this._subdivisionOverride7 = omnitree._subdivisionOverride7;
 14671    }
 14672
 14673    internal OmnitreePointsLinked(
 14674      Omnitree.Location<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> locate,
 14675      bool defaultCompare1,
 14676      Func<Axis1, Axis1, CompareResult> compare1,
 14677      bool defaultCompare2,
 14678      Func<Axis2, Axis2, CompareResult> compare2,
 14679      bool defaultCompare3,
 14680      Func<Axis3, Axis3, CompareResult> compare3,
 14681      bool defaultCompare4,
 14682      Func<Axis4, Axis4, CompareResult> compare4,
 14683      bool defaultCompare5,
 14684      Func<Axis5, Axis5, CompareResult> compare5,
 14685      bool defaultCompare6,
 14686      Func<Axis6, Axis6, CompareResult> compare6,
 14687      bool defaultCompare7,
 14688      Func<Axis7, Axis7, CompareResult> compare7,
 14689      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 14690,
 14691      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 14692,
 14693      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 14694,
 14695      Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 14696,
 14697      Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 14698,
 14699      Omnitree.SubdivisionOverride<T, Axis6, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 14700,
 14701      Omnitree.SubdivisionOverride<T, Axis7, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 14702      )
 14703    {
 14704      if (locate is null)
 14705      {
 14706        throw new ArgumentNullException(nameof(locate));
 14707      }
 14708      if (compare1 is null)
 14709      {
 14710        throw new ArgumentNullException(nameof(compare1));
 14711      }
 14712
 14713      if (compare2 is null)
 14714      {
 14715        throw new ArgumentNullException(nameof(compare2));
 14716      }
 14717
 14718      if (compare3 is null)
 14719      {
 14720        throw new ArgumentNullException(nameof(compare3));
 14721      }
 14722
 14723      if (compare4 is null)
 14724      {
 14725        throw new ArgumentNullException(nameof(compare4));
 14726      }
 14727
 14728      if (compare5 is null)
 14729      {
 14730        throw new ArgumentNullException(nameof(compare5));
 14731      }
 14732
 14733      if (compare6 is null)
 14734      {
 14735        throw new ArgumentNullException(nameof(compare6));
 14736      }
 14737
 14738      if (compare7 is null)
 14739      {
 14740        throw new ArgumentNullException(nameof(compare7));
 14741      }
 14742
 14743      this._locate = locate;
 14744      this._defaultCompare1 = defaultCompare1;
 14745      this._compare1 = compare1;
 14746      this._defaultCompare2 = defaultCompare2;
 14747      this._compare2 = compare2;
 14748      this._defaultCompare3 = defaultCompare3;
 14749      this._compare3 = compare3;
 14750      this._defaultCompare4 = defaultCompare4;
 14751      this._compare4 = compare4;
 14752      this._defaultCompare5 = defaultCompare5;
 14753      this._compare5 = compare5;
 14754      this._defaultCompare6 = defaultCompare6;
 14755      this._compare6 = compare6;
 14756      this._defaultCompare7 = defaultCompare7;
 14757      this._compare7 = compare7;
 14758      this._subdivisionOverride1 = subdivisionOverride1;
 14759      this._subdivisionOverride2 = subdivisionOverride2;
 14760      this._subdivisionOverride3 = subdivisionOverride3;
 14761      this._subdivisionOverride4 = subdivisionOverride4;
 14762      this._subdivisionOverride5 = subdivisionOverride5;
 14763      this._subdivisionOverride6 = subdivisionOverride6;
 14764      this._subdivisionOverride7 = subdivisionOverride7;
 14765      this._top = new Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>.None, null, -1);
 14766      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 14767    }
 14768
 14769    /// <summary>Constructs a new 7D omnitree that stores points.</summary>
 14770    /// <param name="locate">The delegate for locating items in 7D space.</param>
 14771
 14772    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 14773
 14774    /// <param name="compare2">The delegate for comparing values along the 2D axis.</param>
 14775
 14776    /// <param name="compare3">The delegate for comparing values along the 3D axis.</param>
 14777
 14778    /// <param name="compare4">The delegate for comparing values along the 4D axis.</param>
 14779
 14780    /// <param name="compare5">The delegate for comparing values along the 5D axis.</param>
 14781
 14782    /// <param name="compare6">The delegate for comparing values along the 6D axis.</param>
 14783
 14784    /// <param name="compare7">The delegate for comparing values along the 7D axis.</param>
 14785
 14786    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 14787
 14788    /// <param name="subdivisionOverride2">The subdivision overide to be used when splitting the 2 dimension.</param>
 14789
 14790    /// <param name="subdivisionOverride3">The subdivision overide to be used when splitting the 3 dimension.</param>
 14791
 14792    /// <param name="subdivisionOverride4">The subdivision overide to be used when splitting the 4 dimension.</param>
 14793
 14794    /// <param name="subdivisionOverride5">The subdivision overide to be used when splitting the 5 dimension.</param>
 14795
 14796    /// <param name="subdivisionOverride6">The subdivision overide to be used when splitting the 6 dimension.</param>
 14797
 14798    /// <param name="subdivisionOverride7">The subdivision overide to be used when splitting the 7 dimension.</param>
 14799    public OmnitreePointsLinked(
 14800      Omnitree.Location<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> locate,
 14801      Func<Axis1, Axis1, CompareResult> compare1 = null,
 14802      Func<Axis2, Axis2, CompareResult> compare2 = null,
 14803      Func<Axis3, Axis3, CompareResult> compare3 = null,
 14804      Func<Axis4, Axis4, CompareResult> compare4 = null,
 14805      Func<Axis5, Axis5, CompareResult> compare5 = null,
 14806      Func<Axis6, Axis6, CompareResult> compare6 = null,
 14807      Func<Axis7, Axis7, CompareResult> compare7 = null,
 14808      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 14809,
 14810      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 14811,
 14812      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 14813,
 14814      Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 14815,
 14816      Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 14817,
 14818      Omnitree.SubdivisionOverride<T, Axis6, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 14819,
 14820      Omnitree.SubdivisionOverride<T, Axis7, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 14821      )
 14822      : this(
 14823        locate,
 14824        compare1 is null ? true : false,
 14825        compare1 ?? Compare,
 14826        compare2 is null ? true : false,
 14827        compare2 ?? Compare,
 14828        compare3 is null ? true : false,
 14829        compare3 ?? Compare,
 14830        compare4 is null ? true : false,
 14831        compare4 ?? Compare,
 14832        compare5 is null ? true : false,
 14833        compare5 ?? Compare,
 14834        compare6 is null ? true : false,
 14835        compare6 ?? Compare,
 14836        compare7 is null ? true : false,
 14837        compare7 ?? Compare,
 14838        subdivisionOverride1
 14839,
 14840        subdivisionOverride2
 14841,
 14842        subdivisionOverride3
 14843,
 14844        subdivisionOverride4
 14845,
 14846        subdivisionOverride5
 14847,
 14848        subdivisionOverride6
 14849,
 14850        subdivisionOverride7
 14851        ) { }
 14852
 14853    #endregion
 14854
 14855    #region Properties
 14856
 14857    /// <summary>Steps through all the items at a given coordinate.</summary>
 14858    /// <param name="axis1">The coordinate along axis 1.</param>
 14859    /// <param name="axis2">The coordinate along axis 2.</param>
 14860    /// <param name="axis3">The coordinate along axis 3.</param>
 14861    /// <param name="axis4">The coordinate along axis 4.</param>
 14862    /// <param name="axis5">The coordinate along axis 5.</param>
 14863    /// <param name="axis6">The coordinate along axis 6.</param>
 14864    /// <param name="axis7">The coordinate along axis 7.</param>
 14865    /// <returns>The stepper for the items at the given coordinate.</returns>
 14866    public Action<Action<T>> this[Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6, Axis7 ax
 14867      step => Stepper(step, axis1, axis2, axis3, axis4, axis5, axis6, axis7);
 14868
 14869    /// <summary>The number of dimensions in this tree.</summary>
 14870    public int Dimensions { get { return _dimensions; } }
 14871
 14872    /// <summary>The location function the Omnitree is using.</summary>
 14873    public Omnitree.Location<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> Locate { get { return this._locate; } }
 14874
 14875    /// <summary>The comparison function the Omnitree is using along the 1D axis.</summary>
 14876    public Func<Axis1, Axis1, CompareResult> Compare1 { get { return this._compare1; } }
 14877    /// <summary>The comparison function the Omnitree is using along the 2D axis.</summary>
 14878    public Func<Axis2, Axis2, CompareResult> Compare2 { get { return this._compare2; } }
 14879    /// <summary>The comparison function the Omnitree is using along the 3D axis.</summary>
 14880    public Func<Axis3, Axis3, CompareResult> Compare3 { get { return this._compare3; } }
 14881    /// <summary>The comparison function the Omnitree is using along the 4D axis.</summary>
 14882    public Func<Axis4, Axis4, CompareResult> Compare4 { get { return this._compare4; } }
 14883    /// <summary>The comparison function the Omnitree is using along the 5D axis.</summary>
 14884    public Func<Axis5, Axis5, CompareResult> Compare5 { get { return this._compare5; } }
 14885    /// <summary>The comparison function the Omnitree is using along the 6D axis.</summary>
 14886    public Func<Axis6, Axis6, CompareResult> Compare6 { get { return this._compare6; } }
 14887    /// <summary>The comparison function the Omnitree is using along the 7D axis.</summary>
 14888    public Func<Axis7, Axis7, CompareResult> Compare7 { get { return this._compare7; } }
 14889
 14890    /// <summary>The current number of items in the tree.</summary>
 14891    public int Count { get { return this._top.Count; } }
 14892
 14893    internal delegate void MaxDepthFinder(Node node, int current_depth, ref int max_depth);
 14894    /// <summary>Finds the current maximum depth of the tree. NOT AN O(1) OPERATION. Intended for educational purposes o
 14895    public int MaxDepth
 14896    {
 14897      get
 14898      {
 14899        MaxDepthFinder maxDepthFinder = null;
 14900        maxDepthFinder =
 14901          (Node node, int current_depth, ref int max_depth) =>
 14902          {
 14903            if (current_depth > max_depth)
 14904              max_depth = current_depth;
 14905            if (node is Branch)
 14906              foreach (Node child in (node as Branch).Children)
 14907                maxDepthFinder(child, current_depth + 1, ref max_depth);
 14908          };
 14909        int _max_depth = -1;
 14910        maxDepthFinder(this._top, 0, ref _max_depth);
 14911        return _max_depth;
 14912      }
 14913    }
 14914
 14915    internal delegate void NodeCountFinder(Node node, ref int current_count);
 14916    /// <summary>Counts the current number of nodes in the tree. NOT AN O(1) OPERATION. Intended for educational purpose
 14917    public int NodeCount
 14918    {
 14919      get
 14920      {
 14921        NodeCountFinder nodeCountFinder = null;
 14922        nodeCountFinder =
 14923          (Node node, ref int current_count) =>
 14924          {
 14925            current_count++;
 14926            if (node is Branch)
 14927              foreach (Node child in (node as Branch).Children)
 14928                nodeCountFinder(child, ref current_count);
 14929          };
 14930
 14931        int _current_count = 0;
 14932        nodeCountFinder(this._top, ref _current_count);
 14933        return _current_count;
 14934      }
 14935    }
 14936
 14937    internal delegate void BranchCountFinder(Node node, ref int current_count);
 14938    /// <summary>Counts the current number of branches in the tree. NOT AN O(1) OPERATION. Intended for educational purp
 14939    public int BranchCount
 14940    {
 14941      get
 14942      {
 14943        BranchCountFinder branchCountFinder = null;
 14944        branchCountFinder =
 14945          (Node node, ref int current_count) =>
 14946          {
 14947            if (node is Branch)
 14948            {
 14949              current_count++;
 14950              foreach (Node child in (node as Branch).Children)
 14951                branchCountFinder(child, ref current_count);
 14952            }
 14953          };
 14954
 14955        int _current_count = 0;
 14956        branchCountFinder(this._top, ref _current_count);
 14957        return _current_count;
 14958      }
 14959    }
 14960
 14961    internal delegate void LeafCountFinder(Node node, ref int current_count);
 14962    /// <summary>Counts the current number of leaves in the tree. NOT AN O(1) OPERATION. Intended for educational purpos
 14963    public int LeafCount
 14964    {
 14965      get
 14966      {
 14967        LeafCountFinder leafCountFinder = null;
 14968        leafCountFinder =
 14969          (Node node, ref int current_count) =>
 14970          {
 14971            if (node is Leaf)
 14972              current_count++;
 14973            else
 14974              foreach (Node child in (node as Branch).Children)
 14975                leafCountFinder(child, ref current_count);
 14976          };
 14977
 14978        int _current_count = 0;
 14979        leafCountFinder(this._top, ref _current_count);
 14980        return _current_count;
 14981      }
 14982    }
 14983
 14984    #endregion
 14985
 14986    #region Methods
 14987
 14988    #region Add
 14989
 14990
 14991    #region single
 14992
 14993    /// <summary>Tries to add a value.</summary>
 14994    /// <param name="value">The value to be added.</param>
 14995    /// <returns>True if successful or false if not.</returns>
 14996    public (bool Success, Exception? Exception) TryAdd(T value)
 14997    {
 14998      Add(value);
 14999      return (true, null);
 15000    }
 15001
 15002    /// <summary>Adds an item to the tree.</summary>
 15003    /// <param name="addition">The item to be added.</param>
 15004    public void Add(T addition)
 15005    {
 15006      if (this._top.Count is int.MaxValue)
 15007        throw new System.InvalidOperationException("(Count is int.MaxValue) max Omnitree size reached (change ints to lo
 15008
 15009      // dynamic tree sizes
 15010      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 15011
 15012      Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> location = LocateVector(addition);
 15013
 15014      // grow the first branch of the tree
 15015      if (this._top is Leaf && (this._top as Leaf).Count >= _load)
 15016      {
 15017        Leaf top = this._top as Leaf;
 15018
 15019        // create the new branch from the median values
 15020        this._top = new Branch(DetermineMedians(top), Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>.N
 15021
 15022        // iterate through the values and add them to the appropriate children
 15023        for (Leaf.Node list = top.Head; list is not null; list = list.Next)
 15024          Add(list.Value, this._top, LocateVector(list.Value), 0);
 15025      }
 15026
 15027      this.Add(addition, this._top, location, 0);
 15028    }
 15029
 15030    /// <summary>Recursive version of the add function.</summary>
 15031    /// <param name="addition">The item to be added.</param>
 15032    /// <param name="node">The current node for tree trversal.</param>
 15033    /// <param name="location">The location of the addition.</param>
 15034    /// <param name="depth">The current depth of iteration.</param>
 15035    internal void Add(T addition, Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> location, 
 15036    {
 15037      if (node is Leaf)
 15038      {
 15039        Leaf leaf = node as Leaf;
 15040        if (depth >= _load || !(leaf.Count >= _load))
 15041        {
 15042          leaf.Add(addition);
 15043          return;
 15044        }
 15045        else
 15046        {
 15047          Branch parent = node.Parent;
 15048          int child_index = this.DetermineChildIndex(parent.PointOfDivision, location);
 15049          Branch growth = new Branch(DetermineMedians(leaf), leaf.Bounds, parent, child_index);
 15050          parent[child_index] = growth;
 15051          for (Leaf.Node list = leaf.Head; list is not null; list = list.Next)
 15052          {
 15053            Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> temp_location = LocateVector(list.Value);
 15054            if (EncapsulationCheck(growth.Bounds, temp_location))
 15055              Add(list.Value, growth, temp_location, depth);
 15056            else
 15057            {
 15058              ReduceParentCounts(parent, 1);
 15059              Add(list.Value, this._top, temp_location, depth);
 15060            }
 15061          }
 15062
 15063          Add(addition, growth, location, depth);
 15064          return;
 15065        }
 15066      }
 15067      else
 15068      {
 15069        Branch branch = node as Branch;
 15070        int child_index = this.DetermineChildIndex(branch.PointOfDivision, location); // determine the child "index" (0 
 15071        Node child_node = branch[child_index];
 15072
 15073        // null children in branches are just empty leaves
 15074        if (child_node is null)
 15075        {
 15076          Leaf new_leaf = new Leaf(DetermineChildBounds(branch, child_index), branch, child_index);
 15077          branch[child_index] = new_leaf;
 15078          new_leaf.Add(addition);
 15079        }
 15080        else
 15081          // child exists already, continue adding
 15082          Add(addition, child_node, location, depth + 1);
 15083
 15084        branch.Count++;
 15085        return;
 15086      }
 15087    }
 15088
 15089    internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> DetermineMedians(Leaf leaf)
 15090    {
 15091
 15092      Axis1 division1;
 15093      if (!(_subdivisionOverride1 is null))
 15094      {
 15095        division1 = _subdivisionOverride1(leaf.Bounds, x =>
 15096          {
 15097            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 15098            {
 15099              x(node.Value);
 15100            }
 15101          });
 15102      }
 15103      else
 15104      {
 15105        Axis1[] values = new Axis1[leaf.Count];
 15106        Leaf.Node for_current = leaf.Head;
 15107        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 15108          this._locate(for_current.Value
 15109          , out values[i]
 15110          , out _
 15111          , out _
 15112          , out _
 15113          , out _
 15114          , out _
 15115          , out _
 15116          );
 15117        if (_defaultCompare1) Array.Sort(values);
 15118        else SortQuick<Axis1>(values, this._compare1);
 15119        int index = (leaf.Count - 1) / 2;
 15120        division1 = values[index];
 15121      }
 15122
 15123      Axis2 division2;
 15124      if (!(_subdivisionOverride2 is null))
 15125      {
 15126        division2 = _subdivisionOverride2(leaf.Bounds, x =>
 15127          {
 15128            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 15129            {
 15130              x(node.Value);
 15131            }
 15132          });
 15133      }
 15134      else
 15135      {
 15136        Axis2[] values = new Axis2[leaf.Count];
 15137        Leaf.Node for_current = leaf.Head;
 15138        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 15139          this._locate(for_current.Value
 15140          , out _
 15141          , out values[i]
 15142          , out _
 15143          , out _
 15144          , out _
 15145          , out _
 15146          , out _
 15147          );
 15148        if (_defaultCompare2) Array.Sort(values);
 15149        else SortQuick<Axis2>(values, this._compare2);
 15150        int index = (leaf.Count - 1) / 2;
 15151        division2 = values[index];
 15152      }
 15153
 15154      Axis3 division3;
 15155      if (!(_subdivisionOverride3 is null))
 15156      {
 15157        division3 = _subdivisionOverride3(leaf.Bounds, x =>
 15158          {
 15159            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 15160            {
 15161              x(node.Value);
 15162            }
 15163          });
 15164      }
 15165      else
 15166      {
 15167        Axis3[] values = new Axis3[leaf.Count];
 15168        Leaf.Node for_current = leaf.Head;
 15169        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 15170          this._locate(for_current.Value
 15171          , out _
 15172          , out _
 15173          , out values[i]
 15174          , out _
 15175          , out _
 15176          , out _
 15177          , out _
 15178          );
 15179        if (_defaultCompare3) Array.Sort(values);
 15180        else SortQuick<Axis3>(values, this._compare3);
 15181        int index = (leaf.Count - 1) / 2;
 15182        division3 = values[index];
 15183      }
 15184
 15185      Axis4 division4;
 15186      if (!(_subdivisionOverride4 is null))
 15187      {
 15188        division4 = _subdivisionOverride4(leaf.Bounds, x =>
 15189          {
 15190            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 15191            {
 15192              x(node.Value);
 15193            }
 15194          });
 15195      }
 15196      else
 15197      {
 15198        Axis4[] values = new Axis4[leaf.Count];
 15199        Leaf.Node for_current = leaf.Head;
 15200        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 15201          this._locate(for_current.Value
 15202          , out _
 15203          , out _
 15204          , out _
 15205          , out values[i]
 15206          , out _
 15207          , out _
 15208          , out _
 15209          );
 15210        if (_defaultCompare4) Array.Sort(values);
 15211        else SortQuick<Axis4>(values, this._compare4);
 15212        int index = (leaf.Count - 1) / 2;
 15213        division4 = values[index];
 15214      }
 15215
 15216      Axis5 division5;
 15217      if (!(_subdivisionOverride5 is null))
 15218      {
 15219        division5 = _subdivisionOverride5(leaf.Bounds, x =>
 15220          {
 15221            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 15222            {
 15223              x(node.Value);
 15224            }
 15225          });
 15226      }
 15227      else
 15228      {
 15229        Axis5[] values = new Axis5[leaf.Count];
 15230        Leaf.Node for_current = leaf.Head;
 15231        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 15232          this._locate(for_current.Value
 15233          , out _
 15234          , out _
 15235          , out _
 15236          , out _
 15237          , out values[i]
 15238          , out _
 15239          , out _
 15240          );
 15241        if (_defaultCompare5) Array.Sort(values);
 15242        else SortQuick<Axis5>(values, this._compare5);
 15243        int index = (leaf.Count - 1) / 2;
 15244        division5 = values[index];
 15245      }
 15246
 15247      Axis6 division6;
 15248      if (!(_subdivisionOverride6 is null))
 15249      {
 15250        division6 = _subdivisionOverride6(leaf.Bounds, x =>
 15251          {
 15252            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 15253            {
 15254              x(node.Value);
 15255            }
 15256          });
 15257      }
 15258      else
 15259      {
 15260        Axis6[] values = new Axis6[leaf.Count];
 15261        Leaf.Node for_current = leaf.Head;
 15262        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 15263          this._locate(for_current.Value
 15264          , out _
 15265          , out _
 15266          , out _
 15267          , out _
 15268          , out _
 15269          , out values[i]
 15270          , out _
 15271          );
 15272        if (_defaultCompare6) Array.Sort(values);
 15273        else SortQuick<Axis6>(values, this._compare6);
 15274        int index = (leaf.Count - 1) / 2;
 15275        division6 = values[index];
 15276      }
 15277
 15278      Axis7 division7;
 15279      if (!(_subdivisionOverride7 is null))
 15280      {
 15281        division7 = _subdivisionOverride7(leaf.Bounds, x =>
 15282          {
 15283            for (Leaf.Node node = leaf.Head; node is not null; node = node.Next)
 15284            {
 15285              x(node.Value);
 15286            }
 15287          });
 15288      }
 15289      else
 15290      {
 15291        Axis7[] values = new Axis7[leaf.Count];
 15292        Leaf.Node for_current = leaf.Head;
 15293        for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
 15294          this._locate(for_current.Value
 15295          , out _
 15296          , out _
 15297          , out _
 15298          , out _
 15299          , out _
 15300          , out _
 15301          , out values[i]
 15302          );
 15303        if (_defaultCompare7) Array.Sort(values);
 15304        else SortQuick<Axis7>(values, this._compare7);
 15305        int index = (leaf.Count - 1) / 2;
 15306        division7 = values[index];
 15307      }
 15308
 15309      return new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(
 15310        division1
 15311
 15312        , division2
 15313
 15314        , division3
 15315
 15316        , division4
 15317
 15318        , division5
 15319
 15320        , division6
 15321
 15322        , division7
 15323
 15324        );
 15325    }
 15326
 15327    #endregion
 15328
 15329    #region Add Helpers
 15330
 15331    internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> DetermineChildBounds(Branch branch, int ch
 15332    {
 15333
 15334      Omnitree.Bound<Axis7> min7, max7;
 15335      if (child_index >= 64)
 15336      {
 15337        min7 = branch.PointOfDivision.Axis7;
 15338        max7 = branch.Bounds.Max7;
 15339        child_index -= 64;
 15340      }
 15341      else
 15342      {
 15343        min7 = branch.Bounds.Min7;
 15344        max7 = branch.PointOfDivision.Axis7;
 15345      }
 15346
 15347      Omnitree.Bound<Axis6> min6, max6;
 15348      if (child_index >= 32)
 15349      {
 15350        min6 = branch.PointOfDivision.Axis6;
 15351        max6 = branch.Bounds.Max6;
 15352        child_index -= 32;
 15353      }
 15354      else
 15355      {
 15356        min6 = branch.Bounds.Min6;
 15357        max6 = branch.PointOfDivision.Axis6;
 15358      }
 15359
 15360      Omnitree.Bound<Axis5> min5, max5;
 15361      if (child_index >= 16)
 15362      {
 15363        min5 = branch.PointOfDivision.Axis5;
 15364        max5 = branch.Bounds.Max5;
 15365        child_index -= 16;
 15366      }
 15367      else
 15368      {
 15369        min5 = branch.Bounds.Min5;
 15370        max5 = branch.PointOfDivision.Axis5;
 15371      }
 15372
 15373      Omnitree.Bound<Axis4> min4, max4;
 15374      if (child_index >= 8)
 15375      {
 15376        min4 = branch.PointOfDivision.Axis4;
 15377        max4 = branch.Bounds.Max4;
 15378        child_index -= 8;
 15379      }
 15380      else
 15381      {
 15382        min4 = branch.Bounds.Min4;
 15383        max4 = branch.PointOfDivision.Axis4;
 15384      }
 15385
 15386      Omnitree.Bound<Axis3> min3, max3;
 15387      if (child_index >= 4)
 15388      {
 15389        min3 = branch.PointOfDivision.Axis3;
 15390        max3 = branch.Bounds.Max3;
 15391        child_index -= 4;
 15392      }
 15393      else
 15394      {
 15395        min3 = branch.Bounds.Min3;
 15396        max3 = branch.PointOfDivision.Axis3;
 15397      }
 15398
 15399      Omnitree.Bound<Axis2> min2, max2;
 15400      if (child_index >= 2)
 15401      {
 15402        min2 = branch.PointOfDivision.Axis2;
 15403        max2 = branch.Bounds.Max2;
 15404        child_index -= 2;
 15405      }
 15406      else
 15407      {
 15408        min2 = branch.Bounds.Min2;
 15409        max2 = branch.PointOfDivision.Axis2;
 15410      }
 15411
 15412      Omnitree.Bound<Axis1> min1, max1;
 15413      if (child_index >= 1)
 15414      {
 15415        min1 = branch.PointOfDivision.Axis1;
 15416        max1 = branch.Bounds.Max1;
 15417        child_index -= 1;
 15418      }
 15419      else
 15420      {
 15421        min1 = branch.Bounds.Min1;
 15422        max1 = branch.PointOfDivision.Axis1;
 15423      }
 15424
 15425      return new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min2, max2, min3, max3, mi
 15426    }
 15427
 15428    #endregion
 15429
 15430    #endregion
 15431
 15432    #region Clear
 15433
 15434    /// <summary>Returns the tree to an empty state.</summary>
 15435    public void Clear()
 15436    {
 15437      this._top = new Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>.None, null, -1);
 15438      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 15439    }
 15440
 15441    #endregion
 15442
 15443    #region Clone
 15444
 15445    /// <summary>Creates a shallow clone of this data structure.</summary>
 15446    /// <returns>A shallow clone of this data structure.</returns>
 15447    public OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> Clone()
 15448    {
 15449      return new OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(this);
 15450    }
 15451
 15452    #endregion
 15453
 15454    #region Count
 15455
 15456    /// <summary>Counts the number of items in a sub space.</summary>
 15457    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 15458    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 15459    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 15460    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 15461    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 15462    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 15463    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 15464    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 15465    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 15466    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 15467    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 15468    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 15469    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 15470    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 15471    /// <returns>The number of items in the provided sub space.</returns>
 15472    public int CountSubSpace(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 m
 15473    {
 15474      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min2, 
 15475    }
 15476    /// <summary>Counts the number of items in a sub space.</summary>
 15477    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 15478    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 15479    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 15480    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 15481    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 15482    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 15483    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 15484    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 15485    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 15486    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 15487    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 15488    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 15489    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 15490    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 15491    /// <returns>The number of items in the provided sub space.</returns>
 15492    public int CountSubSpace(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitre
 15493    {
 15494      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min2, 
 15495    }
 15496    /// <summary>Counts the number of items in a sub space.</summary>
 15497    /// <param name="axis1">The coordinate along the 1D axis.</param>
 15498    /// <param name="axis2">The coordinate along the 2D axis.</param>
 15499    /// <param name="axis3">The coordinate along the 3D axis.</param>
 15500    /// <param name="axis4">The coordinate along the 4D axis.</param>
 15501    /// <param name="axis5">The coordinate along the 5D axis.</param>
 15502    /// <param name="axis6">The coordinate along the 6D axis.</param>
 15503    /// <param name="axis7">The coordinate along the 7D axis.</param>
 15504    /// <returns>The number of items in the provided sub space.</returns>
 15505    public int CountSubSpace(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6, Axis7 axis7)
 15506    {
 15507      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(axis1, axis1, axis
 15508    }
 15509    /// <summary>Counts the number of items in a sub space.</summary>
 15510    /// <param name="axis1">The coordinate along the 1D axis.</param>
 15511    /// <param name="axis2">The coordinate along the 2D axis.</param>
 15512    /// <param name="axis3">The coordinate along the 3D axis.</param>
 15513    /// <param name="axis4">The coordinate along the 4D axis.</param>
 15514    /// <param name="axis5">The coordinate along the 5D axis.</param>
 15515    /// <param name="axis6">The coordinate along the 6D axis.</param>
 15516    /// <param name="axis7">The coordinate along the 7D axis.</param>
 15517    /// <returns>The number of items in the provided sub space.</returns>
 15518    public int CountSubSpace(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3, Omni
 15519    {
 15520      return CountSubSpace(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(axis1, axis1, axis
 15521    }
 15522    /// <summary>Counts the number of items in a sub space.</summary>
 15523    /// <param name="node">The current traversal node.</param>
 15524    /// <param name="bounds">The bounds of the sub space being counted.</param>
 15525    /// <returns>The number of items in the provided sub space.</returns>
 15526    internal int CountSubSpace(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds)
 15527    {
 15528      // adjust min/max values
 15529      int count = 0;
 15530      if (EncapsulationCheck(bounds, node.Bounds))
 15531        count += node.Count;
 15532      else if (node is Leaf)
 15533      {
 15534        for (Leaf.Node list = (node as Leaf).Head; list is null; list = list.Next)
 15535          if (EncapsulationCheck(bounds, LocateVector(list.Value)))
 15536            count++;
 15537      }
 15538      else
 15539      {
 15540        Branch branch = node as Branch;
 15541        if (!StraddlesLines(branch.Bounds, branch.PointOfDivision))
 15542        {
 15543          int child_index = DetermineChildIndex(branch.PointOfDivision, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, 
 15544            , bounds.Min2.Value
 15545            , bounds.Min3.Value
 15546            , bounds.Min4.Value
 15547            , bounds.Min5.Value
 15548            , bounds.Min6.Value
 15549            , bounds.Min7.Value
 15550            ));
 15551          Node child = branch[child_index];
 15552          if (child is not null)
 15553          {
 15554            count += this.CountSubSpace(child, bounds);
 15555          }
 15556        }
 15557        else
 15558        {
 15559          foreach (Node child in (node as Branch).Children)
 15560            count += this.CountSubSpace(child, bounds);
 15561        }
 15562      }
 15563      return count;
 15564    }
 15565
 15566    #endregion
 15567
 15568    #region Update
 15569
 15570    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 15571    public void Update()
 15572    {
 15573      this.Update(this._top, 0);
 15574    }
 15575
 15576    /// <summary>Recursive version of the Update method.</summary>
 15577    /// <param name="node">The current node of iteration.</param>
 15578    /// <param name="depth">The current depth of iteration.</param>
 15579    internal int Update(Node node, int depth)
 15580    {
 15581      int removals = 0;
 15582
 15583      if (node is Leaf)
 15584      {
 15585        Leaf leaf = node as Leaf;
 15586        Leaf.Node current = leaf.Head;
 15587        Leaf.Node previous = null;
 15588        while (current is not null)
 15589        {
 15590          Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> location = LocateVector(current.Value);
 15591          if (!this.EncapsulationCheck(node.Bounds, location))
 15592          {
 15593            removals++;
 15594            T updated = current.Value;
 15595            if (previous is null)
 15596            {
 15597              leaf.Head = current.Next;
 15598              goto HeadRemoved;
 15599            }
 15600            else
 15601              previous.Next = current.Next;
 15602
 15603            Node whereToAdd = GetEncapsulationParent(node.Parent, location);
 15604
 15605            if (whereToAdd is null)
 15606              throw new System.Exception("an item was updated outside the range of the omnitree");
 15607
 15608            this.Add(updated, whereToAdd, location, whereToAdd.Depth);
 15609          }
 15610          previous = current;
 15611        HeadRemoved:
 15612          current = current.Next;
 15613        }
 15614        leaf.Count -= removals;
 15615        return removals;
 15616      }
 15617      else
 15618      {
 15619        Branch branch = node as Branch;
 15620        int skipped = 0;
 15621        for (int i = 0; i + skipped < branch.Children.Length; )
 15622        {
 15623          removals += this.Update(branch.Children[i], depth + 1);
 15624          if (branch.Children[i].Count is 0)
 15625            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 15626          else
 15627            i++;
 15628        }
 15629        Node[] newArray = new Node[branch.Children.Length - skipped];
 15630        Array.Copy(branch.Children, newArray, newArray.Length);
 15631        branch.Children = newArray;
 15632
 15633        branch.Count -= removals;
 15634
 15635        if (branch.Count < _load && branch.Count != 0)
 15636          ShrinkChild(branch.Parent, branch.Index);
 15637      }
 15638
 15639      return removals;
 15640    }
 15641
 15642    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 15643    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 15644    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 15645    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 15646    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 15647    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 15648    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 15649    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 15650    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 15651    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 15652    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 15653    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 15654    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 15655    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 15656    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 15657    public void Update(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4, A
 15658    {
 15659      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min2, max2, min3, max
 15660    }
 15661    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 15662    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 15663    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 15664    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 15665    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 15666    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 15667    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 15668    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 15669    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 15670    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 15671    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 15672    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 15673    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 15674    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 15675    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 15676    public void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 15677    {
 15678      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min2, max2, min3, max
 15679    }
 15680    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 15681    /// <param name="axis1">The coordinate along the 1D axis.</param>
 15682    /// <param name="axis2">The coordinate along the 2D axis.</param>
 15683    /// <param name="axis3">The coordinate along the 3D axis.</param>
 15684    /// <param name="axis4">The coordinate along the 4D axis.</param>
 15685    /// <param name="axis5">The coordinate along the 5D axis.</param>
 15686    /// <param name="axis6">The coordinate along the 6D axis.</param>
 15687    /// <param name="axis7">The coordinate along the 7D axis.</param>
 15688    public void Update(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6, Axis7 axis7)
 15689    {
 15690      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(axis1, axis1, axis2, axis2, axis3
 15691    }
 15692    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 15693    /// <param name="axis1">The coordinate along the 1D axis.</param>
 15694    /// <param name="axis2">The coordinate along the 2D axis.</param>
 15695    /// <param name="axis3">The coordinate along the 3D axis.</param>
 15696    /// <param name="axis4">The coordinate along the 4D axis.</param>
 15697    /// <param name="axis5">The coordinate along the 5D axis.</param>
 15698    /// <param name="axis6">The coordinate along the 6D axis.</param>
 15699    /// <param name="axis7">The coordinate along the 7D axis.</param>
 15700    public void Update(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3, Omnitree.B
 15701    {
 15702      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(axis1, axis1, axis2, axis2, axis3
 15703    }
 15704    internal int Update(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds, Node node, int depth)
 15705    {
 15706      if (!InclusionCheck(bounds, node.Bounds))
 15707        return 0;
 15708
 15709      int removals = 0;
 15710
 15711      if (node is Leaf)
 15712      {
 15713        Leaf leaf = node as Leaf;
 15714        Leaf.Node current = leaf.Head;
 15715        Leaf.Node previous = null;
 15716        while (current is not null)
 15717        {
 15718          Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> location = LocateVector(current.Value);
 15719          if (!this.EncapsulationCheck(node.Bounds, location))
 15720          {
 15721            removals++;
 15722            T updated = current.Value;
 15723            if (previous is null)
 15724            {
 15725              leaf.Head = current.Next;
 15726              goto HeadRemoved;
 15727            }
 15728            else
 15729              previous.Next = current.Next;
 15730            Node whereToAdd = GetEncapsulationParent(node.Parent, location);
 15731            if (whereToAdd is null)
 15732              throw new System.Exception("an item was updates outside the range of the omnitree");
 15733            this.Add(updated, whereToAdd, location, whereToAdd.Depth);
 15734          }
 15735          previous = current;
 15736        HeadRemoved:
 15737          current = current.Next;
 15738        }
 15739        leaf.Count -= removals;
 15740        return removals;
 15741      }
 15742      else
 15743      {
 15744        Branch branch = node as Branch;
 15745        int skipped = 0;
 15746        for (int i = 0; i + skipped < branch.Children.Length; )
 15747        {
 15748          removals += this.Update(branch.Children[i], depth + 1);
 15749          if (branch.Children[i].Count is 0)
 15750            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 15751          else
 15752            i++;
 15753        }
 15754        Node[] newArray = new Node[branch.Children.Length - skipped];
 15755        Array.Copy(branch.Children, newArray, newArray.Length);
 15756        branch.Children = newArray;
 15757
 15758        branch.Count -= removals;
 15759
 15760        if (branch.Count < _load && branch.Count != 0)
 15761          ShrinkChild(branch.Parent, branch.Index);
 15762      }
 15763
 15764      return removals;
 15765    }
 15766
 15767    #endregion
 15768
 15769    #region Remove
 15770
 15771    /// <summary>Removes all the items qualified by the delegate.</summary>
 15772    /// <param name="where">The predicate to qualify removals.</param>
 15773    public void Remove(Predicate<T> where)
 15774    {
 15775      this.Remove(this._top, where);
 15776      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 15777    }
 15778
 15779    /// <summary>Recursive version of the remove method.</summary>
 15780    /// <param name="node">The current node of traversal.</param>
 15781    /// <param name="where">The predicate to qualify removals.</param>
 15782    internal int Remove(Node node, Predicate<T> where)
 15783    {
 15784      int removals = 0;
 15785      if (node is Leaf)
 15786      {
 15787        Leaf leaf = node as Leaf;
 15788        while (leaf.Head is not null && where(leaf.Head.Value))
 15789        {
 15790          leaf.Head = leaf.Head.Next;
 15791          removals++;
 15792        }
 15793        if (leaf.Head is not null)
 15794        {
 15795          Leaf.Node list = leaf.Head;
 15796          while (list.Next is not null)
 15797          {
 15798            if (where(list.Next.Value))
 15799            {
 15800              list.Next = list.Next.Next;
 15801              removals++;
 15802            }
 15803          }
 15804        }
 15805
 15806        leaf.Count -= removals;
 15807        return removals;
 15808      }
 15809      else
 15810      {
 15811        Branch branch = node as Branch;
 15812        int skipped = 0;
 15813        for (int i = 0; i + skipped < branch.Children.Length; )
 15814        {
 15815          removals += this.Remove(branch.Children[i], where);
 15816          if (branch.Children[i].Count is 0)
 15817            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 15818          else
 15819            i++;
 15820        }
 15821        Node[] newArray = new Node[branch.Children.Length - skipped];
 15822        Array.Copy(branch.Children, newArray, newArray.Length);
 15823        branch.Children = newArray;
 15824
 15825        branch.Count -= removals;
 15826
 15827        if (branch.Count < _load && branch.Count != 0)
 15828          ShrinkChild(branch.Parent, branch.Index);
 15829
 15830        return removals;
 15831      }
 15832    }
 15833
 15834    /// <summary>Removes all the items in a given space.</summary>
 15835    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 15836    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 15837    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 15838    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 15839    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 15840    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 15841    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 15842    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 15843    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 15844    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 15845    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 15846    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 15847    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 15848    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 15849    /// <returns>The number of items that were removed.</returns>
 15850    public void Remove(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4, A
 15851    {
 15852      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min2, max2
 15853      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 15854    }
 15855    /// <summary>Removes all the items in a given space.</summary>
 15856    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 15857    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 15858    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 15859    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 15860    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 15861    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 15862    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 15863    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 15864    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 15865    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 15866    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 15867    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 15868    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 15869    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 15870    /// <returns>The number of items that were removed.</returns>
 15871    public void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 15872    {
 15873      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min2, max2
 15874      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 15875    }
 15876    internal int Remove(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds)
 15877    {
 15878      int removals = 0;
 15879      if (InclusionCheck(bounds, node.Bounds))
 15880      {
 15881        if (node is Leaf)
 15882        {
 15883          Leaf leaf = node as Leaf;
 15884          Leaf.Node current_node = leaf.Head;
 15885          Leaf.Node previous_node = null;
 15886          while (!(current_node is null))
 15887          {
 15888            Leaf.Node temp_previous = current_node;
 15889            if (EncapsulationCheck(bounds, LocateVector(current_node.Value)))
 15890            {
 15891              removals++;
 15892              if (current_node == leaf.Head)
 15893                leaf.Head = leaf.Head.Next;
 15894              else
 15895              {
 15896                previous_node.Next = current_node.Next;
 15897                temp_previous = previous_node;
 15898              }
 15899            }
 15900            previous_node = temp_previous;
 15901            current_node = current_node.Next;
 15902          }
 15903          leaf.Count -= removals;
 15904        }
 15905        else
 15906        {
 15907          Branch branch = node as Branch;
 15908          int skipped = 0;
 15909          for (int i = 0; i + skipped < branch.Children.Length; )
 15910          {
 15911            removals += this.Remove(branch.Children[i], bounds);
 15912            if (branch.Children[i].Count is 0)
 15913              branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 15914            else
 15915              i++;
 15916          }
 15917          Node[] newArray = new Node[branch.Children.Length - skipped];
 15918          Array.Copy(branch.Children, newArray, newArray.Length);
 15919          branch.Children = newArray;
 15920
 15921          branch.Count -= removals;
 15922          // convert this branch back into a leaf
 15923          // Note: if count is zero, it will be chopped off
 15924          if (branch.Count < _load && branch.Count > 0)
 15925            ShrinkChild(branch.Parent, branch.Index);
 15926        }
 15927      }
 15928
 15929      return removals;
 15930    }
 15931
 15932    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 15933    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 15934    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 15935    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 15936    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 15937    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 15938    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 15939    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 15940    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 15941    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 15942    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 15943    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 15944    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 15945    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 15946    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 15947    /// <param name="where">The equality constraint of the removal.</param>
 15948    public void Remove(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4, A
 15949    {
 15950      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min2, max2
 15951      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 15952    }
 15953    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 15954    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 15955    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 15956    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 15957    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 15958    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 15959    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 15960    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 15961    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 15962    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 15963    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 15964    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 15965    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 15966    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 15967    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 15968    /// <param name="where">The equality constraint of the removal.</param>
 15969    public void Remove(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 15970    {
 15971      this.Remove(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min2, max2
 15972      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 15973    }
 15974    internal int Remove(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds, Predicate<T>
 15975    {
 15976      if (!InclusionCheck(node.Bounds, bounds))
 15977        return 0;
 15978      int removals = 0;
 15979      if (node is Leaf)
 15980      {
 15981        Leaf leaf = node as Leaf;
 15982        Leaf.Node current = leaf.Head;
 15983        Leaf.Node previous = null;
 15984        while (current is not null)
 15985        {
 15986          if (this.EncapsulationCheck(bounds, LocateVector(current.Value)) && where(current.Value))
 15987          {
 15988            removals++;
 15989            if (previous is null)
 15990            {
 15991              leaf.Head = current.Next;
 15992              goto HeadRemoved;
 15993            }
 15994            else
 15995              previous.Next = current.Next;
 15996          }
 15997          previous = current;
 15998        HeadRemoved:
 15999          current = current.Next;
 16000        }
 16001
 16002        leaf.Count -= removals;
 16003        return removals;
 16004      }
 16005      else
 16006      {
 16007        Branch branch = node as Branch;
 16008        int skipped = 0;
 16009        for (int i = 0; i + skipped < branch.Children.Length; )
 16010        {
 16011          removals += this.Remove(branch.Children[i], bounds, where);
 16012          if (branch.Children[i].Count is 0)
 16013            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 16014          else
 16015            i++;
 16016        }
 16017        Node[] newArray = new Node[branch.Children.Length - skipped];
 16018        Array.Copy(branch.Children, newArray, newArray.Length);
 16019        branch.Children = newArray;
 16020
 16021        node.Count -= removals;
 16022
 16023        if (node.Count < _load && node.Count != 0)
 16024          ShrinkChild(node.Parent, node.Index);
 16025
 16026        return removals;
 16027      }
 16028    }
 16029
 16030    /// <summary>Tries to remove a value.</summary>
 16031    /// <param name="value">The value to remove.</param>
 16032    /// <returns>True if successful or false if not.</returns>
 16033    public (bool Success, Exception? Exception) TryRemove(T value)
 16034    {
 16035      Remove(value);
 16036      return (true, null);
 16037    }
 16038
 16039    /// <summary>Removes all instances of a given value.</summary>
 16040    public void Remove(T removal) => Omnitree.Remove(this, removal);
 16041
 16042    /// <summary>Removes all instances of a given value.</summary>
 16043    public void Remove(T removal, Func<T, T, bool> equate) => Omnitree.Remove(this, removal, equate);
 16044
 16045    /// <summary>Removes all the items in a given space.</summary>
 16046    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 16047    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 16048    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 16049    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 16050    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 16051    /// <param name="axis6">The axis of the removal along the  6D axis.</param>
 16052    /// <param name="axis7">The axis of the removal along the  7D axis.</param>
 16053    /// <returns>The number of items that were removed.</returns>
 16054    public void Remove(Axis1 axis1
 16055      , Axis2 axis2
 16056      , Axis3 axis3
 16057      , Axis4 axis4
 16058      , Axis5 axis5
 16059      , Axis6 axis6
 16060      , Axis7 axis7
 16061      )
 16062    {
 16063      this.Remove(this._top, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(axis1
 16064        , axis2
 16065        , axis3
 16066        , axis4
 16067        , axis5
 16068        , axis6
 16069        , axis7
 16070        ));
 16071      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 16072    }
 16073    internal int Remove(Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> vector)
 16074    {
 16075      int removals = 0;
 16076      if (node is Leaf)
 16077      {
 16078        Leaf leaf = node as Leaf;
 16079        Leaf.Node current_node = leaf.Head;
 16080        Leaf.Node previous_node = null;
 16081        while (!(current_node is null))
 16082        {
 16083          Leaf.Node temp_previous = current_node;
 16084          if (EqualsCheck(vector, LocateVector(current_node.Value)))
 16085          {
 16086            removals++;
 16087            if (current_node == leaf.Head)
 16088              leaf.Head = leaf.Head.Next;
 16089            else
 16090            {
 16091              previous_node.Next = current_node.Next;
 16092              temp_previous = previous_node;
 16093            }
 16094          }
 16095          previous_node = temp_previous;
 16096          current_node = current_node.Next;
 16097        }
 16098        leaf.Count -= removals;
 16099      }
 16100      else
 16101      {
 16102        Branch branch = node as Branch;
 16103        int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 16104        removals += Remove(branch[child_index], vector);
 16105        branch.Count -= removals;
 16106        // convert this branch back into a leaf
 16107        // Note: if count is zero, it will be chopped off
 16108        if (branch.Count < _load && branch.Count > 0)
 16109          ShrinkChild(branch.Parent, branch.Index);
 16110      }
 16111
 16112      return removals;
 16113    }
 16114
 16115    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 16116    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 16117    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 16118    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 16119    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 16120    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 16121    /// <param name="axis6">The axis of the removal along the  6D axis.</param>
 16122    /// <param name="axis7">The axis of the removal along the  7D axis.</param>
 16123    /// <param name="where">The equality constraint of the removal.</param>
 16124    public void Remove(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6, Axis7 axis7, Predic
 16125    {
 16126      this.Remove(this._top, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(axis1, axis2, axis3, a
 16127      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 16128    }
 16129    internal int Remove(Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> vector, Predicate<T>
 16130    {
 16131      int removals = 0;
 16132      if (node is Leaf)
 16133      {
 16134        Leaf leaf = node as Leaf;
 16135        Leaf.Node current_node = leaf.Head;
 16136        Leaf.Node previous_node = null;
 16137        while (!(current_node is null))
 16138        {
 16139          Leaf.Node temp_previous = current_node;
 16140          if (EqualsCheck(vector, LocateVector(current_node.Value)) && where(current_node.Value))
 16141          {
 16142            removals++;
 16143            if (current_node == leaf.Head)
 16144              leaf.Head = leaf.Head.Next;
 16145            else
 16146            {
 16147              previous_node.Next = current_node.Next;
 16148              temp_previous = previous_node;
 16149            }
 16150          }
 16151          previous_node = temp_previous;
 16152          current_node = current_node.Next;
 16153        }
 16154        leaf.Count -= removals;
 16155      }
 16156      else
 16157      {
 16158        Branch branch = node as Branch;
 16159        int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 16160        removals += Remove(branch[child_index], vector, where);
 16161        branch.Count -= removals;
 16162        // convert this branch back into a leaf
 16163        // Note: if count is zero, it will be chopped off
 16164        if (branch.Count < _load && branch.Count > 0)
 16165          ShrinkChild(branch.Parent, branch.Index);
 16166      }
 16167      return removals;
 16168    }
 16169
 16170    #endregion
 16171
 16172    #region Stepper And IEnumerable
 16173
 16174    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 16175    /// <param name="step">The delegate to perform on every item in the tree.</param>
 16176    public void Stepper(Action<T> step) =>
 16177      this.Stepper(step, this._top);
 16178
 16179    internal void Stepper(Action<T> step, Node node)
 16180    {
 16181      if (node is Leaf)
 16182      {
 16183        Leaf.Node list = (node as Leaf).Head;
 16184        while (list is not null)
 16185        {
 16186          step(list.Value);
 16187          list = list.Next;
 16188        }
 16189      }
 16190      else
 16191      {
 16192        foreach (Node child in (node as Branch).Children)
 16193          this.Stepper(step, child);
 16194      }
 16195    }
 16196
 16197    public StepStatus StepperBreak<TStep>(TStep step = default)
 16198      where TStep : struct, IFunc<T, StepStatus> =>
 16199      StepperBreak(_top, step);
 16200
 16201    internal StepStatus StepperBreak<TStep>(Node node, TStep step)
 16202      where TStep : struct, IFunc<T, StepStatus>
 16203    {
 16204      StepStatus status = StepStatus.Continue;
 16205      if (node is Leaf leaf)
 16206      {
 16207        for (Leaf.Node list = leaf.Head; list is not null; list = list.Next)
 16208        {
 16209          if (step.Invoke(list.Value) is Break) return Break;
 16210        }
 16211      }
 16212      else if (node is Branch branch)
 16213      {
 16214        foreach (Node child in branch.Children)
 16215        {
 16216          if (StepperBreak(child, step) is Break) return Break;
 16217        }
 16218      }
 16219      return Continue;
 16220    }
 16221
 16222    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 16223    /// <param name="step">The delegate to perform on every item in the tree.</param>
 16224    public StepStatus Stepper(Func<T, StepStatus> step) =>
 16225      Stepper(step, _top);
 16226
 16227    internal StepStatus Stepper(Func<T, StepStatus> step, Node node)
 16228    {
 16229      StepStatus status = StepStatus.Continue;
 16230      if (node is Leaf)
 16231      {
 16232        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 16233          if ((status = step(list.Value)) != StepStatus.Continue)
 16234            break;
 16235      }
 16236      else
 16237      {
 16238        foreach (Node child in (node as Branch).Children)
 16239          if ((status = Stepper(step, child)) != StepStatus.Continue)
 16240            break;
 16241      }
 16242      return status;
 16243    }
 16244
 16245    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 16246    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 16247    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 16248    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 16249    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 16250    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 16251    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 16252    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 16253    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 16254    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 16255    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 16256    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 16257    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 16258    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 16259    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 16260    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 16261    public void Stepper(Action<T> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 mi
 16262      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min2, max2, m
 16263
 16264    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 16265    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 16266    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 16267    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 16268    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 16269    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 16270    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 16271    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 16272    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 16273    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 16274    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 16275    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 16276    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 16277    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 16278    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 16279    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 16280    public void Stepper(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> mi
 16281      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min2, max2, m
 16282
 16283    internal void Stepper(Action<T> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bo
 16284    {
 16285      if (node is Leaf)
 16286      {
 16287        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 16288          if (EncapsulationCheck(bounds, LocateVector(list.Value)))
 16289            step(list.Value);
 16290      }
 16291      else
 16292      {
 16293        foreach (Node child in (node as Branch).Children)
 16294          // optimization: stop bounds checking if space encapsulates node
 16295          if (EncapsulationCheck(bounds, child.Bounds))
 16296            this.Stepper(step, child);
 16297          else if (InclusionCheck(child.Bounds, bounds))
 16298            this.Stepper(step, child, bounds);
 16299      }
 16300    }
 16301
 16302    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 16303    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 16304    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 16305    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 16306    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 16307    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 16308    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 16309    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 16310    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 16311    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 16312    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 16313    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 16314    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 16315    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 16316    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 16317    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 16318    public StepStatus Stepper(Func<T, StepStatus> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis
 16319      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min2, max2, m
 16320
 16321    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 16322    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 16323    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 16324    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 16325    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 16326    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 16327    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 16328    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 16329    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 16330    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 16331    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 16332    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 16333    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 16334    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 16335    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 16336    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 16337    public StepStatus Stepper(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree
 16338      Stepper(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min2, max2, m
 16339
 16340    internal StepStatus Stepper(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, 
 16341    {
 16342      StepStatus status = StepStatus.Continue;
 16343      if (node is Leaf)
 16344      {
 16345        for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next)
 16346          if (EncapsulationCheck(bounds, LocateVector(list.Value)) &&
 16347            (status = step(list.Value)) != StepStatus.Continue)
 16348            break;
 16349      }
 16350      else
 16351      {
 16352        foreach (Node child in (node as Branch).Children)
 16353          // optimization: stop bounds checking if space encapsulates node
 16354          if (EncapsulationCheck(bounds, child.Bounds) &&
 16355            (status = this.Stepper(step, child)) != StepStatus.Continue)
 16356            break;
 16357          else if (InclusionCheck(child.Bounds, bounds) &&
 16358            (status = this.Stepper(step, child, bounds)) != StepStatus.Continue)
 16359            break;
 16360      }
 16361      return status;
 16362    }
 16363
 16364    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 16365    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 16366    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 16367    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 16368    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 16369    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 16370    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 16371    /// <param name="axis6">The axis of the removal along the  6D axis.</param>
 16372    /// <param name="axis7">The axis of the removal along the  7D axis.</param>
 16373    public void Stepper(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6, Ax
 16374      Stepper(step, _top, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(axis1, axis2, axis3, axis
 16375
 16376    internal void Stepper(Action<T> step, Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> ve
 16377    {
 16378      Node current = node;
 16379      while (current is not null)
 16380      {
 16381        if (current is Leaf)
 16382        {
 16383          for (Leaf.Node leaf_node = (current as Leaf).Head; leaf_node is not null; leaf_node = leaf_node.Next)
 16384            if (EqualsCheck(vector, LocateVector(leaf_node.Value)))
 16385              step(leaf_node.Value);
 16386          break;
 16387        }
 16388        else
 16389        {
 16390          Branch branch = current as Branch;
 16391          int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 16392          current = branch[child_index];
 16393        }
 16394      }
 16395    }
 16396
 16397    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 16398    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 16399    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 16400    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 16401    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 16402    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 16403    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 16404    /// <param name="axis6">The axis of the removal along the  6D axis.</param>
 16405    /// <param name="axis7">The axis of the removal along the  7D axis.</param>
 16406    public StepStatus Stepper(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5,
 16407      Stepper(step, _top, new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(axis1, axis2, axis3, axis
 16408
 16409    internal StepStatus Stepper(Func<T, StepStatus> step, Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, 
 16410    {
 16411      Node current = node;
 16412      while (current is not null)
 16413      {
 16414        if (current is Leaf)
 16415        {
 16416          for (Leaf.Node list = (current as Leaf).Head; list is not null; list = list.Next)
 16417          {
 16418            StepStatus status = StepStatus.Continue;
 16419            if (EqualsCheck(vector, LocateVector(list.Value)) &&
 16420              (status = step(list.Value)) != StepStatus.Continue)
 16421              return status;
 16422          }
 16423        }
 16424        else
 16425        {
 16426          Branch branch = current as Branch;
 16427          int child_index = DetermineChildIndex(branch.PointOfDivision, vector);
 16428          current = branch[child_index];
 16429        }
 16430      }
 16431      return StepStatus.Continue;
 16432    }
 16433
 16434    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 16435
 16436    public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 16437    {
 16438      // Note: this can be optimized.
 16439      IList<T> list = new ListLinked<T>();
 16440      Stepper(x => list.Add(x));
 16441      return list.GetEnumerator();
 16442    }
 16443
 16444    #endregion
 16445
 16446    /// <inheritdoc/>
 16447    public T[] ToArray() => throw new NotImplementedException();
 16448
 16449    #region Helpers
 16450
 16451    internal bool StraddlesLines(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds, Omnitree.Vecto
 16452      Omnitree.StraddlesLines(bounds, vector
 16453        , _compare1
 16454        , _compare2
 16455        , _compare3
 16456        , _compare4
 16457        , _compare5
 16458        , _compare6
 16459        , _compare7
 16460        );
 16461
 16462    /// <summary>Computes the child index that contains the desired dimensions.</summary>
 16463    /// <param name="pointOfDivision">The point of division to compare against.</param>
 16464    /// <param name="vector">The dimensions to determine the child index.</param>
 16465    /// <returns>The computed child index based on the coordinates relative to the center of the node.</returns>
 16466    internal int DetermineChildIndex(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> pointOfDivision, O
 16467    {
 16468      int child = 0;
 16469      if (!(this._compare1(vector.Axis1, pointOfDivision.Axis1) is Less))
 16470        child += 1 << 0;
 16471      if (!(this._compare2(vector.Axis2, pointOfDivision.Axis2) is Less))
 16472        child += 1 << 1;
 16473      if (!(this._compare3(vector.Axis3, pointOfDivision.Axis3) is Less))
 16474        child += 1 << 2;
 16475      if (!(this._compare4(vector.Axis4, pointOfDivision.Axis4) is Less))
 16476        child += 1 << 3;
 16477      if (!(this._compare5(vector.Axis5, pointOfDivision.Axis5) is Less))
 16478        child += 1 << 4;
 16479      if (!(this._compare6(vector.Axis6, pointOfDivision.Axis6) is Less))
 16480        child += 1 << 5;
 16481      if (!(this._compare7(vector.Axis7, pointOfDivision.Axis7) is Less))
 16482        child += 1 << 6;
 16483      return child;
 16484    }
 16485
 16486    /// <summary>Converts a branch back into a leaf when the count is reduced.</summary>
 16487    /// <param name="parent">The parent to shrink a child of.</param>
 16488    /// <param name="child_index">The index of the child to shrink.</param>
 16489    internal void ShrinkChild(Branch parent, int child_index)
 16490    {
 16491      Leaf leaf;
 16492      Node removal = null;
 16493      if (parent is null) // top of tree
 16494      {
 16495        removal = this._top;
 16496        leaf = new Leaf(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>.None, null, -1);
 16497        this._top = leaf;
 16498      }
 16499      else // non-top branch
 16500      {
 16501        removal = parent[child_index];
 16502        leaf = new Leaf(removal.Bounds, removal.Parent, removal.Index);
 16503        parent[child_index] = leaf;
 16504      }
 16505
 16506      this.Stepper((T step) => { leaf.Add(step); }, removal);
 16507    }
 16508
 16509    /// <summary>Reduces the counts of all the parents of a given node by a given amount.</summary>
 16510    /// <param name="parent">The starting parent of the reduction.</param>
 16511    /// <param name="reduction">The amount to reduce the parent counts by.</param>
 16512    internal void ReduceParentCounts(Node parent, int reduction)
 16513    {
 16514      IncreaseParentCounts(parent, -reduction);
 16515    }
 16516
 16517    /// <summary>Increases the counts of all the parents of a given node by a given amount.</summary>
 16518    /// <param name="parent">The starting parent of the increase.</param>
 16519    /// <param name="increase">The amount to increase the parent counts by.</param>
 16520    internal void IncreaseParentCounts(Node parent, int increase)
 16521    {
 16522      Node node = parent;
 16523      while (node is not null)
 16524      {
 16525        node.Count += increase;
 16526        node = node.Parent;
 16527      }
 16528    }
 16529
 16530    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 16531    /// <returns>True if the spaces overlap; False if not.</returns>
 16532    internal bool InclusionCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> a, Omnitree.Bounds<Axi
 16533      Omnitree.InclusionCheck(a, b
 16534      , _compare1
 16535      , _compare2
 16536      , _compare3
 16537      , _compare4
 16538      , _compare5
 16539      , _compare6
 16540      , _compare7
 16541      );
 16542
 16543    /// <summary>Checks if a space encapsulates a point.</summary>
 16544    /// <returns>True if the space encapsulates the point; False if not.</returns>
 16545    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds, Omnitree.V
 16546      Omnitree.EncapsulationCheck(bounds, vector
 16547      , _compare1
 16548      , _compare2
 16549      , _compare3
 16550      , _compare4
 16551      , _compare5
 16552      , _compare6
 16553      , _compare7
 16554      );
 16555
 16556    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 16557    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 16558    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> a, Omnitree.Bounds
 16559      Omnitree.EncapsulationCheck(a, b
 16560      , _compare1
 16561      , _compare2
 16562      , _compare3
 16563      , _compare4
 16564      , _compare5
 16565      , _compare6
 16566      , _compare7
 16567      );
 16568
 16569    /// <summary>Checks for equality between two locations.</summary>
 16570    /// <returns>True if equal; False if not;</returns>
 16571    internal bool EqualsCheck(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> a, Omnitree.Vector<Axis1,
 16572      Omnitree.EqualsCheck(a, b
 16573      , (a, b) => _compare1(a, b) is Equal
 16574      , (a, b) => _compare2(a, b) is Equal
 16575      , (a, b) => _compare3(a, b) is Equal
 16576      , (a, b) => _compare4(a, b) is Equal
 16577      , (a, b) => _compare5(a, b) is Equal
 16578      , (a, b) => _compare6(a, b) is Equal
 16579      , (a, b) => _compare7(a, b) is Equal
 16580      );
 16581
 16582    /// <summary>Gets the nearest parent that encapsulates a location.</summary>
 16583    /// <param name="node">The starting node to find the encapsulating parent of the location.</param>
 16584    /// <param name="vector">The coordinates of the value.</param>
 16585    /// <returns>The nearest node that encapsulates the given location.</returns>
 16586    internal Node GetEncapsulationParent(Node node, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> vec
 16587    {
 16588      while (node is not null && !EncapsulationCheck(node.Bounds, vector))
 16589      {
 16590        node = node.Parent;
 16591      }
 16592      return node;
 16593    }
 16594
 16595    internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> LocateVector(T value)
 16596    {
 16597      Axis1 axis1;
 16598      Axis2 axis2;
 16599      Axis3 axis3;
 16600      Axis4 axis4;
 16601      Axis5 axis5;
 16602      Axis6 axis6;
 16603      Axis7 axis7;
 16604      this._locate(value, out axis1
 16605, out axis2
 16606, out axis3
 16607, out axis4
 16608, out axis5
 16609, out axis6
 16610, out axis7
 16611);
 16612      return new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(axis1, axis2, axis3, axis4, axis5, axi
 16613    }
 16614
 16615    #endregion
 16616
 16617    #endregion
 16618  }
 16619
 16620  #endregion
 16621
 16622  #endregion
 16623
 16624  #region OmnitreeBounds
 16625
 16626  #region 1 Dimensional
 16627
 16628  /// <summary>Inheritance base for 1D omnitrees that store bounds.</summary>
 16629  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 16630  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 16631  public interface IOmnitreeBounds<T, Axis1> : IOmnitree<T, Axis1>
 16632  {
 16633    #region Properties
 16634
 16635    /// <summary>The number of dimensions in this tree.</summary>
 16636    int Dimensions { get; }
 16637
 16638    /// <summary>The delegate being used by the omnitree to get the bounds of values in 1D space.</summary>
 16639    Omnitree.GetBounds<T, Axis1
 16640      > GetBounds { get; }
 16641
 16642    #endregion
 16643
 16644    #region Methods
 16645
 16646    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 16647    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 16648    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 16649    /// <returns>The number of items in the provided sub space.</returns>
 16650    int CountSubSpaceEncapsulated(Axis1 min1, Axis1 max1);
 16651
 16652    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 16653    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 16654    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 16655    /// <returns>The number of items in the provided sub space.</returns>
 16656    int CountSubSpaceOverlapped(Axis1 min1, Axis1 max1);
 16657
 16658    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 16659    void Update();
 16660    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 16661    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 16662    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 16663    void Update(Axis1 min1, Axis1 max1);
 16664
 16665    /// <summary>Removes all the items in a given space.</summary>
 16666    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 16667    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 16668    void RemoveEncapsulated(Axis1 min1, Axis1 max1);
 16669    /// <summary>Removes all the items in a given space.</summary>
 16670    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 16671    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 16672    void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1);
 16673    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 16674    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 16675    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 16676    /// <param name="where">The predicate constraint of the removal.</param>
 16677    void RemoveEncapsulated(Axis1 min1, Axis1 max1, Predicate<T> where);
 16678    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 16679    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 16680    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 16681    /// <param name="where">The predicate constraint of the removal.</param>
 16682    void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Predicate<T> where);
 16683
 16684    /// <summary>Removes all the items in a given space.</summary>
 16685    /// <param name="axis1">The coordinate along the 1D axis.</param>
 16686    void RemoveOverlapped(Axis1 axis1);
 16687    /// <summary>Removes all the items in a given space.</summary>
 16688    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 16689    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 16690    void RemoveOverlapped(Axis1 min1, Axis1 max1);
 16691    /// <summary>Removes all the items in a given space.</summary>
 16692    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 16693    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 16694    void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1);
 16695    /// <summary>Removes all the items in a given space where equality is met.</summary>
 16696    /// <param name="axis1">The coordinate along the 1D axis.</param>
 16697    /// <param name="where">The equality constraint of the removal.</param>
 16698    void RemoveOverlapped(Axis1 axis1, Predicate<T> where);
 16699    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 16700    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 16701    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 16702    /// <param name="where">The predicate constraint of the removal.</param>
 16703    void RemoveOverlapped(Axis1 min1, Axis1 max1, Predicate<T> where);
 16704    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 16705    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 16706    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 16707    /// <param name="where">The predicate constraint of the removal.</param>
 16708    void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Predicate<T> where);
 16709
 16710    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 16711    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 16712    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 16713    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 16714    void StepperEncapsulated(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1);
 16715    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 16716    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 16717    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 16718    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 16719    StepStatus StepperEncapsulated(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1);
 16720
 16721    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 16722    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 16723    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 16724    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 16725    void StepperOverlapped(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1);
 16726    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 16727    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 16728    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 16729    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 16730    StepStatus StepperOverlapped(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1);
 16731
 16732    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 16733    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 16734    /// <param name="axis1">The coordinate along the 1D axis.</param>
 16735    void StepperOverlapped(Action<T> step, Axis1 axis1);
 16736    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 16737    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 16738    /// <param name="axis1">The coordinate along the 1D axis.</param>
 16739    StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 axis1);
 16740
 16741    #endregion
 16742  }
 16743
 16744  /// <summary>Omnitree that stores bounds along 1 dimensions implemented as a linked tree.</summary>
 16745  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 16746  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 16747  public class OmnitreeBoundsLinked<T, Axis1> : IOmnitreeBounds<T, Axis1>
 16748  {
 16749    internal const int _dimensions = 1;
 16750    internal static int _children_per_node = (int)BigInteger.Pow(2, 1);
 16751
 16752    internal Node _top;
 16753    internal int _naturalLogLower = 1; // caching the next time to calculate loads (lower count)
 16754    internal int _naturalLogUpper = -1; // caching the next time to calculate loads (upper count)
 16755    internal int _load; // ln(count); min = _defaultLoad
 16756    internal Omnitree.GetBounds<T, Axis1
 16757      > _getBounds;
 16758    internal bool _defaultCompare1;
 16759    internal Func<Axis1, Axis1, CompareResult> _compare1;
 16760    internal Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1>> _subdivisionOverride1;
 16761
 16762    #region Nested Types
 16763
 16764    /// <summary>Can be a leaf or a branch.</summary>
 16765    internal class Node
 16766    {
 16767      internal class ValueNode
 16768      {
 16769        internal T Value;
 16770        internal ValueNode Next;
 16771
 16772        internal ValueNode(T value, ValueNode next)
 16773        {
 16774          Value = value;
 16775          Next = next;
 16776        }
 16777      }
 16778
 16779      internal Omnitree.Bounds<Axis1> Bounds;
 16780      internal Node Parent;
 16781      internal int Index;
 16782      internal int Count;
 16783      internal ValueNode Head;
 16784      internal Node[] Children;
 16785      internal Omnitree.Vector<Axis1>? PointOfDivision;
 16786
 16787      /// <summary>Gets child by index.</summary>
 16788      /// <param name="child_index">The index of the child to get.</param>
 16789      /// <returns>The child of the given index or null if non-existent.</returns>
 16790      internal Node this[int child_index]
 16791      {
 16792        get
 16793        {
 16794          if (Children is null)
 16795            return null;
 16796          if (Children.Length == OmnitreePointsLinked<T, Axis1>._children_per_node)
 16797            return Children[(int)child_index];
 16798          foreach (Node node in Children)
 16799            if (node.Index == child_index)
 16800              return node;
 16801          return null;
 16802        }
 16803        set
 16804        {
 16805          // This error check should be unnecessary... but fuck it... might as well
 16806          if (value.Index != child_index)
 16807            throw new System.Exception("Bug in Omnitree (index/property mis-match when setting a child on a branch)");
 16808
 16809          // no children yet
 16810          if (Children is null)
 16811          {
 16812            Children = â±¯(value);
 16813            return;
 16814          }
 16815          // max children overwrite
 16816          else if (Children.Length == OmnitreePointsLinked<T, Axis1>._children_per_node)
 16817          {
 16818            Children[(int)child_index] = value;
 16819            return;
 16820          }
 16821          // non-max child overwrite
 16822          for (int i = 0; i < Children.Length; i++)
 16823            if (Children[i].Index == child_index)
 16824            {
 16825              Children[i] = value;
 16826              return;
 16827            }
 16828          // new child
 16829          Node[] newArray = new Node[Children.Length + 1];
 16830          if (newArray.Length == OmnitreePointsLinked<T, Axis1>._children_per_node)
 16831          {
 16832            // new child resulting in a max children branch (sorting required)
 16833            for (int i = 0; i < Children.Length; i++)
 16834            {
 16835              newArray[(int)Children[i].Index] = Children[i];
 16836            }
 16837            newArray[(int)value.Index] = value;
 16838          }
 16839          else
 16840          {
 16841            // new child resulting in a non-max children branch
 16842            Array.Copy(Children, newArray, Children.Length);
 16843            newArray[newArray.Length - 1] = value;
 16844          }
 16845          Children = newArray;
 16846        }
 16847      }
 16848
 16849      /// <summary>The depth this node is located in the Omnitree.</summary>
 16850      internal int Depth
 16851      {
 16852        get
 16853        {
 16854          int depth = -1;
 16855          for (Node node = this; node is not null; node = node.Parent)
 16856            depth++;
 16857          return depth;
 16858        }
 16859      }
 16860
 16861      /// <summary>Constructs a node.</summary>
 16862      /// <param name="bounds">The bounds of this node.</param>
 16863      /// <param name="parent">The parent of this node.</param>
 16864      /// <param name="index">The number of values stored in this node and its children.</param>
 16865      internal Node(Omnitree.Bounds<Axis1> bounds, Node parent, int index)
 16866      {
 16867        Bounds = bounds;
 16868        Parent = parent;
 16869        Index = index;
 16870      }
 16871
 16872      internal Node(Omnitree.Vector<Axis1> pointOfDivision, Omnitree.Bounds<Axis1> bounds, Node parent, int index)
 16873        : this(bounds, parent, index)
 16874      {
 16875        PointOfDivision = pointOfDivision;
 16876      }
 16877
 16878      internal Node(Node nodeToClone)
 16879      {
 16880        this.Bounds = nodeToClone.Bounds;
 16881        this.Parent = nodeToClone.Parent;
 16882        this.Index = nodeToClone.Index;
 16883        this.Count = nodeToClone.Count;
 16884
 16885        Children = nodeToClone.Children.Clone() as Node[];
 16886        PointOfDivision = nodeToClone.PointOfDivision;
 16887
 16888        ValueNode a = this.Head;
 16889        ValueNode b = nodeToClone.Head;
 16890
 16891        while (b is not null)
 16892        {
 16893          a.Next = new ValueNode(b.Next.Value, null);
 16894          a = a.Next;
 16895          b = b.Next;
 16896        }
 16897      }
 16898
 16899      internal void Add(T addition)
 16900      {
 16901        Head = new ValueNode(addition, Head);
 16902        Count++;
 16903      }
 16904
 16905      internal Node Clone() =>
 16906        new Node(this);
 16907    }
 16908
 16909    #endregion
 16910
 16911    #region Constructors
 16912
 16913    /// <summary>This constructor is for cloning purposes</summary>
 16914    internal OmnitreeBoundsLinked(OmnitreeBoundsLinked<T, Axis1> omnitree)
 16915    {
 16916      this._top = omnitree._top.Clone();
 16917      this._load = omnitree._load;
 16918      this._getBounds = omnitree._getBounds;
 16919      this._defaultCompare1 = omnitree._defaultCompare1;
 16920      this._compare1 = omnitree._compare1;
 16921      this._subdivisionOverride1 = omnitree._subdivisionOverride1;
 16922    }
 16923
 16924    internal OmnitreeBoundsLinked(
 16925      Omnitree.GetBounds<T, Axis1> getBounds,
 16926      bool defaultCompare1,
 16927      Func<Axis1, Axis1, CompareResult> compare1,
 16928      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1>> subdivisionOverride1
 16929      )
 16930    {
 16931      if (getBounds is null)
 16932      {
 16933        throw new ArgumentNullException(nameof(getBounds));
 16934      }
 16935      if (compare1 is null)
 16936      {
 16937        throw new ArgumentNullException(nameof(compare1));
 16938      }
 16939      this._getBounds = getBounds;
 16940      this._defaultCompare1 = defaultCompare1;
 16941      this._compare1 = compare1;
 16942      this._subdivisionOverride1 = subdivisionOverride1;
 16943      this._top = new Node(Omnitree.Bounds<Axis1>.None, null, -1);
 16944      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 16945    }
 16946
 16947    /// <summary>Constructs a new 1D omnitree that stores bounds.</summary>
 16948    /// <param name="getBounds">The delegate for getting object bounds in 1D space.</param>
 16949
 16950    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 16951
 16952    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 16953    public OmnitreeBoundsLinked(
 16954      Omnitree.GetBounds<T, Axis1> getBounds,
 16955      Func<Axis1, Axis1, CompareResult> compare1 = null,
 16956      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1>> subdivisionOverride1 = null
 16957      )
 16958      : this(
 16959      getBounds,
 16960      compare1 is null ? true : false,
 16961      compare1 ?? Compare,
 16962      subdivisionOverride1
 16963      ) { }
 16964
 16965    /// <summary>Constructs a new 1D omnitree that stores bounds.</summary>
 16966    /// <param name="getBoundings">The delegate for getting object bounds in 1D space.</param>
 16967    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 16968
 16969    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 16970    public OmnitreeBoundsLinked(
 16971      Omnitree.GetBoundings<T, Axis1> getBoundings,
 16972      Func<Axis1, Axis1, CompareResult> compare1 = null,
 16973      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1>> subdivisionOverride1 = null
 16974      )
 16975      : this(
 16976      Omnitree.ConvertToGetBounds(getBoundings),
 16977      compare1 is null ? true : false,
 16978      compare1 ?? Compare,
 16979      subdivisionOverride1
 16980      ) { }
 16981
 16982    #endregion
 16983
 16984    #region Properties
 16985
 16986    /// <summary>The number of dimensions in this tree.</summary>
 16987    public int Dimensions => _dimensions;
 16988
 16989    /// <summary>The delegate being used by the omnitree to locate items in 1D space.</summary>
 16990    public Omnitree.GetBounds<T, Axis1
 16991      > GetBounds => _getBounds;
 16992
 16993
 16994    /// <summary>The comparison function the Omnitree is using along the 1D axis.</summary>
 16995    public Func<Axis1, Axis1, CompareResult> Compare1 => _compare1;
 16996
 16997    /// <summary>The current number of items in the tree.</summary>
 16998    public int Count  => _top.Count;
 16999
 17000    internal delegate void MaxDepthFinder(Node node, int current_depth, ref int max_depth);
 17001    /// <summary>Finds the current maximum depth of the tree. NOT AN O(1) OPERATION. Intended for educational purposes o
 17002    public int MaxDepth
 17003    {
 17004      get
 17005      {
 17006        MaxDepthFinder maxDepthFinder = null;
 17007        maxDepthFinder =
 17008            (Node node, int current_depth, ref int max_depth) =>
 17009            {
 17010              if (current_depth > max_depth)
 17011                max_depth = current_depth;
 17012              foreach (Node child in node.Children)
 17013                maxDepthFinder(child, current_depth + 1, ref max_depth);
 17014            };
 17015        int _max_depth = -1;
 17016        maxDepthFinder(this._top, 0, ref _max_depth);
 17017        return _max_depth;
 17018      }
 17019    }
 17020
 17021    internal delegate void NodeCountFinder(Node node, ref int current_count);
 17022    /// <summary>Counts the current number of nodes in the tree. NOT AN O(1) OPERATION. Intended for educational purpose
 17023    public int NodeCount
 17024    {
 17025      get
 17026      {
 17027        NodeCountFinder nodeCountFinder = null;
 17028        nodeCountFinder =
 17029            (Node node, ref int current_count) =>
 17030            {
 17031              current_count++;
 17032              foreach (Node child in node.Children)
 17033                nodeCountFinder(child, ref current_count);
 17034            };
 17035
 17036        int _current_count = 0;
 17037        nodeCountFinder(this._top, ref _current_count);
 17038        return _current_count;
 17039      }
 17040    }
 17041
 17042    #endregion
 17043
 17044    #region Methods
 17045
 17046    #region Add
 17047
 17048
 17049    #region single
 17050
 17051    /// <summary>Tries to add a value.</summary>
 17052    /// <param name="value">The value to be added.</param>
 17053    /// <returns>True if successful or false if not.</returns>
 17054    public (bool Success, Exception? Exception) TryAdd(T value)
 17055    {
 17056      Add(value);
 17057      return (true, null);
 17058    }
 17059
 17060    /// <summary>Adds an item to the tree.</summary>
 17061    /// <param name="addition">The item to be added.</param>
 17062    public void Add(T addition)
 17063    {
 17064      if (this._top.Count is int.MaxValue)
 17065        throw new System.InvalidOperationException("(Count is int.MaxValue) max Omnitree size reached (change ints to lo
 17066
 17067      // dynamic tree sizes
 17068      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 17069
 17070      Omnitree.Bounds<Axis1> bounds = GetBoundings(addition);
 17071
 17072      // grow the first branch of the tree
 17073      if (!this._top.PointOfDivision.HasValue && this._top.Count >= _load)
 17074      {
 17075        Node top = this._top;
 17076
 17077        // create the new branch from the median values
 17078        this._top = new Node(DetermineMedians(top), Omnitree.Bounds<Axis1>.None, null, -1);
 17079
 17080        // iterate through the values and add them to the appropriate children
 17081        for (Node.ValueNode list = top.Head; list is not null; list = list.Next)
 17082          Add(list.Value, this._top, GetBoundings(list.Value), 0);
 17083      }
 17084
 17085      this.Add(addition, this._top, bounds, 0);
 17086    }
 17087
 17088    /// <summary>Recursive version of the add function.</summary>
 17089    /// <param name="addition">The item to be added.</param>
 17090    /// <param name="node">The current node for tree trversal.</param>
 17091    /// <param name="bounds">The bounds of the addition.</param>
 17092    /// <param name="depth">The current depth of iteration.</param>
 17093    internal void Add(T addition, Node node, Omnitree.Bounds<Axis1> bounds, int depth)
 17094    {
 17095      if (!node.PointOfDivision.HasValue)
 17096      {
 17097        //Leaf leaf = node as Leaf;
 17098        if (depth >= _load || !(node.Count >= _load))
 17099        {
 17100          node.Add(addition);
 17101          return;
 17102        }
 17103        else
 17104        {
 17105          //Node parent = node.Parent;
 17106          //int child_index = this.DetermineChildIndex(parent.PointOfDivision, location);
 17107          //Node growth = new Node(DetermineMedians(leaf), leaf.Bounds, parent, child_index);
 17108          //parent[child_index] = growth;
 17109
 17110          Node growth = new Node(DetermineMedians(node), node.Bounds, node.Parent, node.Index);
 17111          node.Parent[node.Index] = growth;
 17112
 17113          for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 17114          {
 17115            Omnitree.Bounds<Axis1> temp_bounds = GetBoundings(list.Value);
 17116            if (EncapsulationCheck(growth.Bounds, temp_bounds))
 17117              Add(list.Value, growth, temp_bounds, depth);
 17118            else
 17119            {
 17120              ReduceParentCounts(node.Parent, 1);
 17121              Add(list.Value, this._top, temp_bounds, depth);
 17122            }
 17123          }
 17124
 17125          Add(addition, growth, bounds, depth);
 17126          return;
 17127        }
 17128      }
 17129      else
 17130      {
 17131        //Node branch = node as Node;
 17132        int child_index = this.DetermineChildIndex(node.PointOfDivision.Value, bounds); // determine the child "index" (
 17133
 17134        // if -1, then the bounds of the addition straddle the point of division (keep it in current node)
 17135        if (child_index is -1)
 17136        {
 17137          node.Add(addition);
 17138          return;
 17139        }
 17140
 17141        Node child_node = node[child_index];
 17142
 17143        // null children in branches are just empty leaves
 17144        if (child_node is null)
 17145        {
 17146          Node new_node = new Node(DetermineChildBounds(node, child_index), node, child_index);
 17147          node[child_index] = new_node;
 17148          new_node.Add(addition);
 17149        }
 17150        else
 17151          // child exists already, continue adding
 17152          Add(addition, child_node, bounds, depth + 1);
 17153
 17154        node.Count++;
 17155        return;
 17156      }
 17157    }
 17158
 17159    internal Omnitree.Vector<Axis1> DetermineMedians(Node node)
 17160    {
 17161      //try
 17162      //{
 17163        // extract the values
 17164        Omnitree.Bound<Axis1>[] values1 = new Omnitree.Bound<Axis1>[node.Count * 2];
 17165        Node.ValueNode for_current = node.Head; // used in for loop
 17166        for (int i = 0; i < node.Count; i++, for_current = for_current.Next)
 17167          this._getBounds(for_current.Value,
 17168          out values1[i * 2], out values1[i * 2 + 1]
 17169          );
 17170        return new Omnitree.Vector<Axis1>(
 17171          Omnitree.SubDivide(values1, this._defaultCompare1 ? Compare : this._compare1)
 17172          );
 17173      //}
 17174      //catch
 17175      //{
 17176        // extract the values
 17177      //  ArrayJagged<Omnitree.Bound<Axis1>> values1 = new ArrayJagged<Omnitree.Bound<Axis1>>(node.Count * 2);
 17178      //  Node.ValueNode for_current = node.Head; // used in for loop
 17179      //  for (int i = 0; i < node.Count; i++, for_current = for_current.Next)
 17180      //  {
 17181      //    Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 17182      //    this._getBounds(for_current.Value,
 17183      //      out min1, out max1
 17184      //      );
 17185      //    values1[i * 2] = min1; values1[i * 2 + 1] = max1;
 17186      //  }
 17187      //  return new Omnitree.Vector<Axis1>(
 17188      //    Omnitree.SubDivide(values1, this._defaultCompare1 ? Compare : this._compare1)
 17189      //  );
 17190      //}
 17191    }
 17192
 17193    #endregion
 17194
 17195    #region Add Helpers
 17196
 17197    internal Omnitree.Bounds<Axis1> DetermineChildBounds(Node node, int child_index)
 17198    {
 17199      // the node parameter should always have a point of division value for this function
 17200      Omnitree.Vector<Axis1> pointOfDivision = node.PointOfDivision.Value;
 17201
 17202      Omnitree.Bound<Axis1> min1, max1;
 17203      if (child_index >= 1)
 17204      {
 17205        min1 = pointOfDivision.Axis1;
 17206        max1 = node.Bounds.Max1;
 17207        child_index -= 1;
 17208      }
 17209      else
 17210      {
 17211        min1 = node.Bounds.Min1;
 17212        max1 = pointOfDivision.Axis1;
 17213      }
 17214
 17215      return new Omnitree.Bounds<Axis1>(min1, max1);
 17216    }
 17217
 17218    #endregion
 17219
 17220    #endregion
 17221
 17222    #region Clear
 17223
 17224    /// <summary>Returns the tree to an empty state.</summary>
 17225    public void Clear()
 17226    {
 17227      this._top = new Node(Omnitree.Bounds<Axis1>.None, null, -1);
 17228      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 17229    }
 17230
 17231    #endregion
 17232
 17233    #region Clone
 17234
 17235    /// <summary>Creates a shallow clone of this data structure.</summary>
 17236    /// <returns>A shallow clone of this data structure.</returns>
 17237    public OmnitreeBoundsLinked<T, Axis1> Clone()
 17238    {
 17239      return new OmnitreeBoundsLinked<T, Axis1>(this);
 17240    }
 17241
 17242    #endregion
 17243
 17244    #region Count
 17245
 17246    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 17247    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17248    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17249    /// <returns>The number of items in the provided sub space.</returns>
 17250    public int CountSubSpaceEncapsulated(Axis1 min1, Axis1 max1)
 17251    {
 17252      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1>(min1, max1));
 17253    }
 17254    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 17255    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17256    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17257    /// <returns>The number of items in the provided sub space.</returns>
 17258    public int CountSubSpaceEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1)
 17259    {
 17260      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1>(min1, max1));
 17261    }
 17262    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 17263    /// <param name="axis1">The coordinate along the 1D axis.</param>
 17264    /// <returns>The number of items in the provided sub space.</returns>
 17265    public int CountSubSpaceEncapsulated(Axis1 axis1)
 17266    {
 17267      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1>(axis1, axis1));
 17268    }
 17269    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 17270    /// <param name="axis1">The coordinate along the 1D axis.</param>
 17271    /// <returns>The number of items in the provided sub space.</returns>
 17272    public int CountSubSpaceEncapsulated(Omnitree.Bound<Axis1> axis1)
 17273    {
 17274      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1>(axis1, axis1));
 17275    }
 17276
 17277    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 17278    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17279    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17280    /// <returns>The number of items in the provided sub space.</returns>
 17281    public int CountSubSpaceOverlapped(Axis1 min1, Axis1 max1)
 17282    {
 17283      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1>(min1, max1));
 17284    }
 17285    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 17286    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17287    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17288    /// <returns>The number of items in the provided sub space.</returns>
 17289    public int CountSubSpaceOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1)
 17290    {
 17291      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1>(min1, max1));
 17292    }
 17293    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 17294    /// <param name="axis1">The coordinate along the 1D axis.</param>
 17295    /// <returns>The number of items in the provided sub space.</returns>
 17296    public int CountSubSpaceOverlapped(Axis1 axis1)
 17297    {
 17298      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1>(axis1, axis1));
 17299    }
 17300    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 17301    /// <param name="axis1">The coordinate along the 1D axis.</param>
 17302    /// <returns>The number of items in the provided sub space.</returns>
 17303    public int CountSubSpaceOverlapped(Omnitree.Bound<Axis1> axis1)
 17304    {
 17305      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1>(axis1, axis1));
 17306    }
 17307
 17308    internal int CountSubSpaceEncapsulated(Node node, Omnitree.Bounds<Axis1> bounds)
 17309    {
 17310      return CountSubSpaceBase(_top, bounds, (a, b) => EncapsulationCheck(a, b));
 17311    }
 17312
 17313    internal int CountSubSpaceOverlapped(Node node, Omnitree.Bounds<Axis1> bounds)
 17314    {
 17315      return CountSubSpaceBase(_top, bounds, (a, b) => InclusionCheck(a, b));
 17316    }
 17317
 17318    internal int CountSubSpaceBase(
 17319      Node node,
 17320      Omnitree.Bounds<Axis1> bounds,
 17321      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1>, Omnitree.Bounds<Axis1>> spatialCheck)
 17322    {
 17323      // adjust min/max values
 17324      int count = 0;
 17325      if (EncapsulationCheck(bounds, node.Bounds))
 17326        count += node.Count;
 17327      else if (!node.PointOfDivision.HasValue)
 17328      {
 17329        for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 17330          if (spatialCheck(bounds, GetBoundings(list.Value)))
 17331            count++;
 17332      }
 17333      else
 17334      {
 17335        Node branch = node as Node;
 17336        if (!StraddlesLines(branch.Bounds, branch.PointOfDivision.Value))
 17337        {
 17338          int child_index = DetermineChildIndex(branch.PointOfDivision.Value, bounds);
 17339          Node child = branch[child_index];
 17340          if (child is not null)
 17341            count += this.CountSubSpaceBase(child, bounds, spatialCheck);
 17342        }
 17343        else
 17344        {
 17345          foreach (Node child in node.Children)
 17346            count += this.CountSubSpaceBase(child, bounds, spatialCheck);
 17347        }
 17348      }
 17349      return count;
 17350    }
 17351
 17352    #endregion
 17353
 17354    #region Update
 17355
 17356    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 17357    public void Update()
 17358    {
 17359      this.Update(this._top, 0);
 17360    }
 17361
 17362    /// <summary>Recursive version of the Update method.</summary>
 17363    /// <param name="node">The current node of iteration.</param>
 17364    /// <param name="depth">The current depth of iteration.</param>
 17365    internal int Update(Node node, int depth)
 17366    {
 17367      int removals = 0;
 17368
 17369      {
 17370        Node branch = node as Node;
 17371        int skipped = 0;
 17372        for (int i = 0; i + skipped < branch.Children.Length; )
 17373        {
 17374          removals += this.Update(branch.Children[i], depth + 1);
 17375          if (branch.Children[i].Count is 0)
 17376            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 17377          else
 17378            i++;
 17379        }
 17380        Node[] newArray = new Node[branch.Children.Length - skipped];
 17381        Array.Copy(branch.Children, newArray, newArray.Length);
 17382        branch.Children = newArray;
 17383
 17384        if (branch.Count < _load && branch.Count != 0)
 17385          ShrinkChild(branch.Parent, branch.Index);
 17386      }
 17387
 17388      {
 17389        Node.ValueNode current = node.Head;
 17390        Node.ValueNode previous = null;
 17391        while (current is not null)
 17392        {
 17393          Omnitree.Bounds<Axis1> bounds = GetBoundings(current.Value);
 17394          if (!this.EncapsulationCheck(node.Bounds, bounds))
 17395          {
 17396            removals++;
 17397            T updated = current.Value;
 17398            if (previous is null)
 17399            {
 17400              node.Head = current.Next;
 17401              goto HeadRemoved;
 17402            }
 17403            else
 17404              previous.Next = current.Next;
 17405
 17406            Node whereToAdd = GetEncapsulationParent(node.Parent, bounds);
 17407
 17408            if (whereToAdd is null)
 17409              throw new System.Exception("an item was updated outside the range of the omnitree");
 17410
 17411            this.Add(updated, whereToAdd, bounds, whereToAdd.Depth);
 17412          }
 17413          previous = current;
 17414        HeadRemoved:
 17415          current = current.Next;
 17416        }
 17417      }
 17418
 17419      node.Count -= removals;
 17420      return removals;
 17421    }
 17422
 17423    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 17424    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17425    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17426    public void Update(Axis1 min1, Axis1 max1)
 17427    {
 17428      this.Update(new Omnitree.Bounds<Axis1>(min1, max1), this._top, 0);
 17429    }
 17430    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 17431    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17432    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17433    public void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1)
 17434    {
 17435      this.Update(new Omnitree.Bounds<Axis1>(min1, max1), this._top, 0);
 17436    }
 17437    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 17438    /// <param name="axis1">The coordinate along the 1D axis.</param>
 17439    public void Update(Axis1 axis1)
 17440    {
 17441      this.Update(new Omnitree.Bounds<Axis1>(axis1, axis1), this._top, 0);
 17442    }
 17443    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 17444    /// <param name="axis1">The coordinate along the 1D axis.</param>
 17445    public void Update(Omnitree.Bound<Axis1> axis1)
 17446    {
 17447      this.Update(new Omnitree.Bounds<Axis1>(axis1, axis1), this._top, 0);
 17448    }
 17449    internal int Update(Omnitree.Bounds<Axis1> bounds, Node node, int depth)
 17450    {
 17451      if (!InclusionCheck(bounds, node.Bounds))
 17452        return 0;
 17453
 17454      int removals = 0;
 17455
 17456      {
 17457        Node branch = node as Node;
 17458        int skipped = 0;
 17459        for (int i = 0; i + skipped < branch.Children.Length; )
 17460        {
 17461          removals += this.Update(branch.Children[i], depth + 1);
 17462          if (branch.Children[i].Count is 0)
 17463            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 17464          else
 17465            i++;
 17466        }
 17467        Node[] newArray = new Node[branch.Children.Length - skipped];
 17468        Array.Copy(branch.Children, newArray, newArray.Length);
 17469        branch.Children = newArray;
 17470
 17471        if (branch.Count < _load && branch.Count != 0)
 17472          ShrinkChild(branch.Parent, branch.Index);
 17473      }
 17474
 17475      {
 17476        Node.ValueNode current = node.Head;
 17477        Node.ValueNode previous = null;
 17478        while (current is not null)
 17479        {
 17480          Omnitree.Bounds<Axis1> item_bounds = GetBoundings(current.Value);
 17481          if (!this.EncapsulationCheck(node.Bounds, item_bounds))
 17482          {
 17483            removals++;
 17484            T updated = current.Value;
 17485            if (previous is null)
 17486            {
 17487              node.Head = current.Next;
 17488              goto HeadRemoved;
 17489            }
 17490            else
 17491              previous.Next = current.Next;
 17492            Node whereToAdd = GetEncapsulationParent(node.Parent, item_bounds);
 17493            if (whereToAdd is null)
 17494              throw new System.Exception("an item was updates outside the range of the omnitree");
 17495            this.Add(updated, whereToAdd, item_bounds, whereToAdd.Depth);
 17496          }
 17497          previous = current;
 17498        HeadRemoved:
 17499          current = current.Next;
 17500        }
 17501      }
 17502
 17503      node.Count -= removals;
 17504      return removals;
 17505    }
 17506
 17507    #endregion
 17508
 17509    #region Remove
 17510
 17511    /// <summary>Removes all the items qualified by the delegate.</summary>
 17512    /// <param name="where">The predicate to qualify removals.</param>
 17513    public void Remove(Predicate<T> where)
 17514    {
 17515      this.Remove(this._top, where);
 17516      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 17517    }
 17518
 17519    /// <summary>Recursive version of the remove method.</summary>
 17520    /// <param name="node">The current node of traversal.</param>
 17521    /// <param name="where">The predicate to qualify removals.</param>
 17522    internal int Remove(Node node, Predicate<T> where)
 17523    {
 17524      int removals = 0;
 17525
 17526      // children
 17527      if (node.Children is not null)
 17528      {
 17529        int skipped = 0;
 17530        for (int i = 0; i + skipped < node.Children.Length; )
 17531        {
 17532          removals += this.Remove(node.Children[i], where);
 17533          if (node.Children[i].Count is 0)
 17534            node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 17535          else
 17536            i++;
 17537        }
 17538        Node[] newArray = new Node[node.Children.Length - skipped];
 17539        Array.Copy(node.Children, newArray, newArray.Length);
 17540        node.Children = newArray;
 17541
 17542        if (node.Count < _load && node.Count != 0)
 17543          ShrinkChild(node.Parent, node.Index);
 17544      }
 17545
 17546      // items
 17547      while (node.Head is not null && where(node.Head.Value))
 17548      {
 17549        node.Head = node.Head.Next;
 17550        removals++;
 17551      }
 17552      if (node.Head is not null)
 17553      {
 17554        Node.ValueNode list = node.Head;
 17555        while (list.Next is not null)
 17556        {
 17557          if (where(list.Next.Value))
 17558          {
 17559            list.Next = list.Next.Next;
 17560            removals++;
 17561          }
 17562        }
 17563      }
 17564
 17565      node.Count -= removals;
 17566      return removals;
 17567    }
 17568
 17569    /// <summary>Removes all the items encapsulated in a given space.</summary>
 17570    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17571    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17572    /// <returns>The number of items that were removed.</returns>
 17573    public void RemoveEncapsulated(Axis1 min1, Axis1 max1)
 17574    {
 17575      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1>(min1, max1));
 17576    }
 17577    /// <summary>Removes all the items encapsulated in a given space.</summary>
 17578    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17579    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17580    /// <returns>The number of items that were removed.</returns>
 17581    public void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1)
 17582    {
 17583      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1>(min1, max1));
 17584    }
 17585    /// <summary>Removes all the items encapsulated in a given space.</summary>
 17586    /// <param name="axis1">The coordinate along the 1D axis.</param>
 17587    public void RemoveEncapsulated(Omnitree.Bound<Axis1> axis1)
 17588    {
 17589      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1>(axis1, axis1));
 17590    }
 17591    internal int RemoveEncapsulated(Node node, Omnitree.Bounds<Axis1> bounds)
 17592    {
 17593      int removals = this.RemoveBase(node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 17594      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 17595      return removals;
 17596    }
 17597
 17598    /// <summary>Removes all the items overlapping a given space.</summary>
 17599    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17600    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17601    /// <returns>The number of items that were removed.</returns>
 17602    public void RemoveOverlapped(Axis1 min1, Axis1 max1)
 17603    {
 17604      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1>(min1, max1));
 17605    }
 17606    /// <summary>Removes all the items overlapping a given space.</summary>
 17607    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17608    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17609    /// <returns>The number of items that were removed.</returns>
 17610    public void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1)
 17611    {
 17612      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1>(min1, max1));
 17613    }
 17614    internal int RemoveOverlapped(Node node, Omnitree.Bounds<Axis1> bounds)
 17615    {
 17616      int removals = this.RemoveBase(node, bounds, (a, b) => this.InclusionCheck(a, b));
 17617      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 17618      return removals;
 17619    }
 17620
 17621    internal int RemoveBase(
 17622      Node node,
 17623      Omnitree.Bounds<Axis1> bounds,
 17624      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1>, Omnitree.Bounds<Axis1>> spatialCheck)
 17625    {
 17626      int removals = 0;
 17627      if (InclusionCheck(bounds, node.Bounds))
 17628      {
 17629        // items
 17630        Node.ValueNode current_node = node.Head;
 17631        Node.ValueNode previous_node = null;
 17632        while (!(current_node is null))
 17633        {
 17634          Node.ValueNode temp_previous = current_node;
 17635          if (spatialCheck(bounds, GetBoundings(current_node.Value)))
 17636          {
 17637            removals++;
 17638            if (current_node == node.Head)
 17639              node.Head = node.Head.Next;
 17640            else
 17641            {
 17642              previous_node.Next = current_node.Next;
 17643              temp_previous = previous_node;
 17644            }
 17645          }
 17646          previous_node = temp_previous;
 17647          current_node = current_node.Next;
 17648        }
 17649
 17650        // children
 17651        if (node.Children is not null)
 17652        {
 17653          int skipped = 0;
 17654          for (int i = 0; i + skipped < node.Children.Length; )
 17655          {
 17656            removals += this.RemoveBase(node.Children[i], bounds, spatialCheck);
 17657            if (node.Children[i].Count is 0)
 17658              node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 17659            else
 17660              i++;
 17661          }
 17662          Node[] newArray = new Node[node.Children.Length - skipped];
 17663          Array.Copy(node.Children, newArray, newArray.Length);
 17664          node.Children = newArray;
 17665
 17666          // convert this branch back into a leaf
 17667          // Note: if count is zero, it will be chopped off
 17668          if (node.Count < _load && node.Count > 0)
 17669            ShrinkChild(node.Parent, node.Index);
 17670        }
 17671      }
 17672
 17673      node.Count -= removals;
 17674      return removals;
 17675    }
 17676
 17677    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 17678    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17679    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17680    /// <param name="where">The equality constraint of the removal.</param>
 17681    public void RemoveEncapsulated(Axis1 min1, Axis1 max1, Predicate<T> where)
 17682    {
 17683      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1>(min1, max1), where);
 17684    }
 17685    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 17686    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17687    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17688    /// <param name="where">The equality constraint of the removal.</param>
 17689    public void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Predicate<T> where)
 17690    {
 17691      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1>(min1, max1), where);
 17692    }
 17693    internal int RemoveEncapsulated(Node node, Omnitree.Bounds<Axis1> bounds, Predicate<T> where)
 17694    {
 17695      int removals = RemoveBase(node, bounds, where, (a, b) => this.EncapsulationCheck(a, b));
 17696      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 17697      return removals;
 17698    }
 17699
 17700    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 17701    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17702    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17703    /// <param name="where">The equality constraint of the removal.</param>
 17704    public void RemoveOverlapped(Axis1 min1, Axis1 max1, Predicate<T> where)
 17705    {
 17706      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1>(min1, max1), where);
 17707    }
 17708    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 17709    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17710    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17711    /// <param name="where">The equality constraint of the removal.</param>
 17712    public void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Predicate<T> where)
 17713    {
 17714      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1>(min1, max1), where);
 17715    }
 17716    internal int RemoveOverlapped(Node node, Omnitree.Bounds<Axis1> bounds, Predicate<T> where)
 17717    {
 17718      int removals = RemoveBase(node, bounds, where, (a, b) => this.InclusionCheck(a, b));
 17719      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 17720      return removals;
 17721    }
 17722
 17723    internal int RemoveBase(
 17724      Node node,
 17725      Omnitree.Bounds<Axis1> bounds,
 17726      Predicate<T> where,
 17727      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1>, Omnitree.Bounds<Axis1>> spatialCheck)
 17728    {
 17729      if (!InclusionCheck(node.Bounds, bounds))
 17730        return 0;
 17731      int removals = 0;
 17732
 17733      // items
 17734      Node.ValueNode current = node.Head;
 17735      Node.ValueNode previous = null;
 17736      while (current is not null)
 17737      {
 17738        if (spatialCheck(bounds, GetBoundings(current.Value)) && where(current.Value))
 17739        {
 17740          removals++;
 17741          if (previous is null)
 17742          {
 17743            node.Head = current.Next;
 17744            goto HeadRemoved;
 17745          }
 17746          else
 17747            previous.Next = current.Next;
 17748        }
 17749        previous = current;
 17750      HeadRemoved:
 17751        current = current.Next;
 17752      }
 17753
 17754      // children
 17755      if (node.Children is not null)
 17756      {
 17757        int skipped = 0;
 17758        for (int i = 0; i + skipped < node.Children.Length; )
 17759        {
 17760          removals += this.RemoveBase(node.Children[i], bounds, where, spatialCheck);
 17761          if (node.Children[i].Count is 0)
 17762            node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 17763          else
 17764            i++;
 17765        }
 17766        Node[] newArray = new Node[node.Children.Length - skipped];
 17767        Array.Copy(node.Children, newArray, newArray.Length);
 17768        node.Children = newArray;
 17769
 17770        if (node.Count < _load && node.Count != 0)
 17771          ShrinkChild(node.Parent, node.Index);
 17772      }
 17773
 17774      node.Count -= removals;
 17775      return removals;
 17776    }
 17777
 17778    /// <summary>Tries to remove a value.</summary>
 17779    /// <param name="value">The value to remove.</param>
 17780    /// <returns>True if successful or false if not.</returns>
 17781    public (bool Success, Exception? Exception) TryRemove(T value)
 17782    {
 17783      Remove(value);
 17784      return (true, null);
 17785    }
 17786
 17787    /// <summary>Removes all instances of a given value.</summary>
 17788    public void Remove(T removal) => Omnitree.Remove(this, removal);
 17789
 17790    /// <summary>Removes all instances of a given value.</summary>
 17791    public void Remove(T removal, Func<T, T, bool> equate) => Omnitree.Remove(this, removal, equate);
 17792
 17793    /// <summary>Removes all the items in a given space.</summary>
 17794    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 17795    /// <returns>The number of items that were removed.</returns>
 17796    public void RemoveOverlapped(Axis1 axis1
 17797      )
 17798    {
 17799      this.RemoveOverlapped(axis1, axis1
 17800        );
 17801      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 17802    }
 17803
 17804    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 17805    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 17806    /// <param name="where">The equality constraint of the removal.</param>
 17807    public void RemoveOverlapped(Axis1 axis1, Predicate<T> where)
 17808    {
 17809      this.RemoveOverlapped(axis1, axis1
 17810        , where);
 17811      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 17812    }
 17813
 17814    #endregion
 17815
 17816    #region Stepper And IEnumerable
 17817
 17818    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 17819    /// <param name="step">The delegate to perform on every item in the tree.</param>
 17820    public void Stepper(Action<T> step) =>
 17821      this.Stepper(step, this._top);
 17822
 17823    internal void Stepper(Action<T> step, Node node)
 17824    {
 17825      Node.ValueNode list = node.Head;
 17826      while (list is not null)
 17827      {
 17828        step(list.Value);
 17829        list = list.Next;
 17830      }
 17831      if (node.Children is not null)
 17832        foreach (Node child in node.Children)
 17833          this.Stepper(step, child);
 17834    }
 17835
 17836    public StepStatus StepperBreak<TStep>(TStep step = default)
 17837      where TStep : struct, IFunc<T, StepStatus> =>
 17838      StepperBreak(_top, step);
 17839
 17840    internal StepStatus StepperBreak<TStep>(Node node, TStep step)
 17841      where TStep : struct, IFunc<T, StepStatus>
 17842    {
 17843      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 17844      {
 17845        if (step.Invoke(list.Value) is Break) return Break;
 17846      }
 17847      if (node.Children is not null)
 17848      {
 17849        foreach (Node child in node.Children)
 17850        {
 17851          if (StepperBreak(child, step) is Break) return Break;
 17852        }
 17853      }
 17854      return Continue;
 17855    }
 17856
 17857    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 17858    /// <param name="step">The delegate to perform on every item in the tree.</param>
 17859    public StepStatus Stepper(Func<T, StepStatus> step) =>
 17860      Stepper(step, _top);
 17861
 17862    internal StepStatus Stepper(Func<T, StepStatus> step, Node node)
 17863    {
 17864      StepStatus status = StepStatus.Continue;
 17865
 17866      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 17867        if ((status = step(list.Value)) != StepStatus.Continue)
 17868          break;
 17869
 17870      if (node.Children is not null)
 17871        foreach (Node child in node.Children)
 17872          if ((status = Stepper(step, child)) != StepStatus.Continue)
 17873            break;
 17874
 17875      return status;
 17876    }
 17877
 17878    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 17879    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 17880    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17881    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17882    public void StepperEncapsulated(Action<T> step, Axis1 min1, Axis1 max1) =>
 17883      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1>(min1, max1));
 17884
 17885    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 17886    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 17887    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17888    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17889    public void StepperEncapsulated(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1) =>
 17890      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1>(min1, max1));
 17891
 17892    internal void StepperEncapsulated(Action<T> step, Node node, Omnitree.Bounds<Axis1> bounds) =>
 17893      StepperBase(step, node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 17894
 17895    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 17896    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 17897    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17898    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17899    public void StepperOverlapped(Action<T> step, Axis1 min1, Axis1 max1) =>
 17900      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1>(min1, max1));
 17901
 17902    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 17903    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 17904    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17905    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17906    public void StepperOverlapped(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1) =>
 17907      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1>(min1, max1));
 17908
 17909    internal void StepperOverlapped(Action<T> step, Node node, Omnitree.Bounds<Axis1> bounds) =>
 17910      StepperBase(step, node, bounds, (a, b) => this.InclusionCheck(a, b));
 17911
 17912    internal void StepperBase(
 17913      Action<T> step,
 17914      Node node,
 17915      Omnitree.Bounds<Axis1> bounds,
 17916      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1>, Omnitree.Bounds<Axis1>> spatialCheck)
 17917    {
 17918      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 17919        if (spatialCheck(bounds, GetBoundings(list.Value)))
 17920          step(list.Value);
 17921
 17922      if (node.Children is not null)
 17923      {
 17924        foreach (Node child in node.Children)
 17925          // optimization: stop bounds checking if space encapsulates node
 17926          if (EncapsulationCheck(bounds, child.Bounds))
 17927            this.Stepper(step, child);
 17928          else if (InclusionCheck(child.Bounds, bounds))
 17929            this.StepperBase(step, child, bounds, spatialCheck);
 17930      }
 17931    }
 17932
 17933    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 17934    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 17935    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17936    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17937    public StepStatus StepperEncapsulated(Func<T, StepStatus> step, Axis1 min1, Axis1 max1) =>
 17938      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1>(min1, max1));
 17939
 17940    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 17941    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 17942    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17943    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17944    public StepStatus StepperEncapsulated(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> ma
 17945      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1>(min1, max1));
 17946
 17947    internal StepStatus StepperEncapsulated(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1> bounds) =>
 17948      StepperBase(step, node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 17949
 17950    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 17951    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 17952    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17953    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17954    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 min1, Axis1 max1) =>
 17955      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1>(min1, max1));
 17956
 17957    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 17958    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 17959    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 17960    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 17961    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1
 17962      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1>(min1, max1));
 17963
 17964    internal StepStatus StepperOverlapped(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1> bounds) =>
 17965      StepperBase(step, node, bounds, (a, b) => this.InclusionCheck(a, b));
 17966
 17967    internal StepStatus StepperBase(
 17968      Func<T, StepStatus> step,
 17969      Node node,
 17970      Omnitree.Bounds<Axis1> bounds,
 17971      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1>, Omnitree.Bounds<Axis1>> spatialCheck)
 17972    {
 17973      StepStatus status = StepStatus.Continue;
 17974
 17975      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 17976        if (spatialCheck(bounds, GetBoundings(list.Value)) &&
 17977          (status = step(list.Value)) != StepStatus.Continue)
 17978          break;
 17979
 17980      if (node.Children is not null)
 17981      {
 17982        foreach (Node child in node.Children)
 17983          // optimization: stop bounds checking if space encapsulates node
 17984          if (EncapsulationCheck(bounds, child.Bounds) &&
 17985            (status = this.Stepper(step, child)) != StepStatus.Continue)
 17986            break;
 17987          else if (InclusionCheck(child.Bounds, bounds) &&
 17988            (status = this.StepperBase(step, child, bounds, spatialCheck)) != StepStatus.Continue)
 17989            break;
 17990      }
 17991
 17992      return status;
 17993    }
 17994
 17995    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 17996    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 17997    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 17998    public void StepperOverlapped(Action<T> step, Axis1 axis1) =>
 17999      StepperOverlapped(step, this._top, new Omnitree.Bounds<Axis1>(axis1, axis1
 18000      ));
 18001
 18002    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 18003    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 18004    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 18005    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 axis1) =>
 18006      StepperOverlapped(step, this._top, new Omnitree.Bounds<Axis1>(axis1, axis1
 18007        ));
 18008
 18009    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 18010
 18011    public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 18012    {
 18013      // Note: this can be optimized.
 18014      IList<T> list = new ListLinked<T>();
 18015      Stepper(x => list.Add(x));
 18016      return list.GetEnumerator();
 18017    }
 18018
 18019    #endregion
 18020
 18021    /// <inheritdoc/>
 18022    public T[] ToArray() => throw new NotImplementedException();
 18023
 18024    #region Helpers
 18025
 18026    internal bool StraddlesLines(Omnitree.Bounds<Axis1> bounds, Omnitree.Vector<Axis1> vector) =>
 18027      Omnitree.StraddlesLines(bounds, vector
 18028        , _compare1
 18029        );
 18030
 18031    /// <summary>Computes the child index that contains the desired dimensions.</summary>
 18032    /// <param name="pointOfDivision">The point of division to compare against.</param>
 18033    /// <param name="bounds">The dimensions to determine the child index.</param>
 18034    /// <returns>The computed child index based on the coordinates relative to the center of the node.</returns>
 18035    internal int DetermineChildIndex(Omnitree.Vector<Axis1> pointOfDivision, Omnitree.Bounds<Axis1> bounds)
 18036    {
 18037      // make sure a child encapsulates the bounds (otherwise the bounds cannot move down the tree)
 18038      if (StraddlesLines(bounds, pointOfDivision))
 18039        return -1;
 18040
 18041      int child = 0;
 18042      if (!bounds.Min1.Exists || !(this._compare1(bounds.Min1.Value, pointOfDivision.Axis1) is Less))
 18043        child += 1 << 0;
 18044      return child;
 18045    }
 18046
 18047    /// <summary>Converts a branch back into a leaf when the count is reduced.</summary>
 18048    /// <param name="parent">The parent to shrink a child of.</param>
 18049    /// <param name="child_index">The index of the child to shrink.</param>
 18050    internal void ShrinkChild(Node parent, int child_index)
 18051    {
 18052      Node leaf;
 18053      Node removal = null;
 18054      if (parent is null) // top of tree
 18055      {
 18056        removal = this._top;
 18057        leaf = new Node(Omnitree.Bounds<Axis1>.None, null, -1);
 18058        this._top = leaf;
 18059      }
 18060      else // non-top branch
 18061      {
 18062        removal = parent[child_index];
 18063        leaf = new Node(removal.Bounds, removal.Parent, removal.Index);
 18064        parent[child_index] = leaf;
 18065      }
 18066
 18067      this.Stepper((T step) => { leaf.Add(step); }, removal);
 18068    }
 18069
 18070    /// <summary>Reduces the counts of all the parents of a given node by a given amount.</summary>
 18071    /// <param name="parent">The starting parent of the reduction.</param>
 18072    /// <param name="reduction">The amount to reduce the parent counts by.</param>
 18073    internal void ReduceParentCounts(Node parent, int reduction)
 18074    {
 18075      IncreaseParentCounts(parent, -reduction);
 18076    }
 18077
 18078    /// <summary>Increases the counts of all the parents of a given node by a given amount.</summary>
 18079    /// <param name="parent">The starting parent of the increase.</param>
 18080    /// <param name="increase">The amount to increase the parent counts by.</param>
 18081    internal void IncreaseParentCounts(Node parent, int increase)
 18082    {
 18083      Node node = parent;
 18084      while (node is not null)
 18085      {
 18086        node.Count += increase;
 18087        node = node.Parent;
 18088      }
 18089    }
 18090
 18091    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 18092    /// <returns>True if the spaces overlap; False if not.</returns>
 18093    internal bool InclusionCheck(Omnitree.Bounds<Axis1> a, Omnitree.Bounds<Axis1> b) =>
 18094      Omnitree.InclusionCheck(a, b
 18095      , _compare1
 18096      );
 18097
 18098    /// <summary>Checks if a space encapsulates a point.</summary>
 18099    /// <returns>True if the space encapsulates the point; False if not.</returns>
 18100    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1> bounds, Omnitree.Vector<Axis1> vector) =>
 18101      Omnitree.EncapsulationCheck(bounds, vector
 18102      , _compare1
 18103      );
 18104
 18105    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 18106    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 18107    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1> a, Omnitree.Bounds<Axis1> b) =>
 18108      Omnitree.EncapsulationCheck(a, b
 18109      , _compare1
 18110      );
 18111
 18112    /// <summary>Checks for equality between two locations.</summary>
 18113    /// <returns>True if equal; False if not;</returns>
 18114    internal bool EqualsCheck(Omnitree.Vector<Axis1> a, Omnitree.Vector<Axis1> b) =>
 18115      Omnitree.EqualsCheck(a, b
 18116      , (a, b) => _compare1(a, b) is Equal
 18117      );
 18118
 18119    /// <summary>Gets the nearest parent that encapsulates a location.</summary>
 18120    /// <param name="node">The starting node to find the encapsulating parent of the location.</param>
 18121    /// <param name="bounds">The bounds to get the encapsulating parent from.</param>
 18122    /// <returns>The nearest node that encapsulates the given location.</returns>
 18123    internal Node GetEncapsulationParent(Node node, Omnitree.Bounds<Axis1> bounds)
 18124    {
 18125      while (node is not null && !EncapsulationCheck(node.Bounds, bounds))
 18126      {
 18127        node = node.Parent;
 18128      }
 18129      return node;
 18130    }
 18131
 18132    internal Omnitree.Bounds<Axis1> GetBoundings(T value)
 18133    {
 18134      Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 18135      this._getBounds(value,
 18136        out min1, out max1
 18137        );
 18138      return new Omnitree.Bounds<Axis1>(
 18139        min1, max1
 18140        );
 18141    }
 18142
 18143    #endregion
 18144
 18145    #endregion
 18146  }
 18147
 18148  #endregion
 18149
 18150  #region 2 Dimensional
 18151
 18152  /// <summary>Inheritance base for 2D omnitrees that store bounds.</summary>
 18153  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 18154  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 18155  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 18156  public interface IOmnitreeBounds<T, Axis1, Axis2> : IOmnitree<T, Axis1, Axis2>
 18157  {
 18158    #region Properties
 18159
 18160    /// <summary>The number of dimensions in this tree.</summary>
 18161    int Dimensions { get; }
 18162
 18163    /// <summary>The delegate being used by the omnitree to get the bounds of values in 2D space.</summary>
 18164    Omnitree.GetBounds<T, Axis1
 18165, Axis2
 18166      > GetBounds { get; }
 18167
 18168    #endregion
 18169
 18170    #region Methods
 18171
 18172    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 18173    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 18174    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 18175    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 18176    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 18177    /// <returns>The number of items in the provided sub space.</returns>
 18178    int CountSubSpaceEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2);
 18179
 18180    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 18181    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 18182    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 18183    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 18184    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 18185    /// <returns>The number of items in the provided sub space.</returns>
 18186    int CountSubSpaceOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2);
 18187
 18188    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 18189    void Update();
 18190    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 18191    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 18192    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 18193    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 18194    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 18195    void Update(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2);
 18196
 18197    /// <summary>Removes all the items in a given space.</summary>
 18198    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 18199    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 18200    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 18201    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 18202    void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2);
 18203    /// <summary>Removes all the items in a given space.</summary>
 18204    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 18205    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 18206    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 18207    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 18208    void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree
 18209    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 18210    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 18211    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 18212    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 18213    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 18214    /// <param name="where">The predicate constraint of the removal.</param>
 18215    void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Predicate<T> where);
 18216    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 18217    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 18218    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 18219    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 18220    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 18221    /// <param name="where">The predicate constraint of the removal.</param>
 18222    void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree
 18223
 18224    /// <summary>Removes all the items in a given space.</summary>
 18225    /// <param name="axis1">The coordinate along the 1D axis.</param>
 18226    /// <param name="axis2">The coordinate along the 2D axis.</param>
 18227    void RemoveOverlapped(Axis1 axis1, Axis2 axis2);
 18228    /// <summary>Removes all the items in a given space.</summary>
 18229    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 18230    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 18231    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 18232    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 18233    void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2);
 18234    /// <summary>Removes all the items in a given space.</summary>
 18235    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 18236    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 18237    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 18238    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 18239    void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.B
 18240    /// <summary>Removes all the items in a given space where equality is met.</summary>
 18241    /// <param name="axis1">The coordinate along the 1D axis.</param>
 18242    /// <param name="axis2">The coordinate along the 2D axis.</param>
 18243    /// <param name="where">The equality constraint of the removal.</param>
 18244    void RemoveOverlapped(Axis1 axis1, Axis2 axis2, Predicate<T> where);
 18245    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 18246    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 18247    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 18248    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 18249    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 18250    /// <param name="where">The predicate constraint of the removal.</param>
 18251    void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Predicate<T> where);
 18252    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 18253    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 18254    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 18255    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 18256    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 18257    /// <param name="where">The predicate constraint of the removal.</param>
 18258    void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.B
 18259
 18260    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 18261    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 18262    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 18263    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 18264    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 18265    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 18266    void StepperEncapsulated(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis
 18267    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 18268    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 18269    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 18270    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 18271    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 18272    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 18273    StepStatus StepperEncapsulated(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omn
 18274
 18275    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 18276    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 18277    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 18278    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 18279    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 18280    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 18281    void StepperOverlapped(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2>
 18282    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 18283    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 18284    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 18285    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 18286    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 18287    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 18288    StepStatus StepperOverlapped(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnit
 18289
 18290    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 18291    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 18292    /// <param name="axis1">The coordinate along the 1D axis.</param>
 18293    /// <param name="axis2">The coordinate along the 2D axis.</param>
 18294    void StepperOverlapped(Action<T> step, Axis1 axis1, Axis2 axis2);
 18295    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 18296    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 18297    /// <param name="axis1">The coordinate along the 1D axis.</param>
 18298    /// <param name="axis2">The coordinate along the 2D axis.</param>
 18299    StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2);
 18300
 18301    #endregion
 18302  }
 18303
 18304  /// <summary>Omnitree that stores bounds along 2 dimensions implemented as a linked tree.</summary>
 18305  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 18306  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 18307  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 18308  public class OmnitreeBoundsLinked<T, Axis1, Axis2> : IOmnitreeBounds<T, Axis1, Axis2>
 18309  {
 18310    internal const int _dimensions = 2;
 18311    internal static int _children_per_node = (int)BigInteger.Pow(2, 2);
 18312
 18313    internal Node _top;
 18314    internal int _naturalLogLower = 1; // caching the next time to calculate loads (lower count)
 18315    internal int _naturalLogUpper = -1; // caching the next time to calculate loads (upper count)
 18316    internal int _load; // ln(count); min = _defaultLoad
 18317    internal Omnitree.GetBounds<T, Axis1
 18318, Axis2
 18319      > _getBounds;
 18320    internal bool _defaultCompare1;
 18321    internal Func<Axis1, Axis1, CompareResult> _compare1;
 18322    internal bool _defaultCompare2;
 18323    internal Func<Axis2, Axis2, CompareResult> _compare2;
 18324    internal Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2>> _subdivisionOverride1;
 18325    internal Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2>> _subdivisionOverride2;
 18326
 18327    #region Nested Types
 18328
 18329    /// <summary>Can be a leaf or a branch.</summary>
 18330    internal class Node
 18331    {
 18332      internal class ValueNode
 18333      {
 18334        internal T Value;
 18335        internal ValueNode Next;
 18336
 18337        internal ValueNode(T value, ValueNode next)
 18338        {
 18339          Value = value;
 18340          Next = next;
 18341        }
 18342      }
 18343
 18344      internal Omnitree.Bounds<Axis1, Axis2> Bounds;
 18345      internal Node Parent;
 18346      internal int Index;
 18347      internal int Count;
 18348      internal ValueNode Head;
 18349      internal Node[] Children;
 18350      internal Omnitree.Vector<Axis1, Axis2>? PointOfDivision;
 18351
 18352      /// <summary>Gets child by index.</summary>
 18353      /// <param name="child_index">The index of the child to get.</param>
 18354      /// <returns>The child of the given index or null if non-existent.</returns>
 18355      internal Node this[int child_index]
 18356      {
 18357        get
 18358        {
 18359          if (Children is null)
 18360            return null;
 18361          if (Children.Length == OmnitreePointsLinked<T, Axis1, Axis2>._children_per_node)
 18362            return Children[(int)child_index];
 18363          foreach (Node node in Children)
 18364            if (node.Index == child_index)
 18365              return node;
 18366          return null;
 18367        }
 18368        set
 18369        {
 18370          // This error check should be unnecessary... but fuck it... might as well
 18371          if (value.Index != child_index)
 18372            throw new System.Exception("Bug in Omnitree (index/property mis-match when setting a child on a branch)");
 18373
 18374          // no children yet
 18375          if (Children is null)
 18376          {
 18377            Children = â±¯(value);
 18378            return;
 18379          }
 18380          // max children overwrite
 18381          else if (Children.Length == OmnitreePointsLinked<T, Axis1, Axis2>._children_per_node)
 18382          {
 18383            Children[(int)child_index] = value;
 18384            return;
 18385          }
 18386          // non-max child overwrite
 18387          for (int i = 0; i < Children.Length; i++)
 18388            if (Children[i].Index == child_index)
 18389            {
 18390              Children[i] = value;
 18391              return;
 18392            }
 18393          // new child
 18394          Node[] newArray = new Node[Children.Length + 1];
 18395          if (newArray.Length == OmnitreePointsLinked<T, Axis1, Axis2>._children_per_node)
 18396          {
 18397            // new child resulting in a max children branch (sorting required)
 18398            for (int i = 0; i < Children.Length; i++)
 18399            {
 18400              newArray[(int)Children[i].Index] = Children[i];
 18401            }
 18402            newArray[(int)value.Index] = value;
 18403          }
 18404          else
 18405          {
 18406            // new child resulting in a non-max children branch
 18407            Array.Copy(Children, newArray, Children.Length);
 18408            newArray[newArray.Length - 1] = value;
 18409          }
 18410          Children = newArray;
 18411        }
 18412      }
 18413
 18414      /// <summary>The depth this node is located in the Omnitree.</summary>
 18415      internal int Depth
 18416      {
 18417        get
 18418        {
 18419          int depth = -1;
 18420          for (Node node = this; node is not null; node = node.Parent)
 18421            depth++;
 18422          return depth;
 18423        }
 18424      }
 18425
 18426      /// <summary>Constructs a node.</summary>
 18427      /// <param name="bounds">The bounds of this node.</param>
 18428      /// <param name="parent">The parent of this node.</param>
 18429      /// <param name="index">The number of values stored in this node and its children.</param>
 18430      internal Node(Omnitree.Bounds<Axis1, Axis2> bounds, Node parent, int index)
 18431      {
 18432        Bounds = bounds;
 18433        Parent = parent;
 18434        Index = index;
 18435      }
 18436
 18437      internal Node(Omnitree.Vector<Axis1, Axis2> pointOfDivision, Omnitree.Bounds<Axis1, Axis2> bounds, Node parent, in
 18438        : this(bounds, parent, index)
 18439      {
 18440        PointOfDivision = pointOfDivision;
 18441      }
 18442
 18443      internal Node(Node nodeToClone)
 18444      {
 18445        this.Bounds = nodeToClone.Bounds;
 18446        this.Parent = nodeToClone.Parent;
 18447        this.Index = nodeToClone.Index;
 18448        this.Count = nodeToClone.Count;
 18449
 18450        Children = nodeToClone.Children.Clone() as Node[];
 18451        PointOfDivision = nodeToClone.PointOfDivision;
 18452
 18453        ValueNode a = this.Head;
 18454        ValueNode b = nodeToClone.Head;
 18455
 18456        while (b is not null)
 18457        {
 18458          a.Next = new ValueNode(b.Next.Value, null);
 18459          a = a.Next;
 18460          b = b.Next;
 18461        }
 18462      }
 18463
 18464      internal void Add(T addition)
 18465      {
 18466        Head = new ValueNode(addition, Head);
 18467        Count++;
 18468      }
 18469
 18470      internal Node Clone() =>
 18471        new Node(this);
 18472    }
 18473
 18474    #endregion
 18475
 18476    #region Constructors
 18477
 18478    /// <summary>This constructor is for cloning purposes</summary>
 18479    internal OmnitreeBoundsLinked(OmnitreeBoundsLinked<T, Axis1, Axis2> omnitree)
 18480    {
 18481      this._top = omnitree._top.Clone();
 18482      this._load = omnitree._load;
 18483      this._getBounds = omnitree._getBounds;
 18484      this._defaultCompare1 = omnitree._defaultCompare1;
 18485      this._compare1 = omnitree._compare1;
 18486      this._defaultCompare2 = omnitree._defaultCompare2;
 18487      this._compare2 = omnitree._compare2;
 18488      this._subdivisionOverride1 = omnitree._subdivisionOverride1;
 18489      this._subdivisionOverride2 = omnitree._subdivisionOverride2;
 18490    }
 18491
 18492    internal OmnitreeBoundsLinked(
 18493      Omnitree.GetBounds<T, Axis1, Axis2> getBounds,
 18494      bool defaultCompare1,
 18495      Func<Axis1, Axis1, CompareResult> compare1,
 18496      bool defaultCompare2,
 18497      Func<Axis2, Axis2, CompareResult> compare2,
 18498      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2>> subdivisionOverride1
 18499,
 18500      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2>> subdivisionOverride2
 18501      )
 18502    {
 18503      if (getBounds is null)
 18504      {
 18505        throw new ArgumentNullException(nameof(getBounds));
 18506      }
 18507      if (compare1 is null)
 18508      {
 18509        throw new ArgumentNullException(nameof(compare1));
 18510      }
 18511      if (compare2 is null)
 18512      {
 18513        throw new ArgumentNullException(nameof(compare2));
 18514      }
 18515      this._getBounds = getBounds;
 18516      this._defaultCompare1 = defaultCompare1;
 18517      this._compare1 = compare1;
 18518      this._defaultCompare2 = defaultCompare2;
 18519      this._compare2 = compare2;
 18520      this._subdivisionOverride1 = subdivisionOverride1;
 18521      this._subdivisionOverride2 = subdivisionOverride2;
 18522      this._top = new Node(Omnitree.Bounds<Axis1, Axis2>.None, null, -1);
 18523      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 18524    }
 18525
 18526    /// <summary>Constructs a new 2D omnitree that stores bounds.</summary>
 18527    /// <param name="getBounds">The delegate for getting object bounds in 2D space.</param>
 18528
 18529    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 18530
 18531    /// <param name="compare2">The delegate for comparing values along the 2D axis.</param>
 18532
 18533    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 18534
 18535    /// <param name="subdivisionOverride2">The subdivision overide to be used when splitting the 2 dimension.</param>
 18536    public OmnitreeBoundsLinked(
 18537      Omnitree.GetBounds<T, Axis1, Axis2> getBounds,
 18538      Func<Axis1, Axis1, CompareResult> compare1 = null,
 18539      Func<Axis2, Axis2, CompareResult> compare2 = null,
 18540      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2>> subdivisionOverride1 = null
 18541,
 18542      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2>> subdivisionOverride2 = null
 18543      )
 18544      : this(
 18545      getBounds,
 18546      compare1 is null ? true : false,
 18547      compare1 ?? Compare,
 18548      compare2 is null ? true : false,
 18549      compare2 ?? Compare,
 18550      subdivisionOverride1
 18551,
 18552      subdivisionOverride2
 18553      ) { }
 18554
 18555    /// <summary>Constructs a new 2D omnitree that stores bounds.</summary>
 18556    /// <param name="getBoundings">The delegate for getting object bounds in 2D space.</param>
 18557    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 18558    /// <param name="compare2">The delegate for comparing values along the 2D axis.</param>
 18559
 18560    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 18561
 18562    /// <param name="subdivisionOverride2">The subdivision overide to be used when splitting the 2 dimension.</param>
 18563    public OmnitreeBoundsLinked(
 18564      Omnitree.GetBoundings<T, Axis1, Axis2> getBoundings,
 18565      Func<Axis1, Axis1, CompareResult> compare1 = null,
 18566      Func<Axis2, Axis2, CompareResult> compare2 = null,
 18567      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2>> subdivisionOverride1 = null
 18568      , Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2>> subdivisionOverride2 = null
 18569      )
 18570      : this(
 18571      Omnitree.ConvertToGetBounds(getBoundings),
 18572      compare1 is null ? true : false,
 18573      compare1 ?? Compare,
 18574      compare2 is null ? true : false,
 18575      compare2 ?? Compare,
 18576      subdivisionOverride1
 18577,
 18578      subdivisionOverride2
 18579      ) { }
 18580
 18581    #endregion
 18582
 18583    #region Properties
 18584
 18585    /// <summary>The number of dimensions in this tree.</summary>
 18586    public int Dimensions => _dimensions;
 18587
 18588    /// <summary>The delegate being used by the omnitree to locate items in 2D space.</summary>
 18589    public Omnitree.GetBounds<T, Axis1
 18590      , Axis2
 18591      > GetBounds => _getBounds;
 18592
 18593
 18594    /// <summary>The comparison function the Omnitree is using along the 1D axis.</summary>
 18595    public Func<Axis1, Axis1, CompareResult> Compare1 => _compare1;
 18596    /// <summary>The comparison function the Omnitree is using along the 2D axis.</summary>
 18597    public Func<Axis2, Axis2, CompareResult> Compare2 => _compare2;
 18598
 18599    /// <summary>The current number of items in the tree.</summary>
 18600    public int Count  => _top.Count;
 18601
 18602    internal delegate void MaxDepthFinder(Node node, int current_depth, ref int max_depth);
 18603    /// <summary>Finds the current maximum depth of the tree. NOT AN O(1) OPERATION. Intended for educational purposes o
 18604    public int MaxDepth
 18605    {
 18606      get
 18607      {
 18608        MaxDepthFinder maxDepthFinder = null;
 18609        maxDepthFinder =
 18610            (Node node, int current_depth, ref int max_depth) =>
 18611            {
 18612              if (current_depth > max_depth)
 18613                max_depth = current_depth;
 18614              foreach (Node child in node.Children)
 18615                maxDepthFinder(child, current_depth + 1, ref max_depth);
 18616            };
 18617        int _max_depth = -1;
 18618        maxDepthFinder(this._top, 0, ref _max_depth);
 18619        return _max_depth;
 18620      }
 18621    }
 18622
 18623    internal delegate void NodeCountFinder(Node node, ref int current_count);
 18624    /// <summary>Counts the current number of nodes in the tree. NOT AN O(1) OPERATION. Intended for educational purpose
 18625    public int NodeCount
 18626    {
 18627      get
 18628      {
 18629        NodeCountFinder nodeCountFinder = null;
 18630        nodeCountFinder =
 18631            (Node node, ref int current_count) =>
 18632            {
 18633              current_count++;
 18634              foreach (Node child in node.Children)
 18635                nodeCountFinder(child, ref current_count);
 18636            };
 18637
 18638        int _current_count = 0;
 18639        nodeCountFinder(this._top, ref _current_count);
 18640        return _current_count;
 18641      }
 18642    }
 18643
 18644    #endregion
 18645
 18646    #region Methods
 18647
 18648    #region Add
 18649
 18650
 18651    #region single
 18652
 18653    /// <summary>Tries to add a value.</summary>
 18654    /// <param name="value">The value to be added.</param>
 18655    /// <returns>True if successful or false if not.</returns>
 18656    public (bool Success, Exception? Exception) TryAdd(T value)
 18657    {
 18658      Add(value);
 18659      return (true, null);
 18660    }
 18661
 18662    /// <summary>Adds an item to the tree.</summary>
 18663    /// <param name="addition">The item to be added.</param>
 18664    public void Add(T addition)
 18665    {
 18666      if (this._top.Count is int.MaxValue)
 18667        throw new System.InvalidOperationException("(Count is int.MaxValue) max Omnitree size reached (change ints to lo
 18668
 18669      // dynamic tree sizes
 18670      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 18671
 18672      Omnitree.Bounds<Axis1, Axis2> bounds = GetBoundings(addition);
 18673
 18674      // grow the first branch of the tree
 18675      if (!this._top.PointOfDivision.HasValue && this._top.Count >= _load)
 18676      {
 18677        Node top = this._top;
 18678
 18679        // create the new branch from the median values
 18680        this._top = new Node(DetermineMedians(top), Omnitree.Bounds<Axis1, Axis2>.None, null, -1);
 18681
 18682        // iterate through the values and add them to the appropriate children
 18683        for (Node.ValueNode list = top.Head; list is not null; list = list.Next)
 18684          Add(list.Value, this._top, GetBoundings(list.Value), 0);
 18685      }
 18686
 18687      this.Add(addition, this._top, bounds, 0);
 18688    }
 18689
 18690    /// <summary>Recursive version of the add function.</summary>
 18691    /// <param name="addition">The item to be added.</param>
 18692    /// <param name="node">The current node for tree trversal.</param>
 18693    /// <param name="bounds">The bounds of the addition.</param>
 18694    /// <param name="depth">The current depth of iteration.</param>
 18695    internal void Add(T addition, Node node, Omnitree.Bounds<Axis1, Axis2> bounds, int depth)
 18696    {
 18697      if (!node.PointOfDivision.HasValue)
 18698      {
 18699        //Leaf leaf = node as Leaf;
 18700        if (depth >= _load || !(node.Count >= _load))
 18701        {
 18702          node.Add(addition);
 18703          return;
 18704        }
 18705        else
 18706        {
 18707          //Node parent = node.Parent;
 18708          //int child_index = this.DetermineChildIndex(parent.PointOfDivision, location);
 18709          //Node growth = new Node(DetermineMedians(leaf), leaf.Bounds, parent, child_index);
 18710          //parent[child_index] = growth;
 18711
 18712          Node growth = new Node(DetermineMedians(node), node.Bounds, node.Parent, node.Index);
 18713          node.Parent[node.Index] = growth;
 18714
 18715          for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 18716          {
 18717            Omnitree.Bounds<Axis1, Axis2> temp_bounds = GetBoundings(list.Value);
 18718            if (EncapsulationCheck(growth.Bounds, temp_bounds))
 18719              Add(list.Value, growth, temp_bounds, depth);
 18720            else
 18721            {
 18722              ReduceParentCounts(node.Parent, 1);
 18723              Add(list.Value, this._top, temp_bounds, depth);
 18724            }
 18725          }
 18726
 18727          Add(addition, growth, bounds, depth);
 18728          return;
 18729        }
 18730      }
 18731      else
 18732      {
 18733        //Node branch = node as Node;
 18734        int child_index = this.DetermineChildIndex(node.PointOfDivision.Value, bounds); // determine the child "index" (
 18735
 18736        // if -1, then the bounds of the addition straddle the point of division (keep it in current node)
 18737        if (child_index is -1)
 18738        {
 18739          node.Add(addition);
 18740          return;
 18741        }
 18742
 18743        Node child_node = node[child_index];
 18744
 18745        // null children in branches are just empty leaves
 18746        if (child_node is null)
 18747        {
 18748          Node new_node = new Node(DetermineChildBounds(node, child_index), node, child_index);
 18749          node[child_index] = new_node;
 18750          new_node.Add(addition);
 18751        }
 18752        else
 18753          // child exists already, continue adding
 18754          Add(addition, child_node, bounds, depth + 1);
 18755
 18756        node.Count++;
 18757        return;
 18758      }
 18759    }
 18760
 18761    internal Omnitree.Vector<Axis1, Axis2> DetermineMedians(Node node)
 18762    {
 18763      //try
 18764      //{
 18765        // extract the values
 18766        Omnitree.Bound<Axis1>[] values1 = new Omnitree.Bound<Axis1>[node.Count * 2];
 18767        Omnitree.Bound<Axis2>[] values2 = new Omnitree.Bound<Axis2>[node.Count * 2];
 18768        Node.ValueNode for_current = node.Head; // used in for loop
 18769        for (int i = 0; i < node.Count; i++, for_current = for_current.Next)
 18770          this._getBounds(for_current.Value,
 18771          out values1[i * 2], out values1[i * 2 + 1]
 18772,
 18773          out values2[i * 2], out values2[i * 2 + 1]
 18774          );
 18775        return new Omnitree.Vector<Axis1, Axis2>(
 18776          Omnitree.SubDivide(values1, this._defaultCompare1 ? Compare : this._compare1)
 18777,
 18778          Omnitree.SubDivide(values2, this._defaultCompare2 ? Compare : this._compare2)
 18779          );
 18780      //}
 18781      //catch
 18782      //{
 18783        // extract the values
 18784      //  ArrayJagged<Omnitree.Bound<Axis1>> values1 = new ArrayJagged<Omnitree.Bound<Axis1>>(node.Count * 2);
 18785      //  ArrayJagged<Omnitree.Bound<Axis2>> values2 = new ArrayJagged<Omnitree.Bound<Axis2>>(node.Count * 2);
 18786      //  Node.ValueNode for_current = node.Head; // used in for loop
 18787      //  for (int i = 0; i < node.Count; i++, for_current = for_current.Next)
 18788      //  {
 18789      //    Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 18790      //    Omnitree.Bound<Axis2> min2; Omnitree.Bound<Axis2> max2;
 18791      //    this._getBounds(for_current.Value,
 18792      //      out min1, out max1
 18793//,
 18794      //      out min2, out max2
 18795      //      );
 18796      //    values1[i * 2] = min1; values1[i * 2 + 1] = max1;
 18797      //    values2[i * 2] = min2; values2[i * 2 + 1] = max2;
 18798      //  }
 18799      //  return new Omnitree.Vector<Axis1, Axis2>(
 18800      //    Omnitree.SubDivide(values1, this._defaultCompare1 ? Compare : this._compare1)
 18801      //    , Omnitree.SubDivide(values2, this._defaultCompare2 ? Compare : this._compare2)
 18802      //  );
 18803      //}
 18804    }
 18805
 18806    #endregion
 18807
 18808    #region Add Helpers
 18809
 18810    internal Omnitree.Bounds<Axis1, Axis2> DetermineChildBounds(Node node, int child_index)
 18811    {
 18812      // the node parameter should always have a point of division value for this function
 18813      Omnitree.Vector<Axis1, Axis2> pointOfDivision = node.PointOfDivision.Value;
 18814
 18815      Omnitree.Bound<Axis2> min2, max2;
 18816      if (child_index >= 2)
 18817      {
 18818        min2 = pointOfDivision.Axis2;
 18819        max2 = node.Bounds.Max2;
 18820        child_index -= 2;
 18821      }
 18822      else
 18823      {
 18824        min2 = node.Bounds.Min2;
 18825        max2 = pointOfDivision.Axis2;
 18826      }
 18827
 18828      Omnitree.Bound<Axis1> min1, max1;
 18829      if (child_index >= 1)
 18830      {
 18831        min1 = pointOfDivision.Axis1;
 18832        max1 = node.Bounds.Max1;
 18833        child_index -= 1;
 18834      }
 18835      else
 18836      {
 18837        min1 = node.Bounds.Min1;
 18838        max1 = pointOfDivision.Axis1;
 18839      }
 18840
 18841      return new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2);
 18842    }
 18843
 18844    #endregion
 18845
 18846    #endregion
 18847
 18848    #region Clear
 18849
 18850    /// <summary>Returns the tree to an empty state.</summary>
 18851    public void Clear()
 18852    {
 18853      this._top = new Node(Omnitree.Bounds<Axis1, Axis2>.None, null, -1);
 18854      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 18855    }
 18856
 18857    #endregion
 18858
 18859    #region Clone
 18860
 18861    /// <summary>Creates a shallow clone of this data structure.</summary>
 18862    /// <returns>A shallow clone of this data structure.</returns>
 18863    public OmnitreeBoundsLinked<T, Axis1, Axis2> Clone()
 18864    {
 18865      return new OmnitreeBoundsLinked<T, Axis1, Axis2>(this);
 18866    }
 18867
 18868    #endregion
 18869
 18870    #region Count
 18871
 18872    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 18873    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 18874    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 18875    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 18876    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 18877    /// <returns>The number of items in the provided sub space.</returns>
 18878    public int CountSubSpaceEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2)
 18879    {
 18880      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 18881    }
 18882    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 18883    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 18884    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 18885    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 18886    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 18887    /// <returns>The number of items in the provided sub space.</returns>
 18888    public int CountSubSpaceEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> m
 18889    {
 18890      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 18891    }
 18892    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 18893    /// <param name="axis1">The coordinate along the 1D axis.</param>
 18894    /// <param name="axis2">The coordinate along the 2D axis.</param>
 18895    /// <returns>The number of items in the provided sub space.</returns>
 18896    public int CountSubSpaceEncapsulated(Axis1 axis1, Axis2 axis2)
 18897    {
 18898      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2>(axis1, axis1, axis2, axis2));
 18899    }
 18900    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 18901    /// <param name="axis1">The coordinate along the 1D axis.</param>
 18902    /// <param name="axis2">The coordinate along the 2D axis.</param>
 18903    /// <returns>The number of items in the provided sub space.</returns>
 18904    public int CountSubSpaceEncapsulated(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2)
 18905    {
 18906      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2>(axis1, axis1, axis2, axis2));
 18907    }
 18908
 18909    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 18910    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 18911    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 18912    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 18913    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 18914    /// <returns>The number of items in the provided sub space.</returns>
 18915    public int CountSubSpaceOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2)
 18916    {
 18917      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 18918    }
 18919    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 18920    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 18921    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 18922    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 18923    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 18924    /// <returns>The number of items in the provided sub space.</returns>
 18925    public int CountSubSpaceOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min
 18926    {
 18927      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 18928    }
 18929    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 18930    /// <param name="axis1">The coordinate along the 1D axis.</param>
 18931    /// <param name="axis2">The coordinate along the 2D axis.</param>
 18932    /// <returns>The number of items in the provided sub space.</returns>
 18933    public int CountSubSpaceOverlapped(Axis1 axis1, Axis2 axis2)
 18934    {
 18935      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2>(axis1, axis1, axis2, axis2));
 18936    }
 18937    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 18938    /// <param name="axis1">The coordinate along the 1D axis.</param>
 18939    /// <param name="axis2">The coordinate along the 2D axis.</param>
 18940    /// <returns>The number of items in the provided sub space.</returns>
 18941    public int CountSubSpaceOverlapped(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2)
 18942    {
 18943      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2>(axis1, axis1, axis2, axis2));
 18944    }
 18945
 18946    internal int CountSubSpaceEncapsulated(Node node, Omnitree.Bounds<Axis1, Axis2> bounds)
 18947    {
 18948      return CountSubSpaceBase(_top, bounds, (a, b) => EncapsulationCheck(a, b));
 18949    }
 18950
 18951    internal int CountSubSpaceOverlapped(Node node, Omnitree.Bounds<Axis1, Axis2> bounds)
 18952    {
 18953      return CountSubSpaceBase(_top, bounds, (a, b) => InclusionCheck(a, b));
 18954    }
 18955
 18956    internal int CountSubSpaceBase(
 18957      Node node,
 18958      Omnitree.Bounds<Axis1, Axis2> bounds,
 18959      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2>, Omnitree.Bounds<Axis1, Axis2>> spatialCheck)
 18960    {
 18961      // adjust min/max values
 18962      int count = 0;
 18963      if (EncapsulationCheck(bounds, node.Bounds))
 18964        count += node.Count;
 18965      else if (!node.PointOfDivision.HasValue)
 18966      {
 18967        for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 18968          if (spatialCheck(bounds, GetBoundings(list.Value)))
 18969            count++;
 18970      }
 18971      else
 18972      {
 18973        Node branch = node as Node;
 18974        if (!StraddlesLines(branch.Bounds, branch.PointOfDivision.Value))
 18975        {
 18976          int child_index = DetermineChildIndex(branch.PointOfDivision.Value, bounds);
 18977          Node child = branch[child_index];
 18978          if (child is not null)
 18979            count += this.CountSubSpaceBase(child, bounds, spatialCheck);
 18980        }
 18981        else
 18982        {
 18983          foreach (Node child in node.Children)
 18984            count += this.CountSubSpaceBase(child, bounds, spatialCheck);
 18985        }
 18986      }
 18987      return count;
 18988    }
 18989
 18990    #endregion
 18991
 18992    #region Update
 18993
 18994    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 18995    public void Update()
 18996    {
 18997      this.Update(this._top, 0);
 18998    }
 18999
 19000    /// <summary>Recursive version of the Update method.</summary>
 19001    /// <param name="node">The current node of iteration.</param>
 19002    /// <param name="depth">The current depth of iteration.</param>
 19003    internal int Update(Node node, int depth)
 19004    {
 19005      int removals = 0;
 19006
 19007      {
 19008        Node branch = node as Node;
 19009        int skipped = 0;
 19010        for (int i = 0; i + skipped < branch.Children.Length; )
 19011        {
 19012          removals += this.Update(branch.Children[i], depth + 1);
 19013          if (branch.Children[i].Count is 0)
 19014            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 19015          else
 19016            i++;
 19017        }
 19018        Node[] newArray = new Node[branch.Children.Length - skipped];
 19019        Array.Copy(branch.Children, newArray, newArray.Length);
 19020        branch.Children = newArray;
 19021
 19022        if (branch.Count < _load && branch.Count != 0)
 19023          ShrinkChild(branch.Parent, branch.Index);
 19024      }
 19025
 19026      {
 19027        Node.ValueNode current = node.Head;
 19028        Node.ValueNode previous = null;
 19029        while (current is not null)
 19030        {
 19031          Omnitree.Bounds<Axis1, Axis2> bounds = GetBoundings(current.Value);
 19032          if (!this.EncapsulationCheck(node.Bounds, bounds))
 19033          {
 19034            removals++;
 19035            T updated = current.Value;
 19036            if (previous is null)
 19037            {
 19038              node.Head = current.Next;
 19039              goto HeadRemoved;
 19040            }
 19041            else
 19042              previous.Next = current.Next;
 19043
 19044            Node whereToAdd = GetEncapsulationParent(node.Parent, bounds);
 19045
 19046            if (whereToAdd is null)
 19047              throw new System.Exception("an item was updated outside the range of the omnitree");
 19048
 19049            this.Add(updated, whereToAdd, bounds, whereToAdd.Depth);
 19050          }
 19051          previous = current;
 19052        HeadRemoved:
 19053          current = current.Next;
 19054        }
 19055      }
 19056
 19057      node.Count -= removals;
 19058      return removals;
 19059    }
 19060
 19061    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 19062    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19063    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19064    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19065    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19066    public void Update(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2)
 19067    {
 19068      this.Update(new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2), this._top, 0);
 19069    }
 19070    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 19071    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19072    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19073    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19074    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19075    public void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 19076    {
 19077      this.Update(new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2), this._top, 0);
 19078    }
 19079    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 19080    /// <param name="axis1">The coordinate along the 1D axis.</param>
 19081    /// <param name="axis2">The coordinate along the 2D axis.</param>
 19082    public void Update(Axis1 axis1, Axis2 axis2)
 19083    {
 19084      this.Update(new Omnitree.Bounds<Axis1, Axis2>(axis1, axis1, axis2, axis2), this._top, 0);
 19085    }
 19086    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 19087    /// <param name="axis1">The coordinate along the 1D axis.</param>
 19088    /// <param name="axis2">The coordinate along the 2D axis.</param>
 19089    public void Update(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2)
 19090    {
 19091      this.Update(new Omnitree.Bounds<Axis1, Axis2>(axis1, axis1, axis2, axis2), this._top, 0);
 19092    }
 19093    internal int Update(Omnitree.Bounds<Axis1, Axis2> bounds, Node node, int depth)
 19094    {
 19095      if (!InclusionCheck(bounds, node.Bounds))
 19096        return 0;
 19097
 19098      int removals = 0;
 19099
 19100      {
 19101        Node branch = node as Node;
 19102        int skipped = 0;
 19103        for (int i = 0; i + skipped < branch.Children.Length; )
 19104        {
 19105          removals += this.Update(branch.Children[i], depth + 1);
 19106          if (branch.Children[i].Count is 0)
 19107            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 19108          else
 19109            i++;
 19110        }
 19111        Node[] newArray = new Node[branch.Children.Length - skipped];
 19112        Array.Copy(branch.Children, newArray, newArray.Length);
 19113        branch.Children = newArray;
 19114
 19115        if (branch.Count < _load && branch.Count != 0)
 19116          ShrinkChild(branch.Parent, branch.Index);
 19117      }
 19118
 19119      {
 19120        Node.ValueNode current = node.Head;
 19121        Node.ValueNode previous = null;
 19122        while (current is not null)
 19123        {
 19124          Omnitree.Bounds<Axis1, Axis2> item_bounds = GetBoundings(current.Value);
 19125          if (!this.EncapsulationCheck(node.Bounds, item_bounds))
 19126          {
 19127            removals++;
 19128            T updated = current.Value;
 19129            if (previous is null)
 19130            {
 19131              node.Head = current.Next;
 19132              goto HeadRemoved;
 19133            }
 19134            else
 19135              previous.Next = current.Next;
 19136            Node whereToAdd = GetEncapsulationParent(node.Parent, item_bounds);
 19137            if (whereToAdd is null)
 19138              throw new System.Exception("an item was updates outside the range of the omnitree");
 19139            this.Add(updated, whereToAdd, item_bounds, whereToAdd.Depth);
 19140          }
 19141          previous = current;
 19142        HeadRemoved:
 19143          current = current.Next;
 19144        }
 19145      }
 19146
 19147      node.Count -= removals;
 19148      return removals;
 19149    }
 19150
 19151    #endregion
 19152
 19153    #region Remove
 19154
 19155    /// <summary>Removes all the items qualified by the delegate.</summary>
 19156    /// <param name="where">The predicate to qualify removals.</param>
 19157    public void Remove(Predicate<T> where)
 19158    {
 19159      this.Remove(this._top, where);
 19160      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 19161    }
 19162
 19163    /// <summary>Recursive version of the remove method.</summary>
 19164    /// <param name="node">The current node of traversal.</param>
 19165    /// <param name="where">The predicate to qualify removals.</param>
 19166    internal int Remove(Node node, Predicate<T> where)
 19167    {
 19168      int removals = 0;
 19169
 19170      // children
 19171      if (node.Children is not null)
 19172      {
 19173        int skipped = 0;
 19174        for (int i = 0; i + skipped < node.Children.Length; )
 19175        {
 19176          removals += this.Remove(node.Children[i], where);
 19177          if (node.Children[i].Count is 0)
 19178            node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 19179          else
 19180            i++;
 19181        }
 19182        Node[] newArray = new Node[node.Children.Length - skipped];
 19183        Array.Copy(node.Children, newArray, newArray.Length);
 19184        node.Children = newArray;
 19185
 19186        if (node.Count < _load && node.Count != 0)
 19187          ShrinkChild(node.Parent, node.Index);
 19188      }
 19189
 19190      // items
 19191      while (node.Head is not null && where(node.Head.Value))
 19192      {
 19193        node.Head = node.Head.Next;
 19194        removals++;
 19195      }
 19196      if (node.Head is not null)
 19197      {
 19198        Node.ValueNode list = node.Head;
 19199        while (list.Next is not null)
 19200        {
 19201          if (where(list.Next.Value))
 19202          {
 19203            list.Next = list.Next.Next;
 19204            removals++;
 19205          }
 19206        }
 19207      }
 19208
 19209      node.Count -= removals;
 19210      return removals;
 19211    }
 19212
 19213    /// <summary>Removes all the items encapsulated in a given space.</summary>
 19214    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19215    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19216    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19217    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19218    /// <returns>The number of items that were removed.</returns>
 19219    public void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2)
 19220    {
 19221      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 19222    }
 19223    /// <summary>Removes all the items encapsulated in a given space.</summary>
 19224    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19225    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19226    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19227    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19228    /// <returns>The number of items that were removed.</returns>
 19229    public void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, O
 19230    {
 19231      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 19232    }
 19233    /// <summary>Removes all the items encapsulated in a given space.</summary>
 19234    /// <param name="axis1">The coordinate along the 1D axis.</param>
 19235    /// <param name="axis2">The coordinate along the 2D axis.</param>
 19236    public void RemoveEncapsulated(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2)
 19237    {
 19238      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2>(axis1, axis1, axis2, axis2));
 19239    }
 19240    internal int RemoveEncapsulated(Node node, Omnitree.Bounds<Axis1, Axis2> bounds)
 19241    {
 19242      int removals = this.RemoveBase(node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 19243      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 19244      return removals;
 19245    }
 19246
 19247    /// <summary>Removes all the items overlapping a given space.</summary>
 19248    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19249    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19250    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19251    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19252    /// <returns>The number of items that were removed.</returns>
 19253    public void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2)
 19254    {
 19255      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 19256    }
 19257    /// <summary>Removes all the items overlapping a given space.</summary>
 19258    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19259    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19260    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19261    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19262    /// <returns>The number of items that were removed.</returns>
 19263    public void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omn
 19264    {
 19265      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 19266    }
 19267    internal int RemoveOverlapped(Node node, Omnitree.Bounds<Axis1, Axis2> bounds)
 19268    {
 19269      int removals = this.RemoveBase(node, bounds, (a, b) => this.InclusionCheck(a, b));
 19270      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 19271      return removals;
 19272    }
 19273
 19274    internal int RemoveBase(
 19275      Node node,
 19276      Omnitree.Bounds<Axis1, Axis2> bounds,
 19277      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2>, Omnitree.Bounds<Axis1, Axis2>> spatialCheck)
 19278    {
 19279      int removals = 0;
 19280      if (InclusionCheck(bounds, node.Bounds))
 19281      {
 19282        // items
 19283        Node.ValueNode current_node = node.Head;
 19284        Node.ValueNode previous_node = null;
 19285        while (!(current_node is null))
 19286        {
 19287          Node.ValueNode temp_previous = current_node;
 19288          if (spatialCheck(bounds, GetBoundings(current_node.Value)))
 19289          {
 19290            removals++;
 19291            if (current_node == node.Head)
 19292              node.Head = node.Head.Next;
 19293            else
 19294            {
 19295              previous_node.Next = current_node.Next;
 19296              temp_previous = previous_node;
 19297            }
 19298          }
 19299          previous_node = temp_previous;
 19300          current_node = current_node.Next;
 19301        }
 19302
 19303        // children
 19304        if (node.Children is not null)
 19305        {
 19306          int skipped = 0;
 19307          for (int i = 0; i + skipped < node.Children.Length; )
 19308          {
 19309            removals += this.RemoveBase(node.Children[i], bounds, spatialCheck);
 19310            if (node.Children[i].Count is 0)
 19311              node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 19312            else
 19313              i++;
 19314          }
 19315          Node[] newArray = new Node[node.Children.Length - skipped];
 19316          Array.Copy(node.Children, newArray, newArray.Length);
 19317          node.Children = newArray;
 19318
 19319          // convert this branch back into a leaf
 19320          // Note: if count is zero, it will be chopped off
 19321          if (node.Count < _load && node.Count > 0)
 19322            ShrinkChild(node.Parent, node.Index);
 19323        }
 19324      }
 19325
 19326      node.Count -= removals;
 19327      return removals;
 19328    }
 19329
 19330    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 19331    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19332    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19333    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19334    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19335    /// <param name="where">The equality constraint of the removal.</param>
 19336    public void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Predicate<T> where)
 19337    {
 19338      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2), where);
 19339    }
 19340    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 19341    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19342    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19343    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19344    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19345    /// <param name="where">The equality constraint of the removal.</param>
 19346    public void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, O
 19347    {
 19348      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2), where);
 19349    }
 19350    internal int RemoveEncapsulated(Node node, Omnitree.Bounds<Axis1, Axis2> bounds, Predicate<T> where)
 19351    {
 19352      int removals = RemoveBase(node, bounds, where, (a, b) => this.EncapsulationCheck(a, b));
 19353      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 19354      return removals;
 19355    }
 19356
 19357    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 19358    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19359    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19360    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19361    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19362    /// <param name="where">The equality constraint of the removal.</param>
 19363    public void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Predicate<T> where)
 19364    {
 19365      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2), where);
 19366    }
 19367    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 19368    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19369    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19370    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19371    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19372    /// <param name="where">The equality constraint of the removal.</param>
 19373    public void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omn
 19374    {
 19375      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2), where);
 19376    }
 19377    internal int RemoveOverlapped(Node node, Omnitree.Bounds<Axis1, Axis2> bounds, Predicate<T> where)
 19378    {
 19379      int removals = RemoveBase(node, bounds, where, (a, b) => this.InclusionCheck(a, b));
 19380      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 19381      return removals;
 19382    }
 19383
 19384    internal int RemoveBase(
 19385      Node node,
 19386      Omnitree.Bounds<Axis1, Axis2> bounds,
 19387      Predicate<T> where,
 19388      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2>, Omnitree.Bounds<Axis1, Axis2>> spatialCheck)
 19389    {
 19390      if (!InclusionCheck(node.Bounds, bounds))
 19391        return 0;
 19392      int removals = 0;
 19393
 19394      // items
 19395      Node.ValueNode current = node.Head;
 19396      Node.ValueNode previous = null;
 19397      while (current is not null)
 19398      {
 19399        if (spatialCheck(bounds, GetBoundings(current.Value)) && where(current.Value))
 19400        {
 19401          removals++;
 19402          if (previous is null)
 19403          {
 19404            node.Head = current.Next;
 19405            goto HeadRemoved;
 19406          }
 19407          else
 19408            previous.Next = current.Next;
 19409        }
 19410        previous = current;
 19411      HeadRemoved:
 19412        current = current.Next;
 19413      }
 19414
 19415      // children
 19416      if (node.Children is not null)
 19417      {
 19418        int skipped = 0;
 19419        for (int i = 0; i + skipped < node.Children.Length; )
 19420        {
 19421          removals += this.RemoveBase(node.Children[i], bounds, where, spatialCheck);
 19422          if (node.Children[i].Count is 0)
 19423            node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 19424          else
 19425            i++;
 19426        }
 19427        Node[] newArray = new Node[node.Children.Length - skipped];
 19428        Array.Copy(node.Children, newArray, newArray.Length);
 19429        node.Children = newArray;
 19430
 19431        if (node.Count < _load && node.Count != 0)
 19432          ShrinkChild(node.Parent, node.Index);
 19433      }
 19434
 19435      node.Count -= removals;
 19436      return removals;
 19437    }
 19438
 19439    /// <summary>Tries to remove a value.</summary>
 19440    /// <param name="value">The value to remove.</param>
 19441    /// <returns>True if successful or false if not.</returns>
 19442    public (bool Success, Exception? Exception) TryRemove(T value)
 19443    {
 19444      Remove(value);
 19445      return (true, null);
 19446    }
 19447
 19448    /// <summary>Removes all instances of a given value.</summary>
 19449    public void Remove(T removal) => Omnitree.Remove(this, removal);
 19450
 19451    /// <summary>Removes all instances of a given value.</summary>
 19452    public void Remove(T removal, Func<T, T, bool> equate) => Omnitree.Remove(this, removal, equate);
 19453
 19454    /// <summary>Removes all the items in a given space.</summary>
 19455    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 19456    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 19457    /// <returns>The number of items that were removed.</returns>
 19458    public void RemoveOverlapped(Axis1 axis1
 19459      , Axis2 axis2
 19460      )
 19461    {
 19462      this.RemoveOverlapped(axis1, axis1
 19463        , axis2, axis2
 19464        );
 19465      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 19466    }
 19467
 19468    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 19469    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 19470    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 19471    /// <param name="where">The equality constraint of the removal.</param>
 19472    public void RemoveOverlapped(Axis1 axis1, Axis2 axis2, Predicate<T> where)
 19473    {
 19474      this.RemoveOverlapped(axis1, axis1
 19475        , axis2, axis2
 19476        , where);
 19477      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 19478    }
 19479
 19480    #endregion
 19481
 19482    #region Stepper And IEnumerable
 19483
 19484    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 19485    /// <param name="step">The delegate to perform on every item in the tree.</param>
 19486    public void Stepper(Action<T> step) =>
 19487      this.Stepper(step, this._top);
 19488
 19489    internal void Stepper(Action<T> step, Node node)
 19490    {
 19491      Node.ValueNode list = node.Head;
 19492      while (list is not null)
 19493      {
 19494        step(list.Value);
 19495        list = list.Next;
 19496      }
 19497      if (node.Children is not null)
 19498        foreach (Node child in node.Children)
 19499          this.Stepper(step, child);
 19500    }
 19501
 19502    public StepStatus StepperBreak<TStep>(TStep step = default)
 19503      where TStep : struct, IFunc<T, StepStatus> =>
 19504      StepperBreak(_top, step);
 19505
 19506    internal StepStatus StepperBreak<TStep>(Node node, TStep step)
 19507      where TStep : struct, IFunc<T, StepStatus>
 19508    {
 19509      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 19510      {
 19511        if (step.Invoke(list.Value) is Break) return Break;
 19512      }
 19513      if (node.Children is not null)
 19514      {
 19515        foreach (Node child in node.Children)
 19516        {
 19517          if (StepperBreak(child, step) is Break) return Break;
 19518        }
 19519      }
 19520      return Continue;
 19521    }
 19522
 19523    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 19524    /// <param name="step">The delegate to perform on every item in the tree.</param>
 19525    public StepStatus Stepper(Func<T, StepStatus> step) =>
 19526      Stepper(step, _top);
 19527
 19528    internal StepStatus Stepper(Func<T, StepStatus> step, Node node)
 19529    {
 19530      StepStatus status = StepStatus.Continue;
 19531
 19532      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 19533        if ((status = step(list.Value)) != StepStatus.Continue)
 19534          break;
 19535
 19536      if (node.Children is not null)
 19537        foreach (Node child in node.Children)
 19538          if ((status = Stepper(step, child)) != StepStatus.Continue)
 19539            break;
 19540
 19541      return status;
 19542    }
 19543
 19544    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 19545    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 19546    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19547    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19548    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19549    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19550    public void StepperEncapsulated(Action<T> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2) =>
 19551      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 19552
 19553    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 19554    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 19555    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19556    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19557    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19558    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19559    public void StepperEncapsulated(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bou
 19560      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 19561
 19562    internal void StepperEncapsulated(Action<T> step, Node node, Omnitree.Bounds<Axis1, Axis2> bounds) =>
 19563      StepperBase(step, node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 19564
 19565    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 19566    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 19567    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19568    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19569    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19570    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19571    public void StepperOverlapped(Action<T> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2) =>
 19572      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 19573
 19574    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 19575    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 19576    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19577    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19578    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19579    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19580    public void StepperOverlapped(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound
 19581      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 19582
 19583    internal void StepperOverlapped(Action<T> step, Node node, Omnitree.Bounds<Axis1, Axis2> bounds) =>
 19584      StepperBase(step, node, bounds, (a, b) => this.InclusionCheck(a, b));
 19585
 19586    internal void StepperBase(
 19587      Action<T> step,
 19588      Node node,
 19589      Omnitree.Bounds<Axis1, Axis2> bounds,
 19590      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2>, Omnitree.Bounds<Axis1, Axis2>> spatialCheck)
 19591    {
 19592      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 19593        if (spatialCheck(bounds, GetBoundings(list.Value)))
 19594          step(list.Value);
 19595
 19596      if (node.Children is not null)
 19597      {
 19598        foreach (Node child in node.Children)
 19599          // optimization: stop bounds checking if space encapsulates node
 19600          if (EncapsulationCheck(bounds, child.Bounds))
 19601            this.Stepper(step, child);
 19602          else if (InclusionCheck(child.Bounds, bounds))
 19603            this.StepperBase(step, child, bounds, spatialCheck);
 19604      }
 19605    }
 19606
 19607    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 19608    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 19609    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19610    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19611    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19612    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19613    public StepStatus StepperEncapsulated(Func<T, StepStatus> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2) =>
 19614      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 19615
 19616    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 19617    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 19618    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19619    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19620    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19621    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19622    public StepStatus StepperEncapsulated(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> ma
 19623      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 19624
 19625    internal StepStatus StepperEncapsulated(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1, Axis2> bounds) =
 19626      StepperBase(step, node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 19627
 19628    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 19629    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 19630    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19631    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19632    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19633    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19634    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2) =>
 19635      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 19636
 19637    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 19638    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 19639    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19640    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19641    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19642    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19643    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1
 19644      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2>(min1, max1, min2, max2));
 19645
 19646    internal StepStatus StepperOverlapped(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1, Axis2> bounds) =>
 19647      StepperBase(step, node, bounds, (a, b) => this.InclusionCheck(a, b));
 19648
 19649    internal StepStatus StepperBase(
 19650      Func<T, StepStatus> step,
 19651      Node node,
 19652      Omnitree.Bounds<Axis1, Axis2> bounds,
 19653      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2>, Omnitree.Bounds<Axis1, Axis2>> spatialCheck)
 19654    {
 19655      StepStatus status = StepStatus.Continue;
 19656
 19657      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 19658        if (spatialCheck(bounds, GetBoundings(list.Value)) &&
 19659          (status = step(list.Value)) != StepStatus.Continue)
 19660          break;
 19661
 19662      if (node.Children is not null)
 19663      {
 19664        foreach (Node child in node.Children)
 19665          // optimization: stop bounds checking if space encapsulates node
 19666          if (EncapsulationCheck(bounds, child.Bounds) &&
 19667            (status = this.Stepper(step, child)) != StepStatus.Continue)
 19668            break;
 19669          else if (InclusionCheck(child.Bounds, bounds) &&
 19670            (status = this.StepperBase(step, child, bounds, spatialCheck)) != StepStatus.Continue)
 19671            break;
 19672      }
 19673
 19674      return status;
 19675    }
 19676
 19677    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 19678    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 19679    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 19680    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 19681    public void StepperOverlapped(Action<T> step, Axis1 axis1, Axis2 axis2) =>
 19682      StepperOverlapped(step, this._top, new Omnitree.Bounds<Axis1, Axis2>(axis1, axis1
 19683        , axis2, axis2
 19684      ));
 19685
 19686    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 19687    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 19688    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 19689    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 19690    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2) =>
 19691      StepperOverlapped(step, this._top, new Omnitree.Bounds<Axis1, Axis2>(axis1, axis1
 19692        , axis2, axis2
 19693        ));
 19694
 19695    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 19696
 19697    public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 19698    {
 19699      // Note: this can be optimized.
 19700      IList<T> list = new ListLinked<T>();
 19701      Stepper(x => list.Add(x));
 19702      return list.GetEnumerator();
 19703    }
 19704
 19705    #endregion
 19706
 19707    /// <inheritdoc/>
 19708    public T[] ToArray() => throw new NotImplementedException();
 19709
 19710    #region Helpers
 19711
 19712    internal bool StraddlesLines(Omnitree.Bounds<Axis1, Axis2> bounds, Omnitree.Vector<Axis1, Axis2> vector) =>
 19713      Omnitree.StraddlesLines(bounds, vector
 19714        , _compare1
 19715        , _compare2
 19716        );
 19717
 19718    /// <summary>Computes the child index that contains the desired dimensions.</summary>
 19719    /// <param name="pointOfDivision">The point of division to compare against.</param>
 19720    /// <param name="bounds">The dimensions to determine the child index.</param>
 19721    /// <returns>The computed child index based on the coordinates relative to the center of the node.</returns>
 19722    internal int DetermineChildIndex(Omnitree.Vector<Axis1, Axis2> pointOfDivision, Omnitree.Bounds<Axis1, Axis2> bounds
 19723    {
 19724      // make sure a child encapsulates the bounds (otherwise the bounds cannot move down the tree)
 19725      if (StraddlesLines(bounds, pointOfDivision))
 19726        return -1;
 19727
 19728      int child = 0;
 19729      if (!bounds.Min1.Exists || !(this._compare1(bounds.Min1.Value, pointOfDivision.Axis1) is Less))
 19730        child += 1 << 0;
 19731      if (!bounds.Min2.Exists || !(this._compare2(bounds.Min2.Value, pointOfDivision.Axis2) is Less))
 19732        child += 1 << 1;
 19733      return child;
 19734    }
 19735
 19736    /// <summary>Converts a branch back into a leaf when the count is reduced.</summary>
 19737    /// <param name="parent">The parent to shrink a child of.</param>
 19738    /// <param name="child_index">The index of the child to shrink.</param>
 19739    internal void ShrinkChild(Node parent, int child_index)
 19740    {
 19741      Node leaf;
 19742      Node removal = null;
 19743      if (parent is null) // top of tree
 19744      {
 19745        removal = this._top;
 19746        leaf = new Node(Omnitree.Bounds<Axis1, Axis2>.None, null, -1);
 19747        this._top = leaf;
 19748      }
 19749      else // non-top branch
 19750      {
 19751        removal = parent[child_index];
 19752        leaf = new Node(removal.Bounds, removal.Parent, removal.Index);
 19753        parent[child_index] = leaf;
 19754      }
 19755
 19756      this.Stepper((T step) => { leaf.Add(step); }, removal);
 19757    }
 19758
 19759    /// <summary>Reduces the counts of all the parents of a given node by a given amount.</summary>
 19760    /// <param name="parent">The starting parent of the reduction.</param>
 19761    /// <param name="reduction">The amount to reduce the parent counts by.</param>
 19762    internal void ReduceParentCounts(Node parent, int reduction)
 19763    {
 19764      IncreaseParentCounts(parent, -reduction);
 19765    }
 19766
 19767    /// <summary>Increases the counts of all the parents of a given node by a given amount.</summary>
 19768    /// <param name="parent">The starting parent of the increase.</param>
 19769    /// <param name="increase">The amount to increase the parent counts by.</param>
 19770    internal void IncreaseParentCounts(Node parent, int increase)
 19771    {
 19772      Node node = parent;
 19773      while (node is not null)
 19774      {
 19775        node.Count += increase;
 19776        node = node.Parent;
 19777      }
 19778    }
 19779
 19780    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 19781    /// <returns>True if the spaces overlap; False if not.</returns>
 19782    internal bool InclusionCheck(Omnitree.Bounds<Axis1, Axis2> a, Omnitree.Bounds<Axis1, Axis2> b) =>
 19783      Omnitree.InclusionCheck(a, b
 19784      , _compare1
 19785      , _compare2
 19786      );
 19787
 19788    /// <summary>Checks if a space encapsulates a point.</summary>
 19789    /// <returns>True if the space encapsulates the point; False if not.</returns>
 19790    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2> bounds, Omnitree.Vector<Axis1, Axis2> vector) =>
 19791      Omnitree.EncapsulationCheck(bounds, vector
 19792      , _compare1
 19793      , _compare2
 19794      );
 19795
 19796    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 19797    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 19798    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2> a, Omnitree.Bounds<Axis1, Axis2> b) =>
 19799      Omnitree.EncapsulationCheck(a, b
 19800      , _compare1
 19801      , _compare2
 19802      );
 19803
 19804    /// <summary>Checks for equality between two locations.</summary>
 19805    /// <returns>True if equal; False if not;</returns>
 19806    internal bool EqualsCheck(Omnitree.Vector<Axis1, Axis2> a, Omnitree.Vector<Axis1, Axis2> b) =>
 19807      Omnitree.EqualsCheck(a, b
 19808      , (a, b) => _compare1(a, b) is Equal
 19809      , (a, b) => _compare2(a, b) is Equal
 19810      );
 19811
 19812    /// <summary>Gets the nearest parent that encapsulates a location.</summary>
 19813    /// <param name="node">The starting node to find the encapsulating parent of the location.</param>
 19814    /// <param name="bounds">The bounds to get the encapsulating parent from.</param>
 19815    /// <returns>The nearest node that encapsulates the given location.</returns>
 19816    internal Node GetEncapsulationParent(Node node, Omnitree.Bounds<Axis1, Axis2> bounds)
 19817    {
 19818      while (node is not null && !EncapsulationCheck(node.Bounds, bounds))
 19819      {
 19820        node = node.Parent;
 19821      }
 19822      return node;
 19823    }
 19824
 19825    internal Omnitree.Bounds<Axis1, Axis2> GetBoundings(T value)
 19826    {
 19827      Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 19828      Omnitree.Bound<Axis2> min2; Omnitree.Bound<Axis2> max2;
 19829      this._getBounds(value,
 19830        out min1, out max1
 19831,
 19832        out min2, out max2
 19833        );
 19834      return new Omnitree.Bounds<Axis1, Axis2>(
 19835        min1, max1
 19836,
 19837        min2, max2
 19838        );
 19839    }
 19840
 19841    #endregion
 19842
 19843    #endregion
 19844  }
 19845
 19846  #endregion
 19847
 19848  #region 3 Dimensional
 19849
 19850  /// <summary>Inheritance base for 3D omnitrees that store bounds.</summary>
 19851  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 19852  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 19853  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 19854  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 19855  public interface IOmnitreeBounds<T, Axis1, Axis2, Axis3> : IOmnitree<T, Axis1, Axis2, Axis3>
 19856  {
 19857    #region Properties
 19858
 19859    /// <summary>The number of dimensions in this tree.</summary>
 19860    int Dimensions { get; }
 19861
 19862    /// <summary>The delegate being used by the omnitree to get the bounds of values in 3D space.</summary>
 19863    Omnitree.GetBounds<T, Axis1
 19864, Axis2
 19865, Axis3
 19866      > GetBounds { get; }
 19867
 19868    #endregion
 19869
 19870    #region Methods
 19871
 19872    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 19873    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19874    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19875    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19876    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19877    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 19878    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 19879    /// <returns>The number of items in the provided sub space.</returns>
 19880    int CountSubSpaceEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3);
 19881
 19882    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 19883    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19884    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19885    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19886    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19887    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 19888    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 19889    /// <returns>The number of items in the provided sub space.</returns>
 19890    int CountSubSpaceOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3);
 19891
 19892    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 19893    void Update();
 19894    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 19895    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19896    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19897    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19898    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19899    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 19900    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 19901    void Update(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3);
 19902
 19903    /// <summary>Removes all the items in a given space.</summary>
 19904    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19905    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19906    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19907    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19908    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 19909    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 19910    void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3);
 19911    /// <summary>Removes all the items in a given space.</summary>
 19912    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19913    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19914    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19915    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19916    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 19917    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 19918    void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree
 19919    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 19920    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19921    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19922    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19923    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19924    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 19925    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 19926    /// <param name="where">The predicate constraint of the removal.</param>
 19927    void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Predicate<T> where);
 19928    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 19929    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19930    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19931    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19932    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19933    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 19934    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 19935    /// <param name="where">The predicate constraint of the removal.</param>
 19936    void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree
 19937
 19938    /// <summary>Removes all the items in a given space.</summary>
 19939    /// <param name="axis1">The coordinate along the 1D axis.</param>
 19940    /// <param name="axis2">The coordinate along the 2D axis.</param>
 19941    /// <param name="axis3">The coordinate along the 3D axis.</param>
 19942    void RemoveOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3);
 19943    /// <summary>Removes all the items in a given space.</summary>
 19944    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19945    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19946    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19947    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19948    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 19949    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 19950    void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3);
 19951    /// <summary>Removes all the items in a given space.</summary>
 19952    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19953    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19954    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19955    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19956    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 19957    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 19958    void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.B
 19959    /// <summary>Removes all the items in a given space where equality is met.</summary>
 19960    /// <param name="axis1">The coordinate along the 1D axis.</param>
 19961    /// <param name="axis2">The coordinate along the 2D axis.</param>
 19962    /// <param name="axis3">The coordinate along the 3D axis.</param>
 19963    /// <param name="where">The equality constraint of the removal.</param>
 19964    void RemoveOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3, Predicate<T> where);
 19965    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 19966    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19967    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19968    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19969    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19970    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 19971    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 19972    /// <param name="where">The predicate constraint of the removal.</param>
 19973    void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Predicate<T> where);
 19974    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 19975    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19976    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19977    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19978    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19979    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 19980    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 19981    /// <param name="where">The predicate constraint of the removal.</param>
 19982    void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.B
 19983
 19984    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 19985    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 19986    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19987    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19988    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19989    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19990    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 19991    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 19992    void StepperEncapsulated(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis
 19993    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 19994    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 19995    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 19996    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 19997    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 19998    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 19999    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 20000    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 20001    StepStatus StepperEncapsulated(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omn
 20002
 20003    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 20004    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 20005    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 20006    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 20007    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 20008    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 20009    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 20010    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 20011    void StepperOverlapped(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2>
 20012    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 20013    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 20014    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 20015    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 20016    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 20017    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 20018    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 20019    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 20020    StepStatus StepperOverlapped(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnit
 20021
 20022    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 20023    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 20024    /// <param name="axis1">The coordinate along the 1D axis.</param>
 20025    /// <param name="axis2">The coordinate along the 2D axis.</param>
 20026    /// <param name="axis3">The coordinate along the 3D axis.</param>
 20027    void StepperOverlapped(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3);
 20028    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 20029    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 20030    /// <param name="axis1">The coordinate along the 1D axis.</param>
 20031    /// <param name="axis2">The coordinate along the 2D axis.</param>
 20032    /// <param name="axis3">The coordinate along the 3D axis.</param>
 20033    StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3);
 20034
 20035    #endregion
 20036  }
 20037
 20038  /// <summary>Omnitree that stores bounds along 3 dimensions implemented as a linked tree.</summary>
 20039  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 20040  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 20041  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 20042  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 20043  public class OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3> : IOmnitreeBounds<T, Axis1, Axis2, Axis3>
 20044  {
 20045    internal const int _dimensions = 3;
 020046    internal static int _children_per_node = (int)BigInteger.Pow(2, 3);
 20047
 20048    internal Node _top;
 020049    internal int _naturalLogLower = 1; // caching the next time to calculate loads (lower count)
 020050    internal int _naturalLogUpper = -1; // caching the next time to calculate loads (upper count)
 20051    internal int _load; // ln(count); min = _defaultLoad
 20052    internal Omnitree.GetBounds<T, Axis1
 20053, Axis2
 20054, Axis3
 20055      > _getBounds;
 20056    internal bool _defaultCompare1;
 20057    internal Func<Axis1, Axis1, CompareResult> _compare1;
 20058    internal bool _defaultCompare2;
 20059    internal Func<Axis2, Axis2, CompareResult> _compare2;
 20060    internal bool _defaultCompare3;
 20061    internal Func<Axis3, Axis3, CompareResult> _compare3;
 20062    internal Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3>> _subdivisionOverride1;
 20063    internal Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3>> _subdivisionOverride2;
 20064    internal Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3>> _subdivisionOverride3;
 20065
 20066    #region Nested Types
 20067
 20068    /// <summary>Can be a leaf or a branch.</summary>
 20069    internal class Node
 20070    {
 20071      internal class ValueNode
 20072      {
 20073        internal T Value;
 20074        internal ValueNode Next;
 20075
 020076        internal ValueNode(T value, ValueNode next)
 020077        {
 020078          Value = value;
 020079          Next = next;
 020080        }
 20081      }
 20082
 20083      internal Omnitree.Bounds<Axis1, Axis2, Axis3> Bounds;
 20084      internal Node Parent;
 20085      internal int Index;
 20086      internal int Count;
 20087      internal ValueNode Head;
 20088      internal Node[] Children;
 20089      internal Omnitree.Vector<Axis1, Axis2, Axis3>? PointOfDivision;
 20090
 20091      /// <summary>Gets child by index.</summary>
 20092      /// <param name="child_index">The index of the child to get.</param>
 20093      /// <returns>The child of the given index or null if non-existent.</returns>
 20094      internal Node this[int child_index]
 20095      {
 20096        get
 020097        {
 020098          if (Children is null)
 020099            return null;
 020100          if (Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3>._children_per_node)
 020101            return Children[(int)child_index];
 020102          foreach (Node node in Children)
 020103            if (node.Index == child_index)
 020104              return node;
 020105          return null;
 020106        }
 20107        set
 020108        {
 20109          // This error check should be unnecessary... but fuck it... might as well
 020110          if (value.Index != child_index)
 020111            throw new System.Exception("Bug in Omnitree (index/property mis-match when setting a child on a branch)");
 20112
 20113          // no children yet
 020114          if (Children is null)
 020115          {
 020116            Children = â±¯(value);
 020117            return;
 20118          }
 20119          // max children overwrite
 020120          else if (Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3>._children_per_node)
 020121          {
 020122            Children[(int)child_index] = value;
 020123            return;
 20124          }
 20125          // non-max child overwrite
 020126          for (int i = 0; i < Children.Length; i++)
 020127            if (Children[i].Index == child_index)
 020128            {
 020129              Children[i] = value;
 020130              return;
 20131            }
 20132          // new child
 020133          Node[] newArray = new Node[Children.Length + 1];
 020134          if (newArray.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3>._children_per_node)
 020135          {
 20136            // new child resulting in a max children branch (sorting required)
 020137            for (int i = 0; i < Children.Length; i++)
 020138            {
 020139              newArray[(int)Children[i].Index] = Children[i];
 020140            }
 020141            newArray[(int)value.Index] = value;
 020142          }
 20143          else
 020144          {
 20145            // new child resulting in a non-max children branch
 020146            Array.Copy(Children, newArray, Children.Length);
 020147            newArray[newArray.Length - 1] = value;
 020148          }
 020149          Children = newArray;
 020150        }
 20151      }
 20152
 20153      /// <summary>The depth this node is located in the Omnitree.</summary>
 20154      internal int Depth
 20155      {
 20156        get
 020157        {
 020158          int depth = -1;
 020159          for (Node node = this; node is not null; node = node.Parent)
 020160            depth++;
 020161          return depth;
 020162        }
 20163      }
 20164
 20165      /// <summary>Constructs a node.</summary>
 20166      /// <param name="bounds">The bounds of this node.</param>
 20167      /// <param name="parent">The parent of this node.</param>
 20168      /// <param name="index">The number of values stored in this node and its children.</param>
 020169      internal Node(Omnitree.Bounds<Axis1, Axis2, Axis3> bounds, Node parent, int index)
 020170      {
 020171        Bounds = bounds;
 020172        Parent = parent;
 020173        Index = index;
 020174      }
 20175
 20176      internal Node(Omnitree.Vector<Axis1, Axis2, Axis3> pointOfDivision, Omnitree.Bounds<Axis1, Axis2, Axis3> bounds, N
 020177        : this(bounds, parent, index)
 020178      {
 020179        PointOfDivision = pointOfDivision;
 020180      }
 20181
 020182      internal Node(Node nodeToClone)
 020183      {
 020184        this.Bounds = nodeToClone.Bounds;
 020185        this.Parent = nodeToClone.Parent;
 020186        this.Index = nodeToClone.Index;
 020187        this.Count = nodeToClone.Count;
 20188
 020189        Children = nodeToClone.Children.Clone() as Node[];
 020190        PointOfDivision = nodeToClone.PointOfDivision;
 20191
 020192        ValueNode a = this.Head;
 020193        ValueNode b = nodeToClone.Head;
 20194
 020195        while (b is not null)
 020196        {
 020197          a.Next = new ValueNode(b.Next.Value, null);
 020198          a = a.Next;
 020199          b = b.Next;
 020200        }
 020201      }
 20202
 20203      internal void Add(T addition)
 020204      {
 020205        Head = new ValueNode(addition, Head);
 020206        Count++;
 020207      }
 20208
 20209      internal Node Clone() =>
 020210        new Node(this);
 20211    }
 20212
 20213    #endregion
 20214
 20215    #region Constructors
 20216
 20217    /// <summary>This constructor is for cloning purposes</summary>
 020218    internal OmnitreeBoundsLinked(OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3> omnitree)
 020219    {
 020220      this._top = omnitree._top.Clone();
 020221      this._load = omnitree._load;
 020222      this._getBounds = omnitree._getBounds;
 020223      this._defaultCompare1 = omnitree._defaultCompare1;
 020224      this._compare1 = omnitree._compare1;
 020225      this._defaultCompare2 = omnitree._defaultCompare2;
 020226      this._compare2 = omnitree._compare2;
 020227      this._defaultCompare3 = omnitree._defaultCompare3;
 020228      this._compare3 = omnitree._compare3;
 020229      this._subdivisionOverride1 = omnitree._subdivisionOverride1;
 020230      this._subdivisionOverride2 = omnitree._subdivisionOverride2;
 020231      this._subdivisionOverride3 = omnitree._subdivisionOverride3;
 020232    }
 20233
 020234    internal OmnitreeBoundsLinked(
 020235      Omnitree.GetBounds<T, Axis1, Axis2, Axis3> getBounds,
 020236      bool defaultCompare1,
 020237      Func<Axis1, Axis1, CompareResult> compare1,
 020238      bool defaultCompare2,
 020239      Func<Axis2, Axis2, CompareResult> compare2,
 020240      bool defaultCompare3,
 020241      Func<Axis3, Axis3, CompareResult> compare3,
 020242      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3>> subdivisionOverride1
 020243,
 020244      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3>> subdivisionOverride2
 020245,
 020246      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3>> subdivisionOverride3
 020247      )
 020248    {
 020249      if (getBounds is null)
 020250      {
 020251        throw new ArgumentNullException(nameof(getBounds));
 20252      }
 020253      if (compare1 is null)
 020254      {
 020255        throw new ArgumentNullException(nameof(compare1));
 20256      }
 020257      if (compare2 is null)
 020258      {
 020259        throw new ArgumentNullException(nameof(compare2));
 20260      }
 020261      if (compare3 is null)
 020262      {
 020263        throw new ArgumentNullException(nameof(compare3));
 20264      }
 020265      this._getBounds = getBounds;
 020266      this._defaultCompare1 = defaultCompare1;
 020267      this._compare1 = compare1;
 020268      this._defaultCompare2 = defaultCompare2;
 020269      this._compare2 = compare2;
 020270      this._defaultCompare3 = defaultCompare3;
 020271      this._compare3 = compare3;
 020272      this._subdivisionOverride1 = subdivisionOverride1;
 020273      this._subdivisionOverride2 = subdivisionOverride2;
 020274      this._subdivisionOverride3 = subdivisionOverride3;
 020275      this._top = new Node(Omnitree.Bounds<Axis1, Axis2, Axis3>.None, null, -1);
 020276      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 020277    }
 20278
 20279    /// <summary>Constructs a new 3D omnitree that stores bounds.</summary>
 20280    /// <param name="getBounds">The delegate for getting object bounds in 3D space.</param>
 20281
 20282    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 20283
 20284    /// <param name="compare2">The delegate for comparing values along the 2D axis.</param>
 20285
 20286    /// <param name="compare3">The delegate for comparing values along the 3D axis.</param>
 20287
 20288    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 20289
 20290    /// <param name="subdivisionOverride2">The subdivision overide to be used when splitting the 2 dimension.</param>
 20291
 20292    /// <param name="subdivisionOverride3">The subdivision overide to be used when splitting the 3 dimension.</param>
 20293    public OmnitreeBoundsLinked(
 20294      Omnitree.GetBounds<T, Axis1, Axis2, Axis3> getBounds,
 20295      Func<Axis1, Axis1, CompareResult> compare1 = null,
 20296      Func<Axis2, Axis2, CompareResult> compare2 = null,
 20297      Func<Axis3, Axis3, CompareResult> compare3 = null,
 20298      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3>> subdivisionOverride1 = null
 20299,
 20300      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3>> subdivisionOverride2 = null
 20301,
 20302      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3>> subdivisionOverride3 = null
 20303      )
 020304      : this(
 020305      getBounds,
 020306      compare1 is null ? true : false,
 020307      compare1 ?? Compare,
 020308      compare2 is null ? true : false,
 020309      compare2 ?? Compare,
 020310      compare3 is null ? true : false,
 020311      compare3 ?? Compare,
 020312      subdivisionOverride1
 020313,
 020314      subdivisionOverride2
 020315,
 020316      subdivisionOverride3
 020317      ) { }
 20318
 20319    /// <summary>Constructs a new 3D omnitree that stores bounds.</summary>
 20320    /// <param name="getBoundings">The delegate for getting object bounds in 3D space.</param>
 20321    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 20322    /// <param name="compare2">The delegate for comparing values along the 2D axis.</param>
 20323    /// <param name="compare3">The delegate for comparing values along the 3D axis.</param>
 20324
 20325    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 20326
 20327    /// <param name="subdivisionOverride2">The subdivision overide to be used when splitting the 2 dimension.</param>
 20328
 20329    /// <param name="subdivisionOverride3">The subdivision overide to be used when splitting the 3 dimension.</param>
 20330    public OmnitreeBoundsLinked(
 20331      Omnitree.GetBoundings<T, Axis1, Axis2, Axis3> getBoundings,
 20332      Func<Axis1, Axis1, CompareResult> compare1 = null,
 20333      Func<Axis2, Axis2, CompareResult> compare2 = null,
 20334      Func<Axis3, Axis3, CompareResult> compare3 = null,
 20335      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3>> subdivisionOverride1 = null
 20336      , Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3>> subdivisionOverride2 = null
 20337      , Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3>> subdivisionOverride3 = null
 20338      )
 020339      : this(
 020340      Omnitree.ConvertToGetBounds(getBoundings),
 020341      compare1 is null ? true : false,
 020342      compare1 ?? Compare,
 020343      compare2 is null ? true : false,
 020344      compare2 ?? Compare,
 020345      compare3 is null ? true : false,
 020346      compare3 ?? Compare,
 020347      subdivisionOverride1
 020348,
 020349      subdivisionOverride2
 020350,
 020351      subdivisionOverride3
 020352      ) { }
 20353
 20354    #endregion
 20355
 20356    #region Properties
 20357
 20358    /// <summary>The number of dimensions in this tree.</summary>
 020359    public int Dimensions => _dimensions;
 20360
 20361    /// <summary>The delegate being used by the omnitree to locate items in 3D space.</summary>
 20362    public Omnitree.GetBounds<T, Axis1
 20363      , Axis2
 20364      , Axis3
 020365      > GetBounds => _getBounds;
 20366
 20367
 20368    /// <summary>The comparison function the Omnitree is using along the 1D axis.</summary>
 020369    public Func<Axis1, Axis1, CompareResult> Compare1 => _compare1;
 20370    /// <summary>The comparison function the Omnitree is using along the 2D axis.</summary>
 020371    public Func<Axis2, Axis2, CompareResult> Compare2 => _compare2;
 20372    /// <summary>The comparison function the Omnitree is using along the 3D axis.</summary>
 020373    public Func<Axis3, Axis3, CompareResult> Compare3 => _compare3;
 20374
 20375    /// <summary>The current number of items in the tree.</summary>
 020376    public int Count  => _top.Count;
 20377
 20378    internal delegate void MaxDepthFinder(Node node, int current_depth, ref int max_depth);
 20379    /// <summary>Finds the current maximum depth of the tree. NOT AN O(1) OPERATION. Intended for educational purposes o
 20380    public int MaxDepth
 20381    {
 20382      get
 020383      {
 020384        MaxDepthFinder maxDepthFinder = null;
 020385        maxDepthFinder =
 020386            (Node node, int current_depth, ref int max_depth) =>
 020387            {
 020388              if (current_depth > max_depth)
 020389                max_depth = current_depth;
 020390              foreach (Node child in node.Children)
 020391                maxDepthFinder(child, current_depth + 1, ref max_depth);
 020392            };
 020393        int _max_depth = -1;
 020394        maxDepthFinder(this._top, 0, ref _max_depth);
 020395        return _max_depth;
 020396      }
 20397    }
 20398
 20399    internal delegate void NodeCountFinder(Node node, ref int current_count);
 20400    /// <summary>Counts the current number of nodes in the tree. NOT AN O(1) OPERATION. Intended for educational purpose
 20401    public int NodeCount
 20402    {
 20403      get
 020404      {
 020405        NodeCountFinder nodeCountFinder = null;
 020406        nodeCountFinder =
 020407            (Node node, ref int current_count) =>
 020408            {
 020409              current_count++;
 020410              foreach (Node child in node.Children)
 020411                nodeCountFinder(child, ref current_count);
 020412            };
 20413
 020414        int _current_count = 0;
 020415        nodeCountFinder(this._top, ref _current_count);
 020416        return _current_count;
 020417      }
 20418    }
 20419
 20420    #endregion
 20421
 20422    #region Methods
 20423
 20424    #region Add
 20425
 20426
 20427    #region single
 20428
 20429    /// <summary>Tries to add a value.</summary>
 20430    /// <param name="value">The value to be added.</param>
 20431    /// <returns>True if successful or false if not.</returns>
 20432    public (bool Success, Exception? Exception) TryAdd(T value)
 020433    {
 020434      Add(value);
 020435      return (true, null);
 020436    }
 20437
 20438    /// <summary>Adds an item to the tree.</summary>
 20439    /// <param name="addition">The item to be added.</param>
 20440    public void Add(T addition)
 020441    {
 020442      if (this._top.Count is int.MaxValue)
 020443        throw new System.InvalidOperationException("(Count is int.MaxValue) max Omnitree size reached (change ints to lo
 20444
 20445      // dynamic tree sizes
 020446      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 20447
 020448      Omnitree.Bounds<Axis1, Axis2, Axis3> bounds = GetBoundings(addition);
 20449
 20450      // grow the first branch of the tree
 020451      if (!this._top.PointOfDivision.HasValue && this._top.Count >= _load)
 020452      {
 020453        Node top = this._top;
 20454
 20455        // create the new branch from the median values
 020456        this._top = new Node(DetermineMedians(top), Omnitree.Bounds<Axis1, Axis2, Axis3>.None, null, -1);
 20457
 20458        // iterate through the values and add them to the appropriate children
 020459        for (Node.ValueNode list = top.Head; list is not null; list = list.Next)
 020460          Add(list.Value, this._top, GetBoundings(list.Value), 0);
 020461      }
 20462
 020463      this.Add(addition, this._top, bounds, 0);
 020464    }
 20465
 20466    /// <summary>Recursive version of the add function.</summary>
 20467    /// <param name="addition">The item to be added.</param>
 20468    /// <param name="node">The current node for tree trversal.</param>
 20469    /// <param name="bounds">The bounds of the addition.</param>
 20470    /// <param name="depth">The current depth of iteration.</param>
 20471    internal void Add(T addition, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3> bounds, int depth)
 020472    {
 020473      if (!node.PointOfDivision.HasValue)
 020474      {
 20475        //Leaf leaf = node as Leaf;
 020476        if (depth >= _load || !(node.Count >= _load))
 020477        {
 020478          node.Add(addition);
 020479          return;
 20480        }
 20481        else
 020482        {
 20483          //Node parent = node.Parent;
 20484          //int child_index = this.DetermineChildIndex(parent.PointOfDivision, location);
 20485          //Node growth = new Node(DetermineMedians(leaf), leaf.Bounds, parent, child_index);
 20486          //parent[child_index] = growth;
 20487
 020488          Node growth = new Node(DetermineMedians(node), node.Bounds, node.Parent, node.Index);
 020489          node.Parent[node.Index] = growth;
 20490
 020491          for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 020492          {
 020493            Omnitree.Bounds<Axis1, Axis2, Axis3> temp_bounds = GetBoundings(list.Value);
 020494            if (EncapsulationCheck(growth.Bounds, temp_bounds))
 020495              Add(list.Value, growth, temp_bounds, depth);
 20496            else
 020497            {
 020498              ReduceParentCounts(node.Parent, 1);
 020499              Add(list.Value, this._top, temp_bounds, depth);
 020500            }
 020501          }
 20502
 020503          Add(addition, growth, bounds, depth);
 020504          return;
 20505        }
 20506      }
 20507      else
 020508      {
 20509        //Node branch = node as Node;
 020510        int child_index = this.DetermineChildIndex(node.PointOfDivision.Value, bounds); // determine the child "index" (
 20511
 20512        // if -1, then the bounds of the addition straddle the point of division (keep it in current node)
 020513        if (child_index is -1)
 020514        {
 020515          node.Add(addition);
 020516          return;
 20517        }
 20518
 020519        Node child_node = node[child_index];
 20520
 20521        // null children in branches are just empty leaves
 020522        if (child_node is null)
 020523        {
 020524          Node new_node = new Node(DetermineChildBounds(node, child_index), node, child_index);
 020525          node[child_index] = new_node;
 020526          new_node.Add(addition);
 020527        }
 20528        else
 20529          // child exists already, continue adding
 020530          Add(addition, child_node, bounds, depth + 1);
 20531
 020532        node.Count++;
 020533        return;
 20534      }
 020535    }
 20536
 20537    internal Omnitree.Vector<Axis1, Axis2, Axis3> DetermineMedians(Node node)
 020538    {
 20539      //try
 20540      //{
 20541        // extract the values
 020542        Omnitree.Bound<Axis1>[] values1 = new Omnitree.Bound<Axis1>[node.Count * 2];
 020543        Omnitree.Bound<Axis2>[] values2 = new Omnitree.Bound<Axis2>[node.Count * 2];
 020544        Omnitree.Bound<Axis3>[] values3 = new Omnitree.Bound<Axis3>[node.Count * 2];
 020545        Node.ValueNode for_current = node.Head; // used in for loop
 020546        for (int i = 0; i < node.Count; i++, for_current = for_current.Next)
 020547          this._getBounds(for_current.Value,
 020548          out values1[i * 2], out values1[i * 2 + 1]
 020549,
 020550          out values2[i * 2], out values2[i * 2 + 1]
 020551,
 020552          out values3[i * 2], out values3[i * 2 + 1]
 020553          );
 020554        return new Omnitree.Vector<Axis1, Axis2, Axis3>(
 020555          Omnitree.SubDivide(values1, this._defaultCompare1 ? Compare : this._compare1)
 020556,
 020557          Omnitree.SubDivide(values2, this._defaultCompare2 ? Compare : this._compare2)
 020558,
 020559          Omnitree.SubDivide(values3, this._defaultCompare3 ? Compare : this._compare3)
 020560          );
 20561      //}
 20562      //catch
 20563      //{
 20564        // extract the values
 20565      //  ArrayJagged<Omnitree.Bound<Axis1>> values1 = new ArrayJagged<Omnitree.Bound<Axis1>>(node.Count * 2);
 20566      //  ArrayJagged<Omnitree.Bound<Axis2>> values2 = new ArrayJagged<Omnitree.Bound<Axis2>>(node.Count * 2);
 20567      //  ArrayJagged<Omnitree.Bound<Axis3>> values3 = new ArrayJagged<Omnitree.Bound<Axis3>>(node.Count * 2);
 20568      //  Node.ValueNode for_current = node.Head; // used in for loop
 20569      //  for (int i = 0; i < node.Count; i++, for_current = for_current.Next)
 20570      //  {
 20571      //    Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 20572      //    Omnitree.Bound<Axis2> min2; Omnitree.Bound<Axis2> max2;
 20573      //    Omnitree.Bound<Axis3> min3; Omnitree.Bound<Axis3> max3;
 20574      //    this._getBounds(for_current.Value,
 20575      //      out min1, out max1
 20576//,
 20577      //      out min2, out max2
 20578//,
 20579      //      out min3, out max3
 20580      //      );
 20581      //    values1[i * 2] = min1; values1[i * 2 + 1] = max1;
 20582      //    values2[i * 2] = min2; values2[i * 2 + 1] = max2;
 20583      //    values3[i * 2] = min3; values3[i * 2 + 1] = max3;
 20584      //  }
 20585      //  return new Omnitree.Vector<Axis1, Axis2, Axis3>(
 20586      //    Omnitree.SubDivide(values1, this._defaultCompare1 ? Compare : this._compare1)
 20587      //    , Omnitree.SubDivide(values2, this._defaultCompare2 ? Compare : this._compare2)
 20588      //    , Omnitree.SubDivide(values3, this._defaultCompare3 ? Compare : this._compare3)
 20589      //  );
 20590      //}
 020591    }
 20592
 20593    #endregion
 20594
 20595    #region Add Helpers
 20596
 20597    internal Omnitree.Bounds<Axis1, Axis2, Axis3> DetermineChildBounds(Node node, int child_index)
 020598    {
 20599      // the node parameter should always have a point of division value for this function
 020600      Omnitree.Vector<Axis1, Axis2, Axis3> pointOfDivision = node.PointOfDivision.Value;
 20601
 20602      Omnitree.Bound<Axis3> min3, max3;
 020603      if (child_index >= 4)
 020604      {
 020605        min3 = pointOfDivision.Axis3;
 020606        max3 = node.Bounds.Max3;
 020607        child_index -= 4;
 020608      }
 20609      else
 020610      {
 020611        min3 = node.Bounds.Min3;
 020612        max3 = pointOfDivision.Axis3;
 020613      }
 20614
 20615      Omnitree.Bound<Axis2> min2, max2;
 020616      if (child_index >= 2)
 020617      {
 020618        min2 = pointOfDivision.Axis2;
 020619        max2 = node.Bounds.Max2;
 020620        child_index -= 2;
 020621      }
 20622      else
 020623      {
 020624        min2 = node.Bounds.Min2;
 020625        max2 = pointOfDivision.Axis2;
 020626      }
 20627
 20628      Omnitree.Bound<Axis1> min1, max1;
 020629      if (child_index >= 1)
 020630      {
 020631        min1 = pointOfDivision.Axis1;
 020632        max1 = node.Bounds.Max1;
 020633        child_index -= 1;
 020634      }
 20635      else
 020636      {
 020637        min1 = node.Bounds.Min1;
 020638        max1 = pointOfDivision.Axis1;
 020639      }
 20640
 020641      return new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3);
 020642    }
 20643
 20644    #endregion
 20645
 20646    #endregion
 20647
 20648    #region Clear
 20649
 20650    /// <summary>Returns the tree to an empty state.</summary>
 20651    public void Clear()
 020652    {
 020653      this._top = new Node(Omnitree.Bounds<Axis1, Axis2, Axis3>.None, null, -1);
 020654      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 020655    }
 20656
 20657    #endregion
 20658
 20659    #region Clone
 20660
 20661    /// <summary>Creates a shallow clone of this data structure.</summary>
 20662    /// <returns>A shallow clone of this data structure.</returns>
 20663    public OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3> Clone()
 020664    {
 020665      return new OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3>(this);
 020666    }
 20667
 20668    #endregion
 20669
 20670    #region Count
 20671
 20672    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 20673    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 20674    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 20675    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 20676    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 20677    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 20678    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 20679    /// <returns>The number of items in the provided sub space.</returns>
 20680    public int CountSubSpaceEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3)
 020681    {
 020682      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3
 020683    }
 20684    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 20685    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 20686    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 20687    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 20688    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 20689    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 20690    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 20691    /// <returns>The number of items in the provided sub space.</returns>
 20692    public int CountSubSpaceEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> m
 020693    {
 020694      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3
 020695    }
 20696    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 20697    /// <param name="axis1">The coordinate along the 1D axis.</param>
 20698    /// <param name="axis2">The coordinate along the 2D axis.</param>
 20699    /// <param name="axis3">The coordinate along the 3D axis.</param>
 20700    /// <returns>The number of items in the provided sub space.</returns>
 20701    public int CountSubSpaceEncapsulated(Axis1 axis1, Axis2 axis2, Axis3 axis3)
 020702    {
 020703      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(axis1, axis1, axis2, axis2, axis3,
 020704    }
 20705    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 20706    /// <param name="axis1">The coordinate along the 1D axis.</param>
 20707    /// <param name="axis2">The coordinate along the 2D axis.</param>
 20708    /// <param name="axis3">The coordinate along the 3D axis.</param>
 20709    /// <returns>The number of items in the provided sub space.</returns>
 20710    public int CountSubSpaceEncapsulated(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3>
 020711    {
 020712      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(axis1, axis1, axis2, axis2, axis3,
 020713    }
 20714
 20715    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 20716    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 20717    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 20718    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 20719    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 20720    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 20721    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 20722    /// <returns>The number of items in the provided sub space.</returns>
 20723    public int CountSubSpaceOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3)
 020724    {
 020725      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3))
 020726    }
 20727    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 20728    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 20729    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 20730    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 20731    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 20732    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 20733    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 20734    /// <returns>The number of items in the provided sub space.</returns>
 20735    public int CountSubSpaceOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min
 020736    {
 020737      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3))
 020738    }
 20739    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 20740    /// <param name="axis1">The coordinate along the 1D axis.</param>
 20741    /// <param name="axis2">The coordinate along the 2D axis.</param>
 20742    /// <param name="axis3">The coordinate along the 3D axis.</param>
 20743    /// <returns>The number of items in the provided sub space.</returns>
 20744    public int CountSubSpaceOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3)
 020745    {
 020746      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(axis1, axis1, axis2, axis2, axis3, a
 020747    }
 20748    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 20749    /// <param name="axis1">The coordinate along the 1D axis.</param>
 20750    /// <param name="axis2">The coordinate along the 2D axis.</param>
 20751    /// <param name="axis3">The coordinate along the 3D axis.</param>
 20752    /// <returns>The number of items in the provided sub space.</returns>
 20753    public int CountSubSpaceOverlapped(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> a
 020754    {
 020755      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(axis1, axis1, axis2, axis2, axis3, a
 020756    }
 20757
 20758    internal int CountSubSpaceEncapsulated(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3> bounds)
 020759    {
 020760      return CountSubSpaceBase(_top, bounds, (a, b) => EncapsulationCheck(a, b));
 020761    }
 20762
 20763    internal int CountSubSpaceOverlapped(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3> bounds)
 020764    {
 020765      return CountSubSpaceBase(_top, bounds, (a, b) => InclusionCheck(a, b));
 020766    }
 20767
 20768    internal int CountSubSpaceBase(
 20769      Node node,
 20770      Omnitree.Bounds<Axis1, Axis2, Axis3> bounds,
 20771      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3>, Omnitree.Bounds<Axis1, Axis2, Axis3>> spatialCheck)
 020772    {
 20773      // adjust min/max values
 020774      int count = 0;
 020775      if (EncapsulationCheck(bounds, node.Bounds))
 020776        count += node.Count;
 020777      else if (!node.PointOfDivision.HasValue)
 020778      {
 020779        for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 020780          if (spatialCheck(bounds, GetBoundings(list.Value)))
 020781            count++;
 020782      }
 20783      else
 020784      {
 020785        Node branch = node as Node;
 020786        if (!StraddlesLines(branch.Bounds, branch.PointOfDivision.Value))
 020787        {
 020788          int child_index = DetermineChildIndex(branch.PointOfDivision.Value, bounds);
 020789          Node child = branch[child_index];
 020790          if (child is not null)
 020791            count += this.CountSubSpaceBase(child, bounds, spatialCheck);
 020792        }
 20793        else
 020794        {
 020795          foreach (Node child in node.Children)
 020796            count += this.CountSubSpaceBase(child, bounds, spatialCheck);
 020797        }
 020798      }
 020799      return count;
 020800    }
 20801
 20802    #endregion
 20803
 20804    #region Update
 20805
 20806    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 20807    public void Update()
 020808    {
 020809      this.Update(this._top, 0);
 020810    }
 20811
 20812    /// <summary>Recursive version of the Update method.</summary>
 20813    /// <param name="node">The current node of iteration.</param>
 20814    /// <param name="depth">The current depth of iteration.</param>
 20815    internal int Update(Node node, int depth)
 020816    {
 020817      int removals = 0;
 20818
 020819      {
 020820        Node branch = node as Node;
 020821        int skipped = 0;
 020822        for (int i = 0; i + skipped < branch.Children.Length; )
 020823        {
 020824          removals += this.Update(branch.Children[i], depth + 1);
 020825          if (branch.Children[i].Count is 0)
 020826            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 20827          else
 020828            i++;
 020829        }
 020830        Node[] newArray = new Node[branch.Children.Length - skipped];
 020831        Array.Copy(branch.Children, newArray, newArray.Length);
 020832        branch.Children = newArray;
 20833
 020834        if (branch.Count < _load && branch.Count != 0)
 020835          ShrinkChild(branch.Parent, branch.Index);
 020836      }
 20837
 020838      {
 020839        Node.ValueNode current = node.Head;
 020840        Node.ValueNode previous = null;
 020841        while (current is not null)
 020842        {
 020843          Omnitree.Bounds<Axis1, Axis2, Axis3> bounds = GetBoundings(current.Value);
 020844          if (!this.EncapsulationCheck(node.Bounds, bounds))
 020845          {
 020846            removals++;
 020847            T updated = current.Value;
 020848            if (previous is null)
 020849            {
 020850              node.Head = current.Next;
 020851              goto HeadRemoved;
 20852            }
 20853            else
 020854              previous.Next = current.Next;
 20855
 020856            Node whereToAdd = GetEncapsulationParent(node.Parent, bounds);
 20857
 020858            if (whereToAdd is null)
 020859              throw new System.Exception("an item was updated outside the range of the omnitree");
 20860
 020861            this.Add(updated, whereToAdd, bounds, whereToAdd.Depth);
 020862          }
 020863          previous = current;
 020864        HeadRemoved:
 020865          current = current.Next;
 020866        }
 020867      }
 20868
 020869      node.Count -= removals;
 020870      return removals;
 020871    }
 20872
 20873    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 20874    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 20875    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 20876    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 20877    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 20878    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 20879    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 20880    public void Update(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3)
 020881    {
 020882      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3), this._top, 0);
 020883    }
 20884    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 20885    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 20886    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 20887    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 20888    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 20889    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 20890    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 20891    public void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 020892    {
 020893      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3), this._top, 0);
 020894    }
 20895    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 20896    /// <param name="axis1">The coordinate along the 1D axis.</param>
 20897    /// <param name="axis2">The coordinate along the 2D axis.</param>
 20898    /// <param name="axis3">The coordinate along the 3D axis.</param>
 20899    public void Update(Axis1 axis1, Axis2 axis2, Axis3 axis3)
 020900    {
 020901      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3>(axis1, axis1, axis2, axis2, axis3, axis3), this._top, 0);
 020902    }
 20903    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 20904    /// <param name="axis1">The coordinate along the 1D axis.</param>
 20905    /// <param name="axis2">The coordinate along the 2D axis.</param>
 20906    /// <param name="axis3">The coordinate along the 3D axis.</param>
 20907    public void Update(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3)
 020908    {
 020909      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3>(axis1, axis1, axis2, axis2, axis3, axis3), this._top, 0);
 020910    }
 20911    internal int Update(Omnitree.Bounds<Axis1, Axis2, Axis3> bounds, Node node, int depth)
 020912    {
 020913      if (!InclusionCheck(bounds, node.Bounds))
 020914        return 0;
 20915
 020916      int removals = 0;
 20917
 020918      {
 020919        Node branch = node as Node;
 020920        int skipped = 0;
 020921        for (int i = 0; i + skipped < branch.Children.Length; )
 020922        {
 020923          removals += this.Update(branch.Children[i], depth + 1);
 020924          if (branch.Children[i].Count is 0)
 020925            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 20926          else
 020927            i++;
 020928        }
 020929        Node[] newArray = new Node[branch.Children.Length - skipped];
 020930        Array.Copy(branch.Children, newArray, newArray.Length);
 020931        branch.Children = newArray;
 20932
 020933        if (branch.Count < _load && branch.Count != 0)
 020934          ShrinkChild(branch.Parent, branch.Index);
 020935      }
 20936
 020937      {
 020938        Node.ValueNode current = node.Head;
 020939        Node.ValueNode previous = null;
 020940        while (current is not null)
 020941        {
 020942          Omnitree.Bounds<Axis1, Axis2, Axis3> item_bounds = GetBoundings(current.Value);
 020943          if (!this.EncapsulationCheck(node.Bounds, item_bounds))
 020944          {
 020945            removals++;
 020946            T updated = current.Value;
 020947            if (previous is null)
 020948            {
 020949              node.Head = current.Next;
 020950              goto HeadRemoved;
 20951            }
 20952            else
 020953              previous.Next = current.Next;
 020954            Node whereToAdd = GetEncapsulationParent(node.Parent, item_bounds);
 020955            if (whereToAdd is null)
 020956              throw new System.Exception("an item was updates outside the range of the omnitree");
 020957            this.Add(updated, whereToAdd, item_bounds, whereToAdd.Depth);
 020958          }
 020959          previous = current;
 020960        HeadRemoved:
 020961          current = current.Next;
 020962        }
 020963      }
 20964
 020965      node.Count -= removals;
 020966      return removals;
 020967    }
 20968
 20969    #endregion
 20970
 20971    #region Remove
 20972
 20973    /// <summary>Removes all the items qualified by the delegate.</summary>
 20974    /// <param name="where">The predicate to qualify removals.</param>
 20975    public void Remove(Predicate<T> where)
 020976    {
 020977      this.Remove(this._top, where);
 020978      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 020979    }
 20980
 20981    /// <summary>Recursive version of the remove method.</summary>
 20982    /// <param name="node">The current node of traversal.</param>
 20983    /// <param name="where">The predicate to qualify removals.</param>
 20984    internal int Remove(Node node, Predicate<T> where)
 020985    {
 020986      int removals = 0;
 20987
 20988      // children
 020989      if (node.Children is not null)
 020990      {
 020991        int skipped = 0;
 020992        for (int i = 0; i + skipped < node.Children.Length; )
 020993        {
 020994          removals += this.Remove(node.Children[i], where);
 020995          if (node.Children[i].Count is 0)
 020996            node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 20997          else
 020998            i++;
 020999        }
 021000        Node[] newArray = new Node[node.Children.Length - skipped];
 021001        Array.Copy(node.Children, newArray, newArray.Length);
 021002        node.Children = newArray;
 21003
 021004        if (node.Count < _load && node.Count != 0)
 021005          ShrinkChild(node.Parent, node.Index);
 021006      }
 21007
 21008      // items
 021009      while (node.Head is not null && where(node.Head.Value))
 021010      {
 021011        node.Head = node.Head.Next;
 021012        removals++;
 021013      }
 021014      if (node.Head is not null)
 021015      {
 021016        Node.ValueNode list = node.Head;
 021017        while (list.Next is not null)
 021018        {
 021019          if (where(list.Next.Value))
 021020          {
 021021            list.Next = list.Next.Next;
 021022            removals++;
 021023          }
 021024        }
 021025      }
 21026
 021027      node.Count -= removals;
 021028      return removals;
 021029    }
 21030
 21031    /// <summary>Removes all the items encapsulated in a given space.</summary>
 21032    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21033    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21034    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21035    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21036    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21037    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21038    /// <returns>The number of items that were removed.</returns>
 21039    public void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3)
 021040    {
 021041      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 021042    }
 21043    /// <summary>Removes all the items encapsulated in a given space.</summary>
 21044    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21045    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21046    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21047    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21048    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21049    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21050    /// <returns>The number of items that were removed.</returns>
 21051    public void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, O
 021052    {
 021053      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 021054    }
 21055    /// <summary>Removes all the items encapsulated in a given space.</summary>
 21056    /// <param name="axis1">The coordinate along the 1D axis.</param>
 21057    /// <param name="axis2">The coordinate along the 2D axis.</param>
 21058    /// <param name="axis3">The coordinate along the 3D axis.</param>
 21059    public void RemoveEncapsulated(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3
 021060    {
 021061      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(axis1, axis1, axis2, axis2, axis3, axi
 021062    }
 21063    internal int RemoveEncapsulated(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3> bounds)
 021064    {
 021065      int removals = this.RemoveBase(node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 021066      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 021067      return removals;
 021068    }
 21069
 21070    /// <summary>Removes all the items overlapping a given space.</summary>
 21071    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21072    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21073    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21074    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21075    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21076    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21077    /// <returns>The number of items that were removed.</returns>
 21078    public void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3)
 021079    {
 021080      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 021081    }
 21082    /// <summary>Removes all the items overlapping a given space.</summary>
 21083    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21084    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21085    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21086    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21087    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21088    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21089    /// <returns>The number of items that were removed.</returns>
 21090    public void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omn
 021091    {
 021092      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 021093    }
 21094    internal int RemoveOverlapped(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3> bounds)
 021095    {
 021096      int removals = this.RemoveBase(node, bounds, (a, b) => this.InclusionCheck(a, b));
 021097      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 021098      return removals;
 021099    }
 21100
 21101    internal int RemoveBase(
 21102      Node node,
 21103      Omnitree.Bounds<Axis1, Axis2, Axis3> bounds,
 21104      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3>, Omnitree.Bounds<Axis1, Axis2, Axis3>> spatialCheck)
 021105    {
 021106      int removals = 0;
 021107      if (InclusionCheck(bounds, node.Bounds))
 021108      {
 21109        // items
 021110        Node.ValueNode current_node = node.Head;
 021111        Node.ValueNode previous_node = null;
 021112        while (!(current_node is null))
 021113        {
 021114          Node.ValueNode temp_previous = current_node;
 021115          if (spatialCheck(bounds, GetBoundings(current_node.Value)))
 021116          {
 021117            removals++;
 021118            if (current_node == node.Head)
 021119              node.Head = node.Head.Next;
 21120            else
 021121            {
 021122              previous_node.Next = current_node.Next;
 021123              temp_previous = previous_node;
 021124            }
 021125          }
 021126          previous_node = temp_previous;
 021127          current_node = current_node.Next;
 021128        }
 21129
 21130        // children
 021131        if (node.Children is not null)
 021132        {
 021133          int skipped = 0;
 021134          for (int i = 0; i + skipped < node.Children.Length; )
 021135          {
 021136            removals += this.RemoveBase(node.Children[i], bounds, spatialCheck);
 021137            if (node.Children[i].Count is 0)
 021138              node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 21139            else
 021140              i++;
 021141          }
 021142          Node[] newArray = new Node[node.Children.Length - skipped];
 021143          Array.Copy(node.Children, newArray, newArray.Length);
 021144          node.Children = newArray;
 21145
 21146          // convert this branch back into a leaf
 21147          // Note: if count is zero, it will be chopped off
 021148          if (node.Count < _load && node.Count > 0)
 021149            ShrinkChild(node.Parent, node.Index);
 021150        }
 021151      }
 21152
 021153      node.Count -= removals;
 021154      return removals;
 021155    }
 21156
 21157    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 21158    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21159    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21160    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21161    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21162    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21163    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21164    /// <param name="where">The equality constraint of the removal.</param>
 21165    public void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Predicate<T> 
 021166    {
 021167      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3), w
 021168    }
 21169    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 21170    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21171    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21172    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21173    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21174    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21175    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21176    /// <param name="where">The equality constraint of the removal.</param>
 21177    public void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, O
 021178    {
 021179      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3), w
 021180    }
 21181    internal int RemoveEncapsulated(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3> bounds, Predicate<T> where)
 021182    {
 021183      int removals = RemoveBase(node, bounds, where, (a, b) => this.EncapsulationCheck(a, b));
 021184      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 021185      return removals;
 021186    }
 21187
 21188    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 21189    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21190    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21191    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21192    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21193    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21194    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21195    /// <param name="where">The equality constraint of the removal.</param>
 21196    public void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Predicate<T> wh
 021197    {
 021198      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3), whe
 021199    }
 21200    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 21201    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21202    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21203    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21204    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21205    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21206    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21207    /// <param name="where">The equality constraint of the removal.</param>
 21208    public void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omn
 021209    {
 021210      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3), whe
 021211    }
 21212    internal int RemoveOverlapped(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3> bounds, Predicate<T> where)
 021213    {
 021214      int removals = RemoveBase(node, bounds, where, (a, b) => this.InclusionCheck(a, b));
 021215      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 021216      return removals;
 021217    }
 21218
 21219    internal int RemoveBase(
 21220      Node node,
 21221      Omnitree.Bounds<Axis1, Axis2, Axis3> bounds,
 21222      Predicate<T> where,
 21223      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3>, Omnitree.Bounds<Axis1, Axis2, Axis3>> spatialCheck)
 021224    {
 021225      if (!InclusionCheck(node.Bounds, bounds))
 021226        return 0;
 021227      int removals = 0;
 21228
 21229      // items
 021230      Node.ValueNode current = node.Head;
 021231      Node.ValueNode previous = null;
 021232      while (current is not null)
 021233      {
 021234        if (spatialCheck(bounds, GetBoundings(current.Value)) && where(current.Value))
 021235        {
 021236          removals++;
 021237          if (previous is null)
 021238          {
 021239            node.Head = current.Next;
 021240            goto HeadRemoved;
 21241          }
 21242          else
 021243            previous.Next = current.Next;
 021244        }
 021245        previous = current;
 021246      HeadRemoved:
 021247        current = current.Next;
 021248      }
 21249
 21250      // children
 021251      if (node.Children is not null)
 021252      {
 021253        int skipped = 0;
 021254        for (int i = 0; i + skipped < node.Children.Length; )
 021255        {
 021256          removals += this.RemoveBase(node.Children[i], bounds, where, spatialCheck);
 021257          if (node.Children[i].Count is 0)
 021258            node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 21259          else
 021260            i++;
 021261        }
 021262        Node[] newArray = new Node[node.Children.Length - skipped];
 021263        Array.Copy(node.Children, newArray, newArray.Length);
 021264        node.Children = newArray;
 21265
 021266        if (node.Count < _load && node.Count != 0)
 021267          ShrinkChild(node.Parent, node.Index);
 021268      }
 21269
 021270      node.Count -= removals;
 021271      return removals;
 021272    }
 21273
 21274    /// <summary>Tries to remove a value.</summary>
 21275    /// <param name="value">The value to remove.</param>
 21276    /// <returns>True if successful or false if not.</returns>
 21277    public (bool Success, Exception? Exception) TryRemove(T value)
 021278    {
 021279      Remove(value);
 021280      return (true, null);
 021281    }
 21282
 21283    /// <summary>Removes all instances of a given value.</summary>
 021284    public void Remove(T removal) => Omnitree.Remove(this, removal);
 21285
 21286    /// <summary>Removes all instances of a given value.</summary>
 021287    public void Remove(T removal, Func<T, T, bool> equate) => Omnitree.Remove(this, removal, equate);
 21288
 21289    /// <summary>Removes all the items in a given space.</summary>
 21290    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 21291    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 21292    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 21293    /// <returns>The number of items that were removed.</returns>
 21294    public void RemoveOverlapped(Axis1 axis1
 21295      , Axis2 axis2
 21296      , Axis3 axis3
 21297      )
 021298    {
 021299      this.RemoveOverlapped(axis1, axis1
 021300        , axis2, axis2
 021301        , axis3, axis3
 021302        );
 021303      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 021304    }
 21305
 21306    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 21307    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 21308    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 21309    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 21310    /// <param name="where">The equality constraint of the removal.</param>
 21311    public void RemoveOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3, Predicate<T> where)
 021312    {
 021313      this.RemoveOverlapped(axis1, axis1
 021314        , axis2, axis2
 021315        , axis3, axis3
 021316        , where);
 021317      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 021318    }
 21319
 21320    #endregion
 21321
 21322    #region Stepper And IEnumerable
 21323
 21324    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 21325    /// <param name="step">The delegate to perform on every item in the tree.</param>
 21326    public void Stepper(Action<T> step) =>
 021327      this.Stepper(step, this._top);
 21328
 21329    internal void Stepper(Action<T> step, Node node)
 021330    {
 021331      Node.ValueNode list = node.Head;
 021332      while (list is not null)
 021333      {
 021334        step(list.Value);
 021335        list = list.Next;
 021336      }
 021337      if (node.Children is not null)
 021338        foreach (Node child in node.Children)
 021339          this.Stepper(step, child);
 021340    }
 21341
 21342    public StepStatus StepperBreak<TStep>(TStep step = default)
 21343      where TStep : struct, IFunc<T, StepStatus> =>
 021344      StepperBreak(_top, step);
 21345
 21346    internal StepStatus StepperBreak<TStep>(Node node, TStep step)
 21347      where TStep : struct, IFunc<T, StepStatus>
 021348    {
 021349      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 021350      {
 021351        if (step.Invoke(list.Value) is Break) return Break;
 021352      }
 021353      if (node.Children is not null)
 021354      {
 021355        foreach (Node child in node.Children)
 021356        {
 021357          if (StepperBreak(child, step) is Break) return Break;
 021358        }
 021359      }
 021360      return Continue;
 021361    }
 21362
 21363    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 21364    /// <param name="step">The delegate to perform on every item in the tree.</param>
 21365    public StepStatus Stepper(Func<T, StepStatus> step) =>
 021366      Stepper(step, _top);
 21367
 21368    internal StepStatus Stepper(Func<T, StepStatus> step, Node node)
 021369    {
 021370      StepStatus status = StepStatus.Continue;
 21371
 021372      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 021373        if ((status = step(list.Value)) != StepStatus.Continue)
 021374          break;
 21375
 021376      if (node.Children is not null)
 021377        foreach (Node child in node.Children)
 021378          if ((status = Stepper(step, child)) != StepStatus.Continue)
 021379            break;
 21380
 021381      return status;
 021382    }
 21383
 21384    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 21385    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 21386    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21387    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21388    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21389    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21390    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21391    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21392    public void StepperEncapsulated(Action<T> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 ma
 021393      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 21394
 21395    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 21396    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 21397    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21398    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21399    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21400    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21401    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21402    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21403    public void StepperEncapsulated(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bou
 021404      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 21405
 21406    internal void StepperEncapsulated(Action<T> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3> bounds) =>
 021407      StepperBase(step, node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 21408
 21409    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 21410    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 21411    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21412    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21413    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21414    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21415    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21416    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21417    public void StepperOverlapped(Action<T> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3
 021418      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 21419
 21420    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 21421    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 21422    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21423    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21424    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21425    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21426    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21427    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21428    public void StepperOverlapped(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound
 021429      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 21430
 21431    internal void StepperOverlapped(Action<T> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3> bounds) =>
 021432      StepperBase(step, node, bounds, (a, b) => this.InclusionCheck(a, b));
 21433
 21434    internal void StepperBase(
 21435      Action<T> step,
 21436      Node node,
 21437      Omnitree.Bounds<Axis1, Axis2, Axis3> bounds,
 21438      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3>, Omnitree.Bounds<Axis1, Axis2, Axis3>> spatialCheck)
 021439    {
 021440      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 021441        if (spatialCheck(bounds, GetBoundings(list.Value)))
 021442          step(list.Value);
 21443
 021444      if (node.Children is not null)
 021445      {
 021446        foreach (Node child in node.Children)
 21447          // optimization: stop bounds checking if space encapsulates node
 021448          if (EncapsulationCheck(bounds, child.Bounds))
 021449            this.Stepper(step, child);
 021450          else if (InclusionCheck(child.Bounds, bounds))
 021451            this.StepperBase(step, child, bounds, spatialCheck);
 021452      }
 021453    }
 21454
 21455    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 21456    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 21457    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21458    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21459    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21460    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21461    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21462    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21463    public StepStatus StepperEncapsulated(Func<T, StepStatus> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis
 021464      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 21465
 21466    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 21467    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 21468    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21469    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21470    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21471    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21472    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21473    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21474    public StepStatus StepperEncapsulated(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> ma
 021475      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 21476
 21477    internal StepStatus StepperEncapsulated(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3> bo
 021478      StepperBase(step, node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 21479
 21480    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 21481    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 21482    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21483    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21484    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21485    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21486    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21487    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21488    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 
 021489      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 21490
 21491    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 21492    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 21493    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21494    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21495    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21496    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21497    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21498    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21499    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1
 021500      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(min1, max1, min2, max2, min3, max3));
 21501
 21502    internal StepStatus StepperOverlapped(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3> boun
 021503      StepperBase(step, node, bounds, (a, b) => this.InclusionCheck(a, b));
 21504
 21505    internal StepStatus StepperBase(
 21506      Func<T, StepStatus> step,
 21507      Node node,
 21508      Omnitree.Bounds<Axis1, Axis2, Axis3> bounds,
 21509      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3>, Omnitree.Bounds<Axis1, Axis2, Axis3>> spatialCheck)
 021510    {
 021511      StepStatus status = StepStatus.Continue;
 21512
 021513      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 021514        if (spatialCheck(bounds, GetBoundings(list.Value)) &&
 021515          (status = step(list.Value)) != StepStatus.Continue)
 021516          break;
 21517
 021518      if (node.Children is not null)
 021519      {
 021520        foreach (Node child in node.Children)
 21521          // optimization: stop bounds checking if space encapsulates node
 021522          if (EncapsulationCheck(bounds, child.Bounds) &&
 021523            (status = this.Stepper(step, child)) != StepStatus.Continue)
 021524            break;
 021525          else if (InclusionCheck(child.Bounds, bounds) &&
 021526            (status = this.StepperBase(step, child, bounds, spatialCheck)) != StepStatus.Continue)
 021527            break;
 021528      }
 21529
 021530      return status;
 021531    }
 21532
 21533    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 21534    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 21535    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 21536    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 21537    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 21538    public void StepperOverlapped(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3) =>
 021539      StepperOverlapped(step, this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(axis1, axis1
 021540        , axis2, axis2
 021541        , axis3, axis3
 021542      ));
 21543
 21544    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 21545    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 21546    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 21547    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 21548    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 21549    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3) =>
 021550      StepperOverlapped(step, this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3>(axis1, axis1
 021551        , axis2, axis2
 021552        , axis3, axis3
 021553        ));
 21554
 021555    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 21556
 21557    public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 021558    {
 21559      // Note: this can be optimized.
 021560      IList<T> list = new ListLinked<T>();
 021561      Stepper(x => list.Add(x));
 021562      return list.GetEnumerator();
 021563    }
 21564
 21565    #endregion
 21566
 21567    /// <inheritdoc/>
 021568    public T[] ToArray() => throw new NotImplementedException();
 21569
 21570    #region Helpers
 21571
 21572    internal bool StraddlesLines(Omnitree.Bounds<Axis1, Axis2, Axis3> bounds, Omnitree.Vector<Axis1, Axis2, Axis3> vecto
 021573      Omnitree.StraddlesLines(bounds, vector
 021574        , _compare1
 021575        , _compare2
 021576        , _compare3
 021577        );
 21578
 21579    /// <summary>Computes the child index that contains the desired dimensions.</summary>
 21580    /// <param name="pointOfDivision">The point of division to compare against.</param>
 21581    /// <param name="bounds">The dimensions to determine the child index.</param>
 21582    /// <returns>The computed child index based on the coordinates relative to the center of the node.</returns>
 21583    internal int DetermineChildIndex(Omnitree.Vector<Axis1, Axis2, Axis3> pointOfDivision, Omnitree.Bounds<Axis1, Axis2,
 021584    {
 21585      // make sure a child encapsulates the bounds (otherwise the bounds cannot move down the tree)
 021586      if (StraddlesLines(bounds, pointOfDivision))
 021587        return -1;
 21588
 021589      int child = 0;
 021590      if (!bounds.Min1.Exists || !(this._compare1(bounds.Min1.Value, pointOfDivision.Axis1) is Less))
 021591        child += 1 << 0;
 021592      if (!bounds.Min2.Exists || !(this._compare2(bounds.Min2.Value, pointOfDivision.Axis2) is Less))
 021593        child += 1 << 1;
 021594      if (!bounds.Min3.Exists || !(this._compare3(bounds.Min3.Value, pointOfDivision.Axis3) is Less))
 021595        child += 1 << 2;
 021596      return child;
 021597    }
 21598
 21599    /// <summary>Converts a branch back into a leaf when the count is reduced.</summary>
 21600    /// <param name="parent">The parent to shrink a child of.</param>
 21601    /// <param name="child_index">The index of the child to shrink.</param>
 21602    internal void ShrinkChild(Node parent, int child_index)
 021603    {
 21604      Node leaf;
 021605      Node removal = null;
 021606      if (parent is null) // top of tree
 021607      {
 021608        removal = this._top;
 021609        leaf = new Node(Omnitree.Bounds<Axis1, Axis2, Axis3>.None, null, -1);
 021610        this._top = leaf;
 021611      }
 21612      else // non-top branch
 021613      {
 021614        removal = parent[child_index];
 021615        leaf = new Node(removal.Bounds, removal.Parent, removal.Index);
 021616        parent[child_index] = leaf;
 021617      }
 21618
 021619      this.Stepper((T step) => { leaf.Add(step); }, removal);
 021620    }
 21621
 21622    /// <summary>Reduces the counts of all the parents of a given node by a given amount.</summary>
 21623    /// <param name="parent">The starting parent of the reduction.</param>
 21624    /// <param name="reduction">The amount to reduce the parent counts by.</param>
 21625    internal void ReduceParentCounts(Node parent, int reduction)
 021626    {
 021627      IncreaseParentCounts(parent, -reduction);
 021628    }
 21629
 21630    /// <summary>Increases the counts of all the parents of a given node by a given amount.</summary>
 21631    /// <param name="parent">The starting parent of the increase.</param>
 21632    /// <param name="increase">The amount to increase the parent counts by.</param>
 21633    internal void IncreaseParentCounts(Node parent, int increase)
 021634    {
 021635      Node node = parent;
 021636      while (node is not null)
 021637      {
 021638        node.Count += increase;
 021639        node = node.Parent;
 021640      }
 021641    }
 21642
 21643    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 21644    /// <returns>True if the spaces overlap; False if not.</returns>
 21645    internal bool InclusionCheck(Omnitree.Bounds<Axis1, Axis2, Axis3> a, Omnitree.Bounds<Axis1, Axis2, Axis3> b) =>
 021646      Omnitree.InclusionCheck(a, b
 021647      , _compare1
 021648      , _compare2
 021649      , _compare3
 021650      );
 21651
 21652    /// <summary>Checks if a space encapsulates a point.</summary>
 21653    /// <returns>True if the space encapsulates the point; False if not.</returns>
 21654    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3> bounds, Omnitree.Vector<Axis1, Axis2, Axis3> v
 021655      Omnitree.EncapsulationCheck(bounds, vector
 021656      , _compare1
 021657      , _compare2
 021658      , _compare3
 021659      );
 21660
 21661    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 21662    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 21663    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3> a, Omnitree.Bounds<Axis1, Axis2, Axis3> b) =>
 021664      Omnitree.EncapsulationCheck(a, b
 021665      , _compare1
 021666      , _compare2
 021667      , _compare3
 021668      );
 21669
 21670    /// <summary>Checks for equality between two locations.</summary>
 21671    /// <returns>True if equal; False if not;</returns>
 21672    internal bool EqualsCheck(Omnitree.Vector<Axis1, Axis2, Axis3> a, Omnitree.Vector<Axis1, Axis2, Axis3> b) =>
 021673      Omnitree.EqualsCheck(a, b
 021674      , (a, b) => _compare1(a, b) is Equal
 021675      , (a, b) => _compare2(a, b) is Equal
 021676      , (a, b) => _compare3(a, b) is Equal
 021677      );
 21678
 21679    /// <summary>Gets the nearest parent that encapsulates a location.</summary>
 21680    /// <param name="node">The starting node to find the encapsulating parent of the location.</param>
 21681    /// <param name="bounds">The bounds to get the encapsulating parent from.</param>
 21682    /// <returns>The nearest node that encapsulates the given location.</returns>
 21683    internal Node GetEncapsulationParent(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3> bounds)
 021684    {
 021685      while (node is not null && !EncapsulationCheck(node.Bounds, bounds))
 021686      {
 021687        node = node.Parent;
 021688      }
 021689      return node;
 021690    }
 21691
 21692    internal Omnitree.Bounds<Axis1, Axis2, Axis3> GetBoundings(T value)
 021693    {
 21694      Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 21695      Omnitree.Bound<Axis2> min2; Omnitree.Bound<Axis2> max2;
 21696      Omnitree.Bound<Axis3> min3; Omnitree.Bound<Axis3> max3;
 021697      this._getBounds(value,
 021698        out min1, out max1
 021699,
 021700        out min2, out max2
 021701,
 021702        out min3, out max3
 021703        );
 021704      return new Omnitree.Bounds<Axis1, Axis2, Axis3>(
 021705        min1, max1
 021706,
 021707        min2, max2
 021708,
 021709        min3, max3
 021710        );
 021711    }
 21712
 21713    #endregion
 21714
 21715    #endregion
 21716  }
 21717
 21718  #endregion
 21719
 21720  #region 4 Dimensional
 21721
 21722  /// <summary>Inheritance base for 4D omnitrees that store bounds.</summary>
 21723  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 21724  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 21725  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 21726  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 21727  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 21728  public interface IOmnitreeBounds<T, Axis1, Axis2, Axis3, Axis4> : IOmnitree<T, Axis1, Axis2, Axis3, Axis4>
 21729  {
 21730    #region Properties
 21731
 21732    /// <summary>The number of dimensions in this tree.</summary>
 21733    int Dimensions { get; }
 21734
 21735    /// <summary>The delegate being used by the omnitree to get the bounds of values in 4D space.</summary>
 21736    Omnitree.GetBounds<T, Axis1
 21737, Axis2
 21738, Axis3
 21739, Axis4
 21740      > GetBounds { get; }
 21741
 21742    #endregion
 21743
 21744    #region Methods
 21745
 21746    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 21747    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21748    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21749    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21750    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21751    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21752    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21753    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 21754    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 21755    /// <returns>The number of items in the provided sub space.</returns>
 21756    int CountSubSpaceEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Ax
 21757
 21758    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 21759    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21760    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21761    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21762    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21763    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21764    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21765    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 21766    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 21767    /// <returns>The number of items in the provided sub space.</returns>
 21768    int CountSubSpaceOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis
 21769
 21770    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 21771    void Update();
 21772    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 21773    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21774    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21775    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21776    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21777    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21778    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21779    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 21780    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 21781    void Update(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4);
 21782
 21783    /// <summary>Removes all the items in a given space.</summary>
 21784    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21785    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21786    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21787    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21788    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21789    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21790    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 21791    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 21792    void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 ma
 21793    /// <summary>Removes all the items in a given space.</summary>
 21794    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21795    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21796    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21797    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21798    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21799    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21800    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 21801    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 21802    void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree
 21803    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 21804    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21805    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21806    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21807    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21808    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21809    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21810    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 21811    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 21812    /// <param name="where">The predicate constraint of the removal.</param>
 21813    void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 ma
 21814    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 21815    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21816    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21817    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21818    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21819    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21820    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21821    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 21822    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 21823    /// <param name="where">The predicate constraint of the removal.</param>
 21824    void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree
 21825
 21826    /// <summary>Removes all the items in a given space.</summary>
 21827    /// <param name="axis1">The coordinate along the 1D axis.</param>
 21828    /// <param name="axis2">The coordinate along the 2D axis.</param>
 21829    /// <param name="axis3">The coordinate along the 3D axis.</param>
 21830    /// <param name="axis4">The coordinate along the 4D axis.</param>
 21831    void RemoveOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4);
 21832    /// <summary>Removes all the items in a given space.</summary>
 21833    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21834    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21835    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21836    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21837    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21838    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21839    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 21840    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 21841    void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4
 21842    /// <summary>Removes all the items in a given space.</summary>
 21843    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21844    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21845    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21846    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21847    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21848    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21849    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 21850    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 21851    void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.B
 21852    /// <summary>Removes all the items in a given space where equality is met.</summary>
 21853    /// <param name="axis1">The coordinate along the 1D axis.</param>
 21854    /// <param name="axis2">The coordinate along the 2D axis.</param>
 21855    /// <param name="axis3">The coordinate along the 3D axis.</param>
 21856    /// <param name="axis4">The coordinate along the 4D axis.</param>
 21857    /// <param name="where">The equality constraint of the removal.</param>
 21858    void RemoveOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Predicate<T> where);
 21859    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 21860    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21861    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21862    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21863    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21864    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21865    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21866    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 21867    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 21868    /// <param name="where">The predicate constraint of the removal.</param>
 21869    void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4
 21870    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 21871    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21872    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21873    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21874    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21875    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21876    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21877    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 21878    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 21879    /// <param name="where">The predicate constraint of the removal.</param>
 21880    void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.B
 21881
 21882    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 21883    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 21884    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21885    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21886    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21887    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21888    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21889    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21890    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 21891    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 21892    void StepperEncapsulated(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis
 21893    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 21894    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 21895    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21896    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21897    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21898    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21899    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21900    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21901    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 21902    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 21903    StepStatus StepperEncapsulated(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omn
 21904
 21905    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 21906    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 21907    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21908    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21909    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21910    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21911    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21912    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21913    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 21914    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 21915    void StepperOverlapped(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2>
 21916    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 21917    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 21918    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 21919    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 21920    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 21921    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 21922    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 21923    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 21924    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 21925    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 21926    StepStatus StepperOverlapped(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnit
 21927
 21928    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 21929    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 21930    /// <param name="axis1">The coordinate along the 1D axis.</param>
 21931    /// <param name="axis2">The coordinate along the 2D axis.</param>
 21932    /// <param name="axis3">The coordinate along the 3D axis.</param>
 21933    /// <param name="axis4">The coordinate along the 4D axis.</param>
 21934    void StepperOverlapped(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4);
 21935    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 21936    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 21937    /// <param name="axis1">The coordinate along the 1D axis.</param>
 21938    /// <param name="axis2">The coordinate along the 2D axis.</param>
 21939    /// <param name="axis3">The coordinate along the 3D axis.</param>
 21940    /// <param name="axis4">The coordinate along the 4D axis.</param>
 21941    StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4);
 21942
 21943    #endregion
 21944  }
 21945
 21946  /// <summary>Omnitree that stores bounds along 4 dimensions implemented as a linked tree.</summary>
 21947  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 21948  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 21949  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 21950  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 21951  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 21952  public class OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3, Axis4> : IOmnitreeBounds<T, Axis1, Axis2, Axis3, Axis4>
 21953  {
 21954    internal const int _dimensions = 4;
 21955    internal static int _children_per_node = (int)BigInteger.Pow(2, 4);
 21956
 21957    internal Node _top;
 21958    internal int _naturalLogLower = 1; // caching the next time to calculate loads (lower count)
 21959    internal int _naturalLogUpper = -1; // caching the next time to calculate loads (upper count)
 21960    internal int _load; // ln(count); min = _defaultLoad
 21961    internal Omnitree.GetBounds<T, Axis1
 21962, Axis2
 21963, Axis3
 21964, Axis4
 21965      > _getBounds;
 21966    internal bool _defaultCompare1;
 21967    internal Func<Axis1, Axis1, CompareResult> _compare1;
 21968    internal bool _defaultCompare2;
 21969    internal Func<Axis2, Axis2, CompareResult> _compare2;
 21970    internal bool _defaultCompare3;
 21971    internal Func<Axis3, Axis3, CompareResult> _compare3;
 21972    internal bool _defaultCompare4;
 21973    internal Func<Axis4, Axis4, CompareResult> _compare4;
 21974    internal Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> _subdivisionOverride1;
 21975    internal Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> _subdivisionOverride2;
 21976    internal Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> _subdivisionOverride3;
 21977    internal Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> _subdivisionOverride4;
 21978
 21979    #region Nested Types
 21980
 21981    /// <summary>Can be a leaf or a branch.</summary>
 21982    internal class Node
 21983    {
 21984      internal class ValueNode
 21985      {
 21986        internal T Value;
 21987        internal ValueNode Next;
 21988
 21989        internal ValueNode(T value, ValueNode next)
 21990        {
 21991          Value = value;
 21992          Next = next;
 21993        }
 21994      }
 21995
 21996      internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> Bounds;
 21997      internal Node Parent;
 21998      internal int Index;
 21999      internal int Count;
 22000      internal ValueNode Head;
 22001      internal Node[] Children;
 22002      internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4>? PointOfDivision;
 22003
 22004      /// <summary>Gets child by index.</summary>
 22005      /// <param name="child_index">The index of the child to get.</param>
 22006      /// <returns>The child of the given index or null if non-existent.</returns>
 22007      internal Node this[int child_index]
 22008      {
 22009        get
 22010        {
 22011          if (Children is null)
 22012            return null;
 22013          if (Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4>._children_per_node)
 22014            return Children[(int)child_index];
 22015          foreach (Node node in Children)
 22016            if (node.Index == child_index)
 22017              return node;
 22018          return null;
 22019        }
 22020        set
 22021        {
 22022          // This error check should be unnecessary... but fuck it... might as well
 22023          if (value.Index != child_index)
 22024            throw new System.Exception("Bug in Omnitree (index/property mis-match when setting a child on a branch)");
 22025
 22026          // no children yet
 22027          if (Children is null)
 22028          {
 22029            Children = â±¯(value);
 22030            return;
 22031          }
 22032          // max children overwrite
 22033          else if (Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4>._children_per_node)
 22034          {
 22035            Children[(int)child_index] = value;
 22036            return;
 22037          }
 22038          // non-max child overwrite
 22039          for (int i = 0; i < Children.Length; i++)
 22040            if (Children[i].Index == child_index)
 22041            {
 22042              Children[i] = value;
 22043              return;
 22044            }
 22045          // new child
 22046          Node[] newArray = new Node[Children.Length + 1];
 22047          if (newArray.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4>._children_per_node)
 22048          {
 22049            // new child resulting in a max children branch (sorting required)
 22050            for (int i = 0; i < Children.Length; i++)
 22051            {
 22052              newArray[(int)Children[i].Index] = Children[i];
 22053            }
 22054            newArray[(int)value.Index] = value;
 22055          }
 22056          else
 22057          {
 22058            // new child resulting in a non-max children branch
 22059            Array.Copy(Children, newArray, Children.Length);
 22060            newArray[newArray.Length - 1] = value;
 22061          }
 22062          Children = newArray;
 22063        }
 22064      }
 22065
 22066      /// <summary>The depth this node is located in the Omnitree.</summary>
 22067      internal int Depth
 22068      {
 22069        get
 22070        {
 22071          int depth = -1;
 22072          for (Node node = this; node is not null; node = node.Parent)
 22073            depth++;
 22074          return depth;
 22075        }
 22076      }
 22077
 22078      /// <summary>Constructs a node.</summary>
 22079      /// <param name="bounds">The bounds of this node.</param>
 22080      /// <param name="parent">The parent of this node.</param>
 22081      /// <param name="index">The number of values stored in this node and its children.</param>
 22082      internal Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds, Node parent, int index)
 22083      {
 22084        Bounds = bounds;
 22085        Parent = parent;
 22086        Index = index;
 22087      }
 22088
 22089      internal Node(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> pointOfDivision, Omnitree.Bounds<Axis1, Axis2, Axis3, Ax
 22090        : this(bounds, parent, index)
 22091      {
 22092        PointOfDivision = pointOfDivision;
 22093      }
 22094
 22095      internal Node(Node nodeToClone)
 22096      {
 22097        this.Bounds = nodeToClone.Bounds;
 22098        this.Parent = nodeToClone.Parent;
 22099        this.Index = nodeToClone.Index;
 22100        this.Count = nodeToClone.Count;
 22101
 22102        Children = nodeToClone.Children.Clone() as Node[];
 22103        PointOfDivision = nodeToClone.PointOfDivision;
 22104
 22105        ValueNode a = this.Head;
 22106        ValueNode b = nodeToClone.Head;
 22107
 22108        while (b is not null)
 22109        {
 22110          a.Next = new ValueNode(b.Next.Value, null);
 22111          a = a.Next;
 22112          b = b.Next;
 22113        }
 22114      }
 22115
 22116      internal void Add(T addition)
 22117      {
 22118        Head = new ValueNode(addition, Head);
 22119        Count++;
 22120      }
 22121
 22122      internal Node Clone() =>
 22123        new Node(this);
 22124    }
 22125
 22126    #endregion
 22127
 22128    #region Constructors
 22129
 22130    /// <summary>This constructor is for cloning purposes</summary>
 22131    internal OmnitreeBoundsLinked(OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3, Axis4> omnitree)
 22132    {
 22133      this._top = omnitree._top.Clone();
 22134      this._load = omnitree._load;
 22135      this._getBounds = omnitree._getBounds;
 22136      this._defaultCompare1 = omnitree._defaultCompare1;
 22137      this._compare1 = omnitree._compare1;
 22138      this._defaultCompare2 = omnitree._defaultCompare2;
 22139      this._compare2 = omnitree._compare2;
 22140      this._defaultCompare3 = omnitree._defaultCompare3;
 22141      this._compare3 = omnitree._compare3;
 22142      this._defaultCompare4 = omnitree._defaultCompare4;
 22143      this._compare4 = omnitree._compare4;
 22144      this._subdivisionOverride1 = omnitree._subdivisionOverride1;
 22145      this._subdivisionOverride2 = omnitree._subdivisionOverride2;
 22146      this._subdivisionOverride3 = omnitree._subdivisionOverride3;
 22147      this._subdivisionOverride4 = omnitree._subdivisionOverride4;
 22148    }
 22149
 22150    internal OmnitreeBoundsLinked(
 22151      Omnitree.GetBounds<T, Axis1, Axis2, Axis3, Axis4> getBounds,
 22152      bool defaultCompare1,
 22153      Func<Axis1, Axis1, CompareResult> compare1,
 22154      bool defaultCompare2,
 22155      Func<Axis2, Axis2, CompareResult> compare2,
 22156      bool defaultCompare3,
 22157      Func<Axis3, Axis3, CompareResult> compare3,
 22158      bool defaultCompare4,
 22159      Func<Axis4, Axis4, CompareResult> compare4,
 22160      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride1
 22161,
 22162      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride2
 22163,
 22164      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride3
 22165,
 22166      Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride4
 22167      )
 22168    {
 22169      if (getBounds is null)
 22170      {
 22171        throw new ArgumentNullException(nameof(getBounds));
 22172      }
 22173      if (compare1 is null)
 22174      {
 22175        throw new ArgumentNullException(nameof(compare1));
 22176      }
 22177      if (compare2 is null)
 22178      {
 22179        throw new ArgumentNullException(nameof(compare2));
 22180      }
 22181      if (compare3 is null)
 22182      {
 22183        throw new ArgumentNullException(nameof(compare3));
 22184      }
 22185      if (compare4 is null)
 22186      {
 22187        throw new ArgumentNullException(nameof(compare4));
 22188      }
 22189      this._getBounds = getBounds;
 22190      this._defaultCompare1 = defaultCompare1;
 22191      this._compare1 = compare1;
 22192      this._defaultCompare2 = defaultCompare2;
 22193      this._compare2 = compare2;
 22194      this._defaultCompare3 = defaultCompare3;
 22195      this._compare3 = compare3;
 22196      this._defaultCompare4 = defaultCompare4;
 22197      this._compare4 = compare4;
 22198      this._subdivisionOverride1 = subdivisionOverride1;
 22199      this._subdivisionOverride2 = subdivisionOverride2;
 22200      this._subdivisionOverride3 = subdivisionOverride3;
 22201      this._subdivisionOverride4 = subdivisionOverride4;
 22202      this._top = new Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>.None, null, -1);
 22203      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 22204    }
 22205
 22206    /// <summary>Constructs a new 4D omnitree that stores bounds.</summary>
 22207    /// <param name="getBounds">The delegate for getting object bounds in 4D space.</param>
 22208
 22209    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 22210
 22211    /// <param name="compare2">The delegate for comparing values along the 2D axis.</param>
 22212
 22213    /// <param name="compare3">The delegate for comparing values along the 3D axis.</param>
 22214
 22215    /// <param name="compare4">The delegate for comparing values along the 4D axis.</param>
 22216
 22217    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 22218
 22219    /// <param name="subdivisionOverride2">The subdivision overide to be used when splitting the 2 dimension.</param>
 22220
 22221    /// <param name="subdivisionOverride3">The subdivision overide to be used when splitting the 3 dimension.</param>
 22222
 22223    /// <param name="subdivisionOverride4">The subdivision overide to be used when splitting the 4 dimension.</param>
 22224    public OmnitreeBoundsLinked(
 22225      Omnitree.GetBounds<T, Axis1, Axis2, Axis3, Axis4> getBounds,
 22226      Func<Axis1, Axis1, CompareResult> compare1 = null,
 22227      Func<Axis2, Axis2, CompareResult> compare2 = null,
 22228      Func<Axis3, Axis3, CompareResult> compare3 = null,
 22229      Func<Axis4, Axis4, CompareResult> compare4 = null,
 22230      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride1 = null
 22231,
 22232      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride2 = null
 22233,
 22234      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride3 = null
 22235,
 22236      Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride4 = null
 22237      )
 22238      : this(
 22239      getBounds,
 22240      compare1 is null ? true : false,
 22241      compare1 ?? Compare,
 22242      compare2 is null ? true : false,
 22243      compare2 ?? Compare,
 22244      compare3 is null ? true : false,
 22245      compare3 ?? Compare,
 22246      compare4 is null ? true : false,
 22247      compare4 ?? Compare,
 22248      subdivisionOverride1
 22249,
 22250      subdivisionOverride2
 22251,
 22252      subdivisionOverride3
 22253,
 22254      subdivisionOverride4
 22255      ) { }
 22256
 22257    /// <summary>Constructs a new 4D omnitree that stores bounds.</summary>
 22258    /// <param name="getBoundings">The delegate for getting object bounds in 4D space.</param>
 22259    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 22260    /// <param name="compare2">The delegate for comparing values along the 2D axis.</param>
 22261    /// <param name="compare3">The delegate for comparing values along the 3D axis.</param>
 22262    /// <param name="compare4">The delegate for comparing values along the 4D axis.</param>
 22263
 22264    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 22265
 22266    /// <param name="subdivisionOverride2">The subdivision overide to be used when splitting the 2 dimension.</param>
 22267
 22268    /// <param name="subdivisionOverride3">The subdivision overide to be used when splitting the 3 dimension.</param>
 22269
 22270    /// <param name="subdivisionOverride4">The subdivision overide to be used when splitting the 4 dimension.</param>
 22271    public OmnitreeBoundsLinked(
 22272      Omnitree.GetBoundings<T, Axis1, Axis2, Axis3, Axis4> getBoundings,
 22273      Func<Axis1, Axis1, CompareResult> compare1 = null,
 22274      Func<Axis2, Axis2, CompareResult> compare2 = null,
 22275      Func<Axis3, Axis3, CompareResult> compare3 = null,
 22276      Func<Axis4, Axis4, CompareResult> compare4 = null,
 22277      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride1 = null
 22278      , Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride2 = null
 22279      , Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride3 = null
 22280      , Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> subdivisionOverride4 = null
 22281      )
 22282      : this(
 22283      Omnitree.ConvertToGetBounds(getBoundings),
 22284      compare1 is null ? true : false,
 22285      compare1 ?? Compare,
 22286      compare2 is null ? true : false,
 22287      compare2 ?? Compare,
 22288      compare3 is null ? true : false,
 22289      compare3 ?? Compare,
 22290      compare4 is null ? true : false,
 22291      compare4 ?? Compare,
 22292      subdivisionOverride1
 22293,
 22294      subdivisionOverride2
 22295,
 22296      subdivisionOverride3
 22297,
 22298      subdivisionOverride4
 22299      ) { }
 22300
 22301    #endregion
 22302
 22303    #region Properties
 22304
 22305    /// <summary>The number of dimensions in this tree.</summary>
 22306    public int Dimensions => _dimensions;
 22307
 22308    /// <summary>The delegate being used by the omnitree to locate items in 4D space.</summary>
 22309    public Omnitree.GetBounds<T, Axis1
 22310      , Axis2
 22311      , Axis3
 22312      , Axis4
 22313      > GetBounds => _getBounds;
 22314
 22315
 22316    /// <summary>The comparison function the Omnitree is using along the 1D axis.</summary>
 22317    public Func<Axis1, Axis1, CompareResult> Compare1 => _compare1;
 22318    /// <summary>The comparison function the Omnitree is using along the 2D axis.</summary>
 22319    public Func<Axis2, Axis2, CompareResult> Compare2 => _compare2;
 22320    /// <summary>The comparison function the Omnitree is using along the 3D axis.</summary>
 22321    public Func<Axis3, Axis3, CompareResult> Compare3 => _compare3;
 22322    /// <summary>The comparison function the Omnitree is using along the 4D axis.</summary>
 22323    public Func<Axis4, Axis4, CompareResult> Compare4 => _compare4;
 22324
 22325    /// <summary>The current number of items in the tree.</summary>
 22326    public int Count  => _top.Count;
 22327
 22328    internal delegate void MaxDepthFinder(Node node, int current_depth, ref int max_depth);
 22329    /// <summary>Finds the current maximum depth of the tree. NOT AN O(1) OPERATION. Intended for educational purposes o
 22330    public int MaxDepth
 22331    {
 22332      get
 22333      {
 22334        MaxDepthFinder maxDepthFinder = null;
 22335        maxDepthFinder =
 22336            (Node node, int current_depth, ref int max_depth) =>
 22337            {
 22338              if (current_depth > max_depth)
 22339                max_depth = current_depth;
 22340              foreach (Node child in node.Children)
 22341                maxDepthFinder(child, current_depth + 1, ref max_depth);
 22342            };
 22343        int _max_depth = -1;
 22344        maxDepthFinder(this._top, 0, ref _max_depth);
 22345        return _max_depth;
 22346      }
 22347    }
 22348
 22349    internal delegate void NodeCountFinder(Node node, ref int current_count);
 22350    /// <summary>Counts the current number of nodes in the tree. NOT AN O(1) OPERATION. Intended for educational purpose
 22351    public int NodeCount
 22352    {
 22353      get
 22354      {
 22355        NodeCountFinder nodeCountFinder = null;
 22356        nodeCountFinder =
 22357            (Node node, ref int current_count) =>
 22358            {
 22359              current_count++;
 22360              foreach (Node child in node.Children)
 22361                nodeCountFinder(child, ref current_count);
 22362            };
 22363
 22364        int _current_count = 0;
 22365        nodeCountFinder(this._top, ref _current_count);
 22366        return _current_count;
 22367      }
 22368    }
 22369
 22370    #endregion
 22371
 22372    #region Methods
 22373
 22374    #region Add
 22375
 22376
 22377    #region single
 22378
 22379    /// <summary>Tries to add a value.</summary>
 22380    /// <param name="value">The value to be added.</param>
 22381    /// <returns>True if successful or false if not.</returns>
 22382    public (bool Success, Exception? Exception) TryAdd(T value)
 22383    {
 22384      Add(value);
 22385      return (true, null);
 22386    }
 22387
 22388    /// <summary>Adds an item to the tree.</summary>
 22389    /// <param name="addition">The item to be added.</param>
 22390    public void Add(T addition)
 22391    {
 22392      if (this._top.Count is int.MaxValue)
 22393        throw new System.InvalidOperationException("(Count is int.MaxValue) max Omnitree size reached (change ints to lo
 22394
 22395      // dynamic tree sizes
 22396      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 22397
 22398      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds = GetBoundings(addition);
 22399
 22400      // grow the first branch of the tree
 22401      if (!this._top.PointOfDivision.HasValue && this._top.Count >= _load)
 22402      {
 22403        Node top = this._top;
 22404
 22405        // create the new branch from the median values
 22406        this._top = new Node(DetermineMedians(top), Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>.None, null, -1);
 22407
 22408        // iterate through the values and add them to the appropriate children
 22409        for (Node.ValueNode list = top.Head; list is not null; list = list.Next)
 22410          Add(list.Value, this._top, GetBoundings(list.Value), 0);
 22411      }
 22412
 22413      this.Add(addition, this._top, bounds, 0);
 22414    }
 22415
 22416    /// <summary>Recursive version of the add function.</summary>
 22417    /// <param name="addition">The item to be added.</param>
 22418    /// <param name="node">The current node for tree trversal.</param>
 22419    /// <param name="bounds">The bounds of the addition.</param>
 22420    /// <param name="depth">The current depth of iteration.</param>
 22421    internal void Add(T addition, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds, int depth)
 22422    {
 22423      if (!node.PointOfDivision.HasValue)
 22424      {
 22425        //Leaf leaf = node as Leaf;
 22426        if (depth >= _load || !(node.Count >= _load))
 22427        {
 22428          node.Add(addition);
 22429          return;
 22430        }
 22431        else
 22432        {
 22433          //Node parent = node.Parent;
 22434          //int child_index = this.DetermineChildIndex(parent.PointOfDivision, location);
 22435          //Node growth = new Node(DetermineMedians(leaf), leaf.Bounds, parent, child_index);
 22436          //parent[child_index] = growth;
 22437
 22438          Node growth = new Node(DetermineMedians(node), node.Bounds, node.Parent, node.Index);
 22439          node.Parent[node.Index] = growth;
 22440
 22441          for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 22442          {
 22443            Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> temp_bounds = GetBoundings(list.Value);
 22444            if (EncapsulationCheck(growth.Bounds, temp_bounds))
 22445              Add(list.Value, growth, temp_bounds, depth);
 22446            else
 22447            {
 22448              ReduceParentCounts(node.Parent, 1);
 22449              Add(list.Value, this._top, temp_bounds, depth);
 22450            }
 22451          }
 22452
 22453          Add(addition, growth, bounds, depth);
 22454          return;
 22455        }
 22456      }
 22457      else
 22458      {
 22459        //Node branch = node as Node;
 22460        int child_index = this.DetermineChildIndex(node.PointOfDivision.Value, bounds); // determine the child "index" (
 22461
 22462        // if -1, then the bounds of the addition straddle the point of division (keep it in current node)
 22463        if (child_index is -1)
 22464        {
 22465          node.Add(addition);
 22466          return;
 22467        }
 22468
 22469        Node child_node = node[child_index];
 22470
 22471        // null children in branches are just empty leaves
 22472        if (child_node is null)
 22473        {
 22474          Node new_node = new Node(DetermineChildBounds(node, child_index), node, child_index);
 22475          node[child_index] = new_node;
 22476          new_node.Add(addition);
 22477        }
 22478        else
 22479          // child exists already, continue adding
 22480          Add(addition, child_node, bounds, depth + 1);
 22481
 22482        node.Count++;
 22483        return;
 22484      }
 22485    }
 22486
 22487    internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> DetermineMedians(Node node)
 22488    {
 22489      //try
 22490      //{
 22491        // extract the values
 22492        Omnitree.Bound<Axis1>[] values1 = new Omnitree.Bound<Axis1>[node.Count * 2];
 22493        Omnitree.Bound<Axis2>[] values2 = new Omnitree.Bound<Axis2>[node.Count * 2];
 22494        Omnitree.Bound<Axis3>[] values3 = new Omnitree.Bound<Axis3>[node.Count * 2];
 22495        Omnitree.Bound<Axis4>[] values4 = new Omnitree.Bound<Axis4>[node.Count * 2];
 22496        Node.ValueNode for_current = node.Head; // used in for loop
 22497        for (int i = 0; i < node.Count; i++, for_current = for_current.Next)
 22498          this._getBounds(for_current.Value,
 22499          out values1[i * 2], out values1[i * 2 + 1]
 22500,
 22501          out values2[i * 2], out values2[i * 2 + 1]
 22502,
 22503          out values3[i * 2], out values3[i * 2 + 1]
 22504,
 22505          out values4[i * 2], out values4[i * 2 + 1]
 22506          );
 22507        return new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4>(
 22508          Omnitree.SubDivide(values1, this._defaultCompare1 ? Compare : this._compare1)
 22509,
 22510          Omnitree.SubDivide(values2, this._defaultCompare2 ? Compare : this._compare2)
 22511,
 22512          Omnitree.SubDivide(values3, this._defaultCompare3 ? Compare : this._compare3)
 22513,
 22514          Omnitree.SubDivide(values4, this._defaultCompare4 ? Compare : this._compare4)
 22515          );
 22516      //}
 22517      //catch
 22518      //{
 22519        // extract the values
 22520      //  ArrayJagged<Omnitree.Bound<Axis1>> values1 = new ArrayJagged<Omnitree.Bound<Axis1>>(node.Count * 2);
 22521      //  ArrayJagged<Omnitree.Bound<Axis2>> values2 = new ArrayJagged<Omnitree.Bound<Axis2>>(node.Count * 2);
 22522      //  ArrayJagged<Omnitree.Bound<Axis3>> values3 = new ArrayJagged<Omnitree.Bound<Axis3>>(node.Count * 2);
 22523      //  ArrayJagged<Omnitree.Bound<Axis4>> values4 = new ArrayJagged<Omnitree.Bound<Axis4>>(node.Count * 2);
 22524      //  Node.ValueNode for_current = node.Head; // used in for loop
 22525      //  for (int i = 0; i < node.Count; i++, for_current = for_current.Next)
 22526      //  {
 22527      //    Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 22528      //    Omnitree.Bound<Axis2> min2; Omnitree.Bound<Axis2> max2;
 22529      //    Omnitree.Bound<Axis3> min3; Omnitree.Bound<Axis3> max3;
 22530      //    Omnitree.Bound<Axis4> min4; Omnitree.Bound<Axis4> max4;
 22531      //    this._getBounds(for_current.Value,
 22532      //      out min1, out max1
 22533//,
 22534      //      out min2, out max2
 22535//,
 22536      //      out min3, out max3
 22537//,
 22538      //      out min4, out max4
 22539      //      );
 22540      //    values1[i * 2] = min1; values1[i * 2 + 1] = max1;
 22541      //    values2[i * 2] = min2; values2[i * 2 + 1] = max2;
 22542      //    values3[i * 2] = min3; values3[i * 2 + 1] = max3;
 22543      //    values4[i * 2] = min4; values4[i * 2 + 1] = max4;
 22544      //  }
 22545      //  return new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4>(
 22546      //    Omnitree.SubDivide(values1, this._defaultCompare1 ? Compare : this._compare1)
 22547      //    , Omnitree.SubDivide(values2, this._defaultCompare2 ? Compare : this._compare2)
 22548      //    , Omnitree.SubDivide(values3, this._defaultCompare3 ? Compare : this._compare3)
 22549      //    , Omnitree.SubDivide(values4, this._defaultCompare4 ? Compare : this._compare4)
 22550      //  );
 22551      //}
 22552    }
 22553
 22554    #endregion
 22555
 22556    #region Add Helpers
 22557
 22558    internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> DetermineChildBounds(Node node, int child_index)
 22559    {
 22560      // the node parameter should always have a point of division value for this function
 22561      Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> pointOfDivision = node.PointOfDivision.Value;
 22562
 22563      Omnitree.Bound<Axis4> min4, max4;
 22564      if (child_index >= 8)
 22565      {
 22566        min4 = pointOfDivision.Axis4;
 22567        max4 = node.Bounds.Max4;
 22568        child_index -= 8;
 22569      }
 22570      else
 22571      {
 22572        min4 = node.Bounds.Min4;
 22573        max4 = pointOfDivision.Axis4;
 22574      }
 22575
 22576      Omnitree.Bound<Axis3> min3, max3;
 22577      if (child_index >= 4)
 22578      {
 22579        min3 = pointOfDivision.Axis3;
 22580        max3 = node.Bounds.Max3;
 22581        child_index -= 4;
 22582      }
 22583      else
 22584      {
 22585        min3 = node.Bounds.Min3;
 22586        max3 = pointOfDivision.Axis3;
 22587      }
 22588
 22589      Omnitree.Bound<Axis2> min2, max2;
 22590      if (child_index >= 2)
 22591      {
 22592        min2 = pointOfDivision.Axis2;
 22593        max2 = node.Bounds.Max2;
 22594        child_index -= 2;
 22595      }
 22596      else
 22597      {
 22598        min2 = node.Bounds.Min2;
 22599        max2 = pointOfDivision.Axis2;
 22600      }
 22601
 22602      Omnitree.Bound<Axis1> min1, max1;
 22603      if (child_index >= 1)
 22604      {
 22605        min1 = pointOfDivision.Axis1;
 22606        max1 = node.Bounds.Max1;
 22607        child_index -= 1;
 22608      }
 22609      else
 22610      {
 22611        min1 = node.Bounds.Min1;
 22612        max1 = pointOfDivision.Axis1;
 22613      }
 22614
 22615      return new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, min4, max4);
 22616    }
 22617
 22618    #endregion
 22619
 22620    #endregion
 22621
 22622    #region Clear
 22623
 22624    /// <summary>Returns the tree to an empty state.</summary>
 22625    public void Clear()
 22626    {
 22627      this._top = new Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>.None, null, -1);
 22628      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 22629    }
 22630
 22631    #endregion
 22632
 22633    #region Clone
 22634
 22635    /// <summary>Creates a shallow clone of this data structure.</summary>
 22636    /// <returns>A shallow clone of this data structure.</returns>
 22637    public OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3, Axis4> Clone()
 22638    {
 22639      return new OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3, Axis4>(this);
 22640    }
 22641
 22642    #endregion
 22643
 22644    #region Count
 22645
 22646    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 22647    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 22648    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 22649    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 22650    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 22651    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 22652    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 22653    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 22654    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 22655    /// <returns>The number of items in the provided sub space.</returns>
 22656    public int CountSubSpaceEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 m
 22657    {
 22658      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min
 22659    }
 22660    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 22661    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 22662    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 22663    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 22664    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 22665    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 22666    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 22667    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 22668    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 22669    /// <returns>The number of items in the provided sub space.</returns>
 22670    public int CountSubSpaceEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> m
 22671    {
 22672      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min
 22673    }
 22674    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 22675    /// <param name="axis1">The coordinate along the 1D axis.</param>
 22676    /// <param name="axis2">The coordinate along the 2D axis.</param>
 22677    /// <param name="axis3">The coordinate along the 3D axis.</param>
 22678    /// <param name="axis4">The coordinate along the 4D axis.</param>
 22679    /// <returns>The number of items in the provided sub space.</returns>
 22680    public int CountSubSpaceEncapsulated(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4)
 22681    {
 22682      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(axis1, axis1, axis2, axis2,
 22683    }
 22684    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 22685    /// <param name="axis1">The coordinate along the 1D axis.</param>
 22686    /// <param name="axis2">The coordinate along the 2D axis.</param>
 22687    /// <param name="axis3">The coordinate along the 3D axis.</param>
 22688    /// <param name="axis4">The coordinate along the 4D axis.</param>
 22689    /// <returns>The number of items in the provided sub space.</returns>
 22690    public int CountSubSpaceEncapsulated(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3>
 22691    {
 22692      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(axis1, axis1, axis2, axis2,
 22693    }
 22694
 22695    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 22696    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 22697    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 22698    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 22699    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 22700    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 22701    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 22702    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 22703    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 22704    /// <returns>The number of items in the provided sub space.</returns>
 22705    public int CountSubSpaceOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min
 22706    {
 22707      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3,
 22708    }
 22709    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 22710    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 22711    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 22712    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 22713    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 22714    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 22715    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 22716    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 22717    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 22718    /// <returns>The number of items in the provided sub space.</returns>
 22719    public int CountSubSpaceOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min
 22720    {
 22721      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3,
 22722    }
 22723    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 22724    /// <param name="axis1">The coordinate along the 1D axis.</param>
 22725    /// <param name="axis2">The coordinate along the 2D axis.</param>
 22726    /// <param name="axis3">The coordinate along the 3D axis.</param>
 22727    /// <param name="axis4">The coordinate along the 4D axis.</param>
 22728    /// <returns>The number of items in the provided sub space.</returns>
 22729    public int CountSubSpaceOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4)
 22730    {
 22731      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(axis1, axis1, axis2, axis2, a
 22732    }
 22733    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 22734    /// <param name="axis1">The coordinate along the 1D axis.</param>
 22735    /// <param name="axis2">The coordinate along the 2D axis.</param>
 22736    /// <param name="axis3">The coordinate along the 3D axis.</param>
 22737    /// <param name="axis4">The coordinate along the 4D axis.</param>
 22738    /// <returns>The number of items in the provided sub space.</returns>
 22739    public int CountSubSpaceOverlapped(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> a
 22740    {
 22741      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(axis1, axis1, axis2, axis2, a
 22742    }
 22743
 22744    internal int CountSubSpaceEncapsulated(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds)
 22745    {
 22746      return CountSubSpaceBase(_top, bounds, (a, b) => EncapsulationCheck(a, b));
 22747    }
 22748
 22749    internal int CountSubSpaceOverlapped(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds)
 22750    {
 22751      return CountSubSpaceBase(_top, bounds, (a, b) => InclusionCheck(a, b));
 22752    }
 22753
 22754    internal int CountSubSpaceBase(
 22755      Node node,
 22756      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds,
 22757      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> sp
 22758    {
 22759      // adjust min/max values
 22760      int count = 0;
 22761      if (EncapsulationCheck(bounds, node.Bounds))
 22762        count += node.Count;
 22763      else if (!node.PointOfDivision.HasValue)
 22764      {
 22765        for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 22766          if (spatialCheck(bounds, GetBoundings(list.Value)))
 22767            count++;
 22768      }
 22769      else
 22770      {
 22771        Node branch = node as Node;
 22772        if (!StraddlesLines(branch.Bounds, branch.PointOfDivision.Value))
 22773        {
 22774          int child_index = DetermineChildIndex(branch.PointOfDivision.Value, bounds);
 22775          Node child = branch[child_index];
 22776          if (child is not null)
 22777            count += this.CountSubSpaceBase(child, bounds, spatialCheck);
 22778        }
 22779        else
 22780        {
 22781          foreach (Node child in node.Children)
 22782            count += this.CountSubSpaceBase(child, bounds, spatialCheck);
 22783        }
 22784      }
 22785      return count;
 22786    }
 22787
 22788    #endregion
 22789
 22790    #region Update
 22791
 22792    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 22793    public void Update()
 22794    {
 22795      this.Update(this._top, 0);
 22796    }
 22797
 22798    /// <summary>Recursive version of the Update method.</summary>
 22799    /// <param name="node">The current node of iteration.</param>
 22800    /// <param name="depth">The current depth of iteration.</param>
 22801    internal int Update(Node node, int depth)
 22802    {
 22803      int removals = 0;
 22804
 22805      {
 22806        Node branch = node as Node;
 22807        int skipped = 0;
 22808        for (int i = 0; i + skipped < branch.Children.Length; )
 22809        {
 22810          removals += this.Update(branch.Children[i], depth + 1);
 22811          if (branch.Children[i].Count is 0)
 22812            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 22813          else
 22814            i++;
 22815        }
 22816        Node[] newArray = new Node[branch.Children.Length - skipped];
 22817        Array.Copy(branch.Children, newArray, newArray.Length);
 22818        branch.Children = newArray;
 22819
 22820        if (branch.Count < _load && branch.Count != 0)
 22821          ShrinkChild(branch.Parent, branch.Index);
 22822      }
 22823
 22824      {
 22825        Node.ValueNode current = node.Head;
 22826        Node.ValueNode previous = null;
 22827        while (current is not null)
 22828        {
 22829          Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds = GetBoundings(current.Value);
 22830          if (!this.EncapsulationCheck(node.Bounds, bounds))
 22831          {
 22832            removals++;
 22833            T updated = current.Value;
 22834            if (previous is null)
 22835            {
 22836              node.Head = current.Next;
 22837              goto HeadRemoved;
 22838            }
 22839            else
 22840              previous.Next = current.Next;
 22841
 22842            Node whereToAdd = GetEncapsulationParent(node.Parent, bounds);
 22843
 22844            if (whereToAdd is null)
 22845              throw new System.Exception("an item was updated outside the range of the omnitree");
 22846
 22847            this.Add(updated, whereToAdd, bounds, whereToAdd.Depth);
 22848          }
 22849          previous = current;
 22850        HeadRemoved:
 22851          current = current.Next;
 22852        }
 22853      }
 22854
 22855      node.Count -= removals;
 22856      return removals;
 22857    }
 22858
 22859    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 22860    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 22861    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 22862    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 22863    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 22864    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 22865    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 22866    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 22867    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 22868    public void Update(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4)
 22869    {
 22870      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, min4, max4), this.
 22871    }
 22872    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 22873    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 22874    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 22875    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 22876    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 22877    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 22878    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 22879    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 22880    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 22881    public void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 22882    {
 22883      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, min4, max4), this.
 22884    }
 22885    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 22886    /// <param name="axis1">The coordinate along the 1D axis.</param>
 22887    /// <param name="axis2">The coordinate along the 2D axis.</param>
 22888    /// <param name="axis3">The coordinate along the 3D axis.</param>
 22889    /// <param name="axis4">The coordinate along the 4D axis.</param>
 22890    public void Update(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4)
 22891    {
 22892      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(axis1, axis1, axis2, axis2, axis3, axis3, axis4, axis4
 22893    }
 22894    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 22895    /// <param name="axis1">The coordinate along the 1D axis.</param>
 22896    /// <param name="axis2">The coordinate along the 2D axis.</param>
 22897    /// <param name="axis3">The coordinate along the 3D axis.</param>
 22898    /// <param name="axis4">The coordinate along the 4D axis.</param>
 22899    public void Update(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3, Omnitree.B
 22900    {
 22901      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(axis1, axis1, axis2, axis2, axis3, axis3, axis4, axis4
 22902    }
 22903    internal int Update(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds, Node node, int depth)
 22904    {
 22905      if (!InclusionCheck(bounds, node.Bounds))
 22906        return 0;
 22907
 22908      int removals = 0;
 22909
 22910      {
 22911        Node branch = node as Node;
 22912        int skipped = 0;
 22913        for (int i = 0; i + skipped < branch.Children.Length; )
 22914        {
 22915          removals += this.Update(branch.Children[i], depth + 1);
 22916          if (branch.Children[i].Count is 0)
 22917            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 22918          else
 22919            i++;
 22920        }
 22921        Node[] newArray = new Node[branch.Children.Length - skipped];
 22922        Array.Copy(branch.Children, newArray, newArray.Length);
 22923        branch.Children = newArray;
 22924
 22925        if (branch.Count < _load && branch.Count != 0)
 22926          ShrinkChild(branch.Parent, branch.Index);
 22927      }
 22928
 22929      {
 22930        Node.ValueNode current = node.Head;
 22931        Node.ValueNode previous = null;
 22932        while (current is not null)
 22933        {
 22934          Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> item_bounds = GetBoundings(current.Value);
 22935          if (!this.EncapsulationCheck(node.Bounds, item_bounds))
 22936          {
 22937            removals++;
 22938            T updated = current.Value;
 22939            if (previous is null)
 22940            {
 22941              node.Head = current.Next;
 22942              goto HeadRemoved;
 22943            }
 22944            else
 22945              previous.Next = current.Next;
 22946            Node whereToAdd = GetEncapsulationParent(node.Parent, item_bounds);
 22947            if (whereToAdd is null)
 22948              throw new System.Exception("an item was updates outside the range of the omnitree");
 22949            this.Add(updated, whereToAdd, item_bounds, whereToAdd.Depth);
 22950          }
 22951          previous = current;
 22952        HeadRemoved:
 22953          current = current.Next;
 22954        }
 22955      }
 22956
 22957      node.Count -= removals;
 22958      return removals;
 22959    }
 22960
 22961    #endregion
 22962
 22963    #region Remove
 22964
 22965    /// <summary>Removes all the items qualified by the delegate.</summary>
 22966    /// <param name="where">The predicate to qualify removals.</param>
 22967    public void Remove(Predicate<T> where)
 22968    {
 22969      this.Remove(this._top, where);
 22970      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 22971    }
 22972
 22973    /// <summary>Recursive version of the remove method.</summary>
 22974    /// <param name="node">The current node of traversal.</param>
 22975    /// <param name="where">The predicate to qualify removals.</param>
 22976    internal int Remove(Node node, Predicate<T> where)
 22977    {
 22978      int removals = 0;
 22979
 22980      // children
 22981      if (node.Children is not null)
 22982      {
 22983        int skipped = 0;
 22984        for (int i = 0; i + skipped < node.Children.Length; )
 22985        {
 22986          removals += this.Remove(node.Children[i], where);
 22987          if (node.Children[i].Count is 0)
 22988            node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 22989          else
 22990            i++;
 22991        }
 22992        Node[] newArray = new Node[node.Children.Length - skipped];
 22993        Array.Copy(node.Children, newArray, newArray.Length);
 22994        node.Children = newArray;
 22995
 22996        if (node.Count < _load && node.Count != 0)
 22997          ShrinkChild(node.Parent, node.Index);
 22998      }
 22999
 23000      // items
 23001      while (node.Head is not null && where(node.Head.Value))
 23002      {
 23003        node.Head = node.Head.Next;
 23004        removals++;
 23005      }
 23006      if (node.Head is not null)
 23007      {
 23008        Node.ValueNode list = node.Head;
 23009        while (list.Next is not null)
 23010        {
 23011          if (where(list.Next.Value))
 23012          {
 23013            list.Next = list.Next.Next;
 23014            removals++;
 23015          }
 23016        }
 23017      }
 23018
 23019      node.Count -= removals;
 23020      return removals;
 23021    }
 23022
 23023    /// <summary>Removes all the items encapsulated in a given space.</summary>
 23024    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23025    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23026    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23027    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23028    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23029    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23030    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23031    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23032    /// <returns>The number of items that were removed.</returns>
 23033    public void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, A
 23034    {
 23035      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, m
 23036    }
 23037    /// <summary>Removes all the items encapsulated in a given space.</summary>
 23038    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23039    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23040    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23041    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23042    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23043    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23044    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23045    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23046    /// <returns>The number of items that were removed.</returns>
 23047    public void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, O
 23048    {
 23049      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, m
 23050    }
 23051    /// <summary>Removes all the items encapsulated in a given space.</summary>
 23052    /// <param name="axis1">The coordinate along the 1D axis.</param>
 23053    /// <param name="axis2">The coordinate along the 2D axis.</param>
 23054    /// <param name="axis3">The coordinate along the 3D axis.</param>
 23055    /// <param name="axis4">The coordinate along the 4D axis.</param>
 23056    public void RemoveEncapsulated(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3
 23057    {
 23058      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(axis1, axis1, axis2, axis2, axi
 23059    }
 23060    internal int RemoveEncapsulated(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds)
 23061    {
 23062      int removals = this.RemoveBase(node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 23063      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 23064      return removals;
 23065    }
 23066
 23067    /// <summary>Removes all the items overlapping a given space.</summary>
 23068    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23069    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23070    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23071    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23072    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23073    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23074    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23075    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23076    /// <returns>The number of items that were removed.</returns>
 23077    public void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axi
 23078    {
 23079      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max
 23080    }
 23081    /// <summary>Removes all the items overlapping a given space.</summary>
 23082    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23083    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23084    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23085    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23086    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23087    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23088    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23089    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23090    /// <returns>The number of items that were removed.</returns>
 23091    public void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omn
 23092    {
 23093      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max
 23094    }
 23095    internal int RemoveOverlapped(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds)
 23096    {
 23097      int removals = this.RemoveBase(node, bounds, (a, b) => this.InclusionCheck(a, b));
 23098      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 23099      return removals;
 23100    }
 23101
 23102    internal int RemoveBase(
 23103      Node node,
 23104      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds,
 23105      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> sp
 23106    {
 23107      int removals = 0;
 23108      if (InclusionCheck(bounds, node.Bounds))
 23109      {
 23110        // items
 23111        Node.ValueNode current_node = node.Head;
 23112        Node.ValueNode previous_node = null;
 23113        while (!(current_node is null))
 23114        {
 23115          Node.ValueNode temp_previous = current_node;
 23116          if (spatialCheck(bounds, GetBoundings(current_node.Value)))
 23117          {
 23118            removals++;
 23119            if (current_node == node.Head)
 23120              node.Head = node.Head.Next;
 23121            else
 23122            {
 23123              previous_node.Next = current_node.Next;
 23124              temp_previous = previous_node;
 23125            }
 23126          }
 23127          previous_node = temp_previous;
 23128          current_node = current_node.Next;
 23129        }
 23130
 23131        // children
 23132        if (node.Children is not null)
 23133        {
 23134          int skipped = 0;
 23135          for (int i = 0; i + skipped < node.Children.Length; )
 23136          {
 23137            removals += this.RemoveBase(node.Children[i], bounds, spatialCheck);
 23138            if (node.Children[i].Count is 0)
 23139              node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 23140            else
 23141              i++;
 23142          }
 23143          Node[] newArray = new Node[node.Children.Length - skipped];
 23144          Array.Copy(node.Children, newArray, newArray.Length);
 23145          node.Children = newArray;
 23146
 23147          // convert this branch back into a leaf
 23148          // Note: if count is zero, it will be chopped off
 23149          if (node.Count < _load && node.Count > 0)
 23150            ShrinkChild(node.Parent, node.Index);
 23151        }
 23152      }
 23153
 23154      node.Count -= removals;
 23155      return removals;
 23156    }
 23157
 23158    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 23159    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23160    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23161    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23162    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23163    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23164    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23165    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23166    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23167    /// <param name="where">The equality constraint of the removal.</param>
 23168    public void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, A
 23169    {
 23170      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, m
 23171    }
 23172    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 23173    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23174    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23175    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23176    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23177    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23178    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23179    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23180    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23181    /// <param name="where">The equality constraint of the removal.</param>
 23182    public void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, O
 23183    {
 23184      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, m
 23185    }
 23186    internal int RemoveEncapsulated(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds, Predicate<T> where)
 23187    {
 23188      int removals = RemoveBase(node, bounds, where, (a, b) => this.EncapsulationCheck(a, b));
 23189      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 23190      return removals;
 23191    }
 23192
 23193    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 23194    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23195    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23196    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23197    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23198    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23199    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23200    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23201    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23202    /// <param name="where">The equality constraint of the removal.</param>
 23203    public void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axi
 23204    {
 23205      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max
 23206    }
 23207    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 23208    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23209    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23210    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23211    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23212    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23213    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23214    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23215    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23216    /// <param name="where">The equality constraint of the removal.</param>
 23217    public void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omn
 23218    {
 23219      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max
 23220    }
 23221    internal int RemoveOverlapped(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds, Predicate<T> where)
 23222    {
 23223      int removals = RemoveBase(node, bounds, where, (a, b) => this.InclusionCheck(a, b));
 23224      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 23225      return removals;
 23226    }
 23227
 23228    internal int RemoveBase(
 23229      Node node,
 23230      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds,
 23231      Predicate<T> where,
 23232      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> sp
 23233    {
 23234      if (!InclusionCheck(node.Bounds, bounds))
 23235        return 0;
 23236      int removals = 0;
 23237
 23238      // items
 23239      Node.ValueNode current = node.Head;
 23240      Node.ValueNode previous = null;
 23241      while (current is not null)
 23242      {
 23243        if (spatialCheck(bounds, GetBoundings(current.Value)) && where(current.Value))
 23244        {
 23245          removals++;
 23246          if (previous is null)
 23247          {
 23248            node.Head = current.Next;
 23249            goto HeadRemoved;
 23250          }
 23251          else
 23252            previous.Next = current.Next;
 23253        }
 23254        previous = current;
 23255      HeadRemoved:
 23256        current = current.Next;
 23257      }
 23258
 23259      // children
 23260      if (node.Children is not null)
 23261      {
 23262        int skipped = 0;
 23263        for (int i = 0; i + skipped < node.Children.Length; )
 23264        {
 23265          removals += this.RemoveBase(node.Children[i], bounds, where, spatialCheck);
 23266          if (node.Children[i].Count is 0)
 23267            node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 23268          else
 23269            i++;
 23270        }
 23271        Node[] newArray = new Node[node.Children.Length - skipped];
 23272        Array.Copy(node.Children, newArray, newArray.Length);
 23273        node.Children = newArray;
 23274
 23275        if (node.Count < _load && node.Count != 0)
 23276          ShrinkChild(node.Parent, node.Index);
 23277      }
 23278
 23279      node.Count -= removals;
 23280      return removals;
 23281    }
 23282
 23283    /// <summary>Tries to remove a value.</summary>
 23284    /// <param name="value">The value to remove.</param>
 23285    /// <returns>True if successful or false if not.</returns>
 23286    public (bool Success, Exception? Exception) TryRemove(T value)
 23287    {
 23288      Remove(value);
 23289      return (true, null);
 23290    }
 23291
 23292    /// <summary>Removes all instances of a given value.</summary>
 23293    public void Remove(T removal) => Omnitree.Remove(this, removal);
 23294
 23295    /// <summary>Removes all instances of a given value.</summary>
 23296    public void Remove(T removal, Func<T, T, bool> equate) => Omnitree.Remove(this, removal, equate);
 23297
 23298    /// <summary>Removes all the items in a given space.</summary>
 23299    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 23300    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 23301    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 23302    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 23303    /// <returns>The number of items that were removed.</returns>
 23304    public void RemoveOverlapped(Axis1 axis1
 23305      , Axis2 axis2
 23306      , Axis3 axis3
 23307      , Axis4 axis4
 23308      )
 23309    {
 23310      this.RemoveOverlapped(axis1, axis1
 23311        , axis2, axis2
 23312        , axis3, axis3
 23313        , axis4, axis4
 23314        );
 23315      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 23316    }
 23317
 23318    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 23319    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 23320    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 23321    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 23322    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 23323    /// <param name="where">The equality constraint of the removal.</param>
 23324    public void RemoveOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Predicate<T> where)
 23325    {
 23326      this.RemoveOverlapped(axis1, axis1
 23327        , axis2, axis2
 23328        , axis3, axis3
 23329        , axis4, axis4
 23330        , where);
 23331      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 23332    }
 23333
 23334    #endregion
 23335
 23336    #region Stepper And IEnumerable
 23337
 23338    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 23339    /// <param name="step">The delegate to perform on every item in the tree.</param>
 23340    public void Stepper(Action<T> step) =>
 23341      this.Stepper(step, this._top);
 23342
 23343    internal void Stepper(Action<T> step, Node node)
 23344    {
 23345      Node.ValueNode list = node.Head;
 23346      while (list is not null)
 23347      {
 23348        step(list.Value);
 23349        list = list.Next;
 23350      }
 23351      if (node.Children is not null)
 23352        foreach (Node child in node.Children)
 23353          this.Stepper(step, child);
 23354    }
 23355
 23356    public StepStatus StepperBreak<TStep>(TStep step = default)
 23357      where TStep : struct, IFunc<T, StepStatus> =>
 23358      StepperBreak(_top, step);
 23359
 23360    internal StepStatus StepperBreak<TStep>(Node node, TStep step)
 23361      where TStep : struct, IFunc<T, StepStatus>
 23362    {
 23363      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 23364      {
 23365        if (step.Invoke(list.Value) is Break) return Break;
 23366      }
 23367      if (node.Children is not null)
 23368      {
 23369        foreach (Node child in node.Children)
 23370        {
 23371          if (StepperBreak(child, step) is Break) return Break;
 23372        }
 23373      }
 23374      return Continue;
 23375    }
 23376
 23377    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 23378    /// <param name="step">The delegate to perform on every item in the tree.</param>
 23379    public StepStatus Stepper(Func<T, StepStatus> step) =>
 23380      Stepper(step, _top);
 23381
 23382    internal StepStatus Stepper(Func<T, StepStatus> step, Node node)
 23383    {
 23384      StepStatus status = StepStatus.Continue;
 23385
 23386      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 23387        if ((status = step(list.Value)) != StepStatus.Continue)
 23388          break;
 23389
 23390      if (node.Children is not null)
 23391        foreach (Node child in node.Children)
 23392          if ((status = Stepper(step, child)) != StepStatus.Continue)
 23393            break;
 23394
 23395      return status;
 23396    }
 23397
 23398    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 23399    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 23400    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23401    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23402    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23403    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23404    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23405    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23406    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23407    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23408    public void StepperEncapsulated(Action<T> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 ma
 23409      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3
 23410
 23411    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 23412    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 23413    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23414    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23415    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23416    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23417    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23418    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23419    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23420    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23421    public void StepperEncapsulated(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bou
 23422      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3
 23423
 23424    internal void StepperEncapsulated(Action<T> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds) =>
 23425      StepperBase(step, node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 23426
 23427    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 23428    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 23429    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23430    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23431    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23432    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23433    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23434    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23435    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23436    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23437    public void StepperOverlapped(Action<T> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3
 23438      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, 
 23439
 23440    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 23441    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 23442    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23443    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23444    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23445    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23446    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23447    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23448    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23449    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23450    public void StepperOverlapped(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound
 23451      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, 
 23452
 23453    internal void StepperOverlapped(Action<T> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds) =>
 23454      StepperBase(step, node, bounds, (a, b) => this.InclusionCheck(a, b));
 23455
 23456    internal void StepperBase(
 23457      Action<T> step,
 23458      Node node,
 23459      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds,
 23460      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> sp
 23461    {
 23462      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 23463        if (spatialCheck(bounds, GetBoundings(list.Value)))
 23464          step(list.Value);
 23465
 23466      if (node.Children is not null)
 23467      {
 23468        foreach (Node child in node.Children)
 23469          // optimization: stop bounds checking if space encapsulates node
 23470          if (EncapsulationCheck(bounds, child.Bounds))
 23471            this.Stepper(step, child);
 23472          else if (InclusionCheck(child.Bounds, bounds))
 23473            this.StepperBase(step, child, bounds, spatialCheck);
 23474      }
 23475    }
 23476
 23477    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 23478    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 23479    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23480    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23481    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23482    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23483    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23484    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23485    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23486    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23487    public StepStatus StepperEncapsulated(Func<T, StepStatus> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis
 23488      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3
 23489
 23490    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 23491    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 23492    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23493    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23494    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23495    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23496    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23497    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23498    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23499    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23500    public StepStatus StepperEncapsulated(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> ma
 23501      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3
 23502
 23503    internal StepStatus StepperEncapsulated(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Ax
 23504      StepperBase(step, node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 23505
 23506    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 23507    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 23508    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23509    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23510    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23511    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23512    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23513    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23514    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23515    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23516    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 
 23517      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, 
 23518
 23519    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 23520    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 23521    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23522    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23523    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23524    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23525    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23526    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23527    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23528    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23529    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1
 23530      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(min1, max1, min2, max2, min3, max3, 
 23531
 23532    internal StepStatus StepperOverlapped(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis
 23533      StepperBase(step, node, bounds, (a, b) => this.InclusionCheck(a, b));
 23534
 23535    internal StepStatus StepperBase(
 23536      Func<T, StepStatus> step,
 23537      Node node,
 23538      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds,
 23539      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>> sp
 23540    {
 23541      StepStatus status = StepStatus.Continue;
 23542
 23543      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 23544        if (spatialCheck(bounds, GetBoundings(list.Value)) &&
 23545          (status = step(list.Value)) != StepStatus.Continue)
 23546          break;
 23547
 23548      if (node.Children is not null)
 23549      {
 23550        foreach (Node child in node.Children)
 23551          // optimization: stop bounds checking if space encapsulates node
 23552          if (EncapsulationCheck(bounds, child.Bounds) &&
 23553            (status = this.Stepper(step, child)) != StepStatus.Continue)
 23554            break;
 23555          else if (InclusionCheck(child.Bounds, bounds) &&
 23556            (status = this.StepperBase(step, child, bounds, spatialCheck)) != StepStatus.Continue)
 23557            break;
 23558      }
 23559
 23560      return status;
 23561    }
 23562
 23563    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 23564    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 23565    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 23566    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 23567    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 23568    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 23569    public void StepperOverlapped(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4) =>
 23570      StepperOverlapped(step, this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(axis1, axis1
 23571        , axis2, axis2
 23572        , axis3, axis3
 23573        , axis4, axis4
 23574      ));
 23575
 23576    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 23577    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 23578    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 23579    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 23580    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 23581    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 23582    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4) =>
 23583      StepperOverlapped(step, this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(axis1, axis1
 23584        , axis2, axis2
 23585        , axis3, axis3
 23586        , axis4, axis4
 23587        ));
 23588
 23589    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 23590
 23591    public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 23592    {
 23593      // Note: this can be optimized.
 23594      IList<T> list = new ListLinked<T>();
 23595      Stepper(x => list.Add(x));
 23596      return list.GetEnumerator();
 23597    }
 23598
 23599    #endregion
 23600
 23601    /// <inheritdoc/>
 23602    public T[] ToArray() => throw new NotImplementedException();
 23603
 23604    #region Helpers
 23605
 23606    internal bool StraddlesLines(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds, Omnitree.Vector<Axis1, Axis2, Axis3
 23607      Omnitree.StraddlesLines(bounds, vector
 23608        , _compare1
 23609        , _compare2
 23610        , _compare3
 23611        , _compare4
 23612        );
 23613
 23614    /// <summary>Computes the child index that contains the desired dimensions.</summary>
 23615    /// <param name="pointOfDivision">The point of division to compare against.</param>
 23616    /// <param name="bounds">The dimensions to determine the child index.</param>
 23617    /// <returns>The computed child index based on the coordinates relative to the center of the node.</returns>
 23618    internal int DetermineChildIndex(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> pointOfDivision, Omnitree.Bounds<Axis1,
 23619    {
 23620      // make sure a child encapsulates the bounds (otherwise the bounds cannot move down the tree)
 23621      if (StraddlesLines(bounds, pointOfDivision))
 23622        return -1;
 23623
 23624      int child = 0;
 23625      if (!bounds.Min1.Exists || !(this._compare1(bounds.Min1.Value, pointOfDivision.Axis1) is Less))
 23626        child += 1 << 0;
 23627      if (!bounds.Min2.Exists || !(this._compare2(bounds.Min2.Value, pointOfDivision.Axis2) is Less))
 23628        child += 1 << 1;
 23629      if (!bounds.Min3.Exists || !(this._compare3(bounds.Min3.Value, pointOfDivision.Axis3) is Less))
 23630        child += 1 << 2;
 23631      if (!bounds.Min4.Exists || !(this._compare4(bounds.Min4.Value, pointOfDivision.Axis4) is Less))
 23632        child += 1 << 3;
 23633      return child;
 23634    }
 23635
 23636    /// <summary>Converts a branch back into a leaf when the count is reduced.</summary>
 23637    /// <param name="parent">The parent to shrink a child of.</param>
 23638    /// <param name="child_index">The index of the child to shrink.</param>
 23639    internal void ShrinkChild(Node parent, int child_index)
 23640    {
 23641      Node leaf;
 23642      Node removal = null;
 23643      if (parent is null) // top of tree
 23644      {
 23645        removal = this._top;
 23646        leaf = new Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>.None, null, -1);
 23647        this._top = leaf;
 23648      }
 23649      else // non-top branch
 23650      {
 23651        removal = parent[child_index];
 23652        leaf = new Node(removal.Bounds, removal.Parent, removal.Index);
 23653        parent[child_index] = leaf;
 23654      }
 23655
 23656      this.Stepper((T step) => { leaf.Add(step); }, removal);
 23657    }
 23658
 23659    /// <summary>Reduces the counts of all the parents of a given node by a given amount.</summary>
 23660    /// <param name="parent">The starting parent of the reduction.</param>
 23661    /// <param name="reduction">The amount to reduce the parent counts by.</param>
 23662    internal void ReduceParentCounts(Node parent, int reduction)
 23663    {
 23664      IncreaseParentCounts(parent, -reduction);
 23665    }
 23666
 23667    /// <summary>Increases the counts of all the parents of a given node by a given amount.</summary>
 23668    /// <param name="parent">The starting parent of the increase.</param>
 23669    /// <param name="increase">The amount to increase the parent counts by.</param>
 23670    internal void IncreaseParentCounts(Node parent, int increase)
 23671    {
 23672      Node node = parent;
 23673      while (node is not null)
 23674      {
 23675        node.Count += increase;
 23676        node = node.Parent;
 23677      }
 23678    }
 23679
 23680    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 23681    /// <returns>True if the spaces overlap; False if not.</returns>
 23682    internal bool InclusionCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> a, Omnitree.Bounds<Axis1, Axis2, Axis3, Axi
 23683      Omnitree.InclusionCheck(a, b
 23684      , _compare1
 23685      , _compare2
 23686      , _compare3
 23687      , _compare4
 23688      );
 23689
 23690    /// <summary>Checks if a space encapsulates a point.</summary>
 23691    /// <returns>True if the space encapsulates the point; False if not.</returns>
 23692    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds, Omnitree.Vector<Axis1, Axis2, A
 23693      Omnitree.EncapsulationCheck(bounds, vector
 23694      , _compare1
 23695      , _compare2
 23696      , _compare3
 23697      , _compare4
 23698      );
 23699
 23700    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 23701    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 23702    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> a, Omnitree.Bounds<Axis1, Axis2, Axis3,
 23703      Omnitree.EncapsulationCheck(a, b
 23704      , _compare1
 23705      , _compare2
 23706      , _compare3
 23707      , _compare4
 23708      );
 23709
 23710    /// <summary>Checks for equality between two locations.</summary>
 23711    /// <returns>True if equal; False if not;</returns>
 23712    internal bool EqualsCheck(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4> a, Omnitree.Vector<Axis1, Axis2, Axis3, Axis4>
 23713      Omnitree.EqualsCheck(a, b
 23714      , (a, b) => _compare1(a, b) is Equal
 23715      , (a, b) => _compare2(a, b) is Equal
 23716      , (a, b) => _compare3(a, b) is Equal
 23717      , (a, b) => _compare4(a, b) is Equal
 23718      );
 23719
 23720    /// <summary>Gets the nearest parent that encapsulates a location.</summary>
 23721    /// <param name="node">The starting node to find the encapsulating parent of the location.</param>
 23722    /// <param name="bounds">The bounds to get the encapsulating parent from.</param>
 23723    /// <returns>The nearest node that encapsulates the given location.</returns>
 23724    internal Node GetEncapsulationParent(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> bounds)
 23725    {
 23726      while (node is not null && !EncapsulationCheck(node.Bounds, bounds))
 23727      {
 23728        node = node.Parent;
 23729      }
 23730      return node;
 23731    }
 23732
 23733    internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4> GetBoundings(T value)
 23734    {
 23735      Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 23736      Omnitree.Bound<Axis2> min2; Omnitree.Bound<Axis2> max2;
 23737      Omnitree.Bound<Axis3> min3; Omnitree.Bound<Axis3> max3;
 23738      Omnitree.Bound<Axis4> min4; Omnitree.Bound<Axis4> max4;
 23739      this._getBounds(value,
 23740        out min1, out max1
 23741,
 23742        out min2, out max2
 23743,
 23744        out min3, out max3
 23745,
 23746        out min4, out max4
 23747        );
 23748      return new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4>(
 23749        min1, max1
 23750,
 23751        min2, max2
 23752,
 23753        min3, max3
 23754,
 23755        min4, max4
 23756        );
 23757    }
 23758
 23759    #endregion
 23760
 23761    #endregion
 23762  }
 23763
 23764  #endregion
 23765
 23766  #region 5 Dimensional
 23767
 23768  /// <summary>Inheritance base for 5D omnitrees that store bounds.</summary>
 23769  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 23770  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 23771  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 23772  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 23773  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 23774  /// <typeparam name="Axis5">The type 5D axis.</typeparam>
 23775  public interface IOmnitreeBounds<T, Axis1, Axis2, Axis3, Axis4, Axis5> : IOmnitree<T, Axis1, Axis2, Axis3, Axis4, Axis
 23776  {
 23777    #region Properties
 23778
 23779    /// <summary>The number of dimensions in this tree.</summary>
 23780    int Dimensions { get; }
 23781
 23782    /// <summary>The delegate being used by the omnitree to get the bounds of values in 5D space.</summary>
 23783    Omnitree.GetBounds<T, Axis1
 23784, Axis2
 23785, Axis3
 23786, Axis4
 23787, Axis5
 23788      > GetBounds { get; }
 23789
 23790    #endregion
 23791
 23792    #region Methods
 23793
 23794    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 23795    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23796    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23797    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23798    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23799    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23800    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23801    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23802    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23803    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 23804    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 23805    /// <returns>The number of items in the provided sub space.</returns>
 23806    int CountSubSpaceEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Ax
 23807
 23808    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 23809    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23810    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23811    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23812    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23813    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23814    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23815    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23816    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23817    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 23818    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 23819    /// <returns>The number of items in the provided sub space.</returns>
 23820    int CountSubSpaceOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis
 23821
 23822    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 23823    void Update();
 23824    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 23825    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23826    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23827    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23828    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23829    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23830    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23831    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23832    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23833    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 23834    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 23835    void Update(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4, Axis5 mi
 23836
 23837    /// <summary>Removes all the items in a given space.</summary>
 23838    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23839    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23840    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23841    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23842    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23843    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23844    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23845    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23846    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 23847    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 23848    void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 ma
 23849    /// <summary>Removes all the items in a given space.</summary>
 23850    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23851    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23852    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23853    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23854    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23855    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23856    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23857    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23858    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 23859    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 23860    void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree
 23861    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 23862    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23863    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23864    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23865    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23866    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23867    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23868    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23869    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23870    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 23871    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 23872    /// <param name="where">The predicate constraint of the removal.</param>
 23873    void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 ma
 23874    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 23875    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23876    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23877    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23878    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23879    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23880    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23881    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23882    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23883    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 23884    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 23885    /// <param name="where">The predicate constraint of the removal.</param>
 23886    void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree
 23887
 23888    /// <summary>Removes all the items in a given space.</summary>
 23889    /// <param name="axis1">The coordinate along the 1D axis.</param>
 23890    /// <param name="axis2">The coordinate along the 2D axis.</param>
 23891    /// <param name="axis3">The coordinate along the 3D axis.</param>
 23892    /// <param name="axis4">The coordinate along the 4D axis.</param>
 23893    /// <param name="axis5">The coordinate along the 5D axis.</param>
 23894    void RemoveOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5);
 23895    /// <summary>Removes all the items in a given space.</summary>
 23896    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23897    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23898    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23899    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23900    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23901    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23902    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23903    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23904    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 23905    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 23906    void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4
 23907    /// <summary>Removes all the items in a given space.</summary>
 23908    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23909    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23910    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23911    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23912    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23913    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23914    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23915    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23916    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 23917    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 23918    void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.B
 23919    /// <summary>Removes all the items in a given space where equality is met.</summary>
 23920    /// <param name="axis1">The coordinate along the 1D axis.</param>
 23921    /// <param name="axis2">The coordinate along the 2D axis.</param>
 23922    /// <param name="axis3">The coordinate along the 3D axis.</param>
 23923    /// <param name="axis4">The coordinate along the 4D axis.</param>
 23924    /// <param name="axis5">The coordinate along the 5D axis.</param>
 23925    /// <param name="where">The equality constraint of the removal.</param>
 23926    void RemoveOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Predicate<T> where);
 23927    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 23928    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23929    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23930    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23931    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23932    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23933    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23934    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23935    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23936    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 23937    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 23938    /// <param name="where">The predicate constraint of the removal.</param>
 23939    void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4
 23940    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 23941    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23942    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23943    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23944    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23945    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23946    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23947    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23948    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23949    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 23950    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 23951    /// <param name="where">The predicate constraint of the removal.</param>
 23952    void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.B
 23953
 23954    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 23955    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 23956    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23957    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23958    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23959    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23960    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23961    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23962    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23963    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23964    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 23965    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 23966    void StepperEncapsulated(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis
 23967    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 23968    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 23969    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23970    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23971    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23972    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23973    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23974    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23975    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23976    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23977    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 23978    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 23979    StepStatus StepperEncapsulated(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omn
 23980
 23981    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 23982    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 23983    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23984    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23985    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23986    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 23987    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 23988    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 23989    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 23990    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 23991    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 23992    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 23993    void StepperOverlapped(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2>
 23994    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 23995    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 23996    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 23997    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 23998    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 23999    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 24000    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 24001    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 24002    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 24003    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 24004    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 24005    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 24006    StepStatus StepperOverlapped(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnit
 24007
 24008    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 24009    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 24010    /// <param name="axis1">The coordinate along the 1D axis.</param>
 24011    /// <param name="axis2">The coordinate along the 2D axis.</param>
 24012    /// <param name="axis3">The coordinate along the 3D axis.</param>
 24013    /// <param name="axis4">The coordinate along the 4D axis.</param>
 24014    /// <param name="axis5">The coordinate along the 5D axis.</param>
 24015    void StepperOverlapped(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5);
 24016    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 24017    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 24018    /// <param name="axis1">The coordinate along the 1D axis.</param>
 24019    /// <param name="axis2">The coordinate along the 2D axis.</param>
 24020    /// <param name="axis3">The coordinate along the 3D axis.</param>
 24021    /// <param name="axis4">The coordinate along the 4D axis.</param>
 24022    /// <param name="axis5">The coordinate along the 5D axis.</param>
 24023    StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axi
 24024
 24025    #endregion
 24026  }
 24027
 24028  /// <summary>Omnitree that stores bounds along 5 dimensions implemented as a linked tree.</summary>
 24029  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 24030  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 24031  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 24032  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 24033  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 24034  /// <typeparam name="Axis5">The type 5D axis.</typeparam>
 24035  public class OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5> : IOmnitreeBounds<T, Axis1, Axis2, Axis3, Axis
 24036  {
 24037    internal const int _dimensions = 5;
 24038    internal static int _children_per_node = (int)BigInteger.Pow(2, 5);
 24039
 24040    internal Node _top;
 24041    internal int _naturalLogLower = 1; // caching the next time to calculate loads (lower count)
 24042    internal int _naturalLogUpper = -1; // caching the next time to calculate loads (upper count)
 24043    internal int _load; // ln(count); min = _defaultLoad
 24044    internal Omnitree.GetBounds<T, Axis1
 24045, Axis2
 24046, Axis3
 24047, Axis4
 24048, Axis5
 24049      > _getBounds;
 24050    internal bool _defaultCompare1;
 24051    internal Func<Axis1, Axis1, CompareResult> _compare1;
 24052    internal bool _defaultCompare2;
 24053    internal Func<Axis2, Axis2, CompareResult> _compare2;
 24054    internal bool _defaultCompare3;
 24055    internal Func<Axis3, Axis3, CompareResult> _compare3;
 24056    internal bool _defaultCompare4;
 24057    internal Func<Axis4, Axis4, CompareResult> _compare4;
 24058    internal bool _defaultCompare5;
 24059    internal Func<Axis5, Axis5, CompareResult> _compare5;
 24060    internal Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> _subdivisionOver
 24061    internal Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> _subdivisionOver
 24062    internal Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> _subdivisionOver
 24063    internal Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> _subdivisionOver
 24064    internal Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> _subdivisionOver
 24065
 24066    #region Nested Types
 24067
 24068    /// <summary>Can be a leaf or a branch.</summary>
 24069    internal class Node
 24070    {
 24071      internal class ValueNode
 24072      {
 24073        internal T Value;
 24074        internal ValueNode Next;
 24075
 24076        internal ValueNode(T value, ValueNode next)
 24077        {
 24078          Value = value;
 24079          Next = next;
 24080        }
 24081      }
 24082
 24083      internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> Bounds;
 24084      internal Node Parent;
 24085      internal int Index;
 24086      internal int Count;
 24087      internal ValueNode Head;
 24088      internal Node[] Children;
 24089      internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5>? PointOfDivision;
 24090
 24091      /// <summary>Gets child by index.</summary>
 24092      /// <param name="child_index">The index of the child to get.</param>
 24093      /// <returns>The child of the given index or null if non-existent.</returns>
 24094      internal Node this[int child_index]
 24095      {
 24096        get
 24097        {
 24098          if (Children is null)
 24099            return null;
 24100          if (Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5>._children_per_node)
 24101            return Children[(int)child_index];
 24102          foreach (Node node in Children)
 24103            if (node.Index == child_index)
 24104              return node;
 24105          return null;
 24106        }
 24107        set
 24108        {
 24109          // This error check should be unnecessary... but fuck it... might as well
 24110          if (value.Index != child_index)
 24111            throw new System.Exception("Bug in Omnitree (index/property mis-match when setting a child on a branch)");
 24112
 24113          // no children yet
 24114          if (Children is null)
 24115          {
 24116            Children = â±¯(value);
 24117            return;
 24118          }
 24119          // max children overwrite
 24120          else if (Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5>._children_per_node)
 24121          {
 24122            Children[(int)child_index] = value;
 24123            return;
 24124          }
 24125          // non-max child overwrite
 24126          for (int i = 0; i < Children.Length; i++)
 24127            if (Children[i].Index == child_index)
 24128            {
 24129              Children[i] = value;
 24130              return;
 24131            }
 24132          // new child
 24133          Node[] newArray = new Node[Children.Length + 1];
 24134          if (newArray.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5>._children_per_node)
 24135          {
 24136            // new child resulting in a max children branch (sorting required)
 24137            for (int i = 0; i < Children.Length; i++)
 24138            {
 24139              newArray[(int)Children[i].Index] = Children[i];
 24140            }
 24141            newArray[(int)value.Index] = value;
 24142          }
 24143          else
 24144          {
 24145            // new child resulting in a non-max children branch
 24146            Array.Copy(Children, newArray, Children.Length);
 24147            newArray[newArray.Length - 1] = value;
 24148          }
 24149          Children = newArray;
 24150        }
 24151      }
 24152
 24153      /// <summary>The depth this node is located in the Omnitree.</summary>
 24154      internal int Depth
 24155      {
 24156        get
 24157        {
 24158          int depth = -1;
 24159          for (Node node = this; node is not null; node = node.Parent)
 24160            depth++;
 24161          return depth;
 24162        }
 24163      }
 24164
 24165      /// <summary>Constructs a node.</summary>
 24166      /// <param name="bounds">The bounds of this node.</param>
 24167      /// <param name="parent">The parent of this node.</param>
 24168      /// <param name="index">The number of values stored in this node and its children.</param>
 24169      internal Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds, Node parent, int index)
 24170      {
 24171        Bounds = bounds;
 24172        Parent = parent;
 24173        Index = index;
 24174      }
 24175
 24176      internal Node(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> pointOfDivision, Omnitree.Bounds<Axis1, Axis2, Ax
 24177        : this(bounds, parent, index)
 24178      {
 24179        PointOfDivision = pointOfDivision;
 24180      }
 24181
 24182      internal Node(Node nodeToClone)
 24183      {
 24184        this.Bounds = nodeToClone.Bounds;
 24185        this.Parent = nodeToClone.Parent;
 24186        this.Index = nodeToClone.Index;
 24187        this.Count = nodeToClone.Count;
 24188
 24189        Children = nodeToClone.Children.Clone() as Node[];
 24190        PointOfDivision = nodeToClone.PointOfDivision;
 24191
 24192        ValueNode a = this.Head;
 24193        ValueNode b = nodeToClone.Head;
 24194
 24195        while (b is not null)
 24196        {
 24197          a.Next = new ValueNode(b.Next.Value, null);
 24198          a = a.Next;
 24199          b = b.Next;
 24200        }
 24201      }
 24202
 24203      internal void Add(T addition)
 24204      {
 24205        Head = new ValueNode(addition, Head);
 24206        Count++;
 24207      }
 24208
 24209      internal Node Clone() =>
 24210        new Node(this);
 24211    }
 24212
 24213    #endregion
 24214
 24215    #region Constructors
 24216
 24217    /// <summary>This constructor is for cloning purposes</summary>
 24218    internal OmnitreeBoundsLinked(OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5> omnitree)
 24219    {
 24220      this._top = omnitree._top.Clone();
 24221      this._load = omnitree._load;
 24222      this._getBounds = omnitree._getBounds;
 24223      this._defaultCompare1 = omnitree._defaultCompare1;
 24224      this._compare1 = omnitree._compare1;
 24225      this._defaultCompare2 = omnitree._defaultCompare2;
 24226      this._compare2 = omnitree._compare2;
 24227      this._defaultCompare3 = omnitree._defaultCompare3;
 24228      this._compare3 = omnitree._compare3;
 24229      this._defaultCompare4 = omnitree._defaultCompare4;
 24230      this._compare4 = omnitree._compare4;
 24231      this._defaultCompare5 = omnitree._defaultCompare5;
 24232      this._compare5 = omnitree._compare5;
 24233      this._subdivisionOverride1 = omnitree._subdivisionOverride1;
 24234      this._subdivisionOverride2 = omnitree._subdivisionOverride2;
 24235      this._subdivisionOverride3 = omnitree._subdivisionOverride3;
 24236      this._subdivisionOverride4 = omnitree._subdivisionOverride4;
 24237      this._subdivisionOverride5 = omnitree._subdivisionOverride5;
 24238    }
 24239
 24240    internal OmnitreeBoundsLinked(
 24241      Omnitree.GetBounds<T, Axis1, Axis2, Axis3, Axis4, Axis5> getBounds,
 24242      bool defaultCompare1,
 24243      Func<Axis1, Axis1, CompareResult> compare1,
 24244      bool defaultCompare2,
 24245      Func<Axis2, Axis2, CompareResult> compare2,
 24246      bool defaultCompare3,
 24247      Func<Axis3, Axis3, CompareResult> compare3,
 24248      bool defaultCompare4,
 24249      Func<Axis4, Axis4, CompareResult> compare4,
 24250      bool defaultCompare5,
 24251      Func<Axis5, Axis5, CompareResult> compare5,
 24252      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride1
 24253,
 24254      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride2
 24255,
 24256      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride3
 24257,
 24258      Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride4
 24259,
 24260      Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride5
 24261      )
 24262    {
 24263      if (getBounds is null)
 24264      {
 24265        throw new ArgumentNullException(nameof(getBounds));
 24266      }
 24267      if (compare1 is null)
 24268      {
 24269        throw new ArgumentNullException(nameof(compare1));
 24270      }
 24271      if (compare2 is null)
 24272      {
 24273        throw new ArgumentNullException(nameof(compare2));
 24274      }
 24275      if (compare3 is null)
 24276      {
 24277        throw new ArgumentNullException(nameof(compare3));
 24278      }
 24279      if (compare4 is null)
 24280      {
 24281        throw new ArgumentNullException(nameof(compare4));
 24282      }
 24283      if (compare5 is null)
 24284      {
 24285        throw new ArgumentNullException(nameof(compare5));
 24286      }
 24287      this._getBounds = getBounds;
 24288      this._defaultCompare1 = defaultCompare1;
 24289      this._compare1 = compare1;
 24290      this._defaultCompare2 = defaultCompare2;
 24291      this._compare2 = compare2;
 24292      this._defaultCompare3 = defaultCompare3;
 24293      this._compare3 = compare3;
 24294      this._defaultCompare4 = defaultCompare4;
 24295      this._compare4 = compare4;
 24296      this._defaultCompare5 = defaultCompare5;
 24297      this._compare5 = compare5;
 24298      this._subdivisionOverride1 = subdivisionOverride1;
 24299      this._subdivisionOverride2 = subdivisionOverride2;
 24300      this._subdivisionOverride3 = subdivisionOverride3;
 24301      this._subdivisionOverride4 = subdivisionOverride4;
 24302      this._subdivisionOverride5 = subdivisionOverride5;
 24303      this._top = new Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>.None, null, -1);
 24304      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 24305    }
 24306
 24307    /// <summary>Constructs a new 5D omnitree that stores bounds.</summary>
 24308    /// <param name="getBounds">The delegate for getting object bounds in 5D space.</param>
 24309
 24310    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 24311
 24312    /// <param name="compare2">The delegate for comparing values along the 2D axis.</param>
 24313
 24314    /// <param name="compare3">The delegate for comparing values along the 3D axis.</param>
 24315
 24316    /// <param name="compare4">The delegate for comparing values along the 4D axis.</param>
 24317
 24318    /// <param name="compare5">The delegate for comparing values along the 5D axis.</param>
 24319
 24320    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 24321
 24322    /// <param name="subdivisionOverride2">The subdivision overide to be used when splitting the 2 dimension.</param>
 24323
 24324    /// <param name="subdivisionOverride3">The subdivision overide to be used when splitting the 3 dimension.</param>
 24325
 24326    /// <param name="subdivisionOverride4">The subdivision overide to be used when splitting the 4 dimension.</param>
 24327
 24328    /// <param name="subdivisionOverride5">The subdivision overide to be used when splitting the 5 dimension.</param>
 24329    public OmnitreeBoundsLinked(
 24330      Omnitree.GetBounds<T, Axis1, Axis2, Axis3, Axis4, Axis5> getBounds,
 24331      Func<Axis1, Axis1, CompareResult> compare1 = null,
 24332      Func<Axis2, Axis2, CompareResult> compare2 = null,
 24333      Func<Axis3, Axis3, CompareResult> compare3 = null,
 24334      Func<Axis4, Axis4, CompareResult> compare4 = null,
 24335      Func<Axis5, Axis5, CompareResult> compare5 = null,
 24336      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride1 = 
 24337,
 24338      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride2 = 
 24339,
 24340      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride3 = 
 24341,
 24342      Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride4 = 
 24343,
 24344      Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride5 = 
 24345      )
 24346      : this(
 24347      getBounds,
 24348      compare1 is null ? true : false,
 24349      compare1 ?? Compare,
 24350      compare2 is null ? true : false,
 24351      compare2 ?? Compare,
 24352      compare3 is null ? true : false,
 24353      compare3 ?? Compare,
 24354      compare4 is null ? true : false,
 24355      compare4 ?? Compare,
 24356      compare5 is null ? true : false,
 24357      compare5 ?? Compare,
 24358      subdivisionOverride1
 24359,
 24360      subdivisionOverride2
 24361,
 24362      subdivisionOverride3
 24363,
 24364      subdivisionOverride4
 24365,
 24366      subdivisionOverride5
 24367      ) { }
 24368
 24369    /// <summary>Constructs a new 5D omnitree that stores bounds.</summary>
 24370    /// <param name="getBoundings">The delegate for getting object bounds in 5D space.</param>
 24371    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 24372    /// <param name="compare2">The delegate for comparing values along the 2D axis.</param>
 24373    /// <param name="compare3">The delegate for comparing values along the 3D axis.</param>
 24374    /// <param name="compare4">The delegate for comparing values along the 4D axis.</param>
 24375    /// <param name="compare5">The delegate for comparing values along the 5D axis.</param>
 24376
 24377    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 24378
 24379    /// <param name="subdivisionOverride2">The subdivision overide to be used when splitting the 2 dimension.</param>
 24380
 24381    /// <param name="subdivisionOverride3">The subdivision overide to be used when splitting the 3 dimension.</param>
 24382
 24383    /// <param name="subdivisionOverride4">The subdivision overide to be used when splitting the 4 dimension.</param>
 24384
 24385    /// <param name="subdivisionOverride5">The subdivision overide to be used when splitting the 5 dimension.</param>
 24386    public OmnitreeBoundsLinked(
 24387      Omnitree.GetBoundings<T, Axis1, Axis2, Axis3, Axis4, Axis5> getBoundings,
 24388      Func<Axis1, Axis1, CompareResult> compare1 = null,
 24389      Func<Axis2, Axis2, CompareResult> compare2 = null,
 24390      Func<Axis3, Axis3, CompareResult> compare3 = null,
 24391      Func<Axis4, Axis4, CompareResult> compare4 = null,
 24392      Func<Axis5, Axis5, CompareResult> compare5 = null,
 24393      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride1 = 
 24394      , Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride2 
 24395      , Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride3 
 24396      , Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride4 
 24397      , Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>> subdivisionOverride5 
 24398      )
 24399      : this(
 24400      Omnitree.ConvertToGetBounds(getBoundings),
 24401      compare1 is null ? true : false,
 24402      compare1 ?? Compare,
 24403      compare2 is null ? true : false,
 24404      compare2 ?? Compare,
 24405      compare3 is null ? true : false,
 24406      compare3 ?? Compare,
 24407      compare4 is null ? true : false,
 24408      compare4 ?? Compare,
 24409      compare5 is null ? true : false,
 24410      compare5 ?? Compare,
 24411      subdivisionOverride1
 24412,
 24413      subdivisionOverride2
 24414,
 24415      subdivisionOverride3
 24416,
 24417      subdivisionOverride4
 24418,
 24419      subdivisionOverride5
 24420      ) { }
 24421
 24422    #endregion
 24423
 24424    #region Properties
 24425
 24426    /// <summary>The number of dimensions in this tree.</summary>
 24427    public int Dimensions => _dimensions;
 24428
 24429    /// <summary>The delegate being used by the omnitree to locate items in 5D space.</summary>
 24430    public Omnitree.GetBounds<T, Axis1
 24431      , Axis2
 24432      , Axis3
 24433      , Axis4
 24434      , Axis5
 24435      > GetBounds => _getBounds;
 24436
 24437
 24438    /// <summary>The comparison function the Omnitree is using along the 1D axis.</summary>
 24439    public Func<Axis1, Axis1, CompareResult> Compare1 => _compare1;
 24440    /// <summary>The comparison function the Omnitree is using along the 2D axis.</summary>
 24441    public Func<Axis2, Axis2, CompareResult> Compare2 => _compare2;
 24442    /// <summary>The comparison function the Omnitree is using along the 3D axis.</summary>
 24443    public Func<Axis3, Axis3, CompareResult> Compare3 => _compare3;
 24444    /// <summary>The comparison function the Omnitree is using along the 4D axis.</summary>
 24445    public Func<Axis4, Axis4, CompareResult> Compare4 => _compare4;
 24446    /// <summary>The comparison function the Omnitree is using along the 5D axis.</summary>
 24447    public Func<Axis5, Axis5, CompareResult> Compare5 => _compare5;
 24448
 24449    /// <summary>The current number of items in the tree.</summary>
 24450    public int Count  => _top.Count;
 24451
 24452    internal delegate void MaxDepthFinder(Node node, int current_depth, ref int max_depth);
 24453    /// <summary>Finds the current maximum depth of the tree. NOT AN O(1) OPERATION. Intended for educational purposes o
 24454    public int MaxDepth
 24455    {
 24456      get
 24457      {
 24458        MaxDepthFinder maxDepthFinder = null;
 24459        maxDepthFinder =
 24460            (Node node, int current_depth, ref int max_depth) =>
 24461            {
 24462              if (current_depth > max_depth)
 24463                max_depth = current_depth;
 24464              foreach (Node child in node.Children)
 24465                maxDepthFinder(child, current_depth + 1, ref max_depth);
 24466            };
 24467        int _max_depth = -1;
 24468        maxDepthFinder(this._top, 0, ref _max_depth);
 24469        return _max_depth;
 24470      }
 24471    }
 24472
 24473    internal delegate void NodeCountFinder(Node node, ref int current_count);
 24474    /// <summary>Counts the current number of nodes in the tree. NOT AN O(1) OPERATION. Intended for educational purpose
 24475    public int NodeCount
 24476    {
 24477      get
 24478      {
 24479        NodeCountFinder nodeCountFinder = null;
 24480        nodeCountFinder =
 24481            (Node node, ref int current_count) =>
 24482            {
 24483              current_count++;
 24484              foreach (Node child in node.Children)
 24485                nodeCountFinder(child, ref current_count);
 24486            };
 24487
 24488        int _current_count = 0;
 24489        nodeCountFinder(this._top, ref _current_count);
 24490        return _current_count;
 24491      }
 24492    }
 24493
 24494    #endregion
 24495
 24496    #region Methods
 24497
 24498    #region Add
 24499
 24500
 24501    #region single
 24502
 24503    /// <summary>Tries to add a value.</summary>
 24504    /// <param name="value">The value to be added.</param>
 24505    /// <returns>True if successful or false if not.</returns>
 24506    public (bool Success, Exception? Exception) TryAdd(T value)
 24507    {
 24508      Add(value);
 24509      return (true, null);
 24510    }
 24511
 24512    /// <summary>Adds an item to the tree.</summary>
 24513    /// <param name="addition">The item to be added.</param>
 24514    public void Add(T addition)
 24515    {
 24516      if (this._top.Count is int.MaxValue)
 24517        throw new System.InvalidOperationException("(Count is int.MaxValue) max Omnitree size reached (change ints to lo
 24518
 24519      // dynamic tree sizes
 24520      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 24521
 24522      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds = GetBoundings(addition);
 24523
 24524      // grow the first branch of the tree
 24525      if (!this._top.PointOfDivision.HasValue && this._top.Count >= _load)
 24526      {
 24527        Node top = this._top;
 24528
 24529        // create the new branch from the median values
 24530        this._top = new Node(DetermineMedians(top), Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>.None, null, -1);
 24531
 24532        // iterate through the values and add them to the appropriate children
 24533        for (Node.ValueNode list = top.Head; list is not null; list = list.Next)
 24534          Add(list.Value, this._top, GetBoundings(list.Value), 0);
 24535      }
 24536
 24537      this.Add(addition, this._top, bounds, 0);
 24538    }
 24539
 24540    /// <summary>Recursive version of the add function.</summary>
 24541    /// <param name="addition">The item to be added.</param>
 24542    /// <param name="node">The current node for tree trversal.</param>
 24543    /// <param name="bounds">The bounds of the addition.</param>
 24544    /// <param name="depth">The current depth of iteration.</param>
 24545    internal void Add(T addition, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds, int depth)
 24546    {
 24547      if (!node.PointOfDivision.HasValue)
 24548      {
 24549        //Leaf leaf = node as Leaf;
 24550        if (depth >= _load || !(node.Count >= _load))
 24551        {
 24552          node.Add(addition);
 24553          return;
 24554        }
 24555        else
 24556        {
 24557          //Node parent = node.Parent;
 24558          //int child_index = this.DetermineChildIndex(parent.PointOfDivision, location);
 24559          //Node growth = new Node(DetermineMedians(leaf), leaf.Bounds, parent, child_index);
 24560          //parent[child_index] = growth;
 24561
 24562          Node growth = new Node(DetermineMedians(node), node.Bounds, node.Parent, node.Index);
 24563          node.Parent[node.Index] = growth;
 24564
 24565          for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 24566          {
 24567            Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> temp_bounds = GetBoundings(list.Value);
 24568            if (EncapsulationCheck(growth.Bounds, temp_bounds))
 24569              Add(list.Value, growth, temp_bounds, depth);
 24570            else
 24571            {
 24572              ReduceParentCounts(node.Parent, 1);
 24573              Add(list.Value, this._top, temp_bounds, depth);
 24574            }
 24575          }
 24576
 24577          Add(addition, growth, bounds, depth);
 24578          return;
 24579        }
 24580      }
 24581      else
 24582      {
 24583        //Node branch = node as Node;
 24584        int child_index = this.DetermineChildIndex(node.PointOfDivision.Value, bounds); // determine the child "index" (
 24585
 24586        // if -1, then the bounds of the addition straddle the point of division (keep it in current node)
 24587        if (child_index is -1)
 24588        {
 24589          node.Add(addition);
 24590          return;
 24591        }
 24592
 24593        Node child_node = node[child_index];
 24594
 24595        // null children in branches are just empty leaves
 24596        if (child_node is null)
 24597        {
 24598          Node new_node = new Node(DetermineChildBounds(node, child_index), node, child_index);
 24599          node[child_index] = new_node;
 24600          new_node.Add(addition);
 24601        }
 24602        else
 24603          // child exists already, continue adding
 24604          Add(addition, child_node, bounds, depth + 1);
 24605
 24606        node.Count++;
 24607        return;
 24608      }
 24609    }
 24610
 24611    internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> DetermineMedians(Node node)
 24612    {
 24613      //try
 24614      //{
 24615        // extract the values
 24616        Omnitree.Bound<Axis1>[] values1 = new Omnitree.Bound<Axis1>[node.Count * 2];
 24617        Omnitree.Bound<Axis2>[] values2 = new Omnitree.Bound<Axis2>[node.Count * 2];
 24618        Omnitree.Bound<Axis3>[] values3 = new Omnitree.Bound<Axis3>[node.Count * 2];
 24619        Omnitree.Bound<Axis4>[] values4 = new Omnitree.Bound<Axis4>[node.Count * 2];
 24620        Omnitree.Bound<Axis5>[] values5 = new Omnitree.Bound<Axis5>[node.Count * 2];
 24621        Node.ValueNode for_current = node.Head; // used in for loop
 24622        for (int i = 0; i < node.Count; i++, for_current = for_current.Next)
 24623          this._getBounds(for_current.Value,
 24624          out values1[i * 2], out values1[i * 2 + 1]
 24625,
 24626          out values2[i * 2], out values2[i * 2 + 1]
 24627,
 24628          out values3[i * 2], out values3[i * 2 + 1]
 24629,
 24630          out values4[i * 2], out values4[i * 2 + 1]
 24631,
 24632          out values5[i * 2], out values5[i * 2 + 1]
 24633          );
 24634        return new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5>(
 24635          Omnitree.SubDivide(values1, this._defaultCompare1 ? Compare : this._compare1)
 24636,
 24637          Omnitree.SubDivide(values2, this._defaultCompare2 ? Compare : this._compare2)
 24638,
 24639          Omnitree.SubDivide(values3, this._defaultCompare3 ? Compare : this._compare3)
 24640,
 24641          Omnitree.SubDivide(values4, this._defaultCompare4 ? Compare : this._compare4)
 24642,
 24643          Omnitree.SubDivide(values5, this._defaultCompare5 ? Compare : this._compare5)
 24644          );
 24645      //}
 24646      //catch
 24647      //{
 24648        // extract the values
 24649      //  ArrayJagged<Omnitree.Bound<Axis1>> values1 = new ArrayJagged<Omnitree.Bound<Axis1>>(node.Count * 2);
 24650      //  ArrayJagged<Omnitree.Bound<Axis2>> values2 = new ArrayJagged<Omnitree.Bound<Axis2>>(node.Count * 2);
 24651      //  ArrayJagged<Omnitree.Bound<Axis3>> values3 = new ArrayJagged<Omnitree.Bound<Axis3>>(node.Count * 2);
 24652      //  ArrayJagged<Omnitree.Bound<Axis4>> values4 = new ArrayJagged<Omnitree.Bound<Axis4>>(node.Count * 2);
 24653      //  ArrayJagged<Omnitree.Bound<Axis5>> values5 = new ArrayJagged<Omnitree.Bound<Axis5>>(node.Count * 2);
 24654      //  Node.ValueNode for_current = node.Head; // used in for loop
 24655      //  for (int i = 0; i < node.Count; i++, for_current = for_current.Next)
 24656      //  {
 24657      //    Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 24658      //    Omnitree.Bound<Axis2> min2; Omnitree.Bound<Axis2> max2;
 24659      //    Omnitree.Bound<Axis3> min3; Omnitree.Bound<Axis3> max3;
 24660      //    Omnitree.Bound<Axis4> min4; Omnitree.Bound<Axis4> max4;
 24661      //    Omnitree.Bound<Axis5> min5; Omnitree.Bound<Axis5> max5;
 24662      //    this._getBounds(for_current.Value,
 24663      //      out min1, out max1
 24664//,
 24665      //      out min2, out max2
 24666//,
 24667      //      out min3, out max3
 24668//,
 24669      //      out min4, out max4
 24670//,
 24671      //      out min5, out max5
 24672      //      );
 24673      //    values1[i * 2] = min1; values1[i * 2 + 1] = max1;
 24674      //    values2[i * 2] = min2; values2[i * 2 + 1] = max2;
 24675      //    values3[i * 2] = min3; values3[i * 2 + 1] = max3;
 24676      //    values4[i * 2] = min4; values4[i * 2 + 1] = max4;
 24677      //    values5[i * 2] = min5; values5[i * 2 + 1] = max5;
 24678      //  }
 24679      //  return new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5>(
 24680      //    Omnitree.SubDivide(values1, this._defaultCompare1 ? Compare : this._compare1)
 24681      //    , Omnitree.SubDivide(values2, this._defaultCompare2 ? Compare : this._compare2)
 24682      //    , Omnitree.SubDivide(values3, this._defaultCompare3 ? Compare : this._compare3)
 24683      //    , Omnitree.SubDivide(values4, this._defaultCompare4 ? Compare : this._compare4)
 24684      //    , Omnitree.SubDivide(values5, this._defaultCompare5 ? Compare : this._compare5)
 24685      //  );
 24686      //}
 24687    }
 24688
 24689    #endregion
 24690
 24691    #region Add Helpers
 24692
 24693    internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> DetermineChildBounds(Node node, int child_index)
 24694    {
 24695      // the node parameter should always have a point of division value for this function
 24696      Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> pointOfDivision = node.PointOfDivision.Value;
 24697
 24698      Omnitree.Bound<Axis5> min5, max5;
 24699      if (child_index >= 16)
 24700      {
 24701        min5 = pointOfDivision.Axis5;
 24702        max5 = node.Bounds.Max5;
 24703        child_index -= 16;
 24704      }
 24705      else
 24706      {
 24707        min5 = node.Bounds.Min5;
 24708        max5 = pointOfDivision.Axis5;
 24709      }
 24710
 24711      Omnitree.Bound<Axis4> min4, max4;
 24712      if (child_index >= 8)
 24713      {
 24714        min4 = pointOfDivision.Axis4;
 24715        max4 = node.Bounds.Max4;
 24716        child_index -= 8;
 24717      }
 24718      else
 24719      {
 24720        min4 = node.Bounds.Min4;
 24721        max4 = pointOfDivision.Axis4;
 24722      }
 24723
 24724      Omnitree.Bound<Axis3> min3, max3;
 24725      if (child_index >= 4)
 24726      {
 24727        min3 = pointOfDivision.Axis3;
 24728        max3 = node.Bounds.Max3;
 24729        child_index -= 4;
 24730      }
 24731      else
 24732      {
 24733        min3 = node.Bounds.Min3;
 24734        max3 = pointOfDivision.Axis3;
 24735      }
 24736
 24737      Omnitree.Bound<Axis2> min2, max2;
 24738      if (child_index >= 2)
 24739      {
 24740        min2 = pointOfDivision.Axis2;
 24741        max2 = node.Bounds.Max2;
 24742        child_index -= 2;
 24743      }
 24744      else
 24745      {
 24746        min2 = node.Bounds.Min2;
 24747        max2 = pointOfDivision.Axis2;
 24748      }
 24749
 24750      Omnitree.Bound<Axis1> min1, max1;
 24751      if (child_index >= 1)
 24752      {
 24753        min1 = pointOfDivision.Axis1;
 24754        max1 = node.Bounds.Max1;
 24755        child_index -= 1;
 24756      }
 24757      else
 24758      {
 24759        min1 = node.Bounds.Min1;
 24760        max1 = pointOfDivision.Axis1;
 24761      }
 24762
 24763      return new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3, max3, min4, max4, min5
 24764    }
 24765
 24766    #endregion
 24767
 24768    #endregion
 24769
 24770    #region Clear
 24771
 24772    /// <summary>Returns the tree to an empty state.</summary>
 24773    public void Clear()
 24774    {
 24775      this._top = new Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>.None, null, -1);
 24776      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 24777    }
 24778
 24779    #endregion
 24780
 24781    #region Clone
 24782
 24783    /// <summary>Creates a shallow clone of this data structure.</summary>
 24784    /// <returns>A shallow clone of this data structure.</returns>
 24785    public OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5> Clone()
 24786    {
 24787      return new OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5>(this);
 24788    }
 24789
 24790    #endregion
 24791
 24792    #region Count
 24793
 24794    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 24795    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 24796    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 24797    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 24798    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 24799    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 24800    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 24801    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 24802    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 24803    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 24804    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 24805    /// <returns>The number of items in the provided sub space.</returns>
 24806    public int CountSubSpaceEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 m
 24807    {
 24808      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, ma
 24809    }
 24810    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 24811    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 24812    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 24813    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 24814    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 24815    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 24816    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 24817    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 24818    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 24819    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 24820    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 24821    /// <returns>The number of items in the provided sub space.</returns>
 24822    public int CountSubSpaceEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> m
 24823    {
 24824      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, ma
 24825    }
 24826    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 24827    /// <param name="axis1">The coordinate along the 1D axis.</param>
 24828    /// <param name="axis2">The coordinate along the 2D axis.</param>
 24829    /// <param name="axis3">The coordinate along the 3D axis.</param>
 24830    /// <param name="axis4">The coordinate along the 4D axis.</param>
 24831    /// <param name="axis5">The coordinate along the 5D axis.</param>
 24832    /// <returns>The number of items in the provided sub space.</returns>
 24833    public int CountSubSpaceEncapsulated(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5)
 24834    {
 24835      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(axis1, axis1, axis2,
 24836    }
 24837    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 24838    /// <param name="axis1">The coordinate along the 1D axis.</param>
 24839    /// <param name="axis2">The coordinate along the 2D axis.</param>
 24840    /// <param name="axis3">The coordinate along the 3D axis.</param>
 24841    /// <param name="axis4">The coordinate along the 4D axis.</param>
 24842    /// <param name="axis5">The coordinate along the 5D axis.</param>
 24843    /// <returns>The number of items in the provided sub space.</returns>
 24844    public int CountSubSpaceEncapsulated(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3>
 24845    {
 24846      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(axis1, axis1, axis2,
 24847    }
 24848
 24849    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 24850    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 24851    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 24852    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 24853    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 24854    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 24855    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 24856    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 24857    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 24858    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 24859    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 24860    /// <returns>The number of items in the provided sub space.</returns>
 24861    public int CountSubSpaceOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min
 24862    {
 24863      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2
 24864    }
 24865    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 24866    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 24867    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 24868    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 24869    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 24870    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 24871    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 24872    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 24873    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 24874    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 24875    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 24876    /// <returns>The number of items in the provided sub space.</returns>
 24877    public int CountSubSpaceOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min
 24878    {
 24879      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2
 24880    }
 24881    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 24882    /// <param name="axis1">The coordinate along the 1D axis.</param>
 24883    /// <param name="axis2">The coordinate along the 2D axis.</param>
 24884    /// <param name="axis3">The coordinate along the 3D axis.</param>
 24885    /// <param name="axis4">The coordinate along the 4D axis.</param>
 24886    /// <param name="axis5">The coordinate along the 5D axis.</param>
 24887    /// <returns>The number of items in the provided sub space.</returns>
 24888    public int CountSubSpaceOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5)
 24889    {
 24890      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(axis1, axis1, axis2, a
 24891    }
 24892    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 24893    /// <param name="axis1">The coordinate along the 1D axis.</param>
 24894    /// <param name="axis2">The coordinate along the 2D axis.</param>
 24895    /// <param name="axis3">The coordinate along the 3D axis.</param>
 24896    /// <param name="axis4">The coordinate along the 4D axis.</param>
 24897    /// <param name="axis5">The coordinate along the 5D axis.</param>
 24898    /// <returns>The number of items in the provided sub space.</returns>
 24899    public int CountSubSpaceOverlapped(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> a
 24900    {
 24901      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(axis1, axis1, axis2, a
 24902    }
 24903
 24904    internal int CountSubSpaceEncapsulated(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds)
 24905    {
 24906      return CountSubSpaceBase(_top, bounds, (a, b) => EncapsulationCheck(a, b));
 24907    }
 24908
 24909    internal int CountSubSpaceOverlapped(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds)
 24910    {
 24911      return CountSubSpaceBase(_top, bounds, (a, b) => InclusionCheck(a, b));
 24912    }
 24913
 24914    internal int CountSubSpaceBase(
 24915      Node node,
 24916      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds,
 24917      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>, Omnitree.Bounds<Axis1, Axis2, Axis3, Axi
 24918    {
 24919      // adjust min/max values
 24920      int count = 0;
 24921      if (EncapsulationCheck(bounds, node.Bounds))
 24922        count += node.Count;
 24923      else if (!node.PointOfDivision.HasValue)
 24924      {
 24925        for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 24926          if (spatialCheck(bounds, GetBoundings(list.Value)))
 24927            count++;
 24928      }
 24929      else
 24930      {
 24931        Node branch = node as Node;
 24932        if (!StraddlesLines(branch.Bounds, branch.PointOfDivision.Value))
 24933        {
 24934          int child_index = DetermineChildIndex(branch.PointOfDivision.Value, bounds);
 24935          Node child = branch[child_index];
 24936          if (child is not null)
 24937            count += this.CountSubSpaceBase(child, bounds, spatialCheck);
 24938        }
 24939        else
 24940        {
 24941          foreach (Node child in node.Children)
 24942            count += this.CountSubSpaceBase(child, bounds, spatialCheck);
 24943        }
 24944      }
 24945      return count;
 24946    }
 24947
 24948    #endregion
 24949
 24950    #region Update
 24951
 24952    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 24953    public void Update()
 24954    {
 24955      this.Update(this._top, 0);
 24956    }
 24957
 24958    /// <summary>Recursive version of the Update method.</summary>
 24959    /// <param name="node">The current node of iteration.</param>
 24960    /// <param name="depth">The current depth of iteration.</param>
 24961    internal int Update(Node node, int depth)
 24962    {
 24963      int removals = 0;
 24964
 24965      {
 24966        Node branch = node as Node;
 24967        int skipped = 0;
 24968        for (int i = 0; i + skipped < branch.Children.Length; )
 24969        {
 24970          removals += this.Update(branch.Children[i], depth + 1);
 24971          if (branch.Children[i].Count is 0)
 24972            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 24973          else
 24974            i++;
 24975        }
 24976        Node[] newArray = new Node[branch.Children.Length - skipped];
 24977        Array.Copy(branch.Children, newArray, newArray.Length);
 24978        branch.Children = newArray;
 24979
 24980        if (branch.Count < _load && branch.Count != 0)
 24981          ShrinkChild(branch.Parent, branch.Index);
 24982      }
 24983
 24984      {
 24985        Node.ValueNode current = node.Head;
 24986        Node.ValueNode previous = null;
 24987        while (current is not null)
 24988        {
 24989          Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds = GetBoundings(current.Value);
 24990          if (!this.EncapsulationCheck(node.Bounds, bounds))
 24991          {
 24992            removals++;
 24993            T updated = current.Value;
 24994            if (previous is null)
 24995            {
 24996              node.Head = current.Next;
 24997              goto HeadRemoved;
 24998            }
 24999            else
 25000              previous.Next = current.Next;
 25001
 25002            Node whereToAdd = GetEncapsulationParent(node.Parent, bounds);
 25003
 25004            if (whereToAdd is null)
 25005              throw new System.Exception("an item was updated outside the range of the omnitree");
 25006
 25007            this.Add(updated, whereToAdd, bounds, whereToAdd.Depth);
 25008          }
 25009          previous = current;
 25010        HeadRemoved:
 25011          current = current.Next;
 25012        }
 25013      }
 25014
 25015      node.Count -= removals;
 25016      return removals;
 25017    }
 25018
 25019    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 25020    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 25021    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 25022    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 25023    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 25024    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 25025    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 25026    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 25027    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 25028    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 25029    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 25030    public void Update(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4, A
 25031    {
 25032      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3, max3, min4, max4,
 25033    }
 25034    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 25035    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 25036    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 25037    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 25038    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 25039    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 25040    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 25041    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 25042    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 25043    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 25044    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 25045    public void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 25046    {
 25047      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3, max3, min4, max4,
 25048    }
 25049    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 25050    /// <param name="axis1">The coordinate along the 1D axis.</param>
 25051    /// <param name="axis2">The coordinate along the 2D axis.</param>
 25052    /// <param name="axis3">The coordinate along the 3D axis.</param>
 25053    /// <param name="axis4">The coordinate along the 4D axis.</param>
 25054    /// <param name="axis5">The coordinate along the 5D axis.</param>
 25055    public void Update(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5)
 25056    {
 25057      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(axis1, axis1, axis2, axis2, axis3, axis3, axis4
 25058    }
 25059    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 25060    /// <param name="axis1">The coordinate along the 1D axis.</param>
 25061    /// <param name="axis2">The coordinate along the 2D axis.</param>
 25062    /// <param name="axis3">The coordinate along the 3D axis.</param>
 25063    /// <param name="axis4">The coordinate along the 4D axis.</param>
 25064    /// <param name="axis5">The coordinate along the 5D axis.</param>
 25065    public void Update(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3, Omnitree.B
 25066    {
 25067      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(axis1, axis1, axis2, axis2, axis3, axis3, axis4
 25068    }
 25069    internal int Update(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds, Node node, int depth)
 25070    {
 25071      if (!InclusionCheck(bounds, node.Bounds))
 25072        return 0;
 25073
 25074      int removals = 0;
 25075
 25076      {
 25077        Node branch = node as Node;
 25078        int skipped = 0;
 25079        for (int i = 0; i + skipped < branch.Children.Length; )
 25080        {
 25081          removals += this.Update(branch.Children[i], depth + 1);
 25082          if (branch.Children[i].Count is 0)
 25083            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 25084          else
 25085            i++;
 25086        }
 25087        Node[] newArray = new Node[branch.Children.Length - skipped];
 25088        Array.Copy(branch.Children, newArray, newArray.Length);
 25089        branch.Children = newArray;
 25090
 25091        if (branch.Count < _load && branch.Count != 0)
 25092          ShrinkChild(branch.Parent, branch.Index);
 25093      }
 25094
 25095      {
 25096        Node.ValueNode current = node.Head;
 25097        Node.ValueNode previous = null;
 25098        while (current is not null)
 25099        {
 25100          Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> item_bounds = GetBoundings(current.Value);
 25101          if (!this.EncapsulationCheck(node.Bounds, item_bounds))
 25102          {
 25103            removals++;
 25104            T updated = current.Value;
 25105            if (previous is null)
 25106            {
 25107              node.Head = current.Next;
 25108              goto HeadRemoved;
 25109            }
 25110            else
 25111              previous.Next = current.Next;
 25112            Node whereToAdd = GetEncapsulationParent(node.Parent, item_bounds);
 25113            if (whereToAdd is null)
 25114              throw new System.Exception("an item was updates outside the range of the omnitree");
 25115            this.Add(updated, whereToAdd, item_bounds, whereToAdd.Depth);
 25116          }
 25117          previous = current;
 25118        HeadRemoved:
 25119          current = current.Next;
 25120        }
 25121      }
 25122
 25123      node.Count -= removals;
 25124      return removals;
 25125    }
 25126
 25127    #endregion
 25128
 25129    #region Remove
 25130
 25131    /// <summary>Removes all the items qualified by the delegate.</summary>
 25132    /// <param name="where">The predicate to qualify removals.</param>
 25133    public void Remove(Predicate<T> where)
 25134    {
 25135      this.Remove(this._top, where);
 25136      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 25137    }
 25138
 25139    /// <summary>Recursive version of the remove method.</summary>
 25140    /// <param name="node">The current node of traversal.</param>
 25141    /// <param name="where">The predicate to qualify removals.</param>
 25142    internal int Remove(Node node, Predicate<T> where)
 25143    {
 25144      int removals = 0;
 25145
 25146      // children
 25147      if (node.Children is not null)
 25148      {
 25149        int skipped = 0;
 25150        for (int i = 0; i + skipped < node.Children.Length; )
 25151        {
 25152          removals += this.Remove(node.Children[i], where);
 25153          if (node.Children[i].Count is 0)
 25154            node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 25155          else
 25156            i++;
 25157        }
 25158        Node[] newArray = new Node[node.Children.Length - skipped];
 25159        Array.Copy(node.Children, newArray, newArray.Length);
 25160        node.Children = newArray;
 25161
 25162        if (node.Count < _load && node.Count != 0)
 25163          ShrinkChild(node.Parent, node.Index);
 25164      }
 25165
 25166      // items
 25167      while (node.Head is not null && where(node.Head.Value))
 25168      {
 25169        node.Head = node.Head.Next;
 25170        removals++;
 25171      }
 25172      if (node.Head is not null)
 25173      {
 25174        Node.ValueNode list = node.Head;
 25175        while (list.Next is not null)
 25176        {
 25177          if (where(list.Next.Value))
 25178          {
 25179            list.Next = list.Next.Next;
 25180            removals++;
 25181          }
 25182        }
 25183      }
 25184
 25185      node.Count -= removals;
 25186      return removals;
 25187    }
 25188
 25189    /// <summary>Removes all the items encapsulated in a given space.</summary>
 25190    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 25191    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 25192    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 25193    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 25194    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 25195    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 25196    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 25197    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 25198    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 25199    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 25200    /// <returns>The number of items that were removed.</returns>
 25201    public void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, A
 25202    {
 25203      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, 
 25204    }
 25205    /// <summary>Removes all the items encapsulated in a given space.</summary>
 25206    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 25207    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 25208    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 25209    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 25210    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 25211    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 25212    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 25213    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 25214    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 25215    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 25216    /// <returns>The number of items that were removed.</returns>
 25217    public void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, O
 25218    {
 25219      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, 
 25220    }
 25221    /// <summary>Removes all the items encapsulated in a given space.</summary>
 25222    /// <param name="axis1">The coordinate along the 1D axis.</param>
 25223    /// <param name="axis2">The coordinate along the 2D axis.</param>
 25224    /// <param name="axis3">The coordinate along the 3D axis.</param>
 25225    /// <param name="axis4">The coordinate along the 4D axis.</param>
 25226    /// <param name="axis5">The coordinate along the 5D axis.</param>
 25227    public void RemoveEncapsulated(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3
 25228    {
 25229      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(axis1, axis1, axis2, axi
 25230    }
 25231    internal int RemoveEncapsulated(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds)
 25232    {
 25233      int removals = this.RemoveBase(node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 25234      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 25235      return removals;
 25236    }
 25237
 25238    /// <summary>Removes all the items overlapping a given space.</summary>
 25239    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 25240    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 25241    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 25242    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 25243    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 25244    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 25245    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 25246    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 25247    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 25248    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 25249    /// <returns>The number of items that were removed.</returns>
 25250    public void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axi
 25251    {
 25252      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, mi
 25253    }
 25254    /// <summary>Removes all the items overlapping a given space.</summary>
 25255    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 25256    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 25257    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 25258    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 25259    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 25260    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 25261    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 25262    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 25263    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 25264    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 25265    /// <returns>The number of items that were removed.</returns>
 25266    public void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omn
 25267    {
 25268      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, mi
 25269    }
 25270    internal int RemoveOverlapped(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds)
 25271    {
 25272      int removals = this.RemoveBase(node, bounds, (a, b) => this.InclusionCheck(a, b));
 25273      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 25274      return removals;
 25275    }
 25276
 25277    internal int RemoveBase(
 25278      Node node,
 25279      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds,
 25280      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>, Omnitree.Bounds<Axis1, Axis2, Axis3, Axi
 25281    {
 25282      int removals = 0;
 25283      if (InclusionCheck(bounds, node.Bounds))
 25284      {
 25285        // items
 25286        Node.ValueNode current_node = node.Head;
 25287        Node.ValueNode previous_node = null;
 25288        while (!(current_node is null))
 25289        {
 25290          Node.ValueNode temp_previous = current_node;
 25291          if (spatialCheck(bounds, GetBoundings(current_node.Value)))
 25292          {
 25293            removals++;
 25294            if (current_node == node.Head)
 25295              node.Head = node.Head.Next;
 25296            else
 25297            {
 25298              previous_node.Next = current_node.Next;
 25299              temp_previous = previous_node;
 25300            }
 25301          }
 25302          previous_node = temp_previous;
 25303          current_node = current_node.Next;
 25304        }
 25305
 25306        // children
 25307        if (node.Children is not null)
 25308        {
 25309          int skipped = 0;
 25310          for (int i = 0; i + skipped < node.Children.Length; )
 25311          {
 25312            removals += this.RemoveBase(node.Children[i], bounds, spatialCheck);
 25313            if (node.Children[i].Count is 0)
 25314              node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 25315            else
 25316              i++;
 25317          }
 25318          Node[] newArray = new Node[node.Children.Length - skipped];
 25319          Array.Copy(node.Children, newArray, newArray.Length);
 25320          node.Children = newArray;
 25321
 25322          // convert this branch back into a leaf
 25323          // Note: if count is zero, it will be chopped off
 25324          if (node.Count < _load && node.Count > 0)
 25325            ShrinkChild(node.Parent, node.Index);
 25326        }
 25327      }
 25328
 25329      node.Count -= removals;
 25330      return removals;
 25331    }
 25332
 25333    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 25334    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 25335    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 25336    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 25337    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 25338    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 25339    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 25340    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 25341    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 25342    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 25343    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 25344    /// <param name="where">The equality constraint of the removal.</param>
 25345    public void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, A
 25346    {
 25347      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, 
 25348    }
 25349    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 25350    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 25351    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 25352    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 25353    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 25354    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 25355    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 25356    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 25357    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 25358    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 25359    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 25360    /// <param name="where">The equality constraint of the removal.</param>
 25361    public void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, O
 25362    {
 25363      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, 
 25364    }
 25365    internal int RemoveEncapsulated(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds, Predicate<T> w
 25366    {
 25367      int removals = RemoveBase(node, bounds, where, (a, b) => this.EncapsulationCheck(a, b));
 25368      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 25369      return removals;
 25370    }
 25371
 25372    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 25373    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 25374    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 25375    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 25376    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 25377    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 25378    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 25379    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 25380    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 25381    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 25382    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 25383    /// <param name="where">The equality constraint of the removal.</param>
 25384    public void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axi
 25385    {
 25386      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, mi
 25387    }
 25388    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 25389    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 25390    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 25391    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 25392    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 25393    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 25394    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 25395    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 25396    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 25397    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 25398    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 25399    /// <param name="where">The equality constraint of the removal.</param>
 25400    public void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omn
 25401    {
 25402      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, mi
 25403    }
 25404    internal int RemoveOverlapped(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds, Predicate<T> whe
 25405    {
 25406      int removals = RemoveBase(node, bounds, where, (a, b) => this.InclusionCheck(a, b));
 25407      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 25408      return removals;
 25409    }
 25410
 25411    internal int RemoveBase(
 25412      Node node,
 25413      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds,
 25414      Predicate<T> where,
 25415      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>, Omnitree.Bounds<Axis1, Axis2, Axis3, Axi
 25416    {
 25417      if (!InclusionCheck(node.Bounds, bounds))
 25418        return 0;
 25419      int removals = 0;
 25420
 25421      // items
 25422      Node.ValueNode current = node.Head;
 25423      Node.ValueNode previous = null;
 25424      while (current is not null)
 25425      {
 25426        if (spatialCheck(bounds, GetBoundings(current.Value)) && where(current.Value))
 25427        {
 25428          removals++;
 25429          if (previous is null)
 25430          {
 25431            node.Head = current.Next;
 25432            goto HeadRemoved;
 25433          }
 25434          else
 25435            previous.Next = current.Next;
 25436        }
 25437        previous = current;
 25438      HeadRemoved:
 25439        current = current.Next;
 25440      }
 25441
 25442      // children
 25443      if (node.Children is not null)
 25444      {
 25445        int skipped = 0;
 25446        for (int i = 0; i + skipped < node.Children.Length; )
 25447        {
 25448          removals += this.RemoveBase(node.Children[i], bounds, where, spatialCheck);
 25449          if (node.Children[i].Count is 0)
 25450            node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 25451          else
 25452            i++;
 25453        }
 25454        Node[] newArray = new Node[node.Children.Length - skipped];
 25455        Array.Copy(node.Children, newArray, newArray.Length);
 25456        node.Children = newArray;
 25457
 25458        if (node.Count < _load && node.Count != 0)
 25459          ShrinkChild(node.Parent, node.Index);
 25460      }
 25461
 25462      node.Count -= removals;
 25463      return removals;
 25464    }
 25465
 25466    /// <summary>Tries to remove a value.</summary>
 25467    /// <param name="value">The value to remove.</param>
 25468    /// <returns>True if successful or false if not.</returns>
 25469    public (bool Success, Exception? Exception) TryRemove(T value)
 25470    {
 25471      Remove(value);
 25472      return (true, null);
 25473    }
 25474
 25475    /// <summary>Removes all instances of a given value.</summary>
 25476    public void Remove(T removal) => Omnitree.Remove(this, removal);
 25477
 25478    /// <summary>Removes all instances of a given value.</summary>
 25479    public void Remove(T removal, Func<T, T, bool> equate) => Omnitree.Remove(this, removal, equate);
 25480
 25481    /// <summary>Removes all the items in a given space.</summary>
 25482    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 25483    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 25484    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 25485    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 25486    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 25487    /// <returns>The number of items that were removed.</returns>
 25488    public void RemoveOverlapped(Axis1 axis1
 25489      , Axis2 axis2
 25490      , Axis3 axis3
 25491      , Axis4 axis4
 25492      , Axis5 axis5
 25493      )
 25494    {
 25495      this.RemoveOverlapped(axis1, axis1
 25496        , axis2, axis2
 25497        , axis3, axis3
 25498        , axis4, axis4
 25499        , axis5, axis5
 25500        );
 25501      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 25502    }
 25503
 25504    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 25505    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 25506    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 25507    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 25508    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 25509    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 25510    /// <param name="where">The equality constraint of the removal.</param>
 25511    public void RemoveOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Predicate<T> where)
 25512    {
 25513      this.RemoveOverlapped(axis1, axis1
 25514        , axis2, axis2
 25515        , axis3, axis3
 25516        , axis4, axis4
 25517        , axis5, axis5
 25518        , where);
 25519      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 25520    }
 25521
 25522    #endregion
 25523
 25524    #region Stepper And IEnumerable
 25525
 25526    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 25527    /// <param name="step">The delegate to perform on every item in the tree.</param>
 25528    public void Stepper(Action<T> step) =>
 25529      this.Stepper(step, this._top);
 25530
 25531    internal void Stepper(Action<T> step, Node node)
 25532    {
 25533      Node.ValueNode list = node.Head;
 25534      while (list is not null)
 25535      {
 25536        step(list.Value);
 25537        list = list.Next;
 25538      }
 25539      if (node.Children is not null)
 25540        foreach (Node child in node.Children)
 25541          this.Stepper(step, child);
 25542    }
 25543
 25544    public StepStatus StepperBreak<TStep>(TStep step = default)
 25545      where TStep : struct, IFunc<T, StepStatus> =>
 25546      StepperBreak(_top, step);
 25547
 25548    internal StepStatus StepperBreak<TStep>(Node node, TStep step)
 25549      where TStep : struct, IFunc<T, StepStatus>
 25550    {
 25551      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 25552      {
 25553        if (step.Invoke(list.Value) is Break) return Break;
 25554      }
 25555      if (node.Children is not null)
 25556      {
 25557        foreach (Node child in node.Children)
 25558        {
 25559          if (StepperBreak(child, step) is Break) return Break;
 25560        }
 25561      }
 25562      return Continue;
 25563    }
 25564
 25565    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 25566    /// <param name="step">The delegate to perform on every item in the tree.</param>
 25567    public StepStatus Stepper(Func<T, StepStatus> step) =>
 25568      Stepper(step, _top);
 25569
 25570    internal StepStatus Stepper(Func<T, StepStatus> step, Node node)
 25571    {
 25572      StepStatus status = StepStatus.Continue;
 25573
 25574      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 25575        if ((status = step(list.Value)) != StepStatus.Continue)
 25576          break;
 25577
 25578      if (node.Children is not null)
 25579        foreach (Node child in node.Children)
 25580          if ((status = Stepper(step, child)) != StepStatus.Continue)
 25581            break;
 25582
 25583      return status;
 25584    }
 25585
 25586    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 25587    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 25588    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 25589    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 25590    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 25591    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 25592    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 25593    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 25594    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 25595    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 25596    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 25597    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 25598    public void StepperEncapsulated(Action<T> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 ma
 25599      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min
 25600
 25601    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 25602    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 25603    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 25604    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 25605    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 25606    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 25607    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 25608    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 25609    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 25610    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 25611    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 25612    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 25613    public void StepperEncapsulated(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bou
 25614      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min
 25615
 25616    internal void StepperEncapsulated(Action<T> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> boun
 25617      StepperBase(step, node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 25618
 25619    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 25620    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 25621    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 25622    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 25623    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 25624    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 25625    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 25626    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 25627    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 25628    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 25629    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 25630    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 25631    public void StepperOverlapped(Action<T> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3
 25632      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3,
 25633
 25634    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 25635    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 25636    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 25637    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 25638    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 25639    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 25640    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 25641    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 25642    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 25643    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 25644    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 25645    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 25646    public void StepperOverlapped(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound
 25647      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3,
 25648
 25649    internal void StepperOverlapped(Action<T> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds
 25650      StepperBase(step, node, bounds, (a, b) => this.InclusionCheck(a, b));
 25651
 25652    internal void StepperBase(
 25653      Action<T> step,
 25654      Node node,
 25655      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds,
 25656      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>, Omnitree.Bounds<Axis1, Axis2, Axis3, Axi
 25657    {
 25658      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 25659        if (spatialCheck(bounds, GetBoundings(list.Value)))
 25660          step(list.Value);
 25661
 25662      if (node.Children is not null)
 25663      {
 25664        foreach (Node child in node.Children)
 25665          // optimization: stop bounds checking if space encapsulates node
 25666          if (EncapsulationCheck(bounds, child.Bounds))
 25667            this.Stepper(step, child);
 25668          else if (InclusionCheck(child.Bounds, bounds))
 25669            this.StepperBase(step, child, bounds, spatialCheck);
 25670      }
 25671    }
 25672
 25673    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 25674    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 25675    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 25676    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 25677    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 25678    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 25679    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 25680    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 25681    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 25682    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 25683    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 25684    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 25685    public StepStatus StepperEncapsulated(Func<T, StepStatus> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis
 25686      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min
 25687
 25688    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 25689    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 25690    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 25691    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 25692    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 25693    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 25694    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 25695    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 25696    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 25697    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 25698    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 25699    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 25700    public StepStatus StepperEncapsulated(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> ma
 25701      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min
 25702
 25703    internal StepStatus StepperEncapsulated(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Ax
 25704      StepperBase(step, node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 25705
 25706    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 25707    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 25708    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 25709    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 25710    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 25711    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 25712    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 25713    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 25714    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 25715    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 25716    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 25717    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 25718    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 
 25719      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3,
 25720
 25721    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 25722    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 25723    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 25724    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 25725    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 25726    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 25727    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 25728    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 25729    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 25730    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 25731    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 25732    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 25733    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1
 25734      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(min1, max1, min2, max2, min3,
 25735
 25736    internal StepStatus StepperOverlapped(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis
 25737      StepperBase(step, node, bounds, (a, b) => this.InclusionCheck(a, b));
 25738
 25739    internal StepStatus StepperBase(
 25740      Func<T, StepStatus> step,
 25741      Node node,
 25742      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds,
 25743      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>, Omnitree.Bounds<Axis1, Axis2, Axis3, Axi
 25744    {
 25745      StepStatus status = StepStatus.Continue;
 25746
 25747      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 25748        if (spatialCheck(bounds, GetBoundings(list.Value)) &&
 25749          (status = step(list.Value)) != StepStatus.Continue)
 25750          break;
 25751
 25752      if (node.Children is not null)
 25753      {
 25754        foreach (Node child in node.Children)
 25755          // optimization: stop bounds checking if space encapsulates node
 25756          if (EncapsulationCheck(bounds, child.Bounds) &&
 25757            (status = this.Stepper(step, child)) != StepStatus.Continue)
 25758            break;
 25759          else if (InclusionCheck(child.Bounds, bounds) &&
 25760            (status = this.StepperBase(step, child, bounds, spatialCheck)) != StepStatus.Continue)
 25761            break;
 25762      }
 25763
 25764      return status;
 25765    }
 25766
 25767    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 25768    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 25769    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 25770    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 25771    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 25772    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 25773    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 25774    public void StepperOverlapped(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5) =>
 25775      StepperOverlapped(step, this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(axis1, axis1
 25776        , axis2, axis2
 25777        , axis3, axis3
 25778        , axis4, axis4
 25779        , axis5, axis5
 25780      ));
 25781
 25782    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 25783    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 25784    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 25785    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 25786    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 25787    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 25788    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 25789    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Ax
 25790      StepperOverlapped(step, this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(axis1, axis1
 25791        , axis2, axis2
 25792        , axis3, axis3
 25793        , axis4, axis4
 25794        , axis5, axis5
 25795        ));
 25796
 25797    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 25798
 25799    public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 25800    {
 25801      // Note: this can be optimized.
 25802      IList<T> list = new ListLinked<T>();
 25803      Stepper(x => list.Add(x));
 25804      return list.GetEnumerator();
 25805    }
 25806
 25807    #endregion
 25808
 25809    /// <inheritdoc/>
 25810    public T[] ToArray() => throw new NotImplementedException();
 25811
 25812    #region Helpers
 25813
 25814    internal bool StraddlesLines(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds, Omnitree.Vector<Axis1, Axis2
 25815      Omnitree.StraddlesLines(bounds, vector
 25816        , _compare1
 25817        , _compare2
 25818        , _compare3
 25819        , _compare4
 25820        , _compare5
 25821        );
 25822
 25823    /// <summary>Computes the child index that contains the desired dimensions.</summary>
 25824    /// <param name="pointOfDivision">The point of division to compare against.</param>
 25825    /// <param name="bounds">The dimensions to determine the child index.</param>
 25826    /// <returns>The computed child index based on the coordinates relative to the center of the node.</returns>
 25827    internal int DetermineChildIndex(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> pointOfDivision, Omnitree.Bounds
 25828    {
 25829      // make sure a child encapsulates the bounds (otherwise the bounds cannot move down the tree)
 25830      if (StraddlesLines(bounds, pointOfDivision))
 25831        return -1;
 25832
 25833      int child = 0;
 25834      if (!bounds.Min1.Exists || !(this._compare1(bounds.Min1.Value, pointOfDivision.Axis1) is Less))
 25835        child += 1 << 0;
 25836      if (!bounds.Min2.Exists || !(this._compare2(bounds.Min2.Value, pointOfDivision.Axis2) is Less))
 25837        child += 1 << 1;
 25838      if (!bounds.Min3.Exists || !(this._compare3(bounds.Min3.Value, pointOfDivision.Axis3) is Less))
 25839        child += 1 << 2;
 25840      if (!bounds.Min4.Exists || !(this._compare4(bounds.Min4.Value, pointOfDivision.Axis4) is Less))
 25841        child += 1 << 3;
 25842      if (!bounds.Min5.Exists || !(this._compare5(bounds.Min5.Value, pointOfDivision.Axis5) is Less))
 25843        child += 1 << 4;
 25844      return child;
 25845    }
 25846
 25847    /// <summary>Converts a branch back into a leaf when the count is reduced.</summary>
 25848    /// <param name="parent">The parent to shrink a child of.</param>
 25849    /// <param name="child_index">The index of the child to shrink.</param>
 25850    internal void ShrinkChild(Node parent, int child_index)
 25851    {
 25852      Node leaf;
 25853      Node removal = null;
 25854      if (parent is null) // top of tree
 25855      {
 25856        removal = this._top;
 25857        leaf = new Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>.None, null, -1);
 25858        this._top = leaf;
 25859      }
 25860      else // non-top branch
 25861      {
 25862        removal = parent[child_index];
 25863        leaf = new Node(removal.Bounds, removal.Parent, removal.Index);
 25864        parent[child_index] = leaf;
 25865      }
 25866
 25867      this.Stepper((T step) => { leaf.Add(step); }, removal);
 25868    }
 25869
 25870    /// <summary>Reduces the counts of all the parents of a given node by a given amount.</summary>
 25871    /// <param name="parent">The starting parent of the reduction.</param>
 25872    /// <param name="reduction">The amount to reduce the parent counts by.</param>
 25873    internal void ReduceParentCounts(Node parent, int reduction)
 25874    {
 25875      IncreaseParentCounts(parent, -reduction);
 25876    }
 25877
 25878    /// <summary>Increases the counts of all the parents of a given node by a given amount.</summary>
 25879    /// <param name="parent">The starting parent of the increase.</param>
 25880    /// <param name="increase">The amount to increase the parent counts by.</param>
 25881    internal void IncreaseParentCounts(Node parent, int increase)
 25882    {
 25883      Node node = parent;
 25884      while (node is not null)
 25885      {
 25886        node.Count += increase;
 25887        node = node.Parent;
 25888      }
 25889    }
 25890
 25891    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 25892    /// <returns>True if the spaces overlap; False if not.</returns>
 25893    internal bool InclusionCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> a, Omnitree.Bounds<Axis1, Axis2, Axi
 25894      Omnitree.InclusionCheck(a, b
 25895      , _compare1
 25896      , _compare2
 25897      , _compare3
 25898      , _compare4
 25899      , _compare5
 25900      );
 25901
 25902    /// <summary>Checks if a space encapsulates a point.</summary>
 25903    /// <returns>True if the space encapsulates the point; False if not.</returns>
 25904    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds, Omnitree.Vector<Axis1, A
 25905      Omnitree.EncapsulationCheck(bounds, vector
 25906      , _compare1
 25907      , _compare2
 25908      , _compare3
 25909      , _compare4
 25910      , _compare5
 25911      );
 25912
 25913    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 25914    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 25915    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> a, Omnitree.Bounds<Axis1, Axis2,
 25916      Omnitree.EncapsulationCheck(a, b
 25917      , _compare1
 25918      , _compare2
 25919      , _compare3
 25920      , _compare4
 25921      , _compare5
 25922      );
 25923
 25924    /// <summary>Checks for equality between two locations.</summary>
 25925    /// <returns>True if equal; False if not;</returns>
 25926    internal bool EqualsCheck(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5> a, Omnitree.Vector<Axis1, Axis2, Axis3,
 25927      Omnitree.EqualsCheck(a, b
 25928      , (a, b) => _compare1(a, b) is Equal
 25929      , (a, b) => _compare2(a, b) is Equal
 25930      , (a, b) => _compare3(a, b) is Equal
 25931      , (a, b) => _compare4(a, b) is Equal
 25932      , (a, b) => _compare5(a, b) is Equal
 25933      );
 25934
 25935    /// <summary>Gets the nearest parent that encapsulates a location.</summary>
 25936    /// <param name="node">The starting node to find the encapsulating parent of the location.</param>
 25937    /// <param name="bounds">The bounds to get the encapsulating parent from.</param>
 25938    /// <returns>The nearest node that encapsulates the given location.</returns>
 25939    internal Node GetEncapsulationParent(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> bounds)
 25940    {
 25941      while (node is not null && !EncapsulationCheck(node.Bounds, bounds))
 25942      {
 25943        node = node.Parent;
 25944      }
 25945      return node;
 25946    }
 25947
 25948    internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5> GetBoundings(T value)
 25949    {
 25950      Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 25951      Omnitree.Bound<Axis2> min2; Omnitree.Bound<Axis2> max2;
 25952      Omnitree.Bound<Axis3> min3; Omnitree.Bound<Axis3> max3;
 25953      Omnitree.Bound<Axis4> min4; Omnitree.Bound<Axis4> max4;
 25954      Omnitree.Bound<Axis5> min5; Omnitree.Bound<Axis5> max5;
 25955      this._getBounds(value,
 25956        out min1, out max1
 25957,
 25958        out min2, out max2
 25959,
 25960        out min3, out max3
 25961,
 25962        out min4, out max4
 25963,
 25964        out min5, out max5
 25965        );
 25966      return new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5>(
 25967        min1, max1
 25968,
 25969        min2, max2
 25970,
 25971        min3, max3
 25972,
 25973        min4, max4
 25974,
 25975        min5, max5
 25976        );
 25977    }
 25978
 25979    #endregion
 25980
 25981    #endregion
 25982  }
 25983
 25984  #endregion
 25985
 25986  #region 6 Dimensional
 25987
 25988  /// <summary>Inheritance base for 6D omnitrees that store bounds.</summary>
 25989  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 25990  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 25991  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 25992  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 25993  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 25994  /// <typeparam name="Axis5">The type 5D axis.</typeparam>
 25995  /// <typeparam name="Axis6">The type 6D axis.</typeparam>
 25996  public interface IOmnitreeBounds<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> : IOmnitree<T, Axis1, Axis2, Axis3, Axis
 25997  {
 25998    #region Properties
 25999
 26000    /// <summary>The number of dimensions in this tree.</summary>
 26001    int Dimensions { get; }
 26002
 26003    /// <summary>The delegate being used by the omnitree to get the bounds of values in 6D space.</summary>
 26004    Omnitree.GetBounds<T, Axis1
 26005, Axis2
 26006, Axis3
 26007, Axis4
 26008, Axis5
 26009, Axis6
 26010      > GetBounds { get; }
 26011
 26012    #endregion
 26013
 26014    #region Methods
 26015
 26016    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 26017    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 26018    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 26019    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 26020    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 26021    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 26022    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 26023    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 26024    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 26025    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 26026    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 26027    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 26028    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 26029    /// <returns>The number of items in the provided sub space.</returns>
 26030    int CountSubSpaceEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Ax
 26031
 26032    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 26033    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 26034    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 26035    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 26036    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 26037    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 26038    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 26039    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 26040    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 26041    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 26042    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 26043    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 26044    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 26045    /// <returns>The number of items in the provided sub space.</returns>
 26046    int CountSubSpaceOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis
 26047
 26048    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 26049    void Update();
 26050    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 26051    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 26052    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 26053    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 26054    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 26055    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 26056    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 26057    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 26058    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 26059    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 26060    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 26061    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 26062    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 26063    void Update(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4, Axis5 mi
 26064
 26065    /// <summary>Removes all the items in a given space.</summary>
 26066    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 26067    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 26068    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 26069    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 26070    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 26071    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 26072    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 26073    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 26074    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 26075    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 26076    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 26077    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 26078    void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 ma
 26079    /// <summary>Removes all the items in a given space.</summary>
 26080    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 26081    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 26082    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 26083    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 26084    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 26085    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 26086    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 26087    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 26088    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 26089    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 26090    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 26091    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 26092    void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree
 26093    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 26094    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 26095    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 26096    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 26097    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 26098    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 26099    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 26100    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 26101    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 26102    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 26103    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 26104    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 26105    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 26106    /// <param name="where">The predicate constraint of the removal.</param>
 26107    void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 ma
 26108    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 26109    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 26110    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 26111    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 26112    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 26113    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 26114    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 26115    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 26116    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 26117    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 26118    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 26119    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 26120    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 26121    /// <param name="where">The predicate constraint of the removal.</param>
 26122    void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree
 26123
 26124    /// <summary>Removes all the items in a given space.</summary>
 26125    /// <param name="axis1">The coordinate along the 1D axis.</param>
 26126    /// <param name="axis2">The coordinate along the 2D axis.</param>
 26127    /// <param name="axis3">The coordinate along the 3D axis.</param>
 26128    /// <param name="axis4">The coordinate along the 4D axis.</param>
 26129    /// <param name="axis5">The coordinate along the 5D axis.</param>
 26130    /// <param name="axis6">The coordinate along the 6D axis.</param>
 26131    void RemoveOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6);
 26132    /// <summary>Removes all the items in a given space.</summary>
 26133    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 26134    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 26135    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 26136    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 26137    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 26138    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 26139    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 26140    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 26141    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 26142    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 26143    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 26144    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 26145    void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4
 26146    /// <summary>Removes all the items in a given space.</summary>
 26147    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 26148    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 26149    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 26150    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 26151    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 26152    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 26153    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 26154    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 26155    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 26156    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 26157    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 26158    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 26159    void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.B
 26160    /// <summary>Removes all the items in a given space where equality is met.</summary>
 26161    /// <param name="axis1">The coordinate along the 1D axis.</param>
 26162    /// <param name="axis2">The coordinate along the 2D axis.</param>
 26163    /// <param name="axis3">The coordinate along the 3D axis.</param>
 26164    /// <param name="axis4">The coordinate along the 4D axis.</param>
 26165    /// <param name="axis5">The coordinate along the 5D axis.</param>
 26166    /// <param name="axis6">The coordinate along the 6D axis.</param>
 26167    /// <param name="where">The equality constraint of the removal.</param>
 26168    void RemoveOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6, Predicate<T> whe
 26169    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 26170    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 26171    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 26172    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 26173    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 26174    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 26175    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 26176    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 26177    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 26178    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 26179    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 26180    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 26181    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 26182    /// <param name="where">The predicate constraint of the removal.</param>
 26183    void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4
 26184    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 26185    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 26186    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 26187    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 26188    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 26189    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 26190    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 26191    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 26192    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 26193    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 26194    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 26195    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 26196    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 26197    /// <param name="where">The predicate constraint of the removal.</param>
 26198    void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.B
 26199
 26200    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 26201    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 26202    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 26203    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 26204    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 26205    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 26206    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 26207    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 26208    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 26209    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 26210    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 26211    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 26212    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 26213    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 26214    void StepperEncapsulated(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis
 26215    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 26216    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 26217    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 26218    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 26219    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 26220    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 26221    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 26222    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 26223    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 26224    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 26225    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 26226    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 26227    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 26228    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 26229    StepStatus StepperEncapsulated(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omn
 26230
 26231    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 26232    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 26233    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 26234    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 26235    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 26236    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 26237    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 26238    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 26239    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 26240    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 26241    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 26242    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 26243    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 26244    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 26245    void StepperOverlapped(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2>
 26246    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 26247    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 26248    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 26249    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 26250    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 26251    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 26252    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 26253    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 26254    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 26255    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 26256    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 26257    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 26258    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 26259    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 26260    StepStatus StepperOverlapped(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnit
 26261
 26262    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 26263    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 26264    /// <param name="axis1">The coordinate along the 1D axis.</param>
 26265    /// <param name="axis2">The coordinate along the 2D axis.</param>
 26266    /// <param name="axis3">The coordinate along the 3D axis.</param>
 26267    /// <param name="axis4">The coordinate along the 4D axis.</param>
 26268    /// <param name="axis5">The coordinate along the 5D axis.</param>
 26269    /// <param name="axis6">The coordinate along the 6D axis.</param>
 26270    void StepperOverlapped(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6)
 26271    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 26272    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 26273    /// <param name="axis1">The coordinate along the 1D axis.</param>
 26274    /// <param name="axis2">The coordinate along the 2D axis.</param>
 26275    /// <param name="axis3">The coordinate along the 3D axis.</param>
 26276    /// <param name="axis4">The coordinate along the 4D axis.</param>
 26277    /// <param name="axis5">The coordinate along the 5D axis.</param>
 26278    /// <param name="axis6">The coordinate along the 6D axis.</param>
 26279    StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axi
 26280
 26281    #endregion
 26282  }
 26283
 26284  /// <summary>Omnitree that stores bounds along 6 dimensions implemented as a linked tree.</summary>
 26285  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 26286  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 26287  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 26288  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 26289  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 26290  /// <typeparam name="Axis5">The type 5D axis.</typeparam>
 26291  /// <typeparam name="Axis6">The type 6D axis.</typeparam>
 26292  public class OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> : IOmnitreeBounds<T, Axis1, Axis2, Axis
 26293  {
 26294    internal const int _dimensions = 6;
 26295    internal static int _children_per_node = (int)BigInteger.Pow(2, 6);
 26296
 26297    internal Node _top;
 26298    internal int _naturalLogLower = 1; // caching the next time to calculate loads (lower count)
 26299    internal int _naturalLogUpper = -1; // caching the next time to calculate loads (upper count)
 26300    internal int _load; // ln(count); min = _defaultLoad
 26301    internal Omnitree.GetBounds<T, Axis1
 26302, Axis2
 26303, Axis3
 26304, Axis4
 26305, Axis5
 26306, Axis6
 26307      > _getBounds;
 26308    internal bool _defaultCompare1;
 26309    internal Func<Axis1, Axis1, CompareResult> _compare1;
 26310    internal bool _defaultCompare2;
 26311    internal Func<Axis2, Axis2, CompareResult> _compare2;
 26312    internal bool _defaultCompare3;
 26313    internal Func<Axis3, Axis3, CompareResult> _compare3;
 26314    internal bool _defaultCompare4;
 26315    internal Func<Axis4, Axis4, CompareResult> _compare4;
 26316    internal bool _defaultCompare5;
 26317    internal Func<Axis5, Axis5, CompareResult> _compare5;
 26318    internal bool _defaultCompare6;
 26319    internal Func<Axis6, Axis6, CompareResult> _compare6;
 26320    internal Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> _subdivis
 26321    internal Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> _subdivis
 26322    internal Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> _subdivis
 26323    internal Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> _subdivis
 26324    internal Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> _subdivis
 26325    internal Omnitree.SubdivisionOverride<T, Axis6, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> _subdivis
 26326
 26327    #region Nested Types
 26328
 26329    /// <summary>Can be a leaf or a branch.</summary>
 26330    internal class Node
 26331    {
 26332      internal class ValueNode
 26333      {
 26334        internal T Value;
 26335        internal ValueNode Next;
 26336
 26337        internal ValueNode(T value, ValueNode next)
 26338        {
 26339          Value = value;
 26340          Next = next;
 26341        }
 26342      }
 26343
 26344      internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> Bounds;
 26345      internal Node Parent;
 26346      internal int Index;
 26347      internal int Count;
 26348      internal ValueNode Head;
 26349      internal Node[] Children;
 26350      internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>? PointOfDivision;
 26351
 26352      /// <summary>Gets child by index.</summary>
 26353      /// <param name="child_index">The index of the child to get.</param>
 26354      /// <returns>The child of the given index or null if non-existent.</returns>
 26355      internal Node this[int child_index]
 26356      {
 26357        get
 26358        {
 26359          if (Children is null)
 26360            return null;
 26361          if (Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>._children_per_node)
 26362            return Children[(int)child_index];
 26363          foreach (Node node in Children)
 26364            if (node.Index == child_index)
 26365              return node;
 26366          return null;
 26367        }
 26368        set
 26369        {
 26370          // This error check should be unnecessary... but fuck it... might as well
 26371          if (value.Index != child_index)
 26372            throw new System.Exception("Bug in Omnitree (index/property mis-match when setting a child on a branch)");
 26373
 26374          // no children yet
 26375          if (Children is null)
 26376          {
 26377            Children = â±¯(value);
 26378            return;
 26379          }
 26380          // max children overwrite
 26381          else if (Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>._children_per_no
 26382          {
 26383            Children[(int)child_index] = value;
 26384            return;
 26385          }
 26386          // non-max child overwrite
 26387          for (int i = 0; i < Children.Length; i++)
 26388            if (Children[i].Index == child_index)
 26389            {
 26390              Children[i] = value;
 26391              return;
 26392            }
 26393          // new child
 26394          Node[] newArray = new Node[Children.Length + 1];
 26395          if (newArray.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>._children_per_node)
 26396          {
 26397            // new child resulting in a max children branch (sorting required)
 26398            for (int i = 0; i < Children.Length; i++)
 26399            {
 26400              newArray[(int)Children[i].Index] = Children[i];
 26401            }
 26402            newArray[(int)value.Index] = value;
 26403          }
 26404          else
 26405          {
 26406            // new child resulting in a non-max children branch
 26407            Array.Copy(Children, newArray, Children.Length);
 26408            newArray[newArray.Length - 1] = value;
 26409          }
 26410          Children = newArray;
 26411        }
 26412      }
 26413
 26414      /// <summary>The depth this node is located in the Omnitree.</summary>
 26415      internal int Depth
 26416      {
 26417        get
 26418        {
 26419          int depth = -1;
 26420          for (Node node = this; node is not null; node = node.Parent)
 26421            depth++;
 26422          return depth;
 26423        }
 26424      }
 26425
 26426      /// <summary>Constructs a node.</summary>
 26427      /// <param name="bounds">The bounds of this node.</param>
 26428      /// <param name="parent">The parent of this node.</param>
 26429      /// <param name="index">The number of values stored in this node and its children.</param>
 26430      internal Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds, Node parent, int index)
 26431      {
 26432        Bounds = bounds;
 26433        Parent = parent;
 26434        Index = index;
 26435      }
 26436
 26437      internal Node(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> pointOfDivision, Omnitree.Bounds<Axis1, Ax
 26438        : this(bounds, parent, index)
 26439      {
 26440        PointOfDivision = pointOfDivision;
 26441      }
 26442
 26443      internal Node(Node nodeToClone)
 26444      {
 26445        this.Bounds = nodeToClone.Bounds;
 26446        this.Parent = nodeToClone.Parent;
 26447        this.Index = nodeToClone.Index;
 26448        this.Count = nodeToClone.Count;
 26449
 26450        Children = nodeToClone.Children.Clone() as Node[];
 26451        PointOfDivision = nodeToClone.PointOfDivision;
 26452
 26453        ValueNode a = this.Head;
 26454        ValueNode b = nodeToClone.Head;
 26455
 26456        while (b is not null)
 26457        {
 26458          a.Next = new ValueNode(b.Next.Value, null);
 26459          a = a.Next;
 26460          b = b.Next;
 26461        }
 26462      }
 26463
 26464      internal void Add(T addition)
 26465      {
 26466        Head = new ValueNode(addition, Head);
 26467        Count++;
 26468      }
 26469
 26470      internal Node Clone() =>
 26471        new Node(this);
 26472    }
 26473
 26474    #endregion
 26475
 26476    #region Constructors
 26477
 26478    /// <summary>This constructor is for cloning purposes</summary>
 26479    internal OmnitreeBoundsLinked(OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> omnitree)
 26480    {
 26481      this._top = omnitree._top.Clone();
 26482      this._load = omnitree._load;
 26483      this._getBounds = omnitree._getBounds;
 26484      this._defaultCompare1 = omnitree._defaultCompare1;
 26485      this._compare1 = omnitree._compare1;
 26486      this._defaultCompare2 = omnitree._defaultCompare2;
 26487      this._compare2 = omnitree._compare2;
 26488      this._defaultCompare3 = omnitree._defaultCompare3;
 26489      this._compare3 = omnitree._compare3;
 26490      this._defaultCompare4 = omnitree._defaultCompare4;
 26491      this._compare4 = omnitree._compare4;
 26492      this._defaultCompare5 = omnitree._defaultCompare5;
 26493      this._compare5 = omnitree._compare5;
 26494      this._defaultCompare6 = omnitree._defaultCompare6;
 26495      this._compare6 = omnitree._compare6;
 26496      this._subdivisionOverride1 = omnitree._subdivisionOverride1;
 26497      this._subdivisionOverride2 = omnitree._subdivisionOverride2;
 26498      this._subdivisionOverride3 = omnitree._subdivisionOverride3;
 26499      this._subdivisionOverride4 = omnitree._subdivisionOverride4;
 26500      this._subdivisionOverride5 = omnitree._subdivisionOverride5;
 26501      this._subdivisionOverride6 = omnitree._subdivisionOverride6;
 26502    }
 26503
 26504    internal OmnitreeBoundsLinked(
 26505      Omnitree.GetBounds<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> getBounds,
 26506      bool defaultCompare1,
 26507      Func<Axis1, Axis1, CompareResult> compare1,
 26508      bool defaultCompare2,
 26509      Func<Axis2, Axis2, CompareResult> compare2,
 26510      bool defaultCompare3,
 26511      Func<Axis3, Axis3, CompareResult> compare3,
 26512      bool defaultCompare4,
 26513      Func<Axis4, Axis4, CompareResult> compare4,
 26514      bool defaultCompare5,
 26515      Func<Axis5, Axis5, CompareResult> compare5,
 26516      bool defaultCompare6,
 26517      Func<Axis6, Axis6, CompareResult> compare6,
 26518      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 26519,
 26520      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 26521,
 26522      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 26523,
 26524      Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 26525,
 26526      Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 26527,
 26528      Omnitree.SubdivisionOverride<T, Axis6, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 26529      )
 26530    {
 26531      if (getBounds is null)
 26532      {
 26533        throw new ArgumentNullException(nameof(getBounds));
 26534      }
 26535      if (compare1 is null)
 26536      {
 26537        throw new ArgumentNullException(nameof(compare1));
 26538      }
 26539      if (compare2 is null)
 26540      {
 26541        throw new ArgumentNullException(nameof(compare2));
 26542      }
 26543      if (compare3 is null)
 26544      {
 26545        throw new ArgumentNullException(nameof(compare3));
 26546      }
 26547      if (compare4 is null)
 26548      {
 26549        throw new ArgumentNullException(nameof(compare4));
 26550      }
 26551      if (compare5 is null)
 26552      {
 26553        throw new ArgumentNullException(nameof(compare5));
 26554      }
 26555      if (compare6 is null)
 26556      {
 26557        throw new ArgumentNullException(nameof(compare6));
 26558      }
 26559      this._getBounds = getBounds;
 26560      this._defaultCompare1 = defaultCompare1;
 26561      this._compare1 = compare1;
 26562      this._defaultCompare2 = defaultCompare2;
 26563      this._compare2 = compare2;
 26564      this._defaultCompare3 = defaultCompare3;
 26565      this._compare3 = compare3;
 26566      this._defaultCompare4 = defaultCompare4;
 26567      this._compare4 = compare4;
 26568      this._defaultCompare5 = defaultCompare5;
 26569      this._compare5 = compare5;
 26570      this._defaultCompare6 = defaultCompare6;
 26571      this._compare6 = compare6;
 26572      this._subdivisionOverride1 = subdivisionOverride1;
 26573      this._subdivisionOverride2 = subdivisionOverride2;
 26574      this._subdivisionOverride3 = subdivisionOverride3;
 26575      this._subdivisionOverride4 = subdivisionOverride4;
 26576      this._subdivisionOverride5 = subdivisionOverride5;
 26577      this._subdivisionOverride6 = subdivisionOverride6;
 26578      this._top = new Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>.None, null, -1);
 26579      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 26580    }
 26581
 26582    /// <summary>Constructs a new 6D omnitree that stores bounds.</summary>
 26583    /// <param name="getBounds">The delegate for getting object bounds in 6D space.</param>
 26584
 26585    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 26586
 26587    /// <param name="compare2">The delegate for comparing values along the 2D axis.</param>
 26588
 26589    /// <param name="compare3">The delegate for comparing values along the 3D axis.</param>
 26590
 26591    /// <param name="compare4">The delegate for comparing values along the 4D axis.</param>
 26592
 26593    /// <param name="compare5">The delegate for comparing values along the 5D axis.</param>
 26594
 26595    /// <param name="compare6">The delegate for comparing values along the 6D axis.</param>
 26596
 26597    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 26598
 26599    /// <param name="subdivisionOverride2">The subdivision overide to be used when splitting the 2 dimension.</param>
 26600
 26601    /// <param name="subdivisionOverride3">The subdivision overide to be used when splitting the 3 dimension.</param>
 26602
 26603    /// <param name="subdivisionOverride4">The subdivision overide to be used when splitting the 4 dimension.</param>
 26604
 26605    /// <param name="subdivisionOverride5">The subdivision overide to be used when splitting the 5 dimension.</param>
 26606
 26607    /// <param name="subdivisionOverride6">The subdivision overide to be used when splitting the 6 dimension.</param>
 26608    public OmnitreeBoundsLinked(
 26609      Omnitree.GetBounds<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> getBounds,
 26610      Func<Axis1, Axis1, CompareResult> compare1 = null,
 26611      Func<Axis2, Axis2, CompareResult> compare2 = null,
 26612      Func<Axis3, Axis3, CompareResult> compare3 = null,
 26613      Func<Axis4, Axis4, CompareResult> compare4 = null,
 26614      Func<Axis5, Axis5, CompareResult> compare5 = null,
 26615      Func<Axis6, Axis6, CompareResult> compare6 = null,
 26616      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 26617,
 26618      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 26619,
 26620      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 26621,
 26622      Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 26623,
 26624      Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 26625,
 26626      Omnitree.SubdivisionOverride<T, Axis6, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 26627      )
 26628      : this(
 26629      getBounds,
 26630      compare1 is null ? true : false,
 26631      compare1 ?? Compare,
 26632      compare2 is null ? true : false,
 26633      compare2 ?? Compare,
 26634      compare3 is null ? true : false,
 26635      compare3 ?? Compare,
 26636      compare4 is null ? true : false,
 26637      compare4 ?? Compare,
 26638      compare5 is null ? true : false,
 26639      compare5 ?? Compare,
 26640      compare6 is null ? true : false,
 26641      compare6 ?? Compare,
 26642      subdivisionOverride1
 26643,
 26644      subdivisionOverride2
 26645,
 26646      subdivisionOverride3
 26647,
 26648      subdivisionOverride4
 26649,
 26650      subdivisionOverride5
 26651,
 26652      subdivisionOverride6
 26653      ) { }
 26654
 26655    /// <summary>Constructs a new 6D omnitree that stores bounds.</summary>
 26656    /// <param name="getBoundings">The delegate for getting object bounds in 6D space.</param>
 26657    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 26658    /// <param name="compare2">The delegate for comparing values along the 2D axis.</param>
 26659    /// <param name="compare3">The delegate for comparing values along the 3D axis.</param>
 26660    /// <param name="compare4">The delegate for comparing values along the 4D axis.</param>
 26661    /// <param name="compare5">The delegate for comparing values along the 5D axis.</param>
 26662    /// <param name="compare6">The delegate for comparing values along the 6D axis.</param>
 26663
 26664    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 26665
 26666    /// <param name="subdivisionOverride2">The subdivision overide to be used when splitting the 2 dimension.</param>
 26667
 26668    /// <param name="subdivisionOverride3">The subdivision overide to be used when splitting the 3 dimension.</param>
 26669
 26670    /// <param name="subdivisionOverride4">The subdivision overide to be used when splitting the 4 dimension.</param>
 26671
 26672    /// <param name="subdivisionOverride5">The subdivision overide to be used when splitting the 5 dimension.</param>
 26673
 26674    /// <param name="subdivisionOverride6">The subdivision overide to be used when splitting the 6 dimension.</param>
 26675    public OmnitreeBoundsLinked(
 26676      Omnitree.GetBoundings<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> getBoundings,
 26677      Func<Axis1, Axis1, CompareResult> compare1 = null,
 26678      Func<Axis2, Axis2, CompareResult> compare2 = null,
 26679      Func<Axis3, Axis3, CompareResult> compare3 = null,
 26680      Func<Axis4, Axis4, CompareResult> compare4 = null,
 26681      Func<Axis5, Axis5, CompareResult> compare5 = null,
 26682      Func<Axis6, Axis6, CompareResult> compare6 = null,
 26683      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOverr
 26684      , Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOve
 26685      , Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOve
 26686      , Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOve
 26687      , Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOve
 26688      , Omnitree.SubdivisionOverride<T, Axis6, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>> subdivisionOve
 26689      )
 26690      : this(
 26691      Omnitree.ConvertToGetBounds(getBoundings),
 26692      compare1 is null ? true : false,
 26693      compare1 ?? Compare,
 26694      compare2 is null ? true : false,
 26695      compare2 ?? Compare,
 26696      compare3 is null ? true : false,
 26697      compare3 ?? Compare,
 26698      compare4 is null ? true : false,
 26699      compare4 ?? Compare,
 26700      compare5 is null ? true : false,
 26701      compare5 ?? Compare,
 26702      compare6 is null ? true : false,
 26703      compare6 ?? Compare,
 26704      subdivisionOverride1
 26705,
 26706      subdivisionOverride2
 26707,
 26708      subdivisionOverride3
 26709,
 26710      subdivisionOverride4
 26711,
 26712      subdivisionOverride5
 26713,
 26714      subdivisionOverride6
 26715      ) { }
 26716
 26717    #endregion
 26718
 26719    #region Properties
 26720
 26721    /// <summary>The number of dimensions in this tree.</summary>
 26722    public int Dimensions => _dimensions;
 26723
 26724    /// <summary>The delegate being used by the omnitree to locate items in 6D space.</summary>
 26725    public Omnitree.GetBounds<T, Axis1
 26726      , Axis2
 26727      , Axis3
 26728      , Axis4
 26729      , Axis5
 26730      , Axis6
 26731      > GetBounds => _getBounds;
 26732
 26733
 26734    /// <summary>The comparison function the Omnitree is using along the 1D axis.</summary>
 26735    public Func<Axis1, Axis1, CompareResult> Compare1 => _compare1;
 26736    /// <summary>The comparison function the Omnitree is using along the 2D axis.</summary>
 26737    public Func<Axis2, Axis2, CompareResult> Compare2 => _compare2;
 26738    /// <summary>The comparison function the Omnitree is using along the 3D axis.</summary>
 26739    public Func<Axis3, Axis3, CompareResult> Compare3 => _compare3;
 26740    /// <summary>The comparison function the Omnitree is using along the 4D axis.</summary>
 26741    public Func<Axis4, Axis4, CompareResult> Compare4 => _compare4;
 26742    /// <summary>The comparison function the Omnitree is using along the 5D axis.</summary>
 26743    public Func<Axis5, Axis5, CompareResult> Compare5 => _compare5;
 26744    /// <summary>The comparison function the Omnitree is using along the 6D axis.</summary>
 26745    public Func<Axis6, Axis6, CompareResult> Compare6 => _compare6;
 26746
 26747    /// <summary>The current number of items in the tree.</summary>
 26748    public int Count  => _top.Count;
 26749
 26750    internal delegate void MaxDepthFinder(Node node, int current_depth, ref int max_depth);
 26751    /// <summary>Finds the current maximum depth of the tree. NOT AN O(1) OPERATION. Intended for educational purposes o
 26752    public int MaxDepth
 26753    {
 26754      get
 26755      {
 26756        MaxDepthFinder maxDepthFinder = null;
 26757        maxDepthFinder =
 26758            (Node node, int current_depth, ref int max_depth) =>
 26759            {
 26760              if (current_depth > max_depth)
 26761                max_depth = current_depth;
 26762              foreach (Node child in node.Children)
 26763                maxDepthFinder(child, current_depth + 1, ref max_depth);
 26764            };
 26765        int _max_depth = -1;
 26766        maxDepthFinder(this._top, 0, ref _max_depth);
 26767        return _max_depth;
 26768      }
 26769    }
 26770
 26771    internal delegate void NodeCountFinder(Node node, ref int current_count);
 26772    /// <summary>Counts the current number of nodes in the tree. NOT AN O(1) OPERATION. Intended for educational purpose
 26773    public int NodeCount
 26774    {
 26775      get
 26776      {
 26777        NodeCountFinder nodeCountFinder = null;
 26778        nodeCountFinder =
 26779            (Node node, ref int current_count) =>
 26780            {
 26781              current_count++;
 26782              foreach (Node child in node.Children)
 26783                nodeCountFinder(child, ref current_count);
 26784            };
 26785
 26786        int _current_count = 0;
 26787        nodeCountFinder(this._top, ref _current_count);
 26788        return _current_count;
 26789      }
 26790    }
 26791
 26792    #endregion
 26793
 26794    #region Methods
 26795
 26796    #region Add
 26797
 26798
 26799    #region single
 26800
 26801    /// <summary>Tries to add a value.</summary>
 26802    /// <param name="value">The value to be added.</param>
 26803    /// <returns>True if successful or false if not.</returns>
 26804    public (bool Success, Exception? Exception) TryAdd(T value)
 26805    {
 26806      Add(value);
 26807      return (true, null);
 26808    }
 26809
 26810    /// <summary>Adds an item to the tree.</summary>
 26811    /// <param name="addition">The item to be added.</param>
 26812    public void Add(T addition)
 26813    {
 26814      if (this._top.Count is int.MaxValue)
 26815        throw new System.InvalidOperationException("(Count is int.MaxValue) max Omnitree size reached (change ints to lo
 26816
 26817      // dynamic tree sizes
 26818      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 26819
 26820      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds = GetBoundings(addition);
 26821
 26822      // grow the first branch of the tree
 26823      if (!this._top.PointOfDivision.HasValue && this._top.Count >= _load)
 26824      {
 26825        Node top = this._top;
 26826
 26827        // create the new branch from the median values
 26828        this._top = new Node(DetermineMedians(top), Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>.None, null
 26829
 26830        // iterate through the values and add them to the appropriate children
 26831        for (Node.ValueNode list = top.Head; list is not null; list = list.Next)
 26832          Add(list.Value, this._top, GetBoundings(list.Value), 0);
 26833      }
 26834
 26835      this.Add(addition, this._top, bounds, 0);
 26836    }
 26837
 26838    /// <summary>Recursive version of the add function.</summary>
 26839    /// <param name="addition">The item to be added.</param>
 26840    /// <param name="node">The current node for tree trversal.</param>
 26841    /// <param name="bounds">The bounds of the addition.</param>
 26842    /// <param name="depth">The current depth of iteration.</param>
 26843    internal void Add(T addition, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds, int depth
 26844    {
 26845      if (!node.PointOfDivision.HasValue)
 26846      {
 26847        //Leaf leaf = node as Leaf;
 26848        if (depth >= _load || !(node.Count >= _load))
 26849        {
 26850          node.Add(addition);
 26851          return;
 26852        }
 26853        else
 26854        {
 26855          //Node parent = node.Parent;
 26856          //int child_index = this.DetermineChildIndex(parent.PointOfDivision, location);
 26857          //Node growth = new Node(DetermineMedians(leaf), leaf.Bounds, parent, child_index);
 26858          //parent[child_index] = growth;
 26859
 26860          Node growth = new Node(DetermineMedians(node), node.Bounds, node.Parent, node.Index);
 26861          node.Parent[node.Index] = growth;
 26862
 26863          for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 26864          {
 26865            Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> temp_bounds = GetBoundings(list.Value);
 26866            if (EncapsulationCheck(growth.Bounds, temp_bounds))
 26867              Add(list.Value, growth, temp_bounds, depth);
 26868            else
 26869            {
 26870              ReduceParentCounts(node.Parent, 1);
 26871              Add(list.Value, this._top, temp_bounds, depth);
 26872            }
 26873          }
 26874
 26875          Add(addition, growth, bounds, depth);
 26876          return;
 26877        }
 26878      }
 26879      else
 26880      {
 26881        //Node branch = node as Node;
 26882        int child_index = this.DetermineChildIndex(node.PointOfDivision.Value, bounds); // determine the child "index" (
 26883
 26884        // if -1, then the bounds of the addition straddle the point of division (keep it in current node)
 26885        if (child_index is -1)
 26886        {
 26887          node.Add(addition);
 26888          return;
 26889        }
 26890
 26891        Node child_node = node[child_index];
 26892
 26893        // null children in branches are just empty leaves
 26894        if (child_node is null)
 26895        {
 26896          Node new_node = new Node(DetermineChildBounds(node, child_index), node, child_index);
 26897          node[child_index] = new_node;
 26898          new_node.Add(addition);
 26899        }
 26900        else
 26901          // child exists already, continue adding
 26902          Add(addition, child_node, bounds, depth + 1);
 26903
 26904        node.Count++;
 26905        return;
 26906      }
 26907    }
 26908
 26909    internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> DetermineMedians(Node node)
 26910    {
 26911      //try
 26912      //{
 26913        // extract the values
 26914        Omnitree.Bound<Axis1>[] values1 = new Omnitree.Bound<Axis1>[node.Count * 2];
 26915        Omnitree.Bound<Axis2>[] values2 = new Omnitree.Bound<Axis2>[node.Count * 2];
 26916        Omnitree.Bound<Axis3>[] values3 = new Omnitree.Bound<Axis3>[node.Count * 2];
 26917        Omnitree.Bound<Axis4>[] values4 = new Omnitree.Bound<Axis4>[node.Count * 2];
 26918        Omnitree.Bound<Axis5>[] values5 = new Omnitree.Bound<Axis5>[node.Count * 2];
 26919        Omnitree.Bound<Axis6>[] values6 = new Omnitree.Bound<Axis6>[node.Count * 2];
 26920        Node.ValueNode for_current = node.Head; // used in for loop
 26921        for (int i = 0; i < node.Count; i++, for_current = for_current.Next)
 26922          this._getBounds(for_current.Value,
 26923          out values1[i * 2], out values1[i * 2 + 1]
 26924,
 26925          out values2[i * 2], out values2[i * 2 + 1]
 26926,
 26927          out values3[i * 2], out values3[i * 2 + 1]
 26928,
 26929          out values4[i * 2], out values4[i * 2 + 1]
 26930,
 26931          out values5[i * 2], out values5[i * 2 + 1]
 26932,
 26933          out values6[i * 2], out values6[i * 2 + 1]
 26934          );
 26935        return new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(
 26936          Omnitree.SubDivide(values1, this._defaultCompare1 ? Compare : this._compare1)
 26937,
 26938          Omnitree.SubDivide(values2, this._defaultCompare2 ? Compare : this._compare2)
 26939,
 26940          Omnitree.SubDivide(values3, this._defaultCompare3 ? Compare : this._compare3)
 26941,
 26942          Omnitree.SubDivide(values4, this._defaultCompare4 ? Compare : this._compare4)
 26943,
 26944          Omnitree.SubDivide(values5, this._defaultCompare5 ? Compare : this._compare5)
 26945,
 26946          Omnitree.SubDivide(values6, this._defaultCompare6 ? Compare : this._compare6)
 26947          );
 26948      //}
 26949      //catch
 26950      //{
 26951        // extract the values
 26952      //  ArrayJagged<Omnitree.Bound<Axis1>> values1 = new ArrayJagged<Omnitree.Bound<Axis1>>(node.Count * 2);
 26953      //  ArrayJagged<Omnitree.Bound<Axis2>> values2 = new ArrayJagged<Omnitree.Bound<Axis2>>(node.Count * 2);
 26954      //  ArrayJagged<Omnitree.Bound<Axis3>> values3 = new ArrayJagged<Omnitree.Bound<Axis3>>(node.Count * 2);
 26955      //  ArrayJagged<Omnitree.Bound<Axis4>> values4 = new ArrayJagged<Omnitree.Bound<Axis4>>(node.Count * 2);
 26956      //  ArrayJagged<Omnitree.Bound<Axis5>> values5 = new ArrayJagged<Omnitree.Bound<Axis5>>(node.Count * 2);
 26957      //  ArrayJagged<Omnitree.Bound<Axis6>> values6 = new ArrayJagged<Omnitree.Bound<Axis6>>(node.Count * 2);
 26958      //  Node.ValueNode for_current = node.Head; // used in for loop
 26959      //  for (int i = 0; i < node.Count; i++, for_current = for_current.Next)
 26960      //  {
 26961      //    Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 26962      //    Omnitree.Bound<Axis2> min2; Omnitree.Bound<Axis2> max2;
 26963      //    Omnitree.Bound<Axis3> min3; Omnitree.Bound<Axis3> max3;
 26964      //    Omnitree.Bound<Axis4> min4; Omnitree.Bound<Axis4> max4;
 26965      //    Omnitree.Bound<Axis5> min5; Omnitree.Bound<Axis5> max5;
 26966      //    Omnitree.Bound<Axis6> min6; Omnitree.Bound<Axis6> max6;
 26967      //    this._getBounds(for_current.Value,
 26968      //      out min1, out max1
 26969//,
 26970      //      out min2, out max2
 26971//,
 26972      //      out min3, out max3
 26973//,
 26974      //      out min4, out max4
 26975//,
 26976      //      out min5, out max5
 26977//,
 26978      //      out min6, out max6
 26979      //      );
 26980      //    values1[i * 2] = min1; values1[i * 2 + 1] = max1;
 26981      //    values2[i * 2] = min2; values2[i * 2 + 1] = max2;
 26982      //    values3[i * 2] = min3; values3[i * 2 + 1] = max3;
 26983      //    values4[i * 2] = min4; values4[i * 2 + 1] = max4;
 26984      //    values5[i * 2] = min5; values5[i * 2 + 1] = max5;
 26985      //    values6[i * 2] = min6; values6[i * 2 + 1] = max6;
 26986      //  }
 26987      //  return new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(
 26988      //    Omnitree.SubDivide(values1, this._defaultCompare1 ? Compare : this._compare1)
 26989      //    , Omnitree.SubDivide(values2, this._defaultCompare2 ? Compare : this._compare2)
 26990      //    , Omnitree.SubDivide(values3, this._defaultCompare3 ? Compare : this._compare3)
 26991      //    , Omnitree.SubDivide(values4, this._defaultCompare4 ? Compare : this._compare4)
 26992      //    , Omnitree.SubDivide(values5, this._defaultCompare5 ? Compare : this._compare5)
 26993      //    , Omnitree.SubDivide(values6, this._defaultCompare6 ? Compare : this._compare6)
 26994      //  );
 26995      //}
 26996    }
 26997
 26998    #endregion
 26999
 27000    #region Add Helpers
 27001
 27002    internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> DetermineChildBounds(Node node, int child_index)
 27003    {
 27004      // the node parameter should always have a point of division value for this function
 27005      Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> pointOfDivision = node.PointOfDivision.Value;
 27006
 27007      Omnitree.Bound<Axis6> min6, max6;
 27008      if (child_index >= 32)
 27009      {
 27010        min6 = pointOfDivision.Axis6;
 27011        max6 = node.Bounds.Max6;
 27012        child_index -= 32;
 27013      }
 27014      else
 27015      {
 27016        min6 = node.Bounds.Min6;
 27017        max6 = pointOfDivision.Axis6;
 27018      }
 27019
 27020      Omnitree.Bound<Axis5> min5, max5;
 27021      if (child_index >= 16)
 27022      {
 27023        min5 = pointOfDivision.Axis5;
 27024        max5 = node.Bounds.Max5;
 27025        child_index -= 16;
 27026      }
 27027      else
 27028      {
 27029        min5 = node.Bounds.Min5;
 27030        max5 = pointOfDivision.Axis5;
 27031      }
 27032
 27033      Omnitree.Bound<Axis4> min4, max4;
 27034      if (child_index >= 8)
 27035      {
 27036        min4 = pointOfDivision.Axis4;
 27037        max4 = node.Bounds.Max4;
 27038        child_index -= 8;
 27039      }
 27040      else
 27041      {
 27042        min4 = node.Bounds.Min4;
 27043        max4 = pointOfDivision.Axis4;
 27044      }
 27045
 27046      Omnitree.Bound<Axis3> min3, max3;
 27047      if (child_index >= 4)
 27048      {
 27049        min3 = pointOfDivision.Axis3;
 27050        max3 = node.Bounds.Max3;
 27051        child_index -= 4;
 27052      }
 27053      else
 27054      {
 27055        min3 = node.Bounds.Min3;
 27056        max3 = pointOfDivision.Axis3;
 27057      }
 27058
 27059      Omnitree.Bound<Axis2> min2, max2;
 27060      if (child_index >= 2)
 27061      {
 27062        min2 = pointOfDivision.Axis2;
 27063        max2 = node.Bounds.Max2;
 27064        child_index -= 2;
 27065      }
 27066      else
 27067      {
 27068        min2 = node.Bounds.Min2;
 27069        max2 = pointOfDivision.Axis2;
 27070      }
 27071
 27072      Omnitree.Bound<Axis1> min1, max1;
 27073      if (child_index >= 1)
 27074      {
 27075        min1 = pointOfDivision.Axis1;
 27076        max1 = node.Bounds.Max1;
 27077        child_index -= 1;
 27078      }
 27079      else
 27080      {
 27081        min1 = node.Bounds.Min1;
 27082        max1 = pointOfDivision.Axis1;
 27083      }
 27084
 27085      return new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2, min3, max3, min4, max
 27086    }
 27087
 27088    #endregion
 27089
 27090    #endregion
 27091
 27092    #region Clear
 27093
 27094    /// <summary>Returns the tree to an empty state.</summary>
 27095    public void Clear()
 27096    {
 27097      this._top = new Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>.None, null, -1);
 27098      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 27099    }
 27100
 27101    #endregion
 27102
 27103    #region Clone
 27104
 27105    /// <summary>Creates a shallow clone of this data structure.</summary>
 27106    /// <returns>A shallow clone of this data structure.</returns>
 27107    public OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> Clone()
 27108    {
 27109      return new OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(this);
 27110    }
 27111
 27112    #endregion
 27113
 27114    #region Count
 27115
 27116    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 27117    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 27118    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 27119    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 27120    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 27121    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 27122    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 27123    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 27124    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 27125    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 27126    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 27127    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 27128    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 27129    /// <returns>The number of items in the provided sub space.</returns>
 27130    public int CountSubSpaceEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 m
 27131    {
 27132      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, m
 27133    }
 27134    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 27135    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 27136    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 27137    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 27138    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 27139    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 27140    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 27141    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 27142    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 27143    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 27144    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 27145    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 27146    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 27147    /// <returns>The number of items in the provided sub space.</returns>
 27148    public int CountSubSpaceEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> m
 27149    {
 27150      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, m
 27151    }
 27152    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 27153    /// <param name="axis1">The coordinate along the 1D axis.</param>
 27154    /// <param name="axis2">The coordinate along the 2D axis.</param>
 27155    /// <param name="axis3">The coordinate along the 3D axis.</param>
 27156    /// <param name="axis4">The coordinate along the 4D axis.</param>
 27157    /// <param name="axis5">The coordinate along the 5D axis.</param>
 27158    /// <param name="axis6">The coordinate along the 6D axis.</param>
 27159    /// <returns>The number of items in the provided sub space.</returns>
 27160    public int CountSubSpaceEncapsulated(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6)
 27161    {
 27162      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(axis1, axis1,
 27163    }
 27164    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 27165    /// <param name="axis1">The coordinate along the 1D axis.</param>
 27166    /// <param name="axis2">The coordinate along the 2D axis.</param>
 27167    /// <param name="axis3">The coordinate along the 3D axis.</param>
 27168    /// <param name="axis4">The coordinate along the 4D axis.</param>
 27169    /// <param name="axis5">The coordinate along the 5D axis.</param>
 27170    /// <param name="axis6">The coordinate along the 6D axis.</param>
 27171    /// <returns>The number of items in the provided sub space.</returns>
 27172    public int CountSubSpaceEncapsulated(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3>
 27173    {
 27174      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(axis1, axis1,
 27175    }
 27176
 27177    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 27178    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 27179    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 27180    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 27181    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 27182    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 27183    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 27184    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 27185    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 27186    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 27187    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 27188    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 27189    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 27190    /// <returns>The number of items in the provided sub space.</returns>
 27191    public int CountSubSpaceOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min
 27192    {
 27193      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min
 27194    }
 27195    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 27196    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 27197    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 27198    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 27199    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 27200    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 27201    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 27202    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 27203    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 27204    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 27205    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 27206    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 27207    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 27208    /// <returns>The number of items in the provided sub space.</returns>
 27209    public int CountSubSpaceOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min
 27210    {
 27211      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min
 27212    }
 27213    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 27214    /// <param name="axis1">The coordinate along the 1D axis.</param>
 27215    /// <param name="axis2">The coordinate along the 2D axis.</param>
 27216    /// <param name="axis3">The coordinate along the 3D axis.</param>
 27217    /// <param name="axis4">The coordinate along the 4D axis.</param>
 27218    /// <param name="axis5">The coordinate along the 5D axis.</param>
 27219    /// <param name="axis6">The coordinate along the 6D axis.</param>
 27220    /// <returns>The number of items in the provided sub space.</returns>
 27221    public int CountSubSpaceOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6)
 27222    {
 27223      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(axis1, axis1, a
 27224    }
 27225    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 27226    /// <param name="axis1">The coordinate along the 1D axis.</param>
 27227    /// <param name="axis2">The coordinate along the 2D axis.</param>
 27228    /// <param name="axis3">The coordinate along the 3D axis.</param>
 27229    /// <param name="axis4">The coordinate along the 4D axis.</param>
 27230    /// <param name="axis5">The coordinate along the 5D axis.</param>
 27231    /// <param name="axis6">The coordinate along the 6D axis.</param>
 27232    /// <returns>The number of items in the provided sub space.</returns>
 27233    public int CountSubSpaceOverlapped(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> a
 27234    {
 27235      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(axis1, axis1, a
 27236    }
 27237
 27238    internal int CountSubSpaceEncapsulated(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds)
 27239    {
 27240      return CountSubSpaceBase(_top, bounds, (a, b) => EncapsulationCheck(a, b));
 27241    }
 27242
 27243    internal int CountSubSpaceOverlapped(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds)
 27244    {
 27245      return CountSubSpaceBase(_top, bounds, (a, b) => InclusionCheck(a, b));
 27246    }
 27247
 27248    internal int CountSubSpaceBase(
 27249      Node node,
 27250      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds,
 27251      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>, Omnitree.Bounds<Axis1, Axis2, Axi
 27252    {
 27253      // adjust min/max values
 27254      int count = 0;
 27255      if (EncapsulationCheck(bounds, node.Bounds))
 27256        count += node.Count;
 27257      else if (!node.PointOfDivision.HasValue)
 27258      {
 27259        for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 27260          if (spatialCheck(bounds, GetBoundings(list.Value)))
 27261            count++;
 27262      }
 27263      else
 27264      {
 27265        Node branch = node as Node;
 27266        if (!StraddlesLines(branch.Bounds, branch.PointOfDivision.Value))
 27267        {
 27268          int child_index = DetermineChildIndex(branch.PointOfDivision.Value, bounds);
 27269          Node child = branch[child_index];
 27270          if (child is not null)
 27271            count += this.CountSubSpaceBase(child, bounds, spatialCheck);
 27272        }
 27273        else
 27274        {
 27275          foreach (Node child in node.Children)
 27276            count += this.CountSubSpaceBase(child, bounds, spatialCheck);
 27277        }
 27278      }
 27279      return count;
 27280    }
 27281
 27282    #endregion
 27283
 27284    #region Update
 27285
 27286    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 27287    public void Update()
 27288    {
 27289      this.Update(this._top, 0);
 27290    }
 27291
 27292    /// <summary>Recursive version of the Update method.</summary>
 27293    /// <param name="node">The current node of iteration.</param>
 27294    /// <param name="depth">The current depth of iteration.</param>
 27295    internal int Update(Node node, int depth)
 27296    {
 27297      int removals = 0;
 27298
 27299      {
 27300        Node branch = node as Node;
 27301        int skipped = 0;
 27302        for (int i = 0; i + skipped < branch.Children.Length; )
 27303        {
 27304          removals += this.Update(branch.Children[i], depth + 1);
 27305          if (branch.Children[i].Count is 0)
 27306            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 27307          else
 27308            i++;
 27309        }
 27310        Node[] newArray = new Node[branch.Children.Length - skipped];
 27311        Array.Copy(branch.Children, newArray, newArray.Length);
 27312        branch.Children = newArray;
 27313
 27314        if (branch.Count < _load && branch.Count != 0)
 27315          ShrinkChild(branch.Parent, branch.Index);
 27316      }
 27317
 27318      {
 27319        Node.ValueNode current = node.Head;
 27320        Node.ValueNode previous = null;
 27321        while (current is not null)
 27322        {
 27323          Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds = GetBoundings(current.Value);
 27324          if (!this.EncapsulationCheck(node.Bounds, bounds))
 27325          {
 27326            removals++;
 27327            T updated = current.Value;
 27328            if (previous is null)
 27329            {
 27330              node.Head = current.Next;
 27331              goto HeadRemoved;
 27332            }
 27333            else
 27334              previous.Next = current.Next;
 27335
 27336            Node whereToAdd = GetEncapsulationParent(node.Parent, bounds);
 27337
 27338            if (whereToAdd is null)
 27339              throw new System.Exception("an item was updated outside the range of the omnitree");
 27340
 27341            this.Add(updated, whereToAdd, bounds, whereToAdd.Depth);
 27342          }
 27343          previous = current;
 27344        HeadRemoved:
 27345          current = current.Next;
 27346        }
 27347      }
 27348
 27349      node.Count -= removals;
 27350      return removals;
 27351    }
 27352
 27353    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 27354    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 27355    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 27356    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 27357    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 27358    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 27359    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 27360    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 27361    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 27362    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 27363    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 27364    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 27365    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 27366    public void Update(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4, A
 27367    {
 27368      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2, min3, max3, min4
 27369    }
 27370    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 27371    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 27372    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 27373    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 27374    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 27375    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 27376    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 27377    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 27378    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 27379    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 27380    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 27381    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 27382    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 27383    public void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 27384    {
 27385      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2, min3, max3, min4
 27386    }
 27387    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 27388    /// <param name="axis1">The coordinate along the 1D axis.</param>
 27389    /// <param name="axis2">The coordinate along the 2D axis.</param>
 27390    /// <param name="axis3">The coordinate along the 3D axis.</param>
 27391    /// <param name="axis4">The coordinate along the 4D axis.</param>
 27392    /// <param name="axis5">The coordinate along the 5D axis.</param>
 27393    /// <param name="axis6">The coordinate along the 6D axis.</param>
 27394    public void Update(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6)
 27395    {
 27396      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(axis1, axis1, axis2, axis2, axis3, axis3
 27397    }
 27398    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 27399    /// <param name="axis1">The coordinate along the 1D axis.</param>
 27400    /// <param name="axis2">The coordinate along the 2D axis.</param>
 27401    /// <param name="axis3">The coordinate along the 3D axis.</param>
 27402    /// <param name="axis4">The coordinate along the 4D axis.</param>
 27403    /// <param name="axis5">The coordinate along the 5D axis.</param>
 27404    /// <param name="axis6">The coordinate along the 6D axis.</param>
 27405    public void Update(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3, Omnitree.B
 27406    {
 27407      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(axis1, axis1, axis2, axis2, axis3, axis3
 27408    }
 27409    internal int Update(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds, Node node, int depth)
 27410    {
 27411      if (!InclusionCheck(bounds, node.Bounds))
 27412        return 0;
 27413
 27414      int removals = 0;
 27415
 27416      {
 27417        Node branch = node as Node;
 27418        int skipped = 0;
 27419        for (int i = 0; i + skipped < branch.Children.Length; )
 27420        {
 27421          removals += this.Update(branch.Children[i], depth + 1);
 27422          if (branch.Children[i].Count is 0)
 27423            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 27424          else
 27425            i++;
 27426        }
 27427        Node[] newArray = new Node[branch.Children.Length - skipped];
 27428        Array.Copy(branch.Children, newArray, newArray.Length);
 27429        branch.Children = newArray;
 27430
 27431        if (branch.Count < _load && branch.Count != 0)
 27432          ShrinkChild(branch.Parent, branch.Index);
 27433      }
 27434
 27435      {
 27436        Node.ValueNode current = node.Head;
 27437        Node.ValueNode previous = null;
 27438        while (current is not null)
 27439        {
 27440          Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> item_bounds = GetBoundings(current.Value);
 27441          if (!this.EncapsulationCheck(node.Bounds, item_bounds))
 27442          {
 27443            removals++;
 27444            T updated = current.Value;
 27445            if (previous is null)
 27446            {
 27447              node.Head = current.Next;
 27448              goto HeadRemoved;
 27449            }
 27450            else
 27451              previous.Next = current.Next;
 27452            Node whereToAdd = GetEncapsulationParent(node.Parent, item_bounds);
 27453            if (whereToAdd is null)
 27454              throw new System.Exception("an item was updates outside the range of the omnitree");
 27455            this.Add(updated, whereToAdd, item_bounds, whereToAdd.Depth);
 27456          }
 27457          previous = current;
 27458        HeadRemoved:
 27459          current = current.Next;
 27460        }
 27461      }
 27462
 27463      node.Count -= removals;
 27464      return removals;
 27465    }
 27466
 27467    #endregion
 27468
 27469    #region Remove
 27470
 27471    /// <summary>Removes all the items qualified by the delegate.</summary>
 27472    /// <param name="where">The predicate to qualify removals.</param>
 27473    public void Remove(Predicate<T> where)
 27474    {
 27475      this.Remove(this._top, where);
 27476      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 27477    }
 27478
 27479    /// <summary>Recursive version of the remove method.</summary>
 27480    /// <param name="node">The current node of traversal.</param>
 27481    /// <param name="where">The predicate to qualify removals.</param>
 27482    internal int Remove(Node node, Predicate<T> where)
 27483    {
 27484      int removals = 0;
 27485
 27486      // children
 27487      if (node.Children is not null)
 27488      {
 27489        int skipped = 0;
 27490        for (int i = 0; i + skipped < node.Children.Length; )
 27491        {
 27492          removals += this.Remove(node.Children[i], where);
 27493          if (node.Children[i].Count is 0)
 27494            node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 27495          else
 27496            i++;
 27497        }
 27498        Node[] newArray = new Node[node.Children.Length - skipped];
 27499        Array.Copy(node.Children, newArray, newArray.Length);
 27500        node.Children = newArray;
 27501
 27502        if (node.Count < _load && node.Count != 0)
 27503          ShrinkChild(node.Parent, node.Index);
 27504      }
 27505
 27506      // items
 27507      while (node.Head is not null && where(node.Head.Value))
 27508      {
 27509        node.Head = node.Head.Next;
 27510        removals++;
 27511      }
 27512      if (node.Head is not null)
 27513      {
 27514        Node.ValueNode list = node.Head;
 27515        while (list.Next is not null)
 27516        {
 27517          if (where(list.Next.Value))
 27518          {
 27519            list.Next = list.Next.Next;
 27520            removals++;
 27521          }
 27522        }
 27523      }
 27524
 27525      node.Count -= removals;
 27526      return removals;
 27527    }
 27528
 27529    /// <summary>Removes all the items encapsulated in a given space.</summary>
 27530    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 27531    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 27532    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 27533    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 27534    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 27535    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 27536    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 27537    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 27538    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 27539    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 27540    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 27541    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 27542    /// <returns>The number of items that were removed.</returns>
 27543    public void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, A
 27544    {
 27545      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2,
 27546    }
 27547    /// <summary>Removes all the items encapsulated in a given space.</summary>
 27548    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 27549    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 27550    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 27551    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 27552    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 27553    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 27554    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 27555    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 27556    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 27557    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 27558    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 27559    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 27560    /// <returns>The number of items that were removed.</returns>
 27561    public void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, O
 27562    {
 27563      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2,
 27564    }
 27565    /// <summary>Removes all the items encapsulated in a given space.</summary>
 27566    /// <param name="axis1">The coordinate along the 1D axis.</param>
 27567    /// <param name="axis2">The coordinate along the 2D axis.</param>
 27568    /// <param name="axis3">The coordinate along the 3D axis.</param>
 27569    /// <param name="axis4">The coordinate along the 4D axis.</param>
 27570    /// <param name="axis5">The coordinate along the 5D axis.</param>
 27571    /// <param name="axis6">The coordinate along the 6D axis.</param>
 27572    public void RemoveEncapsulated(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3
 27573    {
 27574      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(axis1, axis1, axi
 27575    }
 27576    internal int RemoveEncapsulated(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds)
 27577    {
 27578      int removals = this.RemoveBase(node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 27579      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 27580      return removals;
 27581    }
 27582
 27583    /// <summary>Removes all the items overlapping a given space.</summary>
 27584    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 27585    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 27586    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 27587    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 27588    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 27589    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 27590    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 27591    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 27592    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 27593    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 27594    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 27595    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 27596    /// <returns>The number of items that were removed.</returns>
 27597    public void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axi
 27598    {
 27599      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, m
 27600    }
 27601    /// <summary>Removes all the items overlapping a given space.</summary>
 27602    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 27603    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 27604    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 27605    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 27606    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 27607    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 27608    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 27609    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 27610    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 27611    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 27612    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 27613    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 27614    /// <returns>The number of items that were removed.</returns>
 27615    public void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omn
 27616    {
 27617      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, m
 27618    }
 27619    internal int RemoveOverlapped(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds)
 27620    {
 27621      int removals = this.RemoveBase(node, bounds, (a, b) => this.InclusionCheck(a, b));
 27622      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 27623      return removals;
 27624    }
 27625
 27626    internal int RemoveBase(
 27627      Node node,
 27628      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds,
 27629      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>, Omnitree.Bounds<Axis1, Axis2, Axi
 27630    {
 27631      int removals = 0;
 27632      if (InclusionCheck(bounds, node.Bounds))
 27633      {
 27634        // items
 27635        Node.ValueNode current_node = node.Head;
 27636        Node.ValueNode previous_node = null;
 27637        while (!(current_node is null))
 27638        {
 27639          Node.ValueNode temp_previous = current_node;
 27640          if (spatialCheck(bounds, GetBoundings(current_node.Value)))
 27641          {
 27642            removals++;
 27643            if (current_node == node.Head)
 27644              node.Head = node.Head.Next;
 27645            else
 27646            {
 27647              previous_node.Next = current_node.Next;
 27648              temp_previous = previous_node;
 27649            }
 27650          }
 27651          previous_node = temp_previous;
 27652          current_node = current_node.Next;
 27653        }
 27654
 27655        // children
 27656        if (node.Children is not null)
 27657        {
 27658          int skipped = 0;
 27659          for (int i = 0; i + skipped < node.Children.Length; )
 27660          {
 27661            removals += this.RemoveBase(node.Children[i], bounds, spatialCheck);
 27662            if (node.Children[i].Count is 0)
 27663              node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 27664            else
 27665              i++;
 27666          }
 27667          Node[] newArray = new Node[node.Children.Length - skipped];
 27668          Array.Copy(node.Children, newArray, newArray.Length);
 27669          node.Children = newArray;
 27670
 27671          // convert this branch back into a leaf
 27672          // Note: if count is zero, it will be chopped off
 27673          if (node.Count < _load && node.Count > 0)
 27674            ShrinkChild(node.Parent, node.Index);
 27675        }
 27676      }
 27677
 27678      node.Count -= removals;
 27679      return removals;
 27680    }
 27681
 27682    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 27683    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 27684    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 27685    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 27686    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 27687    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 27688    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 27689    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 27690    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 27691    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 27692    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 27693    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 27694    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 27695    /// <param name="where">The equality constraint of the removal.</param>
 27696    public void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, A
 27697    {
 27698      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2,
 27699    }
 27700    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 27701    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 27702    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 27703    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 27704    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 27705    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 27706    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 27707    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 27708    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 27709    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 27710    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 27711    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 27712    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 27713    /// <param name="where">The equality constraint of the removal.</param>
 27714    public void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, O
 27715    {
 27716      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2,
 27717    }
 27718    internal int RemoveEncapsulated(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds, Predica
 27719    {
 27720      int removals = RemoveBase(node, bounds, where, (a, b) => this.EncapsulationCheck(a, b));
 27721      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 27722      return removals;
 27723    }
 27724
 27725    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 27726    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 27727    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 27728    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 27729    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 27730    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 27731    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 27732    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 27733    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 27734    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 27735    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 27736    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 27737    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 27738    /// <param name="where">The equality constraint of the removal.</param>
 27739    public void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axi
 27740    {
 27741      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, m
 27742    }
 27743    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 27744    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 27745    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 27746    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 27747    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 27748    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 27749    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 27750    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 27751    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 27752    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 27753    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 27754    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 27755    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 27756    /// <param name="where">The equality constraint of the removal.</param>
 27757    public void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omn
 27758    {
 27759      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, m
 27760    }
 27761    internal int RemoveOverlapped(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds, Predicate
 27762    {
 27763      int removals = RemoveBase(node, bounds, where, (a, b) => this.InclusionCheck(a, b));
 27764      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 27765      return removals;
 27766    }
 27767
 27768    internal int RemoveBase(
 27769      Node node,
 27770      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds,
 27771      Predicate<T> where,
 27772      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>, Omnitree.Bounds<Axis1, Axis2, Axi
 27773    {
 27774      if (!InclusionCheck(node.Bounds, bounds))
 27775        return 0;
 27776      int removals = 0;
 27777
 27778      // items
 27779      Node.ValueNode current = node.Head;
 27780      Node.ValueNode previous = null;
 27781      while (current is not null)
 27782      {
 27783        if (spatialCheck(bounds, GetBoundings(current.Value)) && where(current.Value))
 27784        {
 27785          removals++;
 27786          if (previous is null)
 27787          {
 27788            node.Head = current.Next;
 27789            goto HeadRemoved;
 27790          }
 27791          else
 27792            previous.Next = current.Next;
 27793        }
 27794        previous = current;
 27795      HeadRemoved:
 27796        current = current.Next;
 27797      }
 27798
 27799      // children
 27800      if (node.Children is not null)
 27801      {
 27802        int skipped = 0;
 27803        for (int i = 0; i + skipped < node.Children.Length; )
 27804        {
 27805          removals += this.RemoveBase(node.Children[i], bounds, where, spatialCheck);
 27806          if (node.Children[i].Count is 0)
 27807            node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 27808          else
 27809            i++;
 27810        }
 27811        Node[] newArray = new Node[node.Children.Length - skipped];
 27812        Array.Copy(node.Children, newArray, newArray.Length);
 27813        node.Children = newArray;
 27814
 27815        if (node.Count < _load && node.Count != 0)
 27816          ShrinkChild(node.Parent, node.Index);
 27817      }
 27818
 27819      node.Count -= removals;
 27820      return removals;
 27821    }
 27822
 27823    /// <summary>Tries to remove a value.</summary>
 27824    /// <param name="value">The value to remove.</param>
 27825    /// <returns>True if successful or false if not.</returns>
 27826    public (bool Success, Exception? Exception) TryRemove(T value)
 27827    {
 27828      Remove(value);
 27829      return (true, null);
 27830    }
 27831
 27832    /// <summary>Removes all instances of a given value.</summary>
 27833    public void Remove(T removal) => Omnitree.Remove(this, removal);
 27834
 27835    /// <summary>Removes all instances of a given value.</summary>
 27836    public void Remove(T removal, Func<T, T, bool> equate) => Omnitree.Remove(this, removal, equate);
 27837
 27838    /// <summary>Removes all the items in a given space.</summary>
 27839    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 27840    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 27841    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 27842    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 27843    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 27844    /// <param name="axis6">The axis of the removal along the  6D axis.</param>
 27845    /// <returns>The number of items that were removed.</returns>
 27846    public void RemoveOverlapped(Axis1 axis1
 27847      , Axis2 axis2
 27848      , Axis3 axis3
 27849      , Axis4 axis4
 27850      , Axis5 axis5
 27851      , Axis6 axis6
 27852      )
 27853    {
 27854      this.RemoveOverlapped(axis1, axis1
 27855        , axis2, axis2
 27856        , axis3, axis3
 27857        , axis4, axis4
 27858        , axis5, axis5
 27859        , axis6, axis6
 27860        );
 27861      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 27862    }
 27863
 27864    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 27865    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 27866    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 27867    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 27868    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 27869    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 27870    /// <param name="axis6">The axis of the removal along the  6D axis.</param>
 27871    /// <param name="where">The equality constraint of the removal.</param>
 27872    public void RemoveOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6, Predicate
 27873    {
 27874      this.RemoveOverlapped(axis1, axis1
 27875        , axis2, axis2
 27876        , axis3, axis3
 27877        , axis4, axis4
 27878        , axis5, axis5
 27879        , axis6, axis6
 27880        , where);
 27881      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 27882    }
 27883
 27884    #endregion
 27885
 27886    #region Stepper And IEnumerable
 27887
 27888    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 27889    /// <param name="step">The delegate to perform on every item in the tree.</param>
 27890    public void Stepper(Action<T> step) =>
 27891      this.Stepper(step, this._top);
 27892
 27893    internal void Stepper(Action<T> step, Node node)
 27894    {
 27895      Node.ValueNode list = node.Head;
 27896      while (list is not null)
 27897      {
 27898        step(list.Value);
 27899        list = list.Next;
 27900      }
 27901      if (node.Children is not null)
 27902        foreach (Node child in node.Children)
 27903          this.Stepper(step, child);
 27904    }
 27905
 27906    public StepStatus StepperBreak<TStep>(TStep step = default)
 27907      where TStep : struct, IFunc<T, StepStatus> =>
 27908      StepperBreak(_top, step);
 27909
 27910    internal StepStatus StepperBreak<TStep>(Node node, TStep step)
 27911      where TStep : struct, IFunc<T, StepStatus>
 27912    {
 27913      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 27914      {
 27915        if (step.Invoke(list.Value) is Break) return Break;
 27916      }
 27917      if (node.Children is not null)
 27918      {
 27919        foreach (Node child in node.Children)
 27920        {
 27921          if (StepperBreak(child, step) is Break) return Break;
 27922        }
 27923      }
 27924      return Continue;
 27925    }
 27926
 27927    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 27928    /// <param name="step">The delegate to perform on every item in the tree.</param>
 27929    public StepStatus Stepper(Func<T, StepStatus> step) =>
 27930      Stepper(step, _top);
 27931
 27932    internal StepStatus Stepper(Func<T, StepStatus> step, Node node)
 27933    {
 27934      StepStatus status = StepStatus.Continue;
 27935
 27936      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 27937        if ((status = step(list.Value)) != StepStatus.Continue)
 27938          break;
 27939
 27940      if (node.Children is not null)
 27941        foreach (Node child in node.Children)
 27942          if ((status = Stepper(step, child)) != StepStatus.Continue)
 27943            break;
 27944
 27945      return status;
 27946    }
 27947
 27948    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 27949    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 27950    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 27951    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 27952    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 27953    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 27954    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 27955    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 27956    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 27957    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 27958    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 27959    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 27960    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 27961    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 27962    public void StepperEncapsulated(Action<T> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 ma
 27963      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, ma
 27964
 27965    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 27966    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 27967    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 27968    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 27969    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 27970    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 27971    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 27972    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 27973    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 27974    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 27975    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 27976    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 27977    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 27978    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 27979    public void StepperEncapsulated(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bou
 27980      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, ma
 27981
 27982    internal void StepperEncapsulated(Action<T> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis
 27983      StepperBase(step, node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 27984
 27985    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 27986    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 27987    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 27988    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 27989    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 27990    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 27991    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 27992    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 27993    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 27994    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 27995    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 27996    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 27997    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 27998    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 27999    public void StepperOverlapped(Action<T> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3
 28000      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2
 28001
 28002    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 28003    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 28004    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28005    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28006    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28007    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28008    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28009    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28010    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28011    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28012    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28013    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28014    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28015    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28016    public void StepperOverlapped(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound
 28017      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2
 28018
 28019    internal void StepperOverlapped(Action<T> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>
 28020      StepperBase(step, node, bounds, (a, b) => this.InclusionCheck(a, b));
 28021
 28022    internal void StepperBase(
 28023      Action<T> step,
 28024      Node node,
 28025      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds,
 28026      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>, Omnitree.Bounds<Axis1, Axis2, Axi
 28027    {
 28028      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 28029        if (spatialCheck(bounds, GetBoundings(list.Value)))
 28030          step(list.Value);
 28031
 28032      if (node.Children is not null)
 28033      {
 28034        foreach (Node child in node.Children)
 28035          // optimization: stop bounds checking if space encapsulates node
 28036          if (EncapsulationCheck(bounds, child.Bounds))
 28037            this.Stepper(step, child);
 28038          else if (InclusionCheck(child.Bounds, bounds))
 28039            this.StepperBase(step, child, bounds, spatialCheck);
 28040      }
 28041    }
 28042
 28043    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 28044    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 28045    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28046    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28047    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28048    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28049    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28050    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28051    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28052    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28053    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28054    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28055    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28056    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28057    public StepStatus StepperEncapsulated(Func<T, StepStatus> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis
 28058      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, ma
 28059
 28060    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 28061    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 28062    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28063    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28064    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28065    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28066    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28067    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28068    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28069    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28070    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28071    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28072    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28073    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28074    public StepStatus StepperEncapsulated(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> ma
 28075      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, ma
 28076
 28077    internal StepStatus StepperEncapsulated(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Ax
 28078      StepperBase(step, node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 28079
 28080    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 28081    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 28082    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28083    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28084    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28085    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28086    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28087    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28088    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28089    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28090    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28091    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28092    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28093    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28094    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 
 28095      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2
 28096
 28097    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 28098    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 28099    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28100    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28101    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28102    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28103    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28104    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28105    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28106    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28107    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28108    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28109    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28110    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28111    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1
 28112      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(min1, max1, min2, max2
 28113
 28114    internal StepStatus StepperOverlapped(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis
 28115      StepperBase(step, node, bounds, (a, b) => this.InclusionCheck(a, b));
 28116
 28117    internal StepStatus StepperBase(
 28118      Func<T, StepStatus> step,
 28119      Node node,
 28120      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds,
 28121      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>, Omnitree.Bounds<Axis1, Axis2, Axi
 28122    {
 28123      StepStatus status = StepStatus.Continue;
 28124
 28125      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 28126        if (spatialCheck(bounds, GetBoundings(list.Value)) &&
 28127          (status = step(list.Value)) != StepStatus.Continue)
 28128          break;
 28129
 28130      if (node.Children is not null)
 28131      {
 28132        foreach (Node child in node.Children)
 28133          // optimization: stop bounds checking if space encapsulates node
 28134          if (EncapsulationCheck(bounds, child.Bounds) &&
 28135            (status = this.Stepper(step, child)) != StepStatus.Continue)
 28136            break;
 28137          else if (InclusionCheck(child.Bounds, bounds) &&
 28138            (status = this.StepperBase(step, child, bounds, spatialCheck)) != StepStatus.Continue)
 28139            break;
 28140      }
 28141
 28142      return status;
 28143    }
 28144
 28145    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 28146    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 28147    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 28148    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 28149    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 28150    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 28151    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 28152    /// <param name="axis6">The axis of the removal along the  6D axis.</param>
 28153    public void StepperOverlapped(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6
 28154      StepperOverlapped(step, this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(axis1, axis1
 28155        , axis2, axis2
 28156        , axis3, axis3
 28157        , axis4, axis4
 28158        , axis5, axis5
 28159        , axis6, axis6
 28160      ));
 28161
 28162    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 28163    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 28164    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 28165    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 28166    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 28167    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 28168    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 28169    /// <param name="axis6">The axis of the removal along the  6D axis.</param>
 28170    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Ax
 28171      StepperOverlapped(step, this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(axis1, axis1
 28172        , axis2, axis2
 28173        , axis3, axis3
 28174        , axis4, axis4
 28175        , axis5, axis5
 28176        , axis6, axis6
 28177        ));
 28178
 28179    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 28180
 28181    public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 28182    {
 28183      // Note: this can be optimized.
 28184      IList<T> list = new ListLinked<T>();
 28185      Stepper(x => list.Add(x));
 28186      return list.GetEnumerator();
 28187    }
 28188
 28189    #endregion
 28190
 28191    /// <inheritdoc/>
 28192    public T[] ToArray() => throw new NotImplementedException();
 28193
 28194    #region Helpers
 28195
 28196    internal bool StraddlesLines(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds, Omnitree.Vector<Axis1
 28197      Omnitree.StraddlesLines(bounds, vector
 28198        , _compare1
 28199        , _compare2
 28200        , _compare3
 28201        , _compare4
 28202        , _compare5
 28203        , _compare6
 28204        );
 28205
 28206    /// <summary>Computes the child index that contains the desired dimensions.</summary>
 28207    /// <param name="pointOfDivision">The point of division to compare against.</param>
 28208    /// <param name="bounds">The dimensions to determine the child index.</param>
 28209    /// <returns>The computed child index based on the coordinates relative to the center of the node.</returns>
 28210    internal int DetermineChildIndex(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> pointOfDivision, Omnitree
 28211    {
 28212      // make sure a child encapsulates the bounds (otherwise the bounds cannot move down the tree)
 28213      if (StraddlesLines(bounds, pointOfDivision))
 28214        return -1;
 28215
 28216      int child = 0;
 28217      if (!bounds.Min1.Exists || !(this._compare1(bounds.Min1.Value, pointOfDivision.Axis1) is Less))
 28218        child += 1 << 0;
 28219      if (!bounds.Min2.Exists || !(this._compare2(bounds.Min2.Value, pointOfDivision.Axis2) is Less))
 28220        child += 1 << 1;
 28221      if (!bounds.Min3.Exists || !(this._compare3(bounds.Min3.Value, pointOfDivision.Axis3) is Less))
 28222        child += 1 << 2;
 28223      if (!bounds.Min4.Exists || !(this._compare4(bounds.Min4.Value, pointOfDivision.Axis4) is Less))
 28224        child += 1 << 3;
 28225      if (!bounds.Min5.Exists || !(this._compare5(bounds.Min5.Value, pointOfDivision.Axis5) is Less))
 28226        child += 1 << 4;
 28227      if (!bounds.Min6.Exists || !(this._compare6(bounds.Min6.Value, pointOfDivision.Axis6) is Less))
 28228        child += 1 << 5;
 28229      return child;
 28230    }
 28231
 28232    /// <summary>Converts a branch back into a leaf when the count is reduced.</summary>
 28233    /// <param name="parent">The parent to shrink a child of.</param>
 28234    /// <param name="child_index">The index of the child to shrink.</param>
 28235    internal void ShrinkChild(Node parent, int child_index)
 28236    {
 28237      Node leaf;
 28238      Node removal = null;
 28239      if (parent is null) // top of tree
 28240      {
 28241        removal = this._top;
 28242        leaf = new Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>.None, null, -1);
 28243        this._top = leaf;
 28244      }
 28245      else // non-top branch
 28246      {
 28247        removal = parent[child_index];
 28248        leaf = new Node(removal.Bounds, removal.Parent, removal.Index);
 28249        parent[child_index] = leaf;
 28250      }
 28251
 28252      this.Stepper((T step) => { leaf.Add(step); }, removal);
 28253    }
 28254
 28255    /// <summary>Reduces the counts of all the parents of a given node by a given amount.</summary>
 28256    /// <param name="parent">The starting parent of the reduction.</param>
 28257    /// <param name="reduction">The amount to reduce the parent counts by.</param>
 28258    internal void ReduceParentCounts(Node parent, int reduction)
 28259    {
 28260      IncreaseParentCounts(parent, -reduction);
 28261    }
 28262
 28263    /// <summary>Increases the counts of all the parents of a given node by a given amount.</summary>
 28264    /// <param name="parent">The starting parent of the increase.</param>
 28265    /// <param name="increase">The amount to increase the parent counts by.</param>
 28266    internal void IncreaseParentCounts(Node parent, int increase)
 28267    {
 28268      Node node = parent;
 28269      while (node is not null)
 28270      {
 28271        node.Count += increase;
 28272        node = node.Parent;
 28273      }
 28274    }
 28275
 28276    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 28277    /// <returns>True if the spaces overlap; False if not.</returns>
 28278    internal bool InclusionCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> a, Omnitree.Bounds<Axis1, Axi
 28279      Omnitree.InclusionCheck(a, b
 28280      , _compare1
 28281      , _compare2
 28282      , _compare3
 28283      , _compare4
 28284      , _compare5
 28285      , _compare6
 28286      );
 28287
 28288    /// <summary>Checks if a space encapsulates a point.</summary>
 28289    /// <returns>True if the space encapsulates the point; False if not.</returns>
 28290    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds, Omnitree.Vector<A
 28291      Omnitree.EncapsulationCheck(bounds, vector
 28292      , _compare1
 28293      , _compare2
 28294      , _compare3
 28295      , _compare4
 28296      , _compare5
 28297      , _compare6
 28298      );
 28299
 28300    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 28301    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 28302    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> a, Omnitree.Bounds<Axis1,
 28303      Omnitree.EncapsulationCheck(a, b
 28304      , _compare1
 28305      , _compare2
 28306      , _compare3
 28307      , _compare4
 28308      , _compare5
 28309      , _compare6
 28310      );
 28311
 28312    /// <summary>Checks for equality between two locations.</summary>
 28313    /// <returns>True if equal; False if not;</returns>
 28314    internal bool EqualsCheck(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> a, Omnitree.Vector<Axis1, Axis2,
 28315      Omnitree.EqualsCheck(a, b
 28316      , (a, b) => _compare1(a, b) is Equal
 28317      , (a, b) => _compare2(a, b) is Equal
 28318      , (a, b) => _compare3(a, b) is Equal
 28319      , (a, b) => _compare4(a, b) is Equal
 28320      , (a, b) => _compare5(a, b) is Equal
 28321      , (a, b) => _compare6(a, b) is Equal
 28322      );
 28323
 28324    /// <summary>Gets the nearest parent that encapsulates a location.</summary>
 28325    /// <param name="node">The starting node to find the encapsulating parent of the location.</param>
 28326    /// <param name="bounds">The bounds to get the encapsulating parent from.</param>
 28327    /// <returns>The nearest node that encapsulates the given location.</returns>
 28328    internal Node GetEncapsulationParent(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> bounds)
 28329    {
 28330      while (node is not null && !EncapsulationCheck(node.Bounds, bounds))
 28331      {
 28332        node = node.Parent;
 28333      }
 28334      return node;
 28335    }
 28336
 28337    internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6> GetBoundings(T value)
 28338    {
 28339      Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 28340      Omnitree.Bound<Axis2> min2; Omnitree.Bound<Axis2> max2;
 28341      Omnitree.Bound<Axis3> min3; Omnitree.Bound<Axis3> max3;
 28342      Omnitree.Bound<Axis4> min4; Omnitree.Bound<Axis4> max4;
 28343      Omnitree.Bound<Axis5> min5; Omnitree.Bound<Axis5> max5;
 28344      Omnitree.Bound<Axis6> min6; Omnitree.Bound<Axis6> max6;
 28345      this._getBounds(value,
 28346        out min1, out max1
 28347,
 28348        out min2, out max2
 28349,
 28350        out min3, out max3
 28351,
 28352        out min4, out max4
 28353,
 28354        out min5, out max5
 28355,
 28356        out min6, out max6
 28357        );
 28358      return new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6>(
 28359        min1, max1
 28360,
 28361        min2, max2
 28362,
 28363        min3, max3
 28364,
 28365        min4, max4
 28366,
 28367        min5, max5
 28368,
 28369        min6, max6
 28370        );
 28371    }
 28372
 28373    #endregion
 28374
 28375    #endregion
 28376  }
 28377
 28378  #endregion
 28379
 28380  #region 7 Dimensional
 28381
 28382  /// <summary>Inheritance base for 7D omnitrees that store bounds.</summary>
 28383  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 28384  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 28385  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 28386  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 28387  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 28388  /// <typeparam name="Axis5">The type 5D axis.</typeparam>
 28389  /// <typeparam name="Axis6">The type 6D axis.</typeparam>
 28390  /// <typeparam name="Axis7">The type 7D axis.</typeparam>
 28391  public interface IOmnitreeBounds<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> : IOmnitree<T, Axis1, Axis2, Axis
 28392  {
 28393    #region Properties
 28394
 28395    /// <summary>The number of dimensions in this tree.</summary>
 28396    int Dimensions { get; }
 28397
 28398    /// <summary>The delegate being used by the omnitree to get the bounds of values in 7D space.</summary>
 28399    Omnitree.GetBounds<T, Axis1
 28400, Axis2
 28401, Axis3
 28402, Axis4
 28403, Axis5
 28404, Axis6
 28405, Axis7
 28406      > GetBounds { get; }
 28407
 28408    #endregion
 28409
 28410    #region Methods
 28411
 28412    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 28413    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28414    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28415    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28416    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28417    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28418    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28419    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28420    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28421    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28422    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28423    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28424    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28425    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 28426    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 28427    /// <returns>The number of items in the provided sub space.</returns>
 28428    int CountSubSpaceEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Ax
 28429
 28430    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 28431    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28432    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28433    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28434    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28435    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28436    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28437    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28438    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28439    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28440    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28441    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28442    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28443    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 28444    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 28445    /// <returns>The number of items in the provided sub space.</returns>
 28446    int CountSubSpaceOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis
 28447
 28448    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 28449    void Update();
 28450    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 28451    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28452    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28453    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28454    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28455    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28456    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28457    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28458    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28459    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28460    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28461    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28462    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28463    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 28464    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 28465    void Update(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4, Axis5 mi
 28466
 28467    /// <summary>Removes all the items in a given space.</summary>
 28468    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28469    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28470    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28471    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28472    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28473    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28474    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28475    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28476    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28477    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28478    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28479    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28480    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 28481    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 28482    void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 ma
 28483    /// <summary>Removes all the items in a given space.</summary>
 28484    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28485    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28486    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28487    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28488    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28489    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28490    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28491    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28492    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28493    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28494    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28495    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28496    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 28497    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 28498    void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree
 28499    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 28500    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28501    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28502    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28503    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28504    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28505    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28506    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28507    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28508    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28509    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28510    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28511    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28512    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 28513    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 28514    /// <param name="where">The predicate constraint of the removal.</param>
 28515    void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 ma
 28516    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 28517    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28518    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28519    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28520    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28521    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28522    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28523    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28524    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28525    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28526    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28527    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28528    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28529    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 28530    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 28531    /// <param name="where">The predicate constraint of the removal.</param>
 28532    void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree
 28533
 28534    /// <summary>Removes all the items in a given space.</summary>
 28535    /// <param name="axis1">The coordinate along the 1D axis.</param>
 28536    /// <param name="axis2">The coordinate along the 2D axis.</param>
 28537    /// <param name="axis3">The coordinate along the 3D axis.</param>
 28538    /// <param name="axis4">The coordinate along the 4D axis.</param>
 28539    /// <param name="axis5">The coordinate along the 5D axis.</param>
 28540    /// <param name="axis6">The coordinate along the 6D axis.</param>
 28541    /// <param name="axis7">The coordinate along the 7D axis.</param>
 28542    void RemoveOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6, Axis7 axis7);
 28543    /// <summary>Removes all the items in a given space.</summary>
 28544    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28545    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28546    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28547    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28548    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28549    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28550    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28551    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28552    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28553    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28554    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28555    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28556    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 28557    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 28558    void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4
 28559    /// <summary>Removes all the items in a given space.</summary>
 28560    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28561    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28562    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28563    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28564    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28565    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28566    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28567    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28568    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28569    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28570    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28571    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28572    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 28573    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 28574    void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.B
 28575    /// <summary>Removes all the items in a given space where equality is met.</summary>
 28576    /// <param name="axis1">The coordinate along the 1D axis.</param>
 28577    /// <param name="axis2">The coordinate along the 2D axis.</param>
 28578    /// <param name="axis3">The coordinate along the 3D axis.</param>
 28579    /// <param name="axis4">The coordinate along the 4D axis.</param>
 28580    /// <param name="axis5">The coordinate along the 5D axis.</param>
 28581    /// <param name="axis6">The coordinate along the 6D axis.</param>
 28582    /// <param name="axis7">The coordinate along the 7D axis.</param>
 28583    /// <param name="where">The equality constraint of the removal.</param>
 28584    void RemoveOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6, Axis7 axis7, Pre
 28585    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 28586    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28587    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28588    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28589    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28590    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28591    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28592    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28593    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28594    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28595    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28596    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28597    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28598    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 28599    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 28600    /// <param name="where">The predicate constraint of the removal.</param>
 28601    void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4
 28602    /// <summary>Removes all the items in a given space where predicate is met.</summary>
 28603    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28604    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28605    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28606    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28607    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28608    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28609    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28610    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28611    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28612    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28613    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28614    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28615    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 28616    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 28617    /// <param name="where">The predicate constraint of the removal.</param>
 28618    void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.B
 28619
 28620    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 28621    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 28622    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28623    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28624    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28625    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28626    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28627    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28628    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28629    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28630    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28631    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28632    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28633    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28634    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 28635    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 28636    void StepperEncapsulated(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis
 28637    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 28638    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 28639    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28640    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28641    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28642    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28643    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28644    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28645    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28646    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28647    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28648    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28649    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28650    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28651    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 28652    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 28653    StepStatus StepperEncapsulated(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omn
 28654
 28655    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 28656    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 28657    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28658    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28659    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28660    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28661    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28662    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28663    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28664    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28665    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28666    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28667    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28668    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28669    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 28670    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 28671    void StepperOverlapped(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2>
 28672    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 28673    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 28674    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 28675    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 28676    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 28677    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 28678    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 28679    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 28680    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 28681    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 28682    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 28683    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 28684    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 28685    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 28686    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 28687    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 28688    StepStatus StepperOverlapped(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnit
 28689
 28690    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 28691    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 28692    /// <param name="axis1">The coordinate along the 1D axis.</param>
 28693    /// <param name="axis2">The coordinate along the 2D axis.</param>
 28694    /// <param name="axis3">The coordinate along the 3D axis.</param>
 28695    /// <param name="axis4">The coordinate along the 4D axis.</param>
 28696    /// <param name="axis5">The coordinate along the 5D axis.</param>
 28697    /// <param name="axis6">The coordinate along the 6D axis.</param>
 28698    /// <param name="axis7">The coordinate along the 7D axis.</param>
 28699    void StepperOverlapped(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6,
 28700    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 28701    /// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
 28702    /// <param name="axis1">The coordinate along the 1D axis.</param>
 28703    /// <param name="axis2">The coordinate along the 2D axis.</param>
 28704    /// <param name="axis3">The coordinate along the 3D axis.</param>
 28705    /// <param name="axis4">The coordinate along the 4D axis.</param>
 28706    /// <param name="axis5">The coordinate along the 5D axis.</param>
 28707    /// <param name="axis6">The coordinate along the 6D axis.</param>
 28708    /// <param name="axis7">The coordinate along the 7D axis.</param>
 28709    StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axi
 28710
 28711    #endregion
 28712  }
 28713
 28714  /// <summary>Omnitree that stores bounds along 7 dimensions implemented as a linked tree.</summary>
 28715  /// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
 28716  /// <typeparam name="Axis1">The type 1D axis.</typeparam>
 28717  /// <typeparam name="Axis2">The type 2D axis.</typeparam>
 28718  /// <typeparam name="Axis3">The type 3D axis.</typeparam>
 28719  /// <typeparam name="Axis4">The type 4D axis.</typeparam>
 28720  /// <typeparam name="Axis5">The type 5D axis.</typeparam>
 28721  /// <typeparam name="Axis6">The type 6D axis.</typeparam>
 28722  /// <typeparam name="Axis7">The type 7D axis.</typeparam>
 28723  public class OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> : IOmnitreeBounds<T, Axis1, Axis
 28724  {
 28725    internal const int _dimensions = 7;
 28726    internal static int _children_per_node = (int)BigInteger.Pow(2, 7);
 28727
 28728    internal Node _top;
 28729    internal int _naturalLogLower = 1; // caching the next time to calculate loads (lower count)
 28730    internal int _naturalLogUpper = -1; // caching the next time to calculate loads (upper count)
 28731    internal int _load; // ln(count); min = _defaultLoad
 28732    internal Omnitree.GetBounds<T, Axis1
 28733, Axis2
 28734, Axis3
 28735, Axis4
 28736, Axis5
 28737, Axis6
 28738, Axis7
 28739      > _getBounds;
 28740    internal bool _defaultCompare1;
 28741    internal Func<Axis1, Axis1, CompareResult> _compare1;
 28742    internal bool _defaultCompare2;
 28743    internal Func<Axis2, Axis2, CompareResult> _compare2;
 28744    internal bool _defaultCompare3;
 28745    internal Func<Axis3, Axis3, CompareResult> _compare3;
 28746    internal bool _defaultCompare4;
 28747    internal Func<Axis4, Axis4, CompareResult> _compare4;
 28748    internal bool _defaultCompare5;
 28749    internal Func<Axis5, Axis5, CompareResult> _compare5;
 28750    internal bool _defaultCompare6;
 28751    internal Func<Axis6, Axis6, CompareResult> _compare6;
 28752    internal bool _defaultCompare7;
 28753    internal Func<Axis7, Axis7, CompareResult> _compare7;
 28754    internal Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> _s
 28755    internal Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> _s
 28756    internal Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> _s
 28757    internal Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> _s
 28758    internal Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> _s
 28759    internal Omnitree.SubdivisionOverride<T, Axis6, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> _s
 28760    internal Omnitree.SubdivisionOverride<T, Axis7, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> _s
 28761
 28762    #region Nested Types
 28763
 28764    /// <summary>Can be a leaf or a branch.</summary>
 28765    internal class Node
 28766    {
 28767      internal class ValueNode
 28768      {
 28769        internal T Value;
 28770        internal ValueNode Next;
 28771
 28772        internal ValueNode(T value, ValueNode next)
 28773        {
 28774          Value = value;
 28775          Next = next;
 28776        }
 28777      }
 28778
 28779      internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> Bounds;
 28780      internal Node Parent;
 28781      internal int Index;
 28782      internal int Count;
 28783      internal ValueNode Head;
 28784      internal Node[] Children;
 28785      internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>? PointOfDivision;
 28786
 28787      /// <summary>Gets child by index.</summary>
 28788      /// <param name="child_index">The index of the child to get.</param>
 28789      /// <returns>The child of the given index or null if non-existent.</returns>
 28790      internal Node this[int child_index]
 28791      {
 28792        get
 28793        {
 28794          if (Children is null)
 28795            return null;
 28796          if (Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>._children_per_
 28797            return Children[(int)child_index];
 28798          foreach (Node node in Children)
 28799            if (node.Index == child_index)
 28800              return node;
 28801          return null;
 28802        }
 28803        set
 28804        {
 28805          // This error check should be unnecessary... but fuck it... might as well
 28806          if (value.Index != child_index)
 28807            throw new System.Exception("Bug in Omnitree (index/property mis-match when setting a child on a branch)");
 28808
 28809          // no children yet
 28810          if (Children is null)
 28811          {
 28812            Children = â±¯(value);
 28813            return;
 28814          }
 28815          // max children overwrite
 28816          else if (Children.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>._children
 28817          {
 28818            Children[(int)child_index] = value;
 28819            return;
 28820          }
 28821          // non-max child overwrite
 28822          for (int i = 0; i < Children.Length; i++)
 28823            if (Children[i].Index == child_index)
 28824            {
 28825              Children[i] = value;
 28826              return;
 28827            }
 28828          // new child
 28829          Node[] newArray = new Node[Children.Length + 1];
 28830          if (newArray.Length == OmnitreePointsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>._children_per_
 28831          {
 28832            // new child resulting in a max children branch (sorting required)
 28833            for (int i = 0; i < Children.Length; i++)
 28834            {
 28835              newArray[(int)Children[i].Index] = Children[i];
 28836            }
 28837            newArray[(int)value.Index] = value;
 28838          }
 28839          else
 28840          {
 28841            // new child resulting in a non-max children branch
 28842            Array.Copy(Children, newArray, Children.Length);
 28843            newArray[newArray.Length - 1] = value;
 28844          }
 28845          Children = newArray;
 28846        }
 28847      }
 28848
 28849      /// <summary>The depth this node is located in the Omnitree.</summary>
 28850      internal int Depth
 28851      {
 28852        get
 28853        {
 28854          int depth = -1;
 28855          for (Node node = this; node is not null; node = node.Parent)
 28856            depth++;
 28857          return depth;
 28858        }
 28859      }
 28860
 28861      /// <summary>Constructs a node.</summary>
 28862      /// <param name="bounds">The bounds of this node.</param>
 28863      /// <param name="parent">The parent of this node.</param>
 28864      /// <param name="index">The number of values stored in this node and its children.</param>
 28865      internal Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds, Node parent, int index)
 28866      {
 28867        Bounds = bounds;
 28868        Parent = parent;
 28869        Index = index;
 28870      }
 28871
 28872      internal Node(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> pointOfDivision, Omnitree.Bounds<Ax
 28873        : this(bounds, parent, index)
 28874      {
 28875        PointOfDivision = pointOfDivision;
 28876      }
 28877
 28878      internal Node(Node nodeToClone)
 28879      {
 28880        this.Bounds = nodeToClone.Bounds;
 28881        this.Parent = nodeToClone.Parent;
 28882        this.Index = nodeToClone.Index;
 28883        this.Count = nodeToClone.Count;
 28884
 28885        Children = nodeToClone.Children.Clone() as Node[];
 28886        PointOfDivision = nodeToClone.PointOfDivision;
 28887
 28888        ValueNode a = this.Head;
 28889        ValueNode b = nodeToClone.Head;
 28890
 28891        while (b is not null)
 28892        {
 28893          a.Next = new ValueNode(b.Next.Value, null);
 28894          a = a.Next;
 28895          b = b.Next;
 28896        }
 28897      }
 28898
 28899      internal void Add(T addition)
 28900      {
 28901        Head = new ValueNode(addition, Head);
 28902        Count++;
 28903      }
 28904
 28905      internal Node Clone() =>
 28906        new Node(this);
 28907    }
 28908
 28909    #endregion
 28910
 28911    #region Constructors
 28912
 28913    /// <summary>This constructor is for cloning purposes</summary>
 28914    internal OmnitreeBoundsLinked(OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> omnitree)
 28915    {
 28916      this._top = omnitree._top.Clone();
 28917      this._load = omnitree._load;
 28918      this._getBounds = omnitree._getBounds;
 28919      this._defaultCompare1 = omnitree._defaultCompare1;
 28920      this._compare1 = omnitree._compare1;
 28921      this._defaultCompare2 = omnitree._defaultCompare2;
 28922      this._compare2 = omnitree._compare2;
 28923      this._defaultCompare3 = omnitree._defaultCompare3;
 28924      this._compare3 = omnitree._compare3;
 28925      this._defaultCompare4 = omnitree._defaultCompare4;
 28926      this._compare4 = omnitree._compare4;
 28927      this._defaultCompare5 = omnitree._defaultCompare5;
 28928      this._compare5 = omnitree._compare5;
 28929      this._defaultCompare6 = omnitree._defaultCompare6;
 28930      this._compare6 = omnitree._compare6;
 28931      this._defaultCompare7 = omnitree._defaultCompare7;
 28932      this._compare7 = omnitree._compare7;
 28933      this._subdivisionOverride1 = omnitree._subdivisionOverride1;
 28934      this._subdivisionOverride2 = omnitree._subdivisionOverride2;
 28935      this._subdivisionOverride3 = omnitree._subdivisionOverride3;
 28936      this._subdivisionOverride4 = omnitree._subdivisionOverride4;
 28937      this._subdivisionOverride5 = omnitree._subdivisionOverride5;
 28938      this._subdivisionOverride6 = omnitree._subdivisionOverride6;
 28939      this._subdivisionOverride7 = omnitree._subdivisionOverride7;
 28940    }
 28941
 28942    internal OmnitreeBoundsLinked(
 28943      Omnitree.GetBounds<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> getBounds,
 28944      bool defaultCompare1,
 28945      Func<Axis1, Axis1, CompareResult> compare1,
 28946      bool defaultCompare2,
 28947      Func<Axis2, Axis2, CompareResult> compare2,
 28948      bool defaultCompare3,
 28949      Func<Axis3, Axis3, CompareResult> compare3,
 28950      bool defaultCompare4,
 28951      Func<Axis4, Axis4, CompareResult> compare4,
 28952      bool defaultCompare5,
 28953      Func<Axis5, Axis5, CompareResult> compare5,
 28954      bool defaultCompare6,
 28955      Func<Axis6, Axis6, CompareResult> compare6,
 28956      bool defaultCompare7,
 28957      Func<Axis7, Axis7, CompareResult> compare7,
 28958      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 28959,
 28960      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 28961,
 28962      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 28963,
 28964      Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 28965,
 28966      Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 28967,
 28968      Omnitree.SubdivisionOverride<T, Axis6, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 28969,
 28970      Omnitree.SubdivisionOverride<T, Axis7, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 28971      )
 28972    {
 28973      if (getBounds is null)
 28974      {
 28975        throw new ArgumentNullException(nameof(getBounds));
 28976      }
 28977      if (compare1 is null)
 28978      {
 28979        throw new ArgumentNullException(nameof(compare1));
 28980      }
 28981      if (compare2 is null)
 28982      {
 28983        throw new ArgumentNullException(nameof(compare2));
 28984      }
 28985      if (compare3 is null)
 28986      {
 28987        throw new ArgumentNullException(nameof(compare3));
 28988      }
 28989      if (compare4 is null)
 28990      {
 28991        throw new ArgumentNullException(nameof(compare4));
 28992      }
 28993      if (compare5 is null)
 28994      {
 28995        throw new ArgumentNullException(nameof(compare5));
 28996      }
 28997      if (compare6 is null)
 28998      {
 28999        throw new ArgumentNullException(nameof(compare6));
 29000      }
 29001      if (compare7 is null)
 29002      {
 29003        throw new ArgumentNullException(nameof(compare7));
 29004      }
 29005      this._getBounds = getBounds;
 29006      this._defaultCompare1 = defaultCompare1;
 29007      this._compare1 = compare1;
 29008      this._defaultCompare2 = defaultCompare2;
 29009      this._compare2 = compare2;
 29010      this._defaultCompare3 = defaultCompare3;
 29011      this._compare3 = compare3;
 29012      this._defaultCompare4 = defaultCompare4;
 29013      this._compare4 = compare4;
 29014      this._defaultCompare5 = defaultCompare5;
 29015      this._compare5 = compare5;
 29016      this._defaultCompare6 = defaultCompare6;
 29017      this._compare6 = compare6;
 29018      this._defaultCompare7 = defaultCompare7;
 29019      this._compare7 = compare7;
 29020      this._subdivisionOverride1 = subdivisionOverride1;
 29021      this._subdivisionOverride2 = subdivisionOverride2;
 29022      this._subdivisionOverride3 = subdivisionOverride3;
 29023      this._subdivisionOverride4 = subdivisionOverride4;
 29024      this._subdivisionOverride5 = subdivisionOverride5;
 29025      this._subdivisionOverride6 = subdivisionOverride6;
 29026      this._subdivisionOverride7 = subdivisionOverride7;
 29027      this._top = new Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>.None, null, -1);
 29028      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 29029    }
 29030
 29031    /// <summary>Constructs a new 7D omnitree that stores bounds.</summary>
 29032    /// <param name="getBounds">The delegate for getting object bounds in 7D space.</param>
 29033
 29034    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 29035
 29036    /// <param name="compare2">The delegate for comparing values along the 2D axis.</param>
 29037
 29038    /// <param name="compare3">The delegate for comparing values along the 3D axis.</param>
 29039
 29040    /// <param name="compare4">The delegate for comparing values along the 4D axis.</param>
 29041
 29042    /// <param name="compare5">The delegate for comparing values along the 5D axis.</param>
 29043
 29044    /// <param name="compare6">The delegate for comparing values along the 6D axis.</param>
 29045
 29046    /// <param name="compare7">The delegate for comparing values along the 7D axis.</param>
 29047
 29048    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 29049
 29050    /// <param name="subdivisionOverride2">The subdivision overide to be used when splitting the 2 dimension.</param>
 29051
 29052    /// <param name="subdivisionOverride3">The subdivision overide to be used when splitting the 3 dimension.</param>
 29053
 29054    /// <param name="subdivisionOverride4">The subdivision overide to be used when splitting the 4 dimension.</param>
 29055
 29056    /// <param name="subdivisionOverride5">The subdivision overide to be used when splitting the 5 dimension.</param>
 29057
 29058    /// <param name="subdivisionOverride6">The subdivision overide to be used when splitting the 6 dimension.</param>
 29059
 29060    /// <param name="subdivisionOverride7">The subdivision overide to be used when splitting the 7 dimension.</param>
 29061    public OmnitreeBoundsLinked(
 29062      Omnitree.GetBounds<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> getBounds,
 29063      Func<Axis1, Axis1, CompareResult> compare1 = null,
 29064      Func<Axis2, Axis2, CompareResult> compare2 = null,
 29065      Func<Axis3, Axis3, CompareResult> compare3 = null,
 29066      Func<Axis4, Axis4, CompareResult> compare4 = null,
 29067      Func<Axis5, Axis5, CompareResult> compare5 = null,
 29068      Func<Axis6, Axis6, CompareResult> compare6 = null,
 29069      Func<Axis7, Axis7, CompareResult> compare7 = null,
 29070      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 29071,
 29072      Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 29073,
 29074      Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 29075,
 29076      Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 29077,
 29078      Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 29079,
 29080      Omnitree.SubdivisionOverride<T, Axis6, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 29081,
 29082      Omnitree.SubdivisionOverride<T, Axis7, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 29083      )
 29084      : this(
 29085      getBounds,
 29086      compare1 is null ? true : false,
 29087      compare1 ?? Compare,
 29088      compare2 is null ? true : false,
 29089      compare2 ?? Compare,
 29090      compare3 is null ? true : false,
 29091      compare3 ?? Compare,
 29092      compare4 is null ? true : false,
 29093      compare4 ?? Compare,
 29094      compare5 is null ? true : false,
 29095      compare5 ?? Compare,
 29096      compare6 is null ? true : false,
 29097      compare6 ?? Compare,
 29098      compare7 is null ? true : false,
 29099      compare7 ?? Compare,
 29100      subdivisionOverride1
 29101,
 29102      subdivisionOverride2
 29103,
 29104      subdivisionOverride3
 29105,
 29106      subdivisionOverride4
 29107,
 29108      subdivisionOverride5
 29109,
 29110      subdivisionOverride6
 29111,
 29112      subdivisionOverride7
 29113      ) { }
 29114
 29115    /// <summary>Constructs a new 7D omnitree that stores bounds.</summary>
 29116    /// <param name="getBoundings">The delegate for getting object bounds in 7D space.</param>
 29117    /// <param name="compare1">The delegate for comparing values along the 1D axis.</param>
 29118    /// <param name="compare2">The delegate for comparing values along the 2D axis.</param>
 29119    /// <param name="compare3">The delegate for comparing values along the 3D axis.</param>
 29120    /// <param name="compare4">The delegate for comparing values along the 4D axis.</param>
 29121    /// <param name="compare5">The delegate for comparing values along the 5D axis.</param>
 29122    /// <param name="compare6">The delegate for comparing values along the 6D axis.</param>
 29123    /// <param name="compare7">The delegate for comparing values along the 7D axis.</param>
 29124
 29125    /// <param name="subdivisionOverride1">The subdivision overide to be used when splitting the 1 dimension.</param>
 29126
 29127    /// <param name="subdivisionOverride2">The subdivision overide to be used when splitting the 2 dimension.</param>
 29128
 29129    /// <param name="subdivisionOverride3">The subdivision overide to be used when splitting the 3 dimension.</param>
 29130
 29131    /// <param name="subdivisionOverride4">The subdivision overide to be used when splitting the 4 dimension.</param>
 29132
 29133    /// <param name="subdivisionOverride5">The subdivision overide to be used when splitting the 5 dimension.</param>
 29134
 29135    /// <param name="subdivisionOverride6">The subdivision overide to be used when splitting the 6 dimension.</param>
 29136
 29137    /// <param name="subdivisionOverride7">The subdivision overide to be used when splitting the 7 dimension.</param>
 29138    public OmnitreeBoundsLinked(
 29139      Omnitree.GetBoundings<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> getBoundings,
 29140      Func<Axis1, Axis1, CompareResult> compare1 = null,
 29141      Func<Axis2, Axis2, CompareResult> compare2 = null,
 29142      Func<Axis3, Axis3, CompareResult> compare3 = null,
 29143      Func<Axis4, Axis4, CompareResult> compare4 = null,
 29144      Func<Axis5, Axis5, CompareResult> compare5 = null,
 29145      Func<Axis6, Axis6, CompareResult> compare6 = null,
 29146      Func<Axis7, Axis7, CompareResult> compare7 = null,
 29147      Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivisi
 29148      , Omnitree.SubdivisionOverride<T, Axis2, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivi
 29149      , Omnitree.SubdivisionOverride<T, Axis3, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivi
 29150      , Omnitree.SubdivisionOverride<T, Axis4, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivi
 29151      , Omnitree.SubdivisionOverride<T, Axis5, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivi
 29152      , Omnitree.SubdivisionOverride<T, Axis6, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivi
 29153      , Omnitree.SubdivisionOverride<T, Axis7, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>> subdivi
 29154      )
 29155      : this(
 29156      Omnitree.ConvertToGetBounds(getBoundings),
 29157      compare1 is null ? true : false,
 29158      compare1 ?? Compare,
 29159      compare2 is null ? true : false,
 29160      compare2 ?? Compare,
 29161      compare3 is null ? true : false,
 29162      compare3 ?? Compare,
 29163      compare4 is null ? true : false,
 29164      compare4 ?? Compare,
 29165      compare5 is null ? true : false,
 29166      compare5 ?? Compare,
 29167      compare6 is null ? true : false,
 29168      compare6 ?? Compare,
 29169      compare7 is null ? true : false,
 29170      compare7 ?? Compare,
 29171      subdivisionOverride1
 29172,
 29173      subdivisionOverride2
 29174,
 29175      subdivisionOverride3
 29176,
 29177      subdivisionOverride4
 29178,
 29179      subdivisionOverride5
 29180,
 29181      subdivisionOverride6
 29182,
 29183      subdivisionOverride7
 29184      ) { }
 29185
 29186    #endregion
 29187
 29188    #region Properties
 29189
 29190    /// <summary>The number of dimensions in this tree.</summary>
 29191    public int Dimensions => _dimensions;
 29192
 29193    /// <summary>The delegate being used by the omnitree to locate items in 7D space.</summary>
 29194    public Omnitree.GetBounds<T, Axis1
 29195      , Axis2
 29196      , Axis3
 29197      , Axis4
 29198      , Axis5
 29199      , Axis6
 29200      , Axis7
 29201      > GetBounds => _getBounds;
 29202
 29203
 29204    /// <summary>The comparison function the Omnitree is using along the 1D axis.</summary>
 29205    public Func<Axis1, Axis1, CompareResult> Compare1 => _compare1;
 29206    /// <summary>The comparison function the Omnitree is using along the 2D axis.</summary>
 29207    public Func<Axis2, Axis2, CompareResult> Compare2 => _compare2;
 29208    /// <summary>The comparison function the Omnitree is using along the 3D axis.</summary>
 29209    public Func<Axis3, Axis3, CompareResult> Compare3 => _compare3;
 29210    /// <summary>The comparison function the Omnitree is using along the 4D axis.</summary>
 29211    public Func<Axis4, Axis4, CompareResult> Compare4 => _compare4;
 29212    /// <summary>The comparison function the Omnitree is using along the 5D axis.</summary>
 29213    public Func<Axis5, Axis5, CompareResult> Compare5 => _compare5;
 29214    /// <summary>The comparison function the Omnitree is using along the 6D axis.</summary>
 29215    public Func<Axis6, Axis6, CompareResult> Compare6 => _compare6;
 29216    /// <summary>The comparison function the Omnitree is using along the 7D axis.</summary>
 29217    public Func<Axis7, Axis7, CompareResult> Compare7 => _compare7;
 29218
 29219    /// <summary>The current number of items in the tree.</summary>
 29220    public int Count  => _top.Count;
 29221
 29222    internal delegate void MaxDepthFinder(Node node, int current_depth, ref int max_depth);
 29223    /// <summary>Finds the current maximum depth of the tree. NOT AN O(1) OPERATION. Intended for educational purposes o
 29224    public int MaxDepth
 29225    {
 29226      get
 29227      {
 29228        MaxDepthFinder maxDepthFinder = null;
 29229        maxDepthFinder =
 29230            (Node node, int current_depth, ref int max_depth) =>
 29231            {
 29232              if (current_depth > max_depth)
 29233                max_depth = current_depth;
 29234              foreach (Node child in node.Children)
 29235                maxDepthFinder(child, current_depth + 1, ref max_depth);
 29236            };
 29237        int _max_depth = -1;
 29238        maxDepthFinder(this._top, 0, ref _max_depth);
 29239        return _max_depth;
 29240      }
 29241    }
 29242
 29243    internal delegate void NodeCountFinder(Node node, ref int current_count);
 29244    /// <summary>Counts the current number of nodes in the tree. NOT AN O(1) OPERATION. Intended for educational purpose
 29245    public int NodeCount
 29246    {
 29247      get
 29248      {
 29249        NodeCountFinder nodeCountFinder = null;
 29250        nodeCountFinder =
 29251            (Node node, ref int current_count) =>
 29252            {
 29253              current_count++;
 29254              foreach (Node child in node.Children)
 29255                nodeCountFinder(child, ref current_count);
 29256            };
 29257
 29258        int _current_count = 0;
 29259        nodeCountFinder(this._top, ref _current_count);
 29260        return _current_count;
 29261      }
 29262    }
 29263
 29264    #endregion
 29265
 29266    #region Methods
 29267
 29268    #region Add
 29269
 29270
 29271    #region single
 29272
 29273    /// <summary>Tries to add a value.</summary>
 29274    /// <param name="value">The value to be added.</param>
 29275    /// <returns>True if successful or false if not.</returns>
 29276    public (bool Success, Exception? Exception) TryAdd(T value)
 29277    {
 29278      Add(value);
 29279      return (true, null);
 29280    }
 29281
 29282    /// <summary>Adds an item to the tree.</summary>
 29283    /// <param name="addition">The item to be added.</param>
 29284    public void Add(T addition)
 29285    {
 29286      if (this._top.Count is int.MaxValue)
 29287        throw new System.InvalidOperationException("(Count is int.MaxValue) max Omnitree size reached (change ints to lo
 29288
 29289      // dynamic tree sizes
 29290      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 29291
 29292      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds = GetBoundings(addition);
 29293
 29294      // grow the first branch of the tree
 29295      if (!this._top.PointOfDivision.HasValue && this._top.Count >= _load)
 29296      {
 29297        Node top = this._top;
 29298
 29299        // create the new branch from the median values
 29300        this._top = new Node(DetermineMedians(top), Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>.Non
 29301
 29302        // iterate through the values and add them to the appropriate children
 29303        for (Node.ValueNode list = top.Head; list is not null; list = list.Next)
 29304          Add(list.Value, this._top, GetBoundings(list.Value), 0);
 29305      }
 29306
 29307      this.Add(addition, this._top, bounds, 0);
 29308    }
 29309
 29310    /// <summary>Recursive version of the add function.</summary>
 29311    /// <param name="addition">The item to be added.</param>
 29312    /// <param name="node">The current node for tree trversal.</param>
 29313    /// <param name="bounds">The bounds of the addition.</param>
 29314    /// <param name="depth">The current depth of iteration.</param>
 29315    internal void Add(T addition, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds, in
 29316    {
 29317      if (!node.PointOfDivision.HasValue)
 29318      {
 29319        //Leaf leaf = node as Leaf;
 29320        if (depth >= _load || !(node.Count >= _load))
 29321        {
 29322          node.Add(addition);
 29323          return;
 29324        }
 29325        else
 29326        {
 29327          //Node parent = node.Parent;
 29328          //int child_index = this.DetermineChildIndex(parent.PointOfDivision, location);
 29329          //Node growth = new Node(DetermineMedians(leaf), leaf.Bounds, parent, child_index);
 29330          //parent[child_index] = growth;
 29331
 29332          Node growth = new Node(DetermineMedians(node), node.Bounds, node.Parent, node.Index);
 29333          node.Parent[node.Index] = growth;
 29334
 29335          for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 29336          {
 29337            Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> temp_bounds = GetBoundings(list.Value);
 29338            if (EncapsulationCheck(growth.Bounds, temp_bounds))
 29339              Add(list.Value, growth, temp_bounds, depth);
 29340            else
 29341            {
 29342              ReduceParentCounts(node.Parent, 1);
 29343              Add(list.Value, this._top, temp_bounds, depth);
 29344            }
 29345          }
 29346
 29347          Add(addition, growth, bounds, depth);
 29348          return;
 29349        }
 29350      }
 29351      else
 29352      {
 29353        //Node branch = node as Node;
 29354        int child_index = this.DetermineChildIndex(node.PointOfDivision.Value, bounds); // determine the child "index" (
 29355
 29356        // if -1, then the bounds of the addition straddle the point of division (keep it in current node)
 29357        if (child_index is -1)
 29358        {
 29359          node.Add(addition);
 29360          return;
 29361        }
 29362
 29363        Node child_node = node[child_index];
 29364
 29365        // null children in branches are just empty leaves
 29366        if (child_node is null)
 29367        {
 29368          Node new_node = new Node(DetermineChildBounds(node, child_index), node, child_index);
 29369          node[child_index] = new_node;
 29370          new_node.Add(addition);
 29371        }
 29372        else
 29373          // child exists already, continue adding
 29374          Add(addition, child_node, bounds, depth + 1);
 29375
 29376        node.Count++;
 29377        return;
 29378      }
 29379    }
 29380
 29381    internal Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> DetermineMedians(Node node)
 29382    {
 29383      //try
 29384      //{
 29385        // extract the values
 29386        Omnitree.Bound<Axis1>[] values1 = new Omnitree.Bound<Axis1>[node.Count * 2];
 29387        Omnitree.Bound<Axis2>[] values2 = new Omnitree.Bound<Axis2>[node.Count * 2];
 29388        Omnitree.Bound<Axis3>[] values3 = new Omnitree.Bound<Axis3>[node.Count * 2];
 29389        Omnitree.Bound<Axis4>[] values4 = new Omnitree.Bound<Axis4>[node.Count * 2];
 29390        Omnitree.Bound<Axis5>[] values5 = new Omnitree.Bound<Axis5>[node.Count * 2];
 29391        Omnitree.Bound<Axis6>[] values6 = new Omnitree.Bound<Axis6>[node.Count * 2];
 29392        Omnitree.Bound<Axis7>[] values7 = new Omnitree.Bound<Axis7>[node.Count * 2];
 29393        Node.ValueNode for_current = node.Head; // used in for loop
 29394        for (int i = 0; i < node.Count; i++, for_current = for_current.Next)
 29395          this._getBounds(for_current.Value,
 29396          out values1[i * 2], out values1[i * 2 + 1]
 29397,
 29398          out values2[i * 2], out values2[i * 2 + 1]
 29399,
 29400          out values3[i * 2], out values3[i * 2 + 1]
 29401,
 29402          out values4[i * 2], out values4[i * 2 + 1]
 29403,
 29404          out values5[i * 2], out values5[i * 2 + 1]
 29405,
 29406          out values6[i * 2], out values6[i * 2 + 1]
 29407,
 29408          out values7[i * 2], out values7[i * 2 + 1]
 29409          );
 29410        return new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(
 29411          Omnitree.SubDivide(values1, this._defaultCompare1 ? Compare : this._compare1)
 29412,
 29413          Omnitree.SubDivide(values2, this._defaultCompare2 ? Compare : this._compare2)
 29414,
 29415          Omnitree.SubDivide(values3, this._defaultCompare3 ? Compare : this._compare3)
 29416,
 29417          Omnitree.SubDivide(values4, this._defaultCompare4 ? Compare : this._compare4)
 29418,
 29419          Omnitree.SubDivide(values5, this._defaultCompare5 ? Compare : this._compare5)
 29420,
 29421          Omnitree.SubDivide(values6, this._defaultCompare6 ? Compare : this._compare6)
 29422,
 29423          Omnitree.SubDivide(values7, this._defaultCompare7 ? Compare : this._compare7)
 29424          );
 29425      //}
 29426      //catch
 29427      //{
 29428        // extract the values
 29429      //  ArrayJagged<Omnitree.Bound<Axis1>> values1 = new ArrayJagged<Omnitree.Bound<Axis1>>(node.Count * 2);
 29430      //  ArrayJagged<Omnitree.Bound<Axis2>> values2 = new ArrayJagged<Omnitree.Bound<Axis2>>(node.Count * 2);
 29431      //  ArrayJagged<Omnitree.Bound<Axis3>> values3 = new ArrayJagged<Omnitree.Bound<Axis3>>(node.Count * 2);
 29432      //  ArrayJagged<Omnitree.Bound<Axis4>> values4 = new ArrayJagged<Omnitree.Bound<Axis4>>(node.Count * 2);
 29433      //  ArrayJagged<Omnitree.Bound<Axis5>> values5 = new ArrayJagged<Omnitree.Bound<Axis5>>(node.Count * 2);
 29434      //  ArrayJagged<Omnitree.Bound<Axis6>> values6 = new ArrayJagged<Omnitree.Bound<Axis6>>(node.Count * 2);
 29435      //  ArrayJagged<Omnitree.Bound<Axis7>> values7 = new ArrayJagged<Omnitree.Bound<Axis7>>(node.Count * 2);
 29436      //  Node.ValueNode for_current = node.Head; // used in for loop
 29437      //  for (int i = 0; i < node.Count; i++, for_current = for_current.Next)
 29438      //  {
 29439      //    Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 29440      //    Omnitree.Bound<Axis2> min2; Omnitree.Bound<Axis2> max2;
 29441      //    Omnitree.Bound<Axis3> min3; Omnitree.Bound<Axis3> max3;
 29442      //    Omnitree.Bound<Axis4> min4; Omnitree.Bound<Axis4> max4;
 29443      //    Omnitree.Bound<Axis5> min5; Omnitree.Bound<Axis5> max5;
 29444      //    Omnitree.Bound<Axis6> min6; Omnitree.Bound<Axis6> max6;
 29445      //    Omnitree.Bound<Axis7> min7; Omnitree.Bound<Axis7> max7;
 29446      //    this._getBounds(for_current.Value,
 29447      //      out min1, out max1
 29448//,
 29449      //      out min2, out max2
 29450//,
 29451      //      out min3, out max3
 29452//,
 29453      //      out min4, out max4
 29454//,
 29455      //      out min5, out max5
 29456//,
 29457      //      out min6, out max6
 29458//,
 29459      //      out min7, out max7
 29460      //      );
 29461      //    values1[i * 2] = min1; values1[i * 2 + 1] = max1;
 29462      //    values2[i * 2] = min2; values2[i * 2 + 1] = max2;
 29463      //    values3[i * 2] = min3; values3[i * 2 + 1] = max3;
 29464      //    values4[i * 2] = min4; values4[i * 2 + 1] = max4;
 29465      //    values5[i * 2] = min5; values5[i * 2 + 1] = max5;
 29466      //    values6[i * 2] = min6; values6[i * 2 + 1] = max6;
 29467      //    values7[i * 2] = min7; values7[i * 2 + 1] = max7;
 29468      //  }
 29469      //  return new Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(
 29470      //    Omnitree.SubDivide(values1, this._defaultCompare1 ? Compare : this._compare1)
 29471      //    , Omnitree.SubDivide(values2, this._defaultCompare2 ? Compare : this._compare2)
 29472      //    , Omnitree.SubDivide(values3, this._defaultCompare3 ? Compare : this._compare3)
 29473      //    , Omnitree.SubDivide(values4, this._defaultCompare4 ? Compare : this._compare4)
 29474      //    , Omnitree.SubDivide(values5, this._defaultCompare5 ? Compare : this._compare5)
 29475      //    , Omnitree.SubDivide(values6, this._defaultCompare6 ? Compare : this._compare6)
 29476      //    , Omnitree.SubDivide(values7, this._defaultCompare7 ? Compare : this._compare7)
 29477      //  );
 29478      //}
 29479    }
 29480
 29481    #endregion
 29482
 29483    #region Add Helpers
 29484
 29485    internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> DetermineChildBounds(Node node, int child_
 29486    {
 29487      // the node parameter should always have a point of division value for this function
 29488      Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> pointOfDivision = node.PointOfDivision.Value;
 29489
 29490      Omnitree.Bound<Axis7> min7, max7;
 29491      if (child_index >= 64)
 29492      {
 29493        min7 = pointOfDivision.Axis7;
 29494        max7 = node.Bounds.Max7;
 29495        child_index -= 64;
 29496      }
 29497      else
 29498      {
 29499        min7 = node.Bounds.Min7;
 29500        max7 = pointOfDivision.Axis7;
 29501      }
 29502
 29503      Omnitree.Bound<Axis6> min6, max6;
 29504      if (child_index >= 32)
 29505      {
 29506        min6 = pointOfDivision.Axis6;
 29507        max6 = node.Bounds.Max6;
 29508        child_index -= 32;
 29509      }
 29510      else
 29511      {
 29512        min6 = node.Bounds.Min6;
 29513        max6 = pointOfDivision.Axis6;
 29514      }
 29515
 29516      Omnitree.Bound<Axis5> min5, max5;
 29517      if (child_index >= 16)
 29518      {
 29519        min5 = pointOfDivision.Axis5;
 29520        max5 = node.Bounds.Max5;
 29521        child_index -= 16;
 29522      }
 29523      else
 29524      {
 29525        min5 = node.Bounds.Min5;
 29526        max5 = pointOfDivision.Axis5;
 29527      }
 29528
 29529      Omnitree.Bound<Axis4> min4, max4;
 29530      if (child_index >= 8)
 29531      {
 29532        min4 = pointOfDivision.Axis4;
 29533        max4 = node.Bounds.Max4;
 29534        child_index -= 8;
 29535      }
 29536      else
 29537      {
 29538        min4 = node.Bounds.Min4;
 29539        max4 = pointOfDivision.Axis4;
 29540      }
 29541
 29542      Omnitree.Bound<Axis3> min3, max3;
 29543      if (child_index >= 4)
 29544      {
 29545        min3 = pointOfDivision.Axis3;
 29546        max3 = node.Bounds.Max3;
 29547        child_index -= 4;
 29548      }
 29549      else
 29550      {
 29551        min3 = node.Bounds.Min3;
 29552        max3 = pointOfDivision.Axis3;
 29553      }
 29554
 29555      Omnitree.Bound<Axis2> min2, max2;
 29556      if (child_index >= 2)
 29557      {
 29558        min2 = pointOfDivision.Axis2;
 29559        max2 = node.Bounds.Max2;
 29560        child_index -= 2;
 29561      }
 29562      else
 29563      {
 29564        min2 = node.Bounds.Min2;
 29565        max2 = pointOfDivision.Axis2;
 29566      }
 29567
 29568      Omnitree.Bound<Axis1> min1, max1;
 29569      if (child_index >= 1)
 29570      {
 29571        min1 = pointOfDivision.Axis1;
 29572        max1 = node.Bounds.Max1;
 29573        child_index -= 1;
 29574      }
 29575      else
 29576      {
 29577        min1 = node.Bounds.Min1;
 29578        max1 = pointOfDivision.Axis1;
 29579      }
 29580
 29581      return new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min2, max2, min3, max3, mi
 29582    }
 29583
 29584    #endregion
 29585
 29586    #endregion
 29587
 29588    #region Clear
 29589
 29590    /// <summary>Returns the tree to an empty state.</summary>
 29591    public void Clear()
 29592    {
 29593      this._top = new Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>.None, null, -1);
 29594      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 29595    }
 29596
 29597    #endregion
 29598
 29599    #region Clone
 29600
 29601    /// <summary>Creates a shallow clone of this data structure.</summary>
 29602    /// <returns>A shallow clone of this data structure.</returns>
 29603    public OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> Clone()
 29604    {
 29605      return new OmnitreeBoundsLinked<T, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(this);
 29606    }
 29607
 29608    #endregion
 29609
 29610    #region Count
 29611
 29612    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 29613    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 29614    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 29615    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 29616    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 29617    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 29618    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 29619    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 29620    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 29621    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 29622    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 29623    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 29624    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 29625    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 29626    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 29627    /// <returns>The number of items in the provided sub space.</returns>
 29628    public int CountSubSpaceEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 m
 29629    {
 29630      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, 
 29631    }
 29632    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 29633    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 29634    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 29635    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 29636    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 29637    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 29638    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 29639    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 29640    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 29641    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 29642    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 29643    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 29644    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 29645    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 29646    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 29647    /// <returns>The number of items in the provided sub space.</returns>
 29648    public int CountSubSpaceEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> m
 29649    {
 29650      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, 
 29651    }
 29652    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 29653    /// <param name="axis1">The coordinate along the 1D axis.</param>
 29654    /// <param name="axis2">The coordinate along the 2D axis.</param>
 29655    /// <param name="axis3">The coordinate along the 3D axis.</param>
 29656    /// <param name="axis4">The coordinate along the 4D axis.</param>
 29657    /// <param name="axis5">The coordinate along the 5D axis.</param>
 29658    /// <param name="axis6">The coordinate along the 6D axis.</param>
 29659    /// <param name="axis7">The coordinate along the 7D axis.</param>
 29660    /// <returns>The number of items in the provided sub space.</returns>
 29661    public int CountSubSpaceEncapsulated(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6, A
 29662    {
 29663      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(axis1,
 29664    }
 29665    /// <summary>Counts the number of items encapsulated by a sub space.</summary>
 29666    /// <param name="axis1">The coordinate along the 1D axis.</param>
 29667    /// <param name="axis2">The coordinate along the 2D axis.</param>
 29668    /// <param name="axis3">The coordinate along the 3D axis.</param>
 29669    /// <param name="axis4">The coordinate along the 4D axis.</param>
 29670    /// <param name="axis5">The coordinate along the 5D axis.</param>
 29671    /// <param name="axis6">The coordinate along the 6D axis.</param>
 29672    /// <param name="axis7">The coordinate along the 7D axis.</param>
 29673    /// <returns>The number of items in the provided sub space.</returns>
 29674    public int CountSubSpaceEncapsulated(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3>
 29675    {
 29676      return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(axis1,
 29677    }
 29678
 29679    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 29680    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 29681    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 29682    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 29683    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 29684    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 29685    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 29686    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 29687    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 29688    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 29689    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 29690    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 29691    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 29692    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 29693    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 29694    /// <returns>The number of items in the provided sub space.</returns>
 29695    public int CountSubSpaceOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min
 29696    {
 29697      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, ma
 29698    }
 29699    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 29700    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 29701    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 29702    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 29703    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 29704    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 29705    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 29706    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 29707    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 29708    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 29709    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 29710    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 29711    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 29712    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 29713    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 29714    /// <returns>The number of items in the provided sub space.</returns>
 29715    public int CountSubSpaceOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min
 29716    {
 29717      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, ma
 29718    }
 29719    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 29720    /// <param name="axis1">The coordinate along the 1D axis.</param>
 29721    /// <param name="axis2">The coordinate along the 2D axis.</param>
 29722    /// <param name="axis3">The coordinate along the 3D axis.</param>
 29723    /// <param name="axis4">The coordinate along the 4D axis.</param>
 29724    /// <param name="axis5">The coordinate along the 5D axis.</param>
 29725    /// <param name="axis6">The coordinate along the 6D axis.</param>
 29726    /// <param name="axis7">The coordinate along the 7D axis.</param>
 29727    /// <returns>The number of items in the provided sub space.</returns>
 29728    public int CountSubSpaceOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6, Axi
 29729    {
 29730      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(axis1, a
 29731    }
 29732    /// <summary>Counts the number of items overlapped by a sub space.</summary>
 29733    /// <param name="axis1">The coordinate along the 1D axis.</param>
 29734    /// <param name="axis2">The coordinate along the 2D axis.</param>
 29735    /// <param name="axis3">The coordinate along the 3D axis.</param>
 29736    /// <param name="axis4">The coordinate along the 4D axis.</param>
 29737    /// <param name="axis5">The coordinate along the 5D axis.</param>
 29738    /// <param name="axis6">The coordinate along the 6D axis.</param>
 29739    /// <param name="axis7">The coordinate along the 7D axis.</param>
 29740    /// <returns>The number of items in the provided sub space.</returns>
 29741    public int CountSubSpaceOverlapped(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> a
 29742    {
 29743      return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(axis1, a
 29744    }
 29745
 29746    internal int CountSubSpaceEncapsulated(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> b
 29747    {
 29748      return CountSubSpaceBase(_top, bounds, (a, b) => EncapsulationCheck(a, b));
 29749    }
 29750
 29751    internal int CountSubSpaceOverlapped(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bou
 29752    {
 29753      return CountSubSpaceBase(_top, bounds, (a, b) => InclusionCheck(a, b));
 29754    }
 29755
 29756    internal int CountSubSpaceBase(
 29757      Node node,
 29758      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds,
 29759      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>, Omnitree.Bounds<Axis1, Axi
 29760    {
 29761      // adjust min/max values
 29762      int count = 0;
 29763      if (EncapsulationCheck(bounds, node.Bounds))
 29764        count += node.Count;
 29765      else if (!node.PointOfDivision.HasValue)
 29766      {
 29767        for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 29768          if (spatialCheck(bounds, GetBoundings(list.Value)))
 29769            count++;
 29770      }
 29771      else
 29772      {
 29773        Node branch = node as Node;
 29774        if (!StraddlesLines(branch.Bounds, branch.PointOfDivision.Value))
 29775        {
 29776          int child_index = DetermineChildIndex(branch.PointOfDivision.Value, bounds);
 29777          Node child = branch[child_index];
 29778          if (child is not null)
 29779            count += this.CountSubSpaceBase(child, bounds, spatialCheck);
 29780        }
 29781        else
 29782        {
 29783          foreach (Node child in node.Children)
 29784            count += this.CountSubSpaceBase(child, bounds, spatialCheck);
 29785        }
 29786      }
 29787      return count;
 29788    }
 29789
 29790    #endregion
 29791
 29792    #region Update
 29793
 29794    /// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
 29795    public void Update()
 29796    {
 29797      this.Update(this._top, 0);
 29798    }
 29799
 29800    /// <summary>Recursive version of the Update method.</summary>
 29801    /// <param name="node">The current node of iteration.</param>
 29802    /// <param name="depth">The current depth of iteration.</param>
 29803    internal int Update(Node node, int depth)
 29804    {
 29805      int removals = 0;
 29806
 29807      {
 29808        Node branch = node as Node;
 29809        int skipped = 0;
 29810        for (int i = 0; i + skipped < branch.Children.Length; )
 29811        {
 29812          removals += this.Update(branch.Children[i], depth + 1);
 29813          if (branch.Children[i].Count is 0)
 29814            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 29815          else
 29816            i++;
 29817        }
 29818        Node[] newArray = new Node[branch.Children.Length - skipped];
 29819        Array.Copy(branch.Children, newArray, newArray.Length);
 29820        branch.Children = newArray;
 29821
 29822        if (branch.Count < _load && branch.Count != 0)
 29823          ShrinkChild(branch.Parent, branch.Index);
 29824      }
 29825
 29826      {
 29827        Node.ValueNode current = node.Head;
 29828        Node.ValueNode previous = null;
 29829        while (current is not null)
 29830        {
 29831          Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds = GetBoundings(current.Value);
 29832          if (!this.EncapsulationCheck(node.Bounds, bounds))
 29833          {
 29834            removals++;
 29835            T updated = current.Value;
 29836            if (previous is null)
 29837            {
 29838              node.Head = current.Next;
 29839              goto HeadRemoved;
 29840            }
 29841            else
 29842              previous.Next = current.Next;
 29843
 29844            Node whereToAdd = GetEncapsulationParent(node.Parent, bounds);
 29845
 29846            if (whereToAdd is null)
 29847              throw new System.Exception("an item was updated outside the range of the omnitree");
 29848
 29849            this.Add(updated, whereToAdd, bounds, whereToAdd.Depth);
 29850          }
 29851          previous = current;
 29852        HeadRemoved:
 29853          current = current.Next;
 29854        }
 29855      }
 29856
 29857      node.Count -= removals;
 29858      return removals;
 29859    }
 29860
 29861    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 29862    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 29863    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 29864    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 29865    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 29866    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 29867    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 29868    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 29869    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 29870    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 29871    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 29872    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 29873    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 29874    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 29875    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 29876    public void Update(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axis4 max4, A
 29877    {
 29878      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min2, max2, min3, max
 29879    }
 29880    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 29881    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 29882    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 29883    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 29884    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 29885    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 29886    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 29887    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 29888    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 29889    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 29890    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 29891    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 29892    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 29893    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 29894    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 29895    public void Update(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omnitree.Boun
 29896    {
 29897      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min2, max2, min3, max
 29898    }
 29899    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 29900    /// <param name="axis1">The coordinate along the 1D axis.</param>
 29901    /// <param name="axis2">The coordinate along the 2D axis.</param>
 29902    /// <param name="axis3">The coordinate along the 3D axis.</param>
 29903    /// <param name="axis4">The coordinate along the 4D axis.</param>
 29904    /// <param name="axis5">The coordinate along the 5D axis.</param>
 29905    /// <param name="axis6">The coordinate along the 6D axis.</param>
 29906    /// <param name="axis7">The coordinate along the 7D axis.</param>
 29907    public void Update(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6, Axis7 axis7)
 29908    {
 29909      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(axis1, axis1, axis2, axis2, axis3
 29910    }
 29911    /// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
 29912    /// <param name="axis1">The coordinate along the 1D axis.</param>
 29913    /// <param name="axis2">The coordinate along the 2D axis.</param>
 29914    /// <param name="axis3">The coordinate along the 3D axis.</param>
 29915    /// <param name="axis4">The coordinate along the 4D axis.</param>
 29916    /// <param name="axis5">The coordinate along the 5D axis.</param>
 29917    /// <param name="axis6">The coordinate along the 6D axis.</param>
 29918    /// <param name="axis7">The coordinate along the 7D axis.</param>
 29919    public void Update(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3, Omnitree.B
 29920    {
 29921      this.Update(new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(axis1, axis1, axis2, axis2, axis3
 29922    }
 29923    internal int Update(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds, Node node, int depth)
 29924    {
 29925      if (!InclusionCheck(bounds, node.Bounds))
 29926        return 0;
 29927
 29928      int removals = 0;
 29929
 29930      {
 29931        Node branch = node as Node;
 29932        int skipped = 0;
 29933        for (int i = 0; i + skipped < branch.Children.Length; )
 29934        {
 29935          removals += this.Update(branch.Children[i], depth + 1);
 29936          if (branch.Children[i].Count is 0)
 29937            branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
 29938          else
 29939            i++;
 29940        }
 29941        Node[] newArray = new Node[branch.Children.Length - skipped];
 29942        Array.Copy(branch.Children, newArray, newArray.Length);
 29943        branch.Children = newArray;
 29944
 29945        if (branch.Count < _load && branch.Count != 0)
 29946          ShrinkChild(branch.Parent, branch.Index);
 29947      }
 29948
 29949      {
 29950        Node.ValueNode current = node.Head;
 29951        Node.ValueNode previous = null;
 29952        while (current is not null)
 29953        {
 29954          Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> item_bounds = GetBoundings(current.Value);
 29955          if (!this.EncapsulationCheck(node.Bounds, item_bounds))
 29956          {
 29957            removals++;
 29958            T updated = current.Value;
 29959            if (previous is null)
 29960            {
 29961              node.Head = current.Next;
 29962              goto HeadRemoved;
 29963            }
 29964            else
 29965              previous.Next = current.Next;
 29966            Node whereToAdd = GetEncapsulationParent(node.Parent, item_bounds);
 29967            if (whereToAdd is null)
 29968              throw new System.Exception("an item was updates outside the range of the omnitree");
 29969            this.Add(updated, whereToAdd, item_bounds, whereToAdd.Depth);
 29970          }
 29971          previous = current;
 29972        HeadRemoved:
 29973          current = current.Next;
 29974        }
 29975      }
 29976
 29977      node.Count -= removals;
 29978      return removals;
 29979    }
 29980
 29981    #endregion
 29982
 29983    #region Remove
 29984
 29985    /// <summary>Removes all the items qualified by the delegate.</summary>
 29986    /// <param name="where">The predicate to qualify removals.</param>
 29987    public void Remove(Predicate<T> where)
 29988    {
 29989      this.Remove(this._top, where);
 29990      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 29991    }
 29992
 29993    /// <summary>Recursive version of the remove method.</summary>
 29994    /// <param name="node">The current node of traversal.</param>
 29995    /// <param name="where">The predicate to qualify removals.</param>
 29996    internal int Remove(Node node, Predicate<T> where)
 29997    {
 29998      int removals = 0;
 29999
 30000      // children
 30001      if (node.Children is not null)
 30002      {
 30003        int skipped = 0;
 30004        for (int i = 0; i + skipped < node.Children.Length; )
 30005        {
 30006          removals += this.Remove(node.Children[i], where);
 30007          if (node.Children[i].Count is 0)
 30008            node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 30009          else
 30010            i++;
 30011        }
 30012        Node[] newArray = new Node[node.Children.Length - skipped];
 30013        Array.Copy(node.Children, newArray, newArray.Length);
 30014        node.Children = newArray;
 30015
 30016        if (node.Count < _load && node.Count != 0)
 30017          ShrinkChild(node.Parent, node.Index);
 30018      }
 30019
 30020      // items
 30021      while (node.Head is not null && where(node.Head.Value))
 30022      {
 30023        node.Head = node.Head.Next;
 30024        removals++;
 30025      }
 30026      if (node.Head is not null)
 30027      {
 30028        Node.ValueNode list = node.Head;
 30029        while (list.Next is not null)
 30030        {
 30031          if (where(list.Next.Value))
 30032          {
 30033            list.Next = list.Next.Next;
 30034            removals++;
 30035          }
 30036        }
 30037      }
 30038
 30039      node.Count -= removals;
 30040      return removals;
 30041    }
 30042
 30043    /// <summary>Removes all the items encapsulated in a given space.</summary>
 30044    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 30045    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 30046    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 30047    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 30048    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 30049    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 30050    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 30051    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 30052    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 30053    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 30054    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 30055    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 30056    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 30057    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 30058    /// <returns>The number of items that were removed.</returns>
 30059    public void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, A
 30060    {
 30061      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1
 30062    }
 30063    /// <summary>Removes all the items encapsulated in a given space.</summary>
 30064    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 30065    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 30066    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 30067    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 30068    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 30069    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 30070    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 30071    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 30072    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 30073    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 30074    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 30075    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 30076    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 30077    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 30078    /// <returns>The number of items that were removed.</returns>
 30079    public void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, O
 30080    {
 30081      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1
 30082    }
 30083    /// <summary>Removes all the items encapsulated in a given space.</summary>
 30084    /// <param name="axis1">The coordinate along the 1D axis.</param>
 30085    /// <param name="axis2">The coordinate along the 2D axis.</param>
 30086    /// <param name="axis3">The coordinate along the 3D axis.</param>
 30087    /// <param name="axis4">The coordinate along the 4D axis.</param>
 30088    /// <param name="axis5">The coordinate along the 5D axis.</param>
 30089    /// <param name="axis6">The coordinate along the 6D axis.</param>
 30090    /// <param name="axis7">The coordinate along the 7D axis.</param>
 30091    public void RemoveEncapsulated(Omnitree.Bound<Axis1> axis1, Omnitree.Bound<Axis2> axis2, Omnitree.Bound<Axis3> axis3
 30092    {
 30093      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(axis1, axi
 30094    }
 30095    internal int RemoveEncapsulated(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds)
 30096    {
 30097      int removals = this.RemoveBase(node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 30098      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 30099      return removals;
 30100    }
 30101
 30102    /// <summary>Removes all the items overlapping a given space.</summary>
 30103    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 30104    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 30105    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 30106    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 30107    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 30108    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 30109    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 30110    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 30111    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 30112    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 30113    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 30114    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 30115    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 30116    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 30117    /// <returns>The number of items that were removed.</returns>
 30118    public void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axi
 30119    {
 30120      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, 
 30121    }
 30122    /// <summary>Removes all the items overlapping a given space.</summary>
 30123    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 30124    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 30125    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 30126    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 30127    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 30128    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 30129    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 30130    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 30131    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 30132    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 30133    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 30134    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 30135    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 30136    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 30137    /// <returns>The number of items that were removed.</returns>
 30138    public void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omn
 30139    {
 30140      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, 
 30141    }
 30142    internal int RemoveOverlapped(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds)
 30143    {
 30144      int removals = this.RemoveBase(node, bounds, (a, b) => this.InclusionCheck(a, b));
 30145      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 30146      return removals;
 30147    }
 30148
 30149    internal int RemoveBase(
 30150      Node node,
 30151      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds,
 30152      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>, Omnitree.Bounds<Axis1, Axi
 30153    {
 30154      int removals = 0;
 30155      if (InclusionCheck(bounds, node.Bounds))
 30156      {
 30157        // items
 30158        Node.ValueNode current_node = node.Head;
 30159        Node.ValueNode previous_node = null;
 30160        while (!(current_node is null))
 30161        {
 30162          Node.ValueNode temp_previous = current_node;
 30163          if (spatialCheck(bounds, GetBoundings(current_node.Value)))
 30164          {
 30165            removals++;
 30166            if (current_node == node.Head)
 30167              node.Head = node.Head.Next;
 30168            else
 30169            {
 30170              previous_node.Next = current_node.Next;
 30171              temp_previous = previous_node;
 30172            }
 30173          }
 30174          previous_node = temp_previous;
 30175          current_node = current_node.Next;
 30176        }
 30177
 30178        // children
 30179        if (node.Children is not null)
 30180        {
 30181          int skipped = 0;
 30182          for (int i = 0; i + skipped < node.Children.Length; )
 30183          {
 30184            removals += this.RemoveBase(node.Children[i], bounds, spatialCheck);
 30185            if (node.Children[i].Count is 0)
 30186              node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 30187            else
 30188              i++;
 30189          }
 30190          Node[] newArray = new Node[node.Children.Length - skipped];
 30191          Array.Copy(node.Children, newArray, newArray.Length);
 30192          node.Children = newArray;
 30193
 30194          // convert this branch back into a leaf
 30195          // Note: if count is zero, it will be chopped off
 30196          if (node.Count < _load && node.Count > 0)
 30197            ShrinkChild(node.Parent, node.Index);
 30198        }
 30199      }
 30200
 30201      node.Count -= removals;
 30202      return removals;
 30203    }
 30204
 30205    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 30206    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 30207    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 30208    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 30209    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 30210    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 30211    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 30212    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 30213    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 30214    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 30215    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 30216    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 30217    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 30218    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 30219    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 30220    /// <param name="where">The equality constraint of the removal.</param>
 30221    public void RemoveEncapsulated(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, A
 30222    {
 30223      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1
 30224    }
 30225    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 30226    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 30227    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 30228    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 30229    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 30230    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 30231    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 30232    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 30233    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 30234    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 30235    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 30236    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 30237    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 30238    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 30239    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 30240    /// <param name="where">The equality constraint of the removal.</param>
 30241    public void RemoveEncapsulated(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, O
 30242    {
 30243      this.RemoveEncapsulated(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1
 30244    }
 30245    internal int RemoveEncapsulated(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds, 
 30246    {
 30247      int removals = RemoveBase(node, bounds, where, (a, b) => this.EncapsulationCheck(a, b));
 30248      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 30249      return removals;
 30250    }
 30251
 30252    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 30253    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 30254    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 30255    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 30256    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 30257    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 30258    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 30259    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 30260    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 30261    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 30262    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 30263    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 30264    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 30265    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 30266    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 30267    /// <param name="where">The equality constraint of the removal.</param>
 30268    public void RemoveOverlapped(Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3, Axis4 min4, Axi
 30269    {
 30270      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, 
 30271    }
 30272    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 30273    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 30274    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 30275    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 30276    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 30277    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 30278    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 30279    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 30280    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 30281    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 30282    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 30283    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 30284    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 30285    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 30286    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 30287    /// <param name="where">The equality constraint of the removal.</param>
 30288    public void RemoveOverlapped(Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound<Axis2> min2, Omn
 30289    {
 30290      this.RemoveOverlapped(this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, 
 30291    }
 30292    internal int RemoveOverlapped(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds, Pr
 30293    {
 30294      int removals = RemoveBase(node, bounds, where, (a, b) => this.InclusionCheck(a, b));
 30295      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 30296      return removals;
 30297    }
 30298
 30299    internal int RemoveBase(
 30300      Node node,
 30301      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds,
 30302      Predicate<T> where,
 30303      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>, Omnitree.Bounds<Axis1, Axi
 30304    {
 30305      if (!InclusionCheck(node.Bounds, bounds))
 30306        return 0;
 30307      int removals = 0;
 30308
 30309      // items
 30310      Node.ValueNode current = node.Head;
 30311      Node.ValueNode previous = null;
 30312      while (current is not null)
 30313      {
 30314        if (spatialCheck(bounds, GetBoundings(current.Value)) && where(current.Value))
 30315        {
 30316          removals++;
 30317          if (previous is null)
 30318          {
 30319            node.Head = current.Next;
 30320            goto HeadRemoved;
 30321          }
 30322          else
 30323            previous.Next = current.Next;
 30324        }
 30325        previous = current;
 30326      HeadRemoved:
 30327        current = current.Next;
 30328      }
 30329
 30330      // children
 30331      if (node.Children is not null)
 30332      {
 30333        int skipped = 0;
 30334        for (int i = 0; i + skipped < node.Children.Length; )
 30335        {
 30336          removals += this.RemoveBase(node.Children[i], bounds, where, spatialCheck);
 30337          if (node.Children[i].Count is 0)
 30338            node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
 30339          else
 30340            i++;
 30341        }
 30342        Node[] newArray = new Node[node.Children.Length - skipped];
 30343        Array.Copy(node.Children, newArray, newArray.Length);
 30344        node.Children = newArray;
 30345
 30346        if (node.Count < _load && node.Count != 0)
 30347          ShrinkChild(node.Parent, node.Index);
 30348      }
 30349
 30350      node.Count -= removals;
 30351      return removals;
 30352    }
 30353
 30354    /// <summary>Tries to remove a value.</summary>
 30355    /// <param name="value">The value to remove.</param>
 30356    /// <returns>True if successful or false if not.</returns>
 30357    public (bool Success, Exception? Exception) TryRemove(T value)
 30358    {
 30359      Remove(value);
 30360      return (true, null);
 30361    }
 30362
 30363    /// <summary>Removes all instances of a given value.</summary>
 30364    public void Remove(T removal) => Omnitree.Remove(this, removal);
 30365
 30366    /// <summary>Removes all instances of a given value.</summary>
 30367    public void Remove(T removal, Func<T, T, bool> equate) => Omnitree.Remove(this, removal, equate);
 30368
 30369    /// <summary>Removes all the items in a given space.</summary>
 30370    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 30371    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 30372    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 30373    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 30374    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 30375    /// <param name="axis6">The axis of the removal along the  6D axis.</param>
 30376    /// <param name="axis7">The axis of the removal along the  7D axis.</param>
 30377    /// <returns>The number of items that were removed.</returns>
 30378    public void RemoveOverlapped(Axis1 axis1
 30379      , Axis2 axis2
 30380      , Axis3 axis3
 30381      , Axis4 axis4
 30382      , Axis5 axis5
 30383      , Axis6 axis6
 30384      , Axis7 axis7
 30385      )
 30386    {
 30387      this.RemoveOverlapped(axis1, axis1
 30388        , axis2, axis2
 30389        , axis3, axis3
 30390        , axis4, axis4
 30391        , axis5, axis5
 30392        , axis6, axis6
 30393        , axis7, axis7
 30394        );
 30395      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 30396    }
 30397
 30398    /// <summary>Removes all the items in a given space validated by a predicate.</summary>
 30399    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 30400    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 30401    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 30402    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 30403    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 30404    /// <param name="axis6">The axis of the removal along the  6D axis.</param>
 30405    /// <param name="axis7">The axis of the removal along the  7D axis.</param>
 30406    /// <param name="where">The equality constraint of the removal.</param>
 30407    public void RemoveOverlapped(Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6 axis6, Axis7 axi
 30408    {
 30409      this.RemoveOverlapped(axis1, axis1
 30410        , axis2, axis2
 30411        , axis3, axis3
 30412        , axis4, axis4
 30413        , axis5, axis5
 30414        , axis6, axis6
 30415        , axis7, axis7
 30416        , where);
 30417      Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
 30418    }
 30419
 30420    #endregion
 30421
 30422    #region Stepper And IEnumerable
 30423
 30424    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 30425    /// <param name="step">The delegate to perform on every item in the tree.</param>
 30426    public void Stepper(Action<T> step) =>
 30427      this.Stepper(step, this._top);
 30428
 30429    internal void Stepper(Action<T> step, Node node)
 30430    {
 30431      Node.ValueNode list = node.Head;
 30432      while (list is not null)
 30433      {
 30434        step(list.Value);
 30435        list = list.Next;
 30436      }
 30437      if (node.Children is not null)
 30438        foreach (Node child in node.Children)
 30439          this.Stepper(step, child);
 30440    }
 30441
 30442    public StepStatus StepperBreak<TStep>(TStep step = default)
 30443      where TStep : struct, IFunc<T, StepStatus> =>
 30444      StepperBreak(_top, step);
 30445
 30446    internal StepStatus StepperBreak<TStep>(Node node, TStep step)
 30447      where TStep : struct, IFunc<T, StepStatus>
 30448    {
 30449      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 30450      {
 30451        if (step.Invoke(list.Value) is Break) return Break;
 30452      }
 30453      if (node.Children is not null)
 30454      {
 30455        foreach (Node child in node.Children)
 30456        {
 30457          if (StepperBreak(child, step) is Break) return Break;
 30458        }
 30459      }
 30460      return Continue;
 30461    }
 30462
 30463    /// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
 30464    /// <param name="step">The delegate to perform on every item in the tree.</param>
 30465    public StepStatus Stepper(Func<T, StepStatus> step) =>
 30466      Stepper(step, _top);
 30467
 30468    internal StepStatus Stepper(Func<T, StepStatus> step, Node node)
 30469    {
 30470      StepStatus status = StepStatus.Continue;
 30471
 30472      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 30473        if ((status = step(list.Value)) != StepStatus.Continue)
 30474          break;
 30475
 30476      if (node.Children is not null)
 30477        foreach (Node child in node.Children)
 30478          if ((status = Stepper(step, child)) != StepStatus.Continue)
 30479            break;
 30480
 30481      return status;
 30482    }
 30483
 30484    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 30485    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 30486    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 30487    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 30488    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 30489    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 30490    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 30491    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 30492    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 30493    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 30494    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 30495    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 30496    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 30497    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 30498    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 30499    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 30500    public void StepperEncapsulated(Action<T> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 ma
 30501      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, m
 30502
 30503    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 30504    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 30505    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 30506    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 30507    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 30508    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 30509    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 30510    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 30511    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 30512    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 30513    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 30514    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 30515    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 30516    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 30517    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 30518    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 30519    public void StepperEncapsulated(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bou
 30520      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, m
 30521
 30522    internal void StepperEncapsulated(Action<T> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis
 30523      StepperBase(step, node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 30524
 30525    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 30526    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 30527    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 30528    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 30529    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 30530    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 30531    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 30532    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 30533    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 30534    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 30535    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 30536    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 30537    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 30538    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 30539    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 30540    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 30541    public void StepperOverlapped(Action<T> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 min3, Axis3 max3
 30542      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min
 30543
 30544    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 30545    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 30546    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 30547    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 30548    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 30549    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 30550    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 30551    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 30552    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 30553    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 30554    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 30555    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 30556    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 30557    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 30558    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 30559    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 30560    public void StepperOverlapped(Action<T> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1, Omnitree.Bound
 30561      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min
 30562
 30563    internal void StepperOverlapped(Action<T> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6,
 30564      StepperBase(step, node, bounds, (a, b) => this.InclusionCheck(a, b));
 30565
 30566    internal void StepperBase(
 30567      Action<T> step,
 30568      Node node,
 30569      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds,
 30570      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>, Omnitree.Bounds<Axis1, Axi
 30571    {
 30572      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 30573        if (spatialCheck(bounds, GetBoundings(list.Value)))
 30574          step(list.Value);
 30575
 30576      if (node.Children is not null)
 30577      {
 30578        foreach (Node child in node.Children)
 30579          // optimization: stop bounds checking if space encapsulates node
 30580          if (EncapsulationCheck(bounds, child.Bounds))
 30581            this.Stepper(step, child);
 30582          else if (InclusionCheck(child.Bounds, bounds))
 30583            this.StepperBase(step, child, bounds, spatialCheck);
 30584      }
 30585    }
 30586
 30587    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 30588    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 30589    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 30590    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 30591    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 30592    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 30593    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 30594    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 30595    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 30596    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 30597    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 30598    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 30599    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 30600    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 30601    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 30602    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 30603    public StepStatus StepperEncapsulated(Func<T, StepStatus> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis
 30604      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, m
 30605
 30606    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 30607    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 30608    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 30609    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 30610    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 30611    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 30612    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 30613    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 30614    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 30615    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 30616    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 30617    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 30618    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 30619    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 30620    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 30621    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 30622    public StepStatus StepperEncapsulated(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> ma
 30623      StepperEncapsulated(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, m
 30624
 30625    internal StepStatus StepperEncapsulated(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Ax
 30626      StepperBase(step, node, bounds, (a, b) => this.EncapsulationCheck(a, b));
 30627
 30628    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 30629    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 30630    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 30631    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 30632    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 30633    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 30634    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 30635    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 30636    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 30637    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 30638    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 30639    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 30640    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 30641    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 30642    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 30643    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 30644    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 min1, Axis1 max1, Axis2 min2, Axis2 max2, Axis3 
 30645      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min
 30646
 30647    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 30648    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 30649    /// <param name="min1">The minimum coordinate of the space along the 1 axis.</param>
 30650    /// <param name="max1">The maximum coordinate of the space along the 1 axis.</param>
 30651    /// <param name="min2">The minimum coordinate of the space along the 2 axis.</param>
 30652    /// <param name="max2">The maximum coordinate of the space along the 2 axis.</param>
 30653    /// <param name="min3">The minimum coordinate of the space along the 3 axis.</param>
 30654    /// <param name="max3">The maximum coordinate of the space along the 3 axis.</param>
 30655    /// <param name="min4">The minimum coordinate of the space along the 4 axis.</param>
 30656    /// <param name="max4">The maximum coordinate of the space along the 4 axis.</param>
 30657    /// <param name="min5">The minimum coordinate of the space along the 5 axis.</param>
 30658    /// <param name="max5">The maximum coordinate of the space along the 5 axis.</param>
 30659    /// <param name="min6">The minimum coordinate of the space along the 6 axis.</param>
 30660    /// <param name="max6">The maximum coordinate of the space along the 6 axis.</param>
 30661    /// <param name="min7">The minimum coordinate of the space along the 7 axis.</param>
 30662    /// <param name="max7">The maximum coordinate of the space along the 7 axis.</param>
 30663    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1
 30664      StepperOverlapped(step, _top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(min1, max1, min
 30665
 30666    internal StepStatus StepperOverlapped(Func<T, StepStatus> step, Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis
 30667      StepperBase(step, node, bounds, (a, b) => this.InclusionCheck(a, b));
 30668
 30669    internal StepStatus StepperBase(
 30670      Func<T, StepStatus> step,
 30671      Node node,
 30672      Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds,
 30673      Omnitree.SpatialCheck<Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>, Omnitree.Bounds<Axis1, Axi
 30674    {
 30675      StepStatus status = StepStatus.Continue;
 30676
 30677      for (Node.ValueNode list = node.Head; list is not null; list = list.Next)
 30678        if (spatialCheck(bounds, GetBoundings(list.Value)) &&
 30679          (status = step(list.Value)) != StepStatus.Continue)
 30680          break;
 30681
 30682      if (node.Children is not null)
 30683      {
 30684        foreach (Node child in node.Children)
 30685          // optimization: stop bounds checking if space encapsulates node
 30686          if (EncapsulationCheck(bounds, child.Bounds) &&
 30687            (status = this.Stepper(step, child)) != StepStatus.Continue)
 30688            break;
 30689          else if (InclusionCheck(child.Bounds, bounds) &&
 30690            (status = this.StepperBase(step, child, bounds, spatialCheck)) != StepStatus.Continue)
 30691            break;
 30692      }
 30693
 30694      return status;
 30695    }
 30696
 30697    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 30698    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 30699    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 30700    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 30701    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 30702    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 30703    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 30704    /// <param name="axis6">The axis of the removal along the  6D axis.</param>
 30705    /// <param name="axis7">The axis of the removal along the  7D axis.</param>
 30706    public void StepperOverlapped(Action<T> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Axis5 axis5, Axis6
 30707      StepperOverlapped(step, this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(axis1, axi
 30708        , axis2, axis2
 30709        , axis3, axis3
 30710        , axis4, axis4
 30711        , axis5, axis5
 30712        , axis6, axis6
 30713        , axis7, axis7
 30714      ));
 30715
 30716    /// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the pr
 30717    /// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
 30718    /// <param name="axis1">The axis of the removal along the  1D axis.</param>
 30719    /// <param name="axis2">The axis of the removal along the  2D axis.</param>
 30720    /// <param name="axis3">The axis of the removal along the  3D axis.</param>
 30721    /// <param name="axis4">The axis of the removal along the  4D axis.</param>
 30722    /// <param name="axis5">The axis of the removal along the  5D axis.</param>
 30723    /// <param name="axis6">The axis of the removal along the  6D axis.</param>
 30724    /// <param name="axis7">The axis of the removal along the  7D axis.</param>
 30725    public StepStatus StepperOverlapped(Func<T, StepStatus> step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 axis4, Ax
 30726      StepperOverlapped(step, this._top, new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(axis1, axi
 30727        , axis2, axis2
 30728        , axis3, axis3
 30729        , axis4, axis4
 30730        , axis5, axis5
 30731        , axis6, axis6
 30732        , axis7, axis7
 30733        ));
 30734
 30735    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 30736
 30737    public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 30738    {
 30739      // Note: this can be optimized.
 30740      IList<T> list = new ListLinked<T>();
 30741      Stepper(x => list.Add(x));
 30742      return list.GetEnumerator();
 30743    }
 30744
 30745    #endregion
 30746
 30747    /// <inheritdoc/>
 30748    public T[] ToArray() => throw new NotImplementedException();
 30749
 30750    #region Helpers
 30751
 30752    internal bool StraddlesLines(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds, Omnitree.Vecto
 30753      Omnitree.StraddlesLines(bounds, vector
 30754        , _compare1
 30755        , _compare2
 30756        , _compare3
 30757        , _compare4
 30758        , _compare5
 30759        , _compare6
 30760        , _compare7
 30761        );
 30762
 30763    /// <summary>Computes the child index that contains the desired dimensions.</summary>
 30764    /// <param name="pointOfDivision">The point of division to compare against.</param>
 30765    /// <param name="bounds">The dimensions to determine the child index.</param>
 30766    /// <returns>The computed child index based on the coordinates relative to the center of the node.</returns>
 30767    internal int DetermineChildIndex(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> pointOfDivision, O
 30768    {
 30769      // make sure a child encapsulates the bounds (otherwise the bounds cannot move down the tree)
 30770      if (StraddlesLines(bounds, pointOfDivision))
 30771        return -1;
 30772
 30773      int child = 0;
 30774      if (!bounds.Min1.Exists || !(this._compare1(bounds.Min1.Value, pointOfDivision.Axis1) is Less))
 30775        child += 1 << 0;
 30776      if (!bounds.Min2.Exists || !(this._compare2(bounds.Min2.Value, pointOfDivision.Axis2) is Less))
 30777        child += 1 << 1;
 30778      if (!bounds.Min3.Exists || !(this._compare3(bounds.Min3.Value, pointOfDivision.Axis3) is Less))
 30779        child += 1 << 2;
 30780      if (!bounds.Min4.Exists || !(this._compare4(bounds.Min4.Value, pointOfDivision.Axis4) is Less))
 30781        child += 1 << 3;
 30782      if (!bounds.Min5.Exists || !(this._compare5(bounds.Min5.Value, pointOfDivision.Axis5) is Less))
 30783        child += 1 << 4;
 30784      if (!bounds.Min6.Exists || !(this._compare6(bounds.Min6.Value, pointOfDivision.Axis6) is Less))
 30785        child += 1 << 5;
 30786      if (!bounds.Min7.Exists || !(this._compare7(bounds.Min7.Value, pointOfDivision.Axis7) is Less))
 30787        child += 1 << 6;
 30788      return child;
 30789    }
 30790
 30791    /// <summary>Converts a branch back into a leaf when the count is reduced.</summary>
 30792    /// <param name="parent">The parent to shrink a child of.</param>
 30793    /// <param name="child_index">The index of the child to shrink.</param>
 30794    internal void ShrinkChild(Node parent, int child_index)
 30795    {
 30796      Node leaf;
 30797      Node removal = null;
 30798      if (parent is null) // top of tree
 30799      {
 30800        removal = this._top;
 30801        leaf = new Node(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>.None, null, -1);
 30802        this._top = leaf;
 30803      }
 30804      else // non-top branch
 30805      {
 30806        removal = parent[child_index];
 30807        leaf = new Node(removal.Bounds, removal.Parent, removal.Index);
 30808        parent[child_index] = leaf;
 30809      }
 30810
 30811      this.Stepper((T step) => { leaf.Add(step); }, removal);
 30812    }
 30813
 30814    /// <summary>Reduces the counts of all the parents of a given node by a given amount.</summary>
 30815    /// <param name="parent">The starting parent of the reduction.</param>
 30816    /// <param name="reduction">The amount to reduce the parent counts by.</param>
 30817    internal void ReduceParentCounts(Node parent, int reduction)
 30818    {
 30819      IncreaseParentCounts(parent, -reduction);
 30820    }
 30821
 30822    /// <summary>Increases the counts of all the parents of a given node by a given amount.</summary>
 30823    /// <param name="parent">The starting parent of the increase.</param>
 30824    /// <param name="increase">The amount to increase the parent counts by.</param>
 30825    internal void IncreaseParentCounts(Node parent, int increase)
 30826    {
 30827      Node node = parent;
 30828      while (node is not null)
 30829      {
 30830        node.Count += increase;
 30831        node = node.Parent;
 30832      }
 30833    }
 30834
 30835    /// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
 30836    /// <returns>True if the spaces overlap; False if not.</returns>
 30837    internal bool InclusionCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> a, Omnitree.Bounds<Axi
 30838      Omnitree.InclusionCheck(a, b
 30839      , _compare1
 30840      , _compare2
 30841      , _compare3
 30842      , _compare4
 30843      , _compare5
 30844      , _compare6
 30845      , _compare7
 30846      );
 30847
 30848    /// <summary>Checks if a space encapsulates a point.</summary>
 30849    /// <returns>True if the space encapsulates the point; False if not.</returns>
 30850    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bounds, Omnitree.V
 30851      Omnitree.EncapsulationCheck(bounds, vector
 30852      , _compare1
 30853      , _compare2
 30854      , _compare3
 30855      , _compare4
 30856      , _compare5
 30857      , _compare6
 30858      , _compare7
 30859      );
 30860
 30861    /// <summary>Checks if a space (left) encapsulates another space (right).</summary>
 30862    /// <returns>True if the left space encapsulates the right; False if not.</returns>
 30863    internal bool EncapsulationCheck(Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> a, Omnitree.Bounds
 30864      Omnitree.EncapsulationCheck(a, b
 30865      , _compare1
 30866      , _compare2
 30867      , _compare3
 30868      , _compare4
 30869      , _compare5
 30870      , _compare6
 30871      , _compare7
 30872      );
 30873
 30874    /// <summary>Checks for equality between two locations.</summary>
 30875    /// <returns>True if equal; False if not;</returns>
 30876    internal bool EqualsCheck(Omnitree.Vector<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> a, Omnitree.Vector<Axis1,
 30877      Omnitree.EqualsCheck(a, b
 30878      , (a, b) => _compare1(a, b) is Equal
 30879      , (a, b) => _compare2(a, b) is Equal
 30880      , (a, b) => _compare3(a, b) is Equal
 30881      , (a, b) => _compare4(a, b) is Equal
 30882      , (a, b) => _compare5(a, b) is Equal
 30883      , (a, b) => _compare6(a, b) is Equal
 30884      , (a, b) => _compare7(a, b) is Equal
 30885      );
 30886
 30887    /// <summary>Gets the nearest parent that encapsulates a location.</summary>
 30888    /// <param name="node">The starting node to find the encapsulating parent of the location.</param>
 30889    /// <param name="bounds">The bounds to get the encapsulating parent from.</param>
 30890    /// <returns>The nearest node that encapsulates the given location.</returns>
 30891    internal Node GetEncapsulationParent(Node node, Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> bou
 30892    {
 30893      while (node is not null && !EncapsulationCheck(node.Bounds, bounds))
 30894      {
 30895        node = node.Parent;
 30896      }
 30897      return node;
 30898    }
 30899
 30900    internal Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7> GetBoundings(T value)
 30901    {
 30902      Omnitree.Bound<Axis1> min1; Omnitree.Bound<Axis1> max1;
 30903      Omnitree.Bound<Axis2> min2; Omnitree.Bound<Axis2> max2;
 30904      Omnitree.Bound<Axis3> min3; Omnitree.Bound<Axis3> max3;
 30905      Omnitree.Bound<Axis4> min4; Omnitree.Bound<Axis4> max4;
 30906      Omnitree.Bound<Axis5> min5; Omnitree.Bound<Axis5> max5;
 30907      Omnitree.Bound<Axis6> min6; Omnitree.Bound<Axis6> max6;
 30908      Omnitree.Bound<Axis7> min7; Omnitree.Bound<Axis7> max7;
 30909      this._getBounds(value,
 30910        out min1, out max1
 30911,
 30912        out min2, out max2
 30913,
 30914        out min3, out max3
 30915,
 30916        out min4, out max4
 30917,
 30918        out min5, out max5
 30919,
 30920        out min6, out max6
 30921,
 30922        out min7, out max7
 30923        );
 30924      return new Omnitree.Bounds<Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7>(
 30925        min1, max1
 30926,
 30927        min2, max2
 30928,
 30929        min3, max3
 30930,
 30931        min4, max4
 30932,
 30933        min5, max5
 30934,
 30935        min6, max6
 30936,
 30937        min7, max7
 30938        );
 30939    }
 30940
 30941    #endregion
 30942
 30943    #endregion
 30944  }
 30945
 30946  #endregion
 30947
 30948  #endregion
 30949}
 30950
 30951#pragma warning enable

Methods/Properties

.cctor()
.ctor(...)
.ctor(...)
get_Item(...)
set_Item(...)
get_Depth()
.ctor(...)
.ctor(...)
.ctor(...)
Add(...)
Clone()
.ctor(...)
.ctor(...)
.ctor(...)
get_Dimensions()
get_GetBounds()
get_Compare1()
get_Compare2()
get_Compare3()
get_Count()
get_MaxDepth()
get_NodeCount()
TryAdd(...)
Add(...)
Add(...)
DetermineMedians(...)
DetermineChildBounds(...)
Clear()
Clone()
CountSubSpaceEncapsulated(...)
CountSubSpaceEncapsulated(...)
CountSubSpaceEncapsulated(...)
CountSubSpaceEncapsulated(...)
CountSubSpaceOverlapped(...)
CountSubSpaceOverlapped(...)
CountSubSpaceOverlapped(...)
CountSubSpaceOverlapped(...)
CountSubSpaceEncapsulated(...)
CountSubSpaceOverlapped(...)
CountSubSpaceBase(...)
Update()
Update(...)
Update(...)
Update(...)
Update(...)
Update(...)
Update(...)
Remove(...)
Remove(...)
RemoveEncapsulated(...)
RemoveEncapsulated(...)
RemoveEncapsulated(...)
RemoveEncapsulated(...)
RemoveOverlapped(...)
RemoveOverlapped(...)
RemoveOverlapped(...)
RemoveBase(...)
RemoveEncapsulated(...)
RemoveEncapsulated(...)
RemoveEncapsulated(...)
RemoveOverlapped(...)
RemoveOverlapped(...)
RemoveOverlapped(...)
RemoveBase(...)
TryRemove(...)
Remove(...)
Remove(...)
RemoveOverlapped(...)
RemoveOverlapped(...)
Stepper(...)
Stepper(...)
StepperBreak(...)
StepperBreak(...)
Stepper(...)
Stepper(...)
StepperEncapsulated(...)
StepperEncapsulated(...)
StepperEncapsulated(...)
StepperOverlapped(...)
StepperOverlapped(...)
StepperOverlapped(...)
StepperBase(...)
StepperEncapsulated(...)
StepperEncapsulated(...)
StepperEncapsulated(...)
StepperOverlapped(...)
StepperOverlapped(...)
StepperOverlapped(...)
StepperBase(...)
StepperOverlapped(...)
StepperOverlapped(...)
System.Collections.IEnumerable.GetEnumerator()
GetEnumerator()
ToArray()
StraddlesLines(...)
DetermineChildIndex(...)
ShrinkChild(...)
ReduceParentCounts(...)
IncreaseParentCounts(...)
InclusionCheck(...)
EncapsulationCheck(...)
EncapsulationCheck(...)
EqualsCheck(...)
GetEncapsulationParent(...)
GetBoundings(...)