/// <summary> /// Find KD-tree nodes whose keys are <I>n</I> farthest neighbors from /// key. Neighbors are returned in descending order of distance to key. /// </summary> /// <param name="key">key for KD-tree node</param> /// <param name="numNeighbors">The Integer showing how many neighbors to find</param> /// <returns>An array of objects at the node nearest to the key</returns> /// <exception cref="KeySizeException">Mismatch if key length doesn't match the dimension for the tree</exception> /// <exception cref="NeighborsOutOfRangeException">if <I>n</I> is negative or exceeds tree size </exception> public object[] Farthest(double[] key, int numNeighbors) { if (numNeighbors < 0 || numNeighbors > _count) { throw new NeighborsOutOfRangeException(); } if (key.Length != _k) { throw new KeySizeException(); } object[] neighbors = new object[numNeighbors]; FarthestNeighborList fnl = new FarthestNeighborList(numNeighbors); // initial call is with infinite hyper-rectangle and max distance HRect hr = HRect.InfiniteHRect(key.Length); //double max_dist_sqd = 1.79769e+30; //Double.MaxValue; HPoint keyp = new HPoint(key); KdNode.FarthestNeighbor(_root, keyp, hr, 0, 0, _k, fnl); //KDNode.nnbr(_root, keyp, hr, max_dist_sqd, 0, _k, nnl); for (int i = 0; i < numNeighbors; ++i) { KdNode kd = (KdNode)fnl.RemoveFarthest(); neighbors[numNeighbors - i - 1] = kd.V; } return(neighbors); }
/// <summary> /// A Static method for returning the square distance between two coordinates /// </summary> /// <param name="x">One coordinate</param> /// <param name="y">A second coordinate</param> /// <returns>A double representing the square distance</returns> public static double SquareDistance(HPoint x, HPoint y) { HPoint a = x; HPoint b = y; int minOrdinate = Math.Min(x.NumOrdinates, y.NumOrdinates); double dist = 0; if (a != null && b != null) { // if we can calculate using direct access to the internal coord variable, // it will be slightly faster. for (int i = 0; i < minOrdinate; ++i) { double diff = (a[i] - b[i]); dist += (diff * diff); } } else { // otherwise, just use the standard ICoordinate accessors for (int i = 0; i < minOrdinate; ++i) { double diff = (x[i] - y[i]); dist += (diff * diff); } } return(dist); }
/// <summary> /// Inserts a /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="t"></param> /// <param name="lev"></param> /// <param name="k"></param> /// <returns></returns> /// <remarks> Method ins translated from 352.ins.c of Gonnet and Baeza-Yates</remarks> public static KdNode Insert(HPoint key, object value, KdNode t, int lev, int k) { if (t == null) { t = new KdNode(key, value); } else if (key.Equals(t.K)) { // "re-insert" if (t.IsDeleted) { t.IsDeleted = false; t.V = value; } else { throw (new KeyDuplicateException()); } } else if (key[lev] > t.K[lev]) { t.Right = Insert(key, value, t.Right, (lev + 1) % k, k); } else { t.Left = Insert(key, value, t.Left, (lev + 1) % k, k); } return(t); }
/// <summary> /// Searches for values in a range /// </summary> /// <param name="lowk"></param> /// <param name="uppk"></param> /// <param name="t"></param> /// <param name="lev"></param> /// <param name="k"></param> /// <param name="v"></param> /// <remarks>Method rsearch translated from 352.range.c of Gonnet and Baeza-Yates</remarks> public static void SearchRange(HPoint lowk, HPoint uppk, KdNode t, int lev, int k, List <KdNode> v) { if (t == null) { return; } if (lowk[lev] <= t.K[lev]) { SearchRange(lowk, uppk, t.Left, (lev + 1) % k, k, v); } int j; for (j = 0; j < k && lowk[j] <= t.K[j] && uppk[j] >= t.K[j]; j++) { } if (j == k) { v.Add(t); } if (uppk[lev] > t.K[lev]) { SearchRange(lowk, uppk, t.Right, (lev + 1) % k, k, v); } }
/// <summary> /// This method calculates the furthest point on the rectangle /// from the specified point. This is to determine if it is /// possible for any of the members of the closer rectangle /// to be positioned further away from the test point than /// the points in the hyper-extent that is further from the point. /// </summary> /// <param name="t"></param> /// <returns></returns> public HPoint Farthest(HPoint t) { int len = t.NumOrdinates; HPoint p = new HPoint(len); for (int i = 0; i < len; ++i) { if (t[i] <= Min[i]) { p[i] = Max[i]; } else if (t[i] >= Max[i]) { p[i] = Min[i]; } else { // Calculating the closest position always uses the point, but // to calculate the furthest position, we actually want to // pick the furhter of two extremes, in order to pick up the // diagonal distance. // p[i] = t[i]; if (t[i] - Min[i] > Max[i] - t[i]) { p[i] = Min[i]; } else { p[i] = Max[i]; } } } return(p); }
/// <summary> /// Find KD-tree nodes whose keys are <I>n</I> nearest neighbors to /// key. Uses algorithm above. Neighbors are returned in ascending /// order of distance to key. /// </summary> /// <param name="key">key for KD-tree node</param> /// <param name="numNeighbors">The Integer showing how many neighbors to find</param> /// <returns>An array of objects at the node nearest to the key</returns> /// <exception cref="KeySizeException">Mismatch if key length doesn't match the dimension for the tree</exception> /// <exception cref="NeighborsOutOfRangeException">if <I>n</I> is negative or exceeds tree size </exception> public object[] Nearest(double[] key, int numNeighbors) { if (numNeighbors < 0 || numNeighbors > _count) { throw new NeighborsOutOfRangeException(); } if (key.Length != _k) { throw new KeySizeException(); } object[] neighbors = new object[numNeighbors]; NearestNeighborList nnl = new NearestNeighborList(numNeighbors); // initial call is with infinite hyper-rectangle and max distance HRect hr = HRect.InfiniteHRect(key.Length); const double maxDistSqd = 1.79769e+30; HPoint keyp = new HPoint(key); KdNode.Nnbr(_root, keyp, hr, maxDistSqd, 0, _k, nnl); for (int i = 0; i < numNeighbors; ++i) { KdNode kd = (KdNode)nnl.RemoveHighest(); neighbors[numNeighbors - i - 1] = kd.V; } return(neighbors); }
/// <summary> /// Constructs a new instance of the KDNode. /// </summary> /// <param name="key">A Hyper Point representing the key to use for storing this value</param> /// <param name="value">A valid object value to use for copying this.</param> /// <remarks>The constructor is used only by class; other methods are static</remarks> private KdNode(HPoint key, object value) { K = key; V = value; Left = null; Right = null; _isDeleted = false; }
/// <summary> /// Calculates the square of the Euclidean distance between this point and the other point. /// </summary> /// <param name="p">Any valid implementation of ICoordinate</param> /// <returns>A double representing the distances.</returns> public double SquareHyperDistance(HPoint p) { int maxOrdinate = Math.Min(p.NumOrdinates, NumOrdinates); double dist = 0; for (int i = 0; i < maxOrdinate; i++) { double diff = (p[i] - this[i]); dist += (diff * diff); } return(dist); }
/// <summary> /// Searches for a specific value /// </summary> /// <param name="key"></param> /// <param name="t"></param> /// <param name="k"></param> /// <returns></returns> /// <remarks>Method srch translated from 352.srch.c of Gonnet and Baeza-Yates</remarks> public static KdNode Search(HPoint key, KdNode t, int k) { for (int lev = 0; t != null; lev = (lev + 1) % k) { if (!t.IsDeleted && key.Equals(t.K)) { return(t); } t = key[lev] > t.K[lev] ? t.Right : t.Left; } return(null); }
/// <summary> /// Calculates a new HRect object that has a nearly infinite bounds. /// </summary> /// <param name="d">THe number of dimensions to use</param> /// <returns>A new HRect where the minimum is negative infinity, and the maximum is positive infinity</returns> /// <remarks>Used in initial conditions of KdTree.nearest()</remarks> public static HRect InfiniteHRect(int d) { HPoint vmin = new HPoint(d); HPoint vmax = new HPoint(d); for (int i = 0; i < d; ++i) { vmin[i] = Double.NegativeInfinity; vmax[i] = Double.PositiveInfinity; } return(new HRect(vmin, vmax)); }
/// <summary> /// If the specified HRect does not intersect this HRect, this returns null. Otherwise, /// this will return a smaller rectangular region that represents the intersection /// of the two bounding regions. /// </summary> /// <param name="region">Another HRect object to intersect with this one.</param> /// <returns>The HRect that represents the intersection area for the two bounding boxes.</returns> /// <remarks>currently unused</remarks> public HRect Intersection(HRect region) { HPoint newmin = new HPoint(Min.NumOrdinates); HPoint newmax = new HPoint(Min.NumOrdinates); for (int i = 0; i < Min.NumOrdinates; ++i) { newmin[i] = Math.Max(Min[i], region.Min[i]); newmax[i] = Math.Min(Max[i], region.Max[i]); if (newmin[i] >= newmax[i]) { return(null); } } return(new HRect(newmin, newmax)); }
/// <summary> /// Calculates the closest point on the hyper-extent to the specified point. /// from Moore's eqn. 6.6 /// </summary> /// <param name="t"></param> /// <returns></returns> public HPoint Closest(HPoint t) { int len = t.NumOrdinates; HPoint p = new HPoint(len); for (int i = 0; i < len; ++i) { if (t[i] <= Min[i]) { p[i] = Min[i]; } else if (t[i] >= Max[i]) { p[i] = Max[i]; } else { p[i] = t[i]; } } return(p); }
/// <summary> /// Calculates the Euclidean distance between the two coordinates /// </summary> /// <param name="x">An ICoordinate</param> /// <param name="y">Another ICoordinate</param> /// <returns>A double representing the distance</returns> public static double EuclideanDistance(HPoint x, HPoint y) { return(Math.Sqrt(SquareDistance(x, y))); }
/// <summary> /// Calculates the distance in comparison with any coordinate. The coordinate with fewer dimensions /// will determine the dimensionality for the comparison. /// </summary> /// <param name="p"></param> /// <returns></returns> public double HyperDistance(HPoint p) { return(Math.Sqrt(SquareHyperDistance(p))); }
/// <summary> /// Find KD-tree nodes whose keys are <I>n</I> farthest neighbors from /// key. Neighbors are returned in descending order of distance to key. /// </summary> /// <param name="key">key for KD-tree node</param> /// <param name="numNeighbors">The Integer showing how many neighbors to find</param> /// <returns>An array of objects at the node nearest to the key</returns> /// <exception cref="KeySizeException">Mismatch if key length doesn't match the dimension for the tree</exception> /// <exception cref="NeighborsOutOfRangeException">if <I>n</I> is negative or exceeds tree size </exception> public object[] Farthest(double[] key, int numNeighbors) { if (numNeighbors < 0 || numNeighbors > _count) throw new NeighborsOutOfRangeException(); if (key.Length != _k) throw new KeySizeException(); object[] neighbors = new object[numNeighbors]; FarthestNeighborList fnl = new FarthestNeighborList(numNeighbors); // initial call is with infinite hyper-rectangle and max distance HRect hr = HRect.InfiniteHRect(key.Length); //double max_dist_sqd = 1.79769e+30; //Double.MaxValue; HPoint keyp = new HPoint(key); KdNode.FarthestNeighbor(_root, keyp, hr, 0, 0, _k, fnl); //KDNode.nnbr(_root, keyp, hr, max_dist_sqd, 0, _k, nnl); for (int i = 0; i < numNeighbors; ++i) { KdNode kd = (KdNode)fnl.RemoveFarthest(); neighbors[numNeighbors - i - 1] = kd.V; } return neighbors; }
// Internal is being used for performance for KD calculations, where these would normally be private. /// <summary> /// Constructs a new instance of a rectangle binding structure based on a specified number of dimensions /// </summary> /// <param name="numDimensions">An integer representing the number of dimensions. For X, Y coordinates, this should be 2.</param> public HRect(int numDimensions) { Min = new HPoint(numDimensions); Max = new HPoint(numDimensions); }
/// <summary> /// If the specified HRect does not intersect this HRect, this returns null. Otherwise, /// this will return a smaller rectangular region that represents the intersection /// of the two bounding regions. /// </summary> /// <param name="region">Another HRect object to intersect with this one.</param> /// <returns>The HRect that represents the intersection area for the two bounding boxes.</returns> /// <remarks>currently unused</remarks> public HRect Intersection(HRect region) { HPoint newmin = new HPoint(Min.NumOrdinates); HPoint newmax = new HPoint(Min.NumOrdinates); for (int i = 0; i < Min.NumOrdinates; ++i) { newmin[i] = Math.Max(Min[i], region.Min[i]); newmax[i] = Math.Min(Max[i], region.Max[i]); if (newmin[i] >= newmax[i]) return null; } return new HRect(newmin, newmax); }
/// <summary> /// Find KD-tree nodes whose keys are <I>n</I> nearest neighbors to /// key. Uses algorithm above. Neighbors are returned in ascending /// order of distance to key. /// </summary> /// <param name="key">key for KD-tree node</param> /// <param name="numNeighbors">The Integer showing how many neighbors to find</param> /// <returns>An array of objects at the node nearest to the key</returns> /// <exception cref="KeySizeException">Mismatch if key length doesn't match the dimension for the tree</exception> /// <exception cref="NeighborsOutOfRangeException">if <I>n</I> is negative or exceeds tree size </exception> public object[] Nearest(double[] key, int numNeighbors) { if (numNeighbors < 0 || numNeighbors > _count) throw new NeighborsOutOfRangeException(); if (key.Length != _k) throw new KeySizeException(); object[] neighbors = new object[numNeighbors]; NearestNeighborList nnl = new NearestNeighborList(numNeighbors); // initial call is with infinite hyper-rectangle and max distance HRect hr = HRect.InfiniteHRect(key.Length); const double maxDistSqd = 1.79769e+30; HPoint keyp = new HPoint(key); KdNode.Nnbr(_root, keyp, hr, maxDistSqd, 0, _k, nnl); for (int i = 0; i < numNeighbors; ++i) { KdNode kd = (KdNode)nnl.RemoveHighest(); neighbors[numNeighbors - i - 1] = kd.V; } return neighbors; }
/// <summary> /// Searches for values in a range /// </summary> /// <param name="lowk"></param> /// <param name="uppk"></param> /// <param name="t"></param> /// <param name="lev"></param> /// <param name="k"></param> /// <param name="v"></param> /// <remarks>Method rsearch translated from 352.range.c of Gonnet and Baeza-Yates</remarks> public static void SearchRange(HPoint lowk, HPoint uppk, KdNode t, int lev, int k, List<KdNode> v) { if (t == null) return; if (lowk[lev] <= t.K[lev]) { SearchRange(lowk, uppk, t.Left, (lev + 1) % k, k, v); } int j; for (j = 0; j < k && lowk[j] <= t.K[j] && uppk[j] >= t.K[j]; j++) { } if (j == k) v.Add(t); if (uppk[lev] > t.K[lev]) { SearchRange(lowk, uppk, t.Right, (lev + 1) % k, k, v); } }
/// <summary> /// This method was written by Ted Dunsford by restructuring the nearest neighbor /// algorithm presented by Andrew and Bjoern /// </summary> /// <param name="kd">Since this is recursive, this represents the current node</param> /// <param name="target">The target is the HPoint that we are trying to calculate the farthest distance from</param> /// <param name="hr">In this case, the hr is the hyper rectangle bounding the region that must contain the furthest point.</param> /// <param name="maxDistSqd">The maximum distance that we have calculated thus far, and will therefore be testing against.</param> /// <param name="lev">The integer based level of that we have recursed to in the tree</param> /// <param name="k">The dimensionality of the kd tree</param> /// <param name="fnl">A list to contain the output, prioritized by distance</param> public static void FarthestNeighbor(KdNode kd, HPoint target, HRect hr, double maxDistSqd, int lev, int k, FarthestNeighborList fnl) { // 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 HPoint pivot = kd.K; double pivotToTarget = HPoint.SquareDistance(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. HRect leftHr = hr; // optimize by not cloning HRect rightHr = hr.Copy(); leftHr.Max[s] = pivot[s]; rightHr.Min[s] = pivot[s]; // 5. target-in-left := target_s <= pivot_s bool targetInLeft = target[s] < pivot[s]; KdNode nearerKd; HRect nearerHr; KdNode furtherKd; HRect furtherHr; if (targetInLeft) { // 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 nearerKd = kd.Left; nearerHr = leftHr; furtherKd = kd.Right; furtherHr = rightHr; } else { // // 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 nearerKd = kd.Right; nearerHr = rightHr; furtherKd = kd.Left; furtherHr = leftHr; } // 8. Recursively call Nearest Neighbor with paramters // (nearer-kd, target, nearer-hr, max-dist-sqd), storing the // results in nearest and dist-sqd //FarthestNeighbor(nearer_kd, target, nearer_hr, max_dist_sqd, lev + 1, K, nnl); // This line changed by Ted Dunsford to attempt to find the farther point FarthestNeighbor(furtherKd, target, furtherHr, maxDistSqd, lev + 1, k, fnl); //KDNode nearest = (KDNode)nnl.Highest; double distSqd; if (!fnl.IsCapacityReached) { //dist_sqd = 1.79769e+30; // Double.MaxValue; distSqd = 0; } else { distSqd = fnl.MinimumPriority; } // 9. max-dist-sqd := minimum of max-dist-sqd and dist-sqd //max_dist_sqd = Math.Min(max_dist_sqd, dist_sqd); maxDistSqd = Math.Max(maxDistSqd, distSqd); // 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 // HPoint closest = further_hr.Closest(target); HPoint furthest = nearerHr.Farthest(target); //if (HPoint.EuclideanDistance(closest, target) < Math.Sqrt(max_dist_sqd)) if (HPoint.EuclideanDistance(furthest, target) > Math.Sqrt(maxDistSqd)) { // 10.1 if (pivot-target)^2 < dist-sqd then if (pivotToTarget > distSqd) { // 10.1.1 nearest := (pivot, range-elt field of kd) //nearest = kd; // 10.1.2 dist-sqd = (pivot-target)^2 distSqd = pivotToTarget; // add to nnl if (!kd.IsDeleted) { fnl.Insert(kd, distSqd); } // 10.1.3 max-dist-sqd = dist-sqd // max_dist_sqd = dist_sqd; if (fnl.IsCapacityReached) { maxDistSqd = fnl.MinimumPriority; } else { // max_dist_sqd = 1.79769e+30; //Double.MaxValue; maxDistSqd = 0; } } // 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 FarthestNeighbor(nearerKd, target, nearerHr, maxDistSqd, lev + 1, k, fnl); double tempDistSqd = fnl.MinimumPriority; // 10.3 If tmp-dist-sqd < dist-sqd then if (tempDistSqd > distSqd) { // 10.3.1 nearest := temp_nearest and dist_sqd := temp_dist_sqd distSqd = tempDistSqd; } } else if (pivotToTarget < maxDistSqd) { // SDL: otherwise, current point is nearest distSqd = pivotToTarget; } }
/// <summary> /// Creates a new bounding rectangle based on the two coordinates specified. It is assumed that /// the vmin and vmax coordinates have already been correctly calculated. /// </summary> /// <param name="vmin"></param> /// <param name="vmax"></param> public HRect(HPoint vmin, HPoint vmax) { Min = vmin.Copy(); Max = vmax.Copy(); }
/// <summary> /// Inserts a /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="t"></param> /// <param name="lev"></param> /// <param name="k"></param> /// <returns></returns> /// <remarks> Method ins translated from 352.ins.c of Gonnet and Baeza-Yates</remarks> public static KdNode Insert(HPoint key, object value, KdNode t, int lev, int k) { if (t == null) { t = new KdNode(key, value); } else if (key.Equals(t.K)) { // "re-insert" if (t.IsDeleted) { t.IsDeleted = false; t.V = value; } else { throw (new KeyDuplicateException()); } } else if (key[lev] > t.K[lev]) { t.Right = Insert(key, value, t.Right, (lev + 1) % k, k); } else { t.Left = Insert(key, value, t.Left, (lev + 1) % k, k); } return t; }
/// <summary> /// This method calculates the furthest point on the rectangle /// from the specified point. This is to determine if it is /// possible for any of the members of the closer rectangle /// to be positioned further away from the test point than /// the points in the hyper-extent that is further from the point. /// </summary> /// <param name="t"></param> /// <returns></returns> public HPoint Farthest(HPoint t) { int len = t.NumOrdinates; HPoint p = new HPoint(len); for (int i = 0; i < len; ++i) { if (t[i] <= Min[i]) { p[i] = Max[i]; } else if (t[i] >= Max[i]) { p[i] = Min[i]; } else { // Calculating the closest position always uses the point, but // to calculate the furthest position, we actually want to // pick the furhter of two extremes, in order to pick up the // diagonal distance. // p[i] = t[i]; if (t[i] - Min[i] > Max[i] - t[i]) { p[i] = Min[i]; } else { p[i] = Max[i]; } } } return p; }
/// <summary> /// Calculates the square of the Euclidean distance between this point and the other point. /// </summary> /// <param name="p">Any valid implementation of ICoordinate</param> /// <returns>A double representing the distances.</returns> public double SquareHyperDistance(HPoint p) { int maxOrdinate = Math.Min(p.NumOrdinates, NumOrdinates); double dist = 0; for (int i = 0; i < maxOrdinate; i++) { double diff = (p[i] - this[i]); dist += (diff * diff); } return dist; }
/// <summary> /// Calculates the closest point on the hyper-extent to the specified point. /// from Moore's eqn. 6.6 /// </summary> /// <param name="t"></param> /// <returns></returns> public HPoint Closest(HPoint t) { int len = t.NumOrdinates; HPoint p = new HPoint(len); for (int i = 0; i < len; ++i) { if (t[i] <= Min[i]) { p[i] = Min[i]; } else if (t[i] >= Max[i]) { p[i] = Max[i]; } else { p[i] = t[i]; } } return p; }
/// <summary> /// A Static method for returning the square distance between two coordinates /// </summary> /// <param name="x">One coordinate</param> /// <param name="y">A second coordinate</param> /// <returns>A double representing the square distance</returns> public static double SquareDistance(HPoint x, HPoint y) { HPoint a = x; HPoint b = y; int minOrdinate = Math.Min(x.NumOrdinates, y.NumOrdinates); double dist = 0; if (a != null && b != null) { // if we can calculate using direct access to the internal coord variable, // it will be slightly faster. for (int i = 0; i < minOrdinate; ++i) { double diff = (a[i] - b[i]); dist += (diff * diff); } } else { // otherwise, just use the standard ICoordinate accessors for (int i = 0; i < minOrdinate; ++i) { double diff = (x[i] - y[i]); dist += (diff * diff); } } return dist; }
/// <summary> /// Calculates the Euclidean distance between the two coordinates /// </summary> /// <param name="x">An ICoordinate</param> /// <param name="y">Another ICoordinate</param> /// <returns>A double representing the distance</returns> public static double EuclideanDistance(HPoint x, HPoint y) { return Math.Sqrt(SquareDistance(x, y)); }
/// <summary> /// Calculates a new HRect object that has a nearly infinite bounds. /// </summary> /// <param name="d">THe number of dimensions to use</param> /// <returns>A new HRect where the minimum is negative infinity, and the maximum is positive infinity</returns> /// <remarks>Used in initial conditions of KdTree.nearest()</remarks> public static HRect InfiniteHRect(int d) { HPoint vmin = new HPoint(d); HPoint vmax = new HPoint(d); for (int i = 0; i < d; ++i) { vmin[i] = Double.NegativeInfinity; vmax[i] = Double.PositiveInfinity; } return new HRect(vmin, vmax); }
/// <summary> /// Calculates the distance in comparison with any coordinate. The coordinate with fewer dimensions /// will determine the dimensionality for the comparison. /// </summary> /// <param name="p"></param> /// <returns></returns> public double HyperDistance(HPoint p) { return Math.Sqrt(SquareHyperDistance(p)); }
/// <summary> /// Searches for a specific value /// </summary> /// <param name="key"></param> /// <param name="t"></param> /// <param name="k"></param> /// <returns></returns> /// <remarks>Method srch translated from 352.srch.c of Gonnet and Baeza-Yates</remarks> public static KdNode Search(HPoint key, KdNode t, int k) { for (int lev = 0; t != null; lev = (lev + 1) % k) { if (!t.IsDeleted && key.Equals(t.K)) { return t; } t = key[lev] > t.K[lev] ? t.Right : t.Left; } return null; }