Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
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);
        }