private void Expand(IBoundable <Envelope, TItem> bndComposite, IBoundable <Envelope, TItem> bndOther, bool isFlipped,
                            PriorityQueue <BoundablePair <TItem> > priQ, double minDistance)
        {
            var children = ((AbstractNode <Envelope, TItem>)bndComposite).ChildBoundables;

            foreach (var child in children)
            {
                BoundablePair <TItem> bp;
                if (isFlipped)
                {
                    bp = new BoundablePair <TItem>(bndOther, child, _itemDistance);
                }
                else
                {
                    bp = new BoundablePair <TItem>(child, bndOther, _itemDistance);
                }

                // only add to queue if this pair might contain the closest points
                // MD - it's actually faster to construct the object rather than called distance(child, bndOther)!
                if (bp.Distance < minDistance)
                {
                    priQ.Add(bp);
                }
            }
        }
Example #2
0
        /// <inheritdoc cref="IComparer{T}.Compare"/>
        public int Compare(BoundablePair <TItem> p1, BoundablePair <TItem> p2)
        {
            double distance1 = p1.Distance;
            double distance2 = p2.Distance;

            if (_normalOrder)
            {
                if (distance1 > distance2)
                {
                    return(1);
                }
                if (distance1 == distance2)
                {
                    return(0);
                }

                return(-1);
            }
            else
            {
                if (distance1 > distance2)
                {
                    return(-1);
                }
                else if (distance1 == distance2)
                {
                    return(0);
                }

                return(1);
            }
        }
Example #3
0
        /// <summary>
        /// Finds the item in this tree which is nearest to the given <paramref name="item"/>,
        /// using <see cref="IItemDistance{Envelope,TItem}"/> as the distance metric.
        /// A Branch-and-Bound tree traversal algorithm is used
        /// to provide an efficient search.
        /// <para/>
        /// The query <paramref name="item"/> does <b>not</b> have to be
        /// contained in the tree, but it does
        /// have to be compatible with the <paramref name="itemDist"/>
        /// distance metric.
        /// </summary>
        /// <param name="env">The envelope of the query item</param>
        /// <param name="item">The item to find the nearest neighbour of</param>
        /// <param name="itemDist">A distance metric applicable to the items in this tree and the query item</param>
        /// <returns>The nearest item in this tree</returns>
        public TItem NearestNeighbour(Envelope env, TItem item, IItemDistance <Envelope, TItem> itemDist)
        {
            var bnd = new ItemBoundable <Envelope, TItem>(env, item);
            var bp  = new BoundablePair <TItem>(Root, bnd, itemDist);

            return(NearestNeighbour(bp)[0]);
        }
 /// <summary>
 /// Compares two pairs based on their minimum distances
 /// </summary>
 public int CompareTo(BoundablePair <TItem> o)
 {
     if (_distance < o._distance)
     {
         return(-1);
     }
     if (_distance > o._distance)
     {
         return(1);
     }
     return(0);
 }
Example #5
0
        private TItem[] NearestNeighbour(BoundablePair <TItem> initBndPair, double maxDistance, int k)
        {
            double distanceLowerBound = maxDistance;

            // initialize internal structures
            var priQ = new PriorityQueue <BoundablePair <TItem> >();

            // initialize queue
            priQ.Add(initBndPair);

            var kNearestNeighbors = new PriorityQueue <BoundablePair <TItem> >(k, new BoundablePairDistanceComparer <TItem>(false));

            while (!priQ.IsEmpty() && distanceLowerBound >= 0.0)
            {
                // pop head of queue and expand one side of pair
                var bndPair = priQ.Poll();

                double currentDistance = bndPair.Distance;

                /**
                 * If the distance for the first node in the queue
                 * is >= the current maximum distance in the k queue , all other nodes
                 * in the queue must also have a greater distance.
                 * So the current minDistance must be the true minimum,
                 * and we are done.
                 */

                if (currentDistance >= distanceLowerBound)
                {
                    break;
                }

                /**
                 * If the pair members are leaves
                 * then their distance is the exact lower bound.
                 * Update the distanceLowerBound to reflect this
                 * (which must be smaller, due to the test
                 * immediately prior to this).
                 */
                if (bndPair.IsLeaves)
                {
                    // assert: currentDistance < minimumDistanceFound

                    if (kNearestNeighbors.Size < k)
                    {
                        kNearestNeighbors.Add(bndPair);
                    }
                    else
                    {
                        if (kNearestNeighbors.Peek().Distance > currentDistance)
                        {
                            kNearestNeighbors.Poll();
                            kNearestNeighbors.Add(bndPair);
                        }

                        /*
                         * minDistance should be the farthest point in the K nearest neighbor queue.
                         */
                        distanceLowerBound = kNearestNeighbors.Peek().Distance;
                    }
                }
                else
                {
                    // testing - does allowing a tolerance improve speed?
                    // Ans: by only about 10% - not enough to matter

                    /*
                     * double maxDist = bndPair.getMaximumDistance();
                     * if (maxDist * .99 < lastComputedDistance)
                     * return;
                     * //*/

                    /**
                     * Otherwise, expand one side of the pair,
                     * (the choice of which side to expand is heuristically determined)
                     * and insert the new expanded pairs into the queue
                     */
                    bndPair.ExpandToQueue(priQ, distanceLowerBound);
                }
            }
            // done - return items with min distance

            return(GetItems(kNearestNeighbors));
        }
