public void search(SearchRecord sr) { // the core search routine. // This uses true distance to bounding box as the // criterion to search the secondary node. // // This results in somewhat fewer searches of the secondary nodes // than 'search', which uses the vdiff vector, but as this // takes more computational time, the overall performance may not // be improved in actual run time. // if ((ChildLeft == null) && (ChildRight == null)) { // we are on a leaf node if (sr.NumberOfNeighbours == 0) { process_leaf_node_fixedball(sr); } else { process_leaf_node(sr); } } else { KDTreeNodeKennell ncloser; KDTreeNodeKennell nfarther; float extra; float qval = sr.VectorTarget[cutAxis]; // value of the wall boundary on the cut dimension. if (qval < cut_val) { ncloser = ChildLeft; nfarther = ChildRight; extra = cut_val_right - qval; } else { ncloser = ChildRight; nfarther = ChildLeft; extra = qval - cut_val_left; }; if (ncloser != null) { ncloser.search(sr); } if ((nfarther != null) && (extra * extra < sr.Radius)) { // first cut if (nfarther.box_in_search_range(sr)) { nfarther.search(sr); } } } }
///// <summary> ///// number of search result ///// </summary> ///// <param name="qv"></param> ///// <param name="r2"></param> ///// <returns></returns> //public int r_count(Vector3 qv, float r2) //{ // { // // search for all within a ball of a certain radius // ListKDTreeResultVectors result = new ListKDTreeResultVectors(); // SearchRecord sr = new SearchRecord(qv, this, result); // sr.IndexCenter = -1; // sr.correltime = 0; // sr.IndexNeighbour = 0; // sr.Ballsize = r2; // root.search(sr); // return (result.Count); // } //} public ListKDTreeResultVectors r_nearest_around_point(int idxin, int correltime, float r2) { ListKDTreeResultVectors result = new ListKDTreeResultVectors(); Vector3 qv = TreeVectors[idxin].Vector.Clone(); // query vector // copy the query vector. SearchRecord sr = new SearchRecord(qv); // construct the search record. sr.Radius = r2; sr.NumberOfNeighbours = 0; root.search(sr); //if (sort_results) //{ // result.So // sort(result.begin(), result.end()); //} return(sr.SearchResult); }
public ListKDTreeResultVectors n_nearest_around_point(int idxin, int correltime, int numberOfNeighbours) { Vector3 qv = new Vector3(); qv = TreeVectors[idxin].Vector.Clone(); // copy the query vector. SearchRecord sr = new SearchRecord(qv); // construct the search record. //sr.IndexCenter = idxin; //sr.correltime = correltime; sr.NumberOfNeighbours = numberOfNeighbours; root.search(sr); //if (sort_results) //{ // sort(result.begin(), result.end()); //} // ListKDTreeResultVectors result = new ListKDTreeResultVectors(); return(sr.SearchResult); }
public ListKDTreeResultVectors Find_N_Nearest(Vector3 qv, int numberOfNeighbours) { SearchRecord sr = new SearchRecord(qv); sr.NumberOfNeighbours = numberOfNeighbours; root.search(sr); return(sr.SearchResult); }
public void FindClosestPoints_Radius(VertexKDTree vertex, float radius, ref int neighboursCount) { // search for all within a ball of a certain radius //ListKDTreeResultVectors result = new ListKDTreeResultVectors(); SearchRecord sr = new SearchRecord(vertex.Vector); // Vector3 vdiff = new Vector3(); sr.Radius = radius; root.search(sr); ListKDTreeResultVectors listResult = sr.SearchResult; neighboursCount = listResult.Count; }
public ListKDTreeResultVectors r_nearest(Vector3 qv, float r2) { // search for all within a ball of a certain radius //ListKDTreeResultVectors result = new ListKDTreeResultVectors(); SearchRecord sr = new SearchRecord(qv); // Vector3 vdiff = new Vector3(); sr.NumberOfNeighbours = 0; sr.Radius = r2; root.search(sr); //if (sort_results) //{ // sort(result.begin(), result.end()); //} return(sr.SearchResult); }
public bool box_in_search_range(SearchRecord sr) { // // does the bounding box, represented by minbox[*],maxbox[*] // have any point which is within 'sr.ballsize' to 'sr.qv'?? // float dis2 = 0.0F; float ballsize = sr.Radius; for (int i = 0; i < 3; i++) { float f = dis_from_bnd(sr.VectorTarget[i], box[i].lower, box[i].upper); dis2 += f * f; if (dis2 > ballsize) { return(false); } } return(true); }
public void process_leaf_node_fixedball(SearchRecord sr) { float ballsize = sr.Radius; // bool rearrange = sr.rearrange; for (int i = IndexLeafVector; i <= endIndex; i++) { uint indexofi = this.Parent.Indices[i]; float distance; bool early_exit; if (rearrange) { early_exit = false; distance = 0.0F; for (int k = 0; k < 3; k++) { float f = this.Parent.TreeVectors[i].Vector[k] - sr.VectorTarget[k]; distance += f * f; if (distance > ballsize) { early_exit = true; break; } } if (early_exit) { continue; // next iteration of mainloop } // why do we do things like this? because if we take an early // exit (due to distance being too large) which is common, then // we need not read in the actual point index, thus saving main // memory bandwidth. If the distance to point is less than the // ballsize, though, then we need the index. // indexofi = this.Parent.Indices[i]; } else { // // but if we are not using the rearranged data, then // we must always indexofi = this.Parent.Indices[i]; early_exit = false; distance = 0.0F; for (int k = 0; k < 3; k++) { float f = this.Parent.TreeVectors[Convert.ToInt32(indexofi)].Vector[k] - sr.VectorTarget[k]; distance += f * f; if (distance > ballsize) { early_exit = true; break; } } if (early_exit) { continue; // next iteration of mainloop } } // end if rearrange. KDTreeResult e = new KDTreeResult(indexofi, distance); //sr.result.push_back(e); sr.SearchResult.Add(e); } }
public void process_leaf_node(SearchRecord sr) { float ballsize = sr.Radius; // bool rearrange = sr.rearrange; for (int i = IndexLeafVector; i <= endIndex; i++) { uint indexofi; // sr.ind[i]; float distance; if (rearrange) { if (CheckDistance(this.Parent.TreeVectors[i].Vector, sr.VectorTarget, ballsize, out distance)) { continue;// next iteration of mainloop } // why do we do things like this? because if we take an early // exit (due to distance being too large) which is common, then // we need not read in the actual point index, thus saving main // memory bandwidth. If the distance to point is less than the // ballsize, though, then we need the index. // indexofi = this.Parent.Indices[i]; } else { // // but if we are not using the rearranged data, then // we must always compare all indexofi = this.Parent.Indices[i]; if (CheckDistance(this.Parent.TreeVectors[Convert.ToInt32(indexofi)].Vector, sr.VectorTarget, ballsize, out distance)) { continue;// next iteration of mainloop } } // end if rearrange. // here the point must be added to the list. // // two choices for any point. The list so far is either // undersized, or it is not. // if (sr.SearchResult.Count < sr.NumberOfNeighbours) { KDTreeResult e = new KDTreeResult(indexofi, distance); if (!this.Parent.TakenAlgorithm) { sr.SearchResult.Add(e); if (sr.SearchResult.Count == sr.NumberOfNeighbours) { ballsize = sr.SearchResult[0].Distance; } } else { if (!this.Parent.TreeVectors[Convert.ToInt32(indexofi)].TakenInTree) { this.Parent.TreeVectors[Convert.ToInt32(indexofi)].TakenInTree = true; sr.SearchResult.Add(e); if (sr.SearchResult.Count == sr.NumberOfNeighbours) { ballsize = sr.SearchResult[0].Distance; } } else { } } // Set the ball radius to the largest on the list (maximum priority). } else { // // if we get here then the current node, has a squared // distance smaller // than the last on the list, and belongs on the list. // KDTreeResult e = new KDTreeResult(indexofi, distance); ballsize = sr.SearchResult.ReplaceLast_ReturnFirst(e); } if (distance == 0f) { break; } } // main loop sr.Radius = ballsize; }