public int Compare(NodeMeasured <T> x, NodeMeasured <T> y) { var diff = x.Distance - y.Distance; if (diff < 0) { return(-1); } else if (diff > 0) { return(1); } return(0); }
private double invEarthDiameter = 1.0 / 12742018.0; /* meters */ /// <summary> /// Return the n elements closes to the search element for a given startingNode, withing max kilometers /// </summary> /// <param name="search"></param> /// <param name="startingNode"></param> /// <param name="n">Return N elements</param> /// <param name="max">Maxim distance to look for</param> /// <returns></returns> public List <NodeMeasured <T> > Lookup(T search, Node <T> node, int n, double max) { if (max > 0) { max = 2 * Math.Sin(max * invEarthDiameter); //max = 10000; } var result = new List <NodeMeasured <T> >(); if (node == null || max <= 0 || n == 0) { return(result); } var stack = new Stack <object>(); stack.Push(node); stack.Push(0.0); while (stack.Count > 0) { double dist = (double)stack.Pop(); node = (Node <T>)stack.Pop(); if (node == null) { continue; } // If this subtree is further away than we care about, then skip it. if (dist > max) { continue; } // If we've already found enough locations, and the furthest one is closer // than this subtree possibly could be, just skip the subtree. if (result.Count == n && result[result.Count - 1].Distance < dist * dist) { continue; } //Iterate all the way down the tree, adding nodes that we need to remember //to visit later onto the stack. var searchPosition = Position(search); while (node != null) { Node <T> m; if (searchPosition[node.Axis] < node.Split) { stack.Push(node.Right); stack.Push(node.Split - searchPosition[node.Axis]); m = node.Left; } else { stack.Push(node.Left); stack.Push(searchPosition[node.Axis] - node.Split); m = node.Right; } if (m != null) { node = m; } else { break; } } // Once hit a leaf node, insert into the list of candidates, making sure the list keep sorted dist = this.Distance(searchPosition, Position(node.Data)); if (dist <= max * max) { var candidate = new NodeMeasured <T>(node, dist); var index = result.BinarySearch(candidate, new CompareByDistance <T>()); if (index < 0) { result.Insert(~index, candidate); } if (result.Count > n) { result.Remove(result.Last()); } } } return(result); }