Example #6
0
        private static TItem[] NearestNeighbour(BoundablePair <TItem> initBndPair, double maxDistance)
        {
            double distanceLowerBound     = maxDistance;
            BoundablePair <TItem> minPair = null;

            // initialize internal structures
            var priQ = new PriorityQueue <BoundablePair <TItem> >();

            // initialize queue
            priQ.Add(initBndPair);

            while (!priQ.IsEmpty() && distanceLowerBound > 0.0)
            {
                // pop head of queue and expand one side of pair
                var    bndPair         = priQ.Poll();
                double currentDistance = bndPair.Distance; //bndPair.GetDistance();

                /**
                 * If the distance for the first node in the queue
                 * is >= the current minimum distance, all other nodes
                 * in the queue must also have a greater distance.
                 * So the current minDistance must be the true minimum,
                 * and we are done.
                 */
                if (currentDistance >= distanceLowerBound)
                {
                    break;
                }

                /**
                 * If the pair members are leaves
                 * then their distance is the exact lower bound.
                 * Update the distanceLowerBound to reflect this
                 * (which must be smaller, due to the test
                 * immediately prior to this).
                 */
                if (bndPair.IsLeaves)
                {
                    // assert: currentDistance < minimumDistanceFound
                    distanceLowerBound = currentDistance;
                    minPair            = bndPair;
                }
                else
                {
                    // testing - does allowing a tolerance improve speed?
                    // Ans: by only about 10% - not enough to matter

                    /*
                     * double maxDist = bndPair.getMaximumDistance();
                     * if (maxDist * .99 < lastComputedDistance)
                     * return;
                     * //*/

                    /**
                     * Otherwise, expand one side of the pair,
                     * (the choice of which side to expand is heuristically determined)
                     * and insert the new expanded pairs into the queue
                     */
                    bndPair.ExpandToQueue(priQ, distanceLowerBound);
                }
            }
            if (minPair != null)
            {
                // done - return items with min distance
                return new[]
                       {
                           ((ItemBoundable <Envelope, TItem>)minPair.GetBoundable(0)).Item,
                           ((ItemBoundable <Envelope, TItem>)minPair.GetBoundable(1)).Item
                       }
            }
            ;
            return(null);
        }
Example #7
0
 private TItem[] NearestNeighbour(BoundablePair <TItem> initBndPair, int k)
 {
     return(NearestNeighbour(initBndPair, double.PositiveInfinity, k));
 }
Example #8
0
 private static TItem[] NearestNeighbour(BoundablePair <TItem> initBndPair)
 {
     return(NearestNeighbour(initBndPair, double.PositiveInfinity));
 }
Example #9
0
        /// <summary>
        /// Finds the two nearest items from this tree
        /// and another tree,
        /// using <see cref="IItemDistance{Envelope, TItem}"/> as the distance metric.
        /// A Branch-and-Bound tree traversal algorithm is used
        /// to provide an efficient search.
        /// The result value is a pair of items,
        /// the first from this tree and the second
        /// from the argument tree.
        /// </summary>
        /// <param name="tree">Another tree</param>
        /// <param name="itemDist">A distance metric applicable to the items in the trees</param>
        /// <returns>The pair of the nearest items, one from each tree</returns>
        public TItem[] NearestNeighbour(STRtree <TItem> tree, IItemDistance <Envelope, TItem> itemDist)
        {
            var bp = new BoundablePair <TItem>(Root, tree.Root, itemDist);

            return(NearestNeighbour(bp));
        }