Пример #1
0
        internal static void rsearch(HyperPoint lowk, HyperPoint uppk, KDNode t, int lev, int K, List <KDNode> v)
        {
            if (t == null)
            {
                return;
            }
            if (lowk.coord[lev] <= t.k.coord[lev])
            {
                rsearch(lowk, uppk, t.left, (lev + 1) % K, K, v);
            }
            int j;

            for (j = 0; j < K && lowk.coord[j] <= t.k.coord[j] &&
                 uppk.coord[j] >= t.k.coord[j]; j++)
            {
                ;
            }
            if (j == K)
            {
                v.Add(t);
            }
            if (uppk.coord[lev] > t.k.coord[lev])
            {
                rsearch(lowk, uppk, t.right, (lev + 1) % K, K, v);
            }
        }
Пример #2
0
        internal static KDNode ins(HyperPoint key, Object val, KDNode t, int lev, int K)
        {
            if (t == null)
            {
                t = new KDNode(key, val);
            }

            else if (key.equals(t.k))
            {
                if (t.deleted)
                {
                    t.deleted = false;
                    t.v       = val;
                }
                else
                {
                    if (t.duplicates == null)
                    {
                        t.duplicates = new List <object>();
                    }
                    t.duplicates.Add(val);
                }
            }

            else if (key.coord[lev] > t.k.coord[lev])
            {
                t.right = ins(key, val, t.right, (lev + 1) % K, K);
            }
            else
            {
                t.left = ins(key, val, t.left, (lev + 1) % K, K);
            }

            return(t);
        }
Пример #3
0
        /// <summary>
        /// Look for 'n' neighbours to a given point. Each neighbour must be unique..
        /// </summary>
        /// <param name="inputVector">vector to find neighbours of</param>
        /// <param name="neighbourCount">number of neighbours to find</param>
        /// <param name="distances">array of distances</param>
        public void UniqueSearch(double[] inputVector, int neighbourCount, ref List <KDTreePoint> distances)  //
        {
            distances.Clear();
            if (neighbourCount < 0 || neighbourCount > m_count)
            {
                throw new ArgumentOutOfRangeException("Number of neighbors cannot" +
                                                      " be negative or greater than number of nodes");
            }

            if (inputVector.Length != dimensions)
            {
                throw new ArgumentOutOfRangeException();
            }

            Object []           nbrs = new Object [neighbourCount];
            NearestNeighborList nnl  = new NearestNeighborList(neighbourCount);

            // initial call is with infinite hyper-rectangle and max distance
            HyperRect  hr           = HyperRect.infiniteHyperRect(inputVector.Length);
            double     max_dist_sqd = Double.MaxValue;
            HyperPoint keyp         = new HyperPoint(inputVector);

            KDNode.nnbr(root, keyp, hr, max_dist_sqd, 0, dimensions, nnl);
            while (distances.Count < neighbourCount)
            {
                KDNode kd   = (KDNode)nnl.removeHighest();
                double dist = HyperPoint.eucdist(keyp, kd.k);
                distances.Add(new KDTreePoint(kd.v, dist * dist));
            }
            distances.Sort();
        }
Пример #4
0
 private KDNode(HyperPoint key, Object val)
 {
     k       = key;
     v       = val;
     left    = null;
     right   = null;
     deleted = false;
 }
Пример #5
0
        internal static double sqrdist(HyperPoint x, HyperPoint y)
        {
            double dist = 0;

            for (int i = 0; i < x.coord.Length; ++i)
            {
                double diff = (x.coord[i] - y.coord[i]);
                dist += (diff * diff);
            }
            return(dist);
        }
Пример #6
0
 internal bool equals(HyperPoint p)
 {
     for (int i = 0; i < coord.Length; ++i)
     {
         if (coord[i] != p.coord[i])
         {
             return(false);
         }
     }
     return(true);
 }
Пример #7
0
        // used in initial conditions of KDTree.nearest()
        internal static HyperRect infiniteHyperRect(int d)
        {
            HyperPoint vmin = new HyperPoint(d);
            HyperPoint vmax = new HyperPoint(d);

            for (int i = 0; i < d; ++i)
            {
                vmin.coord[i] = Double.NegativeInfinity;
                vmax.coord[i] = Double.PositiveInfinity;
            }

            return(new HyperRect(vmin, vmax));
        }
