/// <summary> /// Add a voxel to the octree. /// </summary> /// <param name="Voxel">A voxel of type T.</param> public void Add(IVoxel <T> Voxel) { if (this.Contains(Voxel)) { #region Check subtrees... if (Subtree1 != null && Subtree1.Contains(Voxel)) { Subtree1.Add(Voxel); } else if (Subtree2 != null && Subtree2.Contains(Voxel)) { Subtree2.Add(Voxel); } else if (Subtree3 != null && Subtree3.Contains(Voxel)) { Subtree3.Add(Voxel); } else if (Subtree4 != null && Subtree4.Contains(Voxel)) { Subtree4.Add(Voxel); } else if (Subtree5 != null && Subtree5.Contains(Voxel)) { Subtree5.Add(Voxel); } else if (Subtree6 != null && Subtree6.Contains(Voxel)) { Subtree6.Add(Voxel); } else if (Subtree7 != null && Subtree7.Contains(Voxel)) { Subtree7.Add(Voxel); } else if (Subtree8 != null && Subtree8.Contains(Voxel)) { Subtree8.Add(Voxel); } #endregion #region ...or the embedded data. else if (EmbeddedVoxels.Count < MaxNumberOfEmbeddedVoxels) { EmbeddedVoxels.Add(Voxel); } #endregion #region If necessary create subtrees... else { #region Create Subtrees if (Subtree1 == null) { Subtree1 = new Octree <T>(Left, Top, Front, Math.Add(Left, Math.Div2(Width)), Math.Add(Top, Math.Div2(Height)), Math.Add(Front, Math.Div2(Depth)), MaxNumberOfEmbeddedVoxels); Subtree1.OnTreeSplit += OnTreeSplit; } if (Subtree2 == null) { Subtree2 = new Octree <T>(Math.Add(Left, Math.Div2(Width)), Top, Front, Right, Math.Add(Top, Math.Div2(Height)), Math.Add(Front, Math.Div2(Depth)), MaxNumberOfEmbeddedVoxels); Subtree2.OnTreeSplit += OnTreeSplit; } if (Subtree3 == null) { Subtree3 = new Octree <T>(Left, Math.Add(Top, Math.Div2(Height)), Front, Math.Add(Left, Math.Div2(Width)), Bottom, Math.Add(Front, Math.Div2(Depth)), MaxNumberOfEmbeddedVoxels); Subtree3.OnTreeSplit += OnTreeSplit; } if (Subtree4 == null) { Subtree4 = new Octree <T>(Math.Add(Left, Math.Div2(Width)), Math.Add(Top, Math.Div2(Height)), Front, Right, Bottom, Math.Add(Front, Math.Div2(Depth)), MaxNumberOfEmbeddedVoxels); Subtree4.OnTreeSplit += OnTreeSplit; } if (Subtree5 == null) { Subtree5 = new Octree <T>(Left, Top, Math.Add(Front, Math.Div2(Depth)), Math.Add(Left, Math.Div2(Width)), Math.Add(Top, Math.Div2(Height)), Behind, MaxNumberOfEmbeddedVoxels); Subtree5.OnTreeSplit += OnTreeSplit; } if (Subtree6 == null) { Subtree6 = new Octree <T>(Math.Add(Left, Math.Div2(Width)), Top, Math.Add(Front, Math.Div2(Depth)), Right, Math.Add(Top, Math.Div2(Height)), Behind, MaxNumberOfEmbeddedVoxels); Subtree6.OnTreeSplit += OnTreeSplit; } if (Subtree7 == null) { Subtree7 = new Octree <T>(Left, Math.Add(Top, Math.Div2(Height)), Math.Add(Front, Math.Div2(Depth)), Math.Add(Left, Math.Div2(Width)), Bottom, Behind, MaxNumberOfEmbeddedVoxels); Subtree7.OnTreeSplit += OnTreeSplit; } if (Subtree8 == null) { Subtree8 = new Octree <T>(Math.Add(Left, Math.Div2(Width)), Math.Add(Top, Math.Div2(Height)), Math.Add(Front, Math.Div2(Depth)), Right, Bottom, Behind, MaxNumberOfEmbeddedVoxels); Subtree8.OnTreeSplit += OnTreeSplit; } #endregion #region Fire OctreeSplit event if (OnTreeSplit != null) { OnTreeSplit(this, Voxel); } #endregion #region Move all embedded data into the subtrees EmbeddedVoxels.Add(Voxel); foreach (var _Voxel in EmbeddedVoxels) { if (Subtree1.Contains(_Voxel)) { Subtree1.Add(_Voxel); } else if (Subtree2.Contains(_Voxel)) { Subtree2.Add(_Voxel); } else if (Subtree3.Contains(_Voxel)) { Subtree3.Add(_Voxel); } else if (Subtree4.Contains(_Voxel)) { Subtree4.Add(_Voxel); } else if (Subtree5.Contains(_Voxel)) { Subtree5.Add(_Voxel); } else if (Subtree6.Contains(_Voxel)) { Subtree6.Add(_Voxel); } else if (Subtree7.Contains(_Voxel)) { Subtree7.Add(_Voxel); } else if (Subtree8.Contains(_Voxel)) { Subtree8.Add(_Voxel); } else { throw new Exception("Mist!"); } } EmbeddedVoxels.Clear(); #endregion } #endregion } else { throw new OT_OutOfBoundsException <T>(this, Voxel); } }
/// <summary> /// A general octree exception occurred! /// </summary> /// <param name="Octree">The octree causing this exception.</param> /// <param name="Voxel">An optional voxel causing this exception.</param> /// <param name="Message">The message that describes the error.</param> /// <param name="InnerException">The exception that is the cause of the current exception.</param> public OctreeException(Octree <T> Octree, IVoxel <T> Voxel = null, String Message = null, Exception InnerException = null) : base(Message, InnerException) { this.Octree = Octree; this.Voxel = Voxel; }
/// <summary> /// An exception thrown when at least one dimension /// of the octree is zero. /// </summary> /// <param name="Octree">The octree causing this exception.</param> /// <param name="Message">The message that describes the error.</param> /// <param name="InnerException">The exception that is the cause of the current exception.</param> public OT_ZeroDimensionException(Octree <T> Octree, String Message = null, Exception InnerException = null) : base(Octree, Message: "The given octree has at least one zero dimension!" + Message, InnerException: InnerException) { }
/// <summary> /// An exception thrown when the given voxel is /// located outside of the octree bounds! /// </summary> /// <param name="Octree">The octree causing this exception.</param> /// <param name="Voxel">The voxel causing this exception.</param> /// <param name="Message">The message that describes the error.</param> /// <param name="InnerException">The exception that is the cause of the current exception.</param> public OT_OutOfBoundsException(Octree <T> Octree, IVoxel <T> Voxel, String Message = null, Exception InnerException = null) : base(Octree, Voxel, "The given voxel is located outside of the octree bounds!" + Message, InnerException) { }