@@ -11,16 +11,17 @@ namespace Quadtree
1111 /// </summary>
1212 public class Node < TItem > where TItem : IItem < TItem >
1313 {
14+ /// <summary>
15+ /// Describes relative local position in respect to the current node.
16+ /// </summary>
17+ /// <remarks>
18+ /// Integer values of <c>UPPER_LEFT</c>, <c>UPPER_RIGHT</c>, <c>LOWER_RIGHT</c>, <c>LOWER_LEFT</c> do correspond with the indices of the sub-nodes.
19+ /// </remarks>
1420 public enum IntraLocation {
1521 UPPER_LEFT , UPPER_RIGHT , LOWER_RIGHT , LOWER_LEFT ,
1622 SPANNING_LEFT , SPANNING_RIGHT , SPANNING_UPPER , SPANNING_LOWER , SPANNING
1723 } ;
1824
19- /// <summary>
20- /// Minimum possible value for node size.
21- /// </summary>
22- public const float MinSize = 1f ;
23-
2425 /// <summary>
2526 /// Bounds of this tree node.
2627 /// </summary>
@@ -35,8 +36,11 @@ public enum IntraLocation {
3536 public Node < TItem > ParentNode { get => _parentNode ; internal set => _parentNode = value ; }
3637
3738 /// <summary>
38- /// Parent tree node.
39+ /// Reference to parent tree node.
3940 /// </summary>
41+ /// <remarks>
42+ /// Is <c>null</c> for root node of the tree.
43+ /// </remarks>
4044 private Node < TItem > _parentNode = null ;
4145
4246 /// <summary>
@@ -45,16 +49,16 @@ public enum IntraLocation {
4549 private RootNode < TItem > _root ;
4650
4751 /// <summary>
48- /// Child tree nodes.
52+ /// List of child tree nodes.
4953 /// </summary>
5054 private readonly List < Node < TItem > > _subNodes ;
5155
5256 /// <summary>
53- /// Creates new tree node at provided point with provided sizes.
54- /// List of predefined sub-nodes and/or items may be provided.
57+ /// Creates new tree node at provided point (<paramref name="center"/>) with provided sizes (<paramref name="size"/>) .
58+ /// List of predefined sub-nodes (<paramref name="subNodes"/>) and/or items (<paramref name="items"/>) may be provided.
5559 /// </summary>
5660 /// <remarks>
57- /// No boundary validation is performed neither for provided sub-nodes nor items.
61+ /// No boundary validation is performed neither for provided sub-nodes (<paramref name="subNodes"/>) nor items (<paramref name="items"/>) .
5862 /// </remarks>
5963 ///
6064 /// <param name="root">Root node of the tree</param>
@@ -74,22 +78,22 @@ public Node(RootNode<TItem> root, Node<TItem> parent, Vector3 center, Vector3 si
7478 }
7579
7680 /// <summary>
77- /// Verifies whether provided boundaries are fully contained within boundaries of this node.
81+ /// Verifies whether provided boundaries (<paramref name="bounds"/>) are fully contained within the boundaries of the node.
7882 /// </summary>
7983 ///
8084 /// <param name="bounds">Boundaries of an object</param>
81- /// <returns>Object is/is not fully contained</returns>
85+ /// <returns><c>True</c> if object is fully contained within the node, <c>False</c> otherwise </returns>
8286 public bool Contains ( Bounds bounds ) =>
8387 bounds . min . x >= Bounds . min . x
8488 && bounds . min . z >= Bounds . min . z
8589 && bounds . max . x < Bounds . max . x
8690 && bounds . max . z < Bounds . max . z ;
8791
8892 /// <summary>
89- /// Calculates relative internal position of the provided bounds within the node.
93+ /// Calculates relative internal position of the provided bounds (<paramref name="bounds"/>) within the node.
9094 /// </summary>
9195 /// <remarks>
92- /// Method does not check if bounds are actually contained within the node.
96+ /// The method expects the boundaries to be fully contained within the node.
9397 /// </remarks>
9498 ///
9599 /// <param name="bounds">Boundaries contained within the node</param>
@@ -159,10 +163,10 @@ public IntraLocation Location(Bounds bounds)
159163 }
160164
161165 /// <summary>
162- /// Inserts item into smallest node possible in the tree .
166+ /// Inserts item (<paramref name="item"/>) into the smallest node possible in the subtree .
163167 /// </summary>
164168 /// <remarks>
165- /// Node's insert method expects item boundaries to be fully contained within the node.
169+ /// The method expects item boundaries to be fully contained within the node.
166170 /// </remarks>
167171 ///
168172 /// <param name="item">Item to be inserted</param>
@@ -204,13 +208,71 @@ public void Insert(TItem item)
204208 }
205209
206210 /// <summary>
207- /// Updates provided item's location within the tree.
211+ /// Removes the provided item (<paramref name="item"/>) from the node and its subtree.
212+ /// </summary>
213+ ///
214+ /// <param name="item">Item to be removed from the tree</param>
215+ public void Remove ( TItem item )
216+ {
217+ var itemBounds = item . GetBounds ( ) ;
218+ var itemBoundsLocation = Location ( itemBounds ) ;
219+ switch ( itemBoundsLocation )
220+ {
221+ // boundaries are contained within one of the subnodes
222+ case IntraLocation . UPPER_LEFT :
223+ case IntraLocation . UPPER_RIGHT :
224+ case IntraLocation . LOWER_RIGHT :
225+ case IntraLocation . LOWER_LEFT :
226+ _subNodes [ ( int ) itemBoundsLocation ] . Remove ( item ) ;
227+ break ;
228+
229+ // boundaries are spanning over 2 or more subnodes
230+ default :
231+ RemoveOwnItem ( item ) ;
232+ break ;
233+ }
234+ }
235+
236+ /// <summary>
237+ /// Removes provided item (<paramref name="item"/>) from the node.
238+ /// </summary>
239+ ///
240+ /// <param name="item">Item to be removed from the node</param>
241+ protected internal void RemoveOwnItem ( TItem item )
242+ {
243+ // remove the item from the node
244+ _items . Remove ( item ) ;
245+ // update its parent node
246+ item . ParentNode = null ;
247+
248+ if ( IsEmpty ( ) )
249+ {
250+ // remove subnodes if subtree of this node is empty
251+ _subNodes . Clear ( ) ;
252+ }
253+ }
254+
255+ /// <summary>
256+ /// Checks whether the node and recursively all its subnodes are empty.
257+ /// </summary>
258+ ///
259+ /// <returns><c>True</c> if node and all its subnodes are empty, <c>False</c> otherwise</returns>
260+ public bool IsEmpty ( )
261+ {
262+ if ( _items . Count > 0 )
263+ return false ;
264+
265+ return _subNodes . TrueForAll ( node => node . IsEmpty ( ) ) ;
266+ }
267+
268+ /// <summary>
269+ /// Updates provided item's (<paramref name="item"/>) location within the tree.
208270 /// </summary>
209271 ///
210272 /// <param name="item">Item which's location is to be updated</param>
211273 /// <param name="forceInsertionEvaluation"><c>True</c> forces tree to re-insert the item</param>
212274 /// <param name="hasOriginallyContainedItem"><c>True</c> only for the first called node</param>
213- protected internal void Update ( TItem item , bool forceInsertionEvaluation = false , bool hasOriginallyContainedItem = true )
275+ protected internal void Update ( TItem item , bool forceInsertionEvaluation = true , bool hasOriginallyContainedItem = true )
214276 {
215277 if ( Contains ( item . GetBounds ( ) ) )
216278 {
@@ -264,50 +326,13 @@ protected internal void Update(TItem item, bool forceInsertionEvaluation = false
264326 }
265327
266328 /// <summary>
267- /// Removes provided item from the subtree.
268- /// </summary>
269- ///
270- /// <param name="item">Item to be removed from the tree</param>
271- public void Remove ( TItem item )
272- {
273-
274- }
275-
276- /// <summary>
277- /// Removes provided item from the node.
278- /// </summary>
279- ///
280- /// <param name="item">Item to be removed from the node</param>
281- protected internal void RemoveOwnItem ( TItem item )
282- {
283- _items . Remove ( item ) ;
284-
285- if ( IsEmpty ( ) )
286- {
287- _subNodes . Clear ( ) ;
288- }
289- }
290-
291- /// <summary>
292- /// Checks whether the node and recursively all its subnodes are empty.
293- /// </summary>
294- ///
295- /// <returns><c>True</c> if node and all its subnodes are empty, <c>False</c> otherwise</returns>
296- public bool IsEmpty ( )
297- {
298- if ( _items . Count > 0 )
299- return false ;
300-
301- return _subNodes . TrueForAll ( node => node . IsEmpty ( ) ) ;
302- }
303-
304- /// <summary>
305- /// Splits current node to appropriate sub-nodes.
329+ /// Creates sub-nodes for the node.
306330 /// </summary>
307- private void CreateSubNodes ( )
331+ protected internal void CreateSubNodes ( )
308332 {
309333 var subBoundsSize = Bounds . size * .5f ;
310- if ( subBoundsSize . x < MinSize || subBoundsSize . z < MinSize )
334+ if ( subBoundsSize . x < _root . NodeMinimumPossibleSize
335+ || subBoundsSize . z < _root . NodeMinimumPossibleSize )
311336 {
312337 // new sub-node bounds are too small
313338 return ;
@@ -345,7 +370,7 @@ private void CreateSubNodes()
345370 }
346371
347372 /// <summary>
348- /// Finds items located within provided boundaries.
373+ /// Finds items (<paramref name="items"/>) located within provided boundaries (<paramref name="bounds"/>) .
349374 /// </summary>
350375 ///
351376 /// <param name="bounds">Boundaries to look for items within</param>
@@ -406,8 +431,8 @@ public void FindAndAddItems(Bounds bounds, ref List<TItem> items)
406431 }
407432
408433 /// <summary>
409- /// Adds all items of this node and its sub-nodes to provided list of items.
410- /// If additional boundaries are provided only items truly intersecting with them will be added.
434+ /// Adds all items of this node and its sub-nodes to the provided list of items (<paramref name="items"/>) .
435+ /// If boundaries (<paramref name="bounds"/>) are provided then only items intersecting with them will be added.
411436 /// </summary>
412437 ///
413438 /// <param name="items">Output list for found items</param>
@@ -419,8 +444,8 @@ public void AddItems(ref List<TItem> items, Bounds? bounds = null)
419444 }
420445
421446 /// <summary>
422- /// Adds all items belonging to this node (ignoring sub-nodes).
423- /// If additional boundaries are provided only items truly intersecting with them will be added.
447+ /// Adds all items belonging to this node (ignoring sub-nodes) to the provided list of items (<paramref name="items"/>) .
448+ /// If boundaries (<paramref name="bounds"/>) are provided then only items intersecting with them will be added.
424449 /// </summary>
425450 ///
426451 /// <param name="items">Output list for found items</param>
@@ -435,8 +460,8 @@ protected internal void AddOwnItems(ref List<TItem> items, Bounds? bounds = null
435460 }
436461
437462 /// <summary>
438- /// Adds all items belonging to sub-nodes (ignoring own items).
439- /// If additional boundaries are provided only items truly intersecting with them will be added.
463+ /// Adds all items belonging to sub-nodes (ignoring own items) to the provided list of items (<paramref name="items"/>) .
464+ /// If boundaries (<paramref name="bounds"/>) are provided then only items intersecting with them will be added.
440465 /// </summary>
441466 ///
442467 /// <param name="items">Output list for found items</param>
@@ -448,7 +473,7 @@ protected internal void AddSubNodeItems(ref List<TItem> items, Bounds? bounds =
448473 }
449474
450475 /// <summary>
451- /// Removes any existing items or sub-nodes.
476+ /// Removes any existing items from the node and removes all of its sub-nodes.
452477 /// </summary>
453478 public void Clear ( )
454479 {
@@ -457,7 +482,7 @@ public void Clear()
457482 }
458483
459484 /// <summary>
460- /// Displays boundaries of this node and all its sub-nodes.
485+ /// Displays boundaries of this node and all its sub-nodes and a current number of contained items if allowed .
461486 /// </summary>
462487 public void DrawBounds ( )
463488 {
0 commit comments