private void AddNodeToStringBuilder(KdTreeNavNode <TKey> node, StringBuilder sb, int depth, int maxCount) { if (maxCount <= 0) { return; } sb.AppendLine(node.ToString()); for (var side = -1; side <= 1; side += 2) { for (var index = 0; index <= depth; index++) { sb.Append("\t"); } sb.Append(side == -1 ? "L " : "R "); if (node[side] == null) { sb.AppendLine(""); } else { AddNodeToStringBuilder(node[side], sb, depth + 1, maxCount--); } } }
internal KdTreeNavNode <TKey> this[int compare] { get { if (compare <= 0) { return(LeftChild); } else { return(RightChild); } } set { if (compare <= 0) { LeftChild = value; } else { RightChild = value; } } }
public void Clear() { if (root != null) { RemoveChildNodes(root); } Count = 0; root = null; }
private void RemoveChildNodes(KdTreeNavNode <TKey> node) { for (var side = -1; side <= 1; side += 2) { if (node[side] != null) { RemoveChildNodes(node[side]); node[side] = null; } } }
public KdTreeNode <TKey, TValue> Remove(KdTreeNode <TKey, TValue> removedNode)//may be not working correct { // Is tree empty? if (root == null) { return(null); } KdTreeNavNode <TKey> navNode = root; KdTreeNavNode <TKey> parentNode = root; var node = ConvertNavNode(root); if (typeMath.AreEqual(removedNode.Points, node.Points)) { root = null; Count--; ReaddChildNodes(navNode); return(node); } int dimension = -1; int compare = 0; do { dimension = (dimension + 1) % dimensions; if (isNode(dimension)) { node = ConvertNavNode(navNode);//todo: may be optimized without using cast if (typeMath.AreEqual(removedNode.Points, node.Points) && removedNode.Value.Equals(node.Value)) { var nodeToRemove = node; parentNode[compare] = null; Count--; ReaddChildNodes(nodeToRemove); return(nodeToRemove); } } compare = typeMath.Compare(removedNode.Points[dimension], navNode.Point); if (navNode[compare] == null) { // Can't find node return(null); } parentNode = navNode; navNode = navNode[compare]; }while (navNode != null); return(null); }
private void ReaddChildNodes(KdTreeNavNode <TKey> removedNode)//todo: Maybe bug { if (removedNode.IsLeaf) { return; } // The folllowing code might seem a little redundant but we're using // 2 queues so we can add the child nodes back in, in (more or less) // the same order they were added in the first place var nodesToReadd = new Queue <KdTreeNavNode <TKey> >(); var nodesToReaddQueue = new Queue <KdTreeNavNode <TKey> >(); if (removedNode.LeftChild != null) { nodesToReaddQueue.Enqueue(removedNode.LeftChild); } if (removedNode.RightChild != null) { nodesToReaddQueue.Enqueue(removedNode.RightChild); } while (nodesToReaddQueue.Count > 0) { var nodeToReadd = nodesToReaddQueue.Dequeue(); nodesToReadd.Enqueue(nodeToReadd); for (int side = -1; side <= 1; side += 2) { if (nodeToReadd[side] != null) { nodesToReaddQueue.Enqueue(nodeToReadd[side]); nodeToReadd[side] = null; } } } while (nodesToReadd.Count > 0) { var navNodeToReadd = nodesToReadd.Dequeue(); if (navNodeToReadd.GetType() == typeof(KdTreeNavNode <TKey>)) { continue; } var nodeToReadd = (KdTreeNode <TKey, TValue>)navNodeToReadd; Count--; Add(nodeToReadd.Points, nodeToReadd.Value); } }
private void AddNodesToList(KdTreeNavNode <TKey> node, List <KdTreeNode <TKey, TValue> > nodes) { if (node == null) { return; } if (isNode(node)) { nodes.Add((KdTreeNode <TKey, TValue>)node); } for (var side = -1; side <= 1; side += 2) { if (node[side] != null) { AddNodesToList(node[side], nodes); node[side] = null; } } }
private bool TryFindValueAt(TKey[] point, KdTreeNavNode <TKey> navParent, int dimension, out TValue value, List <Vector2> path) { do { dimension = (dimension + 1) % dimensions; if (navParent == null) { value = default(TValue); //Debug.Log(log); return(false); } if (isNode(dimension)) { var parent = ConvertNavNode(navParent); path.Add((parent.Value as Cell).Position); if (typeMath.AreEqual(point, parent.Points)) { value = parent.Value; return(true); } } // Keep searching int compare = typeMath.Compare(point[dimension], navParent.Point); if (compare == 0) { if (TryFindValueAt(point, navParent[-1], dimension, out value, path)) { return(true); } if (TryFindValueAt(point, navParent[1], dimension, out value, path)) { return(true); } return(false); } navParent = navParent[compare]; }while (true); }
/// <summary> /// Add new node to tree /// </summary> /// <param name="point">Key</param> /// <param name="value">Value</param> /// <returns>Return <code>true</code> if node was added</returns> public bool Add(TKey[] point, TValue value) { var nodeToAdd = new KdTreeNode <TKey, TValue>(point, value); if (root == null) { root = nodeToAdd; } else { int dimension = -1; var navParent = root; do { dimension = (dimension + 1) % dimensions; if (isNode(dimension)) { var parent = (KdTreeNode <TKey, TValue>)navParent; if (typeMath.AreEqual(point, parent.Points)) { switch (AddDuplicateBehavior) { case AddDuplicateBehavior.Skip: return(false); case AddDuplicateBehavior.Continue: break; case AddDuplicateBehavior.Error: throw new DuplicateNodeError(); case AddDuplicateBehavior.Update: if (OnNodeUpdate != null) { if (OnNodeUpdate.Invoke(this, parent, nodeToAdd)) { return(true); } } else { parent.Value = value; return(true); } break; default: // Should never happen throw new Exception("Unexpected AddDuplicateBehavior"); } } } // Which side does this node sit under in relation to it's parent at this level? int compare = typeMath.Compare(point[dimension], navParent.Point); if (navParent[compare] == null) { if (isNavNode(dimension + 1)) { navParent[compare] = new KdTreeNavNode <TKey>(point[(dimension + 1) % dimensions]); navParent = navParent[compare]; } else { navParent[compare] = nodeToAdd; break; } } else { navParent = navParent[compare]; } } while (true); } Count++; return(true); }
private bool TryFindValueAt(TKey[] point, onAdditionalCheckEqualsDelegate additionalCheckEquals, KdTreeNavNode <TKey> navParent, int dimension, out TValue value) { do { dimension = (dimension + 1) % dimensions; if (navParent == null) { value = default(TValue); return(false); } else if (isNode(dimension)) { var parent = (KdTreeNode <TKey, TValue>)navParent; if (typeMath.AreEqual(point, parent.Points)) { if (additionalCheckEquals(parent, point)) { value = parent.Value; return(true); } else { if (TryFindValueAt(point, additionalCheckEquals, parent[-1], dimension, out value)) { return(true); } if (TryFindValueAt(point, additionalCheckEquals, parent[1], dimension, out value)) { return(true); } return(false); } } } // Keep searching int compare = typeMath.Compare(point[dimension], navParent.Point); navParent = navParent[compare]; }while (true); }
private void AddNearestNeighbours(//todo: not working correct. Very slow KdTreeNavNode <TKey> navNode, TKey[] target, int depth, //TKey[] prevDistance, Stack <TKey>[] prevDistances, LinkedList <TValue> nearestNeighbours, Stack <bool>[] wasLess) { if (navNode == null) { return; } int dimension = (depth) % dimensions; if (isNode(dimension)) { var node = ConvertNavNode(navNode); var canAdd = true; for (int dim = 0; dim < dimensions; dim++) { var distance = typeMath.DistanceBetweenPoints(node.Points[dim], target[dim]); var prevDistance = prevDistances[dim].Peek(); var prevWasLess = wasLess[dim].Peek(); if (typeMath.Compare(distance, prevDistance) > 0) { if (prevWasLess) { for (int dim1 = 0; dim1 < dim; dim1++) { prevDistances[dim1].Pop(); wasLess[dim1].Pop(); } return; } wasLess[dim].Push(true); } else { wasLess[dim].Push(false); } prevDistances[dim].Push(distance); if (typeMath.Compare( distance, typeMath.Zero) > 0) { canAdd = false; } //break; } if (canAdd) { nearestNeighbours.AddFirst(node.Value); } AddNearestNeighbours(navNode.LeftChild, target, depth + 1, prevDistances, nearestNeighbours, wasLess); AddNearestNeighbours(navNode.RightChild, target, depth + 1, prevDistances, nearestNeighbours, wasLess); for (int dim = 0; dim < dimensions; dim++) { prevDistances[dim].Pop(); wasLess[dim].Pop(); } } else { AddNearestNeighbours(navNode.LeftChild, target, depth + 1, prevDistances, nearestNeighbours, wasLess); AddNearestNeighbours(navNode.RightChild, target, depth + 1, prevDistances, nearestNeighbours, wasLess); } }
protected KdTreeNode <TKey, TValue> ConvertNavNode(KdTreeNavNode <TKey> node) { return((KdTreeNode <TKey, TValue>)node); }
protected bool isNode(KdTreeNavNode <TKey> node) { return(node.GetType() == typeof(KdTreeNode <TKey, TValue>)); }