Пример #8
0
        // currently unused
        internal HyperRect intersection(HyperRect r)
        {
            HyperPoint newmin = new HyperPoint(min.coord.Length);
            HyperPoint newmax = new HyperPoint(min.coord.Length);

            for (int i = 0; i < min.coord.Length; ++i)
            {
                newmin.coord[i] = Math.Max(min.coord[i], r.min.coord[i]);
                newmax.coord[i] = Math.Min(max.coord[i], r.max.coord[i]);
                if (newmin.coord[i] >= newmax.coord[i])
                {
                    return(null);
                }
            }

            return(new HyperRect(newmin, newmax));
        }
Пример #9
0
        internal static KDNode srch(HyperPoint key, KDNode t, int K)
        {
            for (int lev = 0; t != null; lev = (lev + 1) % K)
            {
                if (!t.deleted && key.equals(t.k))
                {
                    return(t);
                }
                else if (key.coord[lev] > t.k.coord[lev])
                {
                    t = t.right;
                }
                else
                {
                    t = t.left;
                }
            }

            return(null);
        }
Пример #10
0
 /// <summary>
 /// find the neighbours within a distance of a point
 /// </summary>
 /// <remarks>Note that the distance array contains the squares of the distances found.</remarks>
 /// <param name="inputVector">Vector to find neighbours of</param>
 /// <param name="maxDistance">distance to search over</param>
 /// <param name="neighbourCount">number of neighbours found within distance</param>
 /// <param name="distances">array of squared distances of neighbours from the input vector</param>
 /// <param name="maxNeighbourCount">maximum permissable size of arrays</param>
 public void SearchByDistance(double[] inputVector, double maxDistance, out int neighbourCount, ref List <KDTreePoint> distances, int maxNeighbourCount)
 {
     double[] lower = new double[inputVector.Length];
     double[] upper = new double[inputVector.Length];
     for (int n = 0; n < inputVector.Length; n++)
     {
         lower[n] = inputVector[n] - maxDistance;
         upper[n] = inputVector[n] + maxDistance;
     }
     KDNode[] list = this.range(lower, upper);
     foreach (KDNode node in list)
     {
         double dist = HyperPoint.eucdist(new HyperPoint(inputVector), node.k);
         if (dist <= maxDistance)
         {
             distances.Add(new KDTreePoint(node.v, dist * dist));
         }
     }
     distances.Sort();
     neighbourCount = distances.Count;
 }
Пример #11
0
        // from Moore's eqn. 6.6
        internal HyperPoint closest(HyperPoint t)
        {
            HyperPoint p = new HyperPoint(t.coord.Length);

            for (int i = 0; i < t.coord.Length; ++i)
            {
                if (t.coord[i] <= min.coord[i])
                {
                    p.coord[i] = min.coord[i];
                }
                else if (t.coord[i] >= max.coord[i])
                {
                    p.coord[i] = max.coord[i];
                }
                else
                {
                    p.coord[i] = t.coord[i];
                }
            }

            return(p);
        }
Пример #12
0
 internal static double eucdist(HyperPoint x, HyperPoint y)
 {
     return(Math.Sqrt(sqrdist(x, y)));
 }
