public float GetDistsQuantile(float quantile) { float[] d = Dists.Data; int[] indices = Enumerable.Range(0, d.Length).ToArray(); int n = (int)(d.Length * quantile); QuickSelect.Select(indices, 0, d.Length - 1, n, i => d[i]); return(d[indices[n]]); }
/// <summary> /// This method essentially recurses, building a k-d tree of the points between first and last /// Once the number of points is smaller than knn, it uses that set of points to compute a surface normal /// From that set of points, /// </summary> void buildNew(BuildData data, int first, int last, Vector3 minValues, Vector3 maxValues) { int count = last - first; if (count <= knn) { // compute for this range fuseRange(data, first, last); // TODO: make another filter that creates constant-density clouds, // typically by stopping recursion after the median of the bounding cuboid // is below a threshold, or that the number of points falls under a threshold return; } // find the largest dimension of the box int cutDim = MaxDim(maxValues - minValues); // compute number of elements int rightCount = count / 2; int leftCount = count - rightCount; Debug.Assert(last - rightCount == first + leftCount); // select the cut point and partition the indices around it var pts = data.points; QuickSelect.Select(data.indices, first, last - 1, first + leftCount, i => GetAt(data.points[i].point, cutDim)); // get value int cutIndex = data.indices[first + leftCount]; float cutVal = GetAt(data.points[cutIndex].point, cutDim); // update bounds for left Vector3 leftMaxValues = SetAt(maxValues, cutDim, cutVal); // update bounds for right Vector3 rightMinValues = SetAt(minValues, cutDim, cutVal); // recurse buildNew(data, first, first + leftCount, minValues, leftMaxValues); buildNew(data, first + leftCount, last, rightMinValues, maxValues); }