protected NearestNeighborIterator(KdNode <T> treeRoot, double[] searchPoint, int maxPointsReturned, IDistanceFunction distanceFunction)
 {
     this.searchPoint      = Arrays.copyOf(searchPoint, searchPoint.Length);
     this.pointsRemaining  = Math.Min(maxPointsReturned, treeRoot.size());
     this.distanceFunction = distanceFunction;
     this.pendingPaths     = new BinaryHeap.Min <KdNode <T> >();
     this.pendingPaths.offer(0, treeRoot);
     this.evaluatedPoints = new KDTreeRednaxela.IntervalHeap <T>();
 }
Beispiel #2
0
        protected static <T> nearestNeighborSearchStep(
            KDTreeRednaxela.MinHeap <KdNode <T> > pendingPaths, MaxHeap <T> evaluatedPoints, int desiredPoints,
            IDistanceFunction distanceFunction, double[] searchPoint)
        {
            // If there are pending paths possibly closer than the nearest evaluated point, check it out
            KdNode <T> cursor = pendingPaths.getMin();

            pendingPaths.removeMin();

            // Descend the tree, recording paths not taken
            while (!cursor.isLeaf())
            {
                KdNode <T> pathNotTaken;
                if (searchPoint[cursor.splitDimension] > cursor.splitValue)
                {
                    pathNotTaken = cursor.left;
                    cursor       = cursor.right;
                }
                else
                {
                    pathNotTaken = cursor.right;
                    cursor       = cursor.left;
                }
                double otherDistance = distanceFunction.distanceToRect(searchPoint, pathNotTaken.minBound, pathNotTaken.maxBound);
                // Only add a path if we either need more points or it's closer than furthest point on list so far
                if (evaluatedPoints.size() < desiredPoints || otherDistance <= evaluatedPoints.getMaxKey())
                {
                    pendingPaths.offer(otherDistance, pathNotTaken);
                }
            }

            if (cursor.singlePoint)
            {
                double nodeDistance = distanceFunction.distance(cursor.points[0], searchPoint);
                // Only add a point if either need more points or it's closer than furthest on list so far
                if (evaluatedPoints.size() < desiredPoints || nodeDistance <= evaluatedPoints.getMaxKey())
                {
                    for (int i = 0; i < cursor.size(); i++)
                    {
                        T value = (T)cursor.data[i];

                        // If we don't need any more, replace max
                        if (evaluatedPoints.size() == desiredPoints)
                        {
                            evaluatedPoints.replaceMax(nodeDistance, value);
                        }
                        else
                        {
                            evaluatedPoints.offer(nodeDistance, value);
                        }
                    }
                }
            }
            else
            {
                // Add the points at the cursor
                for (int i = 0; i < cursor.size(); i++)
                {
                    double[] point    = cursor.points[i];
                    T        value    = (T)cursor.data[i];
                    double   distance = distanceFunction.distance(point, searchPoint);
                    // Only add a point if either need more points or it's closer than furthest on list so far
                    if (evaluatedPoints.size() < desiredPoints)
                    {
                        evaluatedPoints.offer(distance, value);
                    }
                    else if (distance < evaluatedPoints.getMaxKey())
                    {
                        evaluatedPoints.replaceMax(distance, value);
                    }
                }
            }
        }