Пример #13
0
        internal static void nnbr(KDNode kd, HyperPoint target, HyperRect hr, double max_dist_sqd, int lev, int K, NearestNeighborList nnl)
        {
            // 1. if kd is empty then set dist-sqd to infinity and exit.
            if (kd == null)
            {
                return;
            }

            // 2. s := split field of kd
            int s = lev % K;

            // 3. pivot := dom-elt field of kd
            HyperPoint pivot           = kd.k;
            double     pivot_to_target = HyperPoint.sqrdist(pivot, target);

            // 4. Cut hr into to sub-hyperrectangles left-hr and right-hr.
            //    The cut plane is through pivot and perpendicular to the s
            //    dimension.
            HyperRect left_hr  = hr;            // optimize by not cloning
            HyperRect right_hr = (HyperRect)hr.clone();

            left_hr.max.coord[s]  = pivot.coord[s];
            right_hr.min.coord[s] = pivot.coord[s];

            // 5. target-in-left := target_s <= pivot_s
            bool target_in_left = target.coord[s] < pivot.coord[s];

            KDNode    nearer_kd;
            HyperRect nearer_hr;
            KDNode    further_kd;
            HyperRect further_hr;

            // 6. if target-in-left then
            //    6.1. nearer-kd := left field of kd and nearer-hr := left-hr
            //    6.2. further-kd := right field of kd and further-hr := right-hr
            if (target_in_left)
            {
                nearer_kd  = kd.left;
                nearer_hr  = left_hr;
                further_kd = kd.right;
                further_hr = right_hr;
            }
            //
            // 7. if not target-in-left then
            //    7.1. nearer-kd := right field of kd and nearer-hr := right-hr
            //    7.2. further-kd := left field of kd and further-hr := left-hr
            else
            {
                nearer_kd  = kd.right;
                nearer_hr  = right_hr;
                further_kd = kd.left;
                further_hr = left_hr;
            }

            // 8. Recursively call Nearest Neighbor with paramters
            //    (nearer-kd, target, nearer-hr, max-dist-sqd), storing the
            //    results in nearest and dist-sqd
            nnbr(nearer_kd, target, nearer_hr, max_dist_sqd, lev + 1, K, nnl);

            KDNode nearest = (KDNode)nnl.getHighest();
            double dist_sqd;

            if (!nnl.isCapacityReached())
            {
                dist_sqd = Double.MaxValue;
            }
            else
            {
                dist_sqd = nnl.getMaxPriority();
            }

            // 9. max-dist-sqd := minimum of max-dist-sqd and dist-sqd
            max_dist_sqd = Math.Min(max_dist_sqd, dist_sqd);

            // 10. A nearer point could only lie in further-kd if there were some
            //     part of further-hr within distance sqrt(max-dist-sqd) of
            //     target.  If this is the case then
            HyperPoint closest = further_hr.closest(target);

            if (HyperPoint.eucdist(closest, target) < Math.Sqrt(max_dist_sqd))
            {
                // 10.1 if (pivot-target)^2 < dist-sqd then
                if (pivot_to_target < dist_sqd)
                {
                    // 10.1.1 nearest := (pivot, range-elt field of kd)
                    nearest = kd;

                    // 10.1.2 dist-sqd = (pivot-target)^2
                    dist_sqd = pivot_to_target;

                    // add to nnl
                    if (!kd.deleted)
                    {
                        nnl.insert(kd, dist_sqd);
                    }

                    // 10.1.3 max-dist-sqd = dist-sqd
                    // max_dist_sqd = dist_sqd;
                    if (nnl.isCapacityReached())
                    {
                        max_dist_sqd = nnl.getMaxPriority();
                    }
                    else
                    {
                        max_dist_sqd = Double.MaxValue;
                    }
                }

                // 10.2 Recursively call Nearest Neighbor with parameters
                //      (further-kd, target, further-hr, max-dist_sqd),
                //      storing results in temp-nearest and temp-dist-sqd
                nnbr(further_kd, target, further_hr, max_dist_sqd, lev + 1, K, nnl);
                KDNode temp_nearest  = (KDNode)nnl.getHighest();
                double temp_dist_sqd = nnl.getMaxPriority();

                // 10.3 If tmp-dist-sqd < dist-sqd then
                if (temp_dist_sqd < dist_sqd)
                {
                    // 10.3.1 nearest := temp_nearest and dist_sqd := temp_dist_sqd
                    nearest  = temp_nearest;
                    dist_sqd = temp_dist_sqd;
                }
            }

            // SDL: otherwise, current point is nearest
            else if (pivot_to_target < max_dist_sqd)
            {
                nearest  = kd;
                dist_sqd = pivot_to_target;
            }
        }
Пример #14
0
 internal HyperRect(HyperPoint vmin, HyperPoint vmax)
 {
     min = (HyperPoint)vmin.clone();
     max = (HyperPoint)vmax.clone();
 }
Пример #15
0
 internal HyperRect(int ndims)
 {
     min = new HyperPoint(ndims);
     max = new HyperPoint(ndims);
 }