// Prepare a list of points for Delaunay triangulation: randomly assign into logarithmic bins, sort within bins, and add sentinels. // For details, see Amenta et al., Incremental Constructions con BRIO. static Array<Perturbed2> partially_sorted_shuffle(RawArray<const EV> Xin) { const int n = Xin.size(); Array<Perturbed2> X(n+3,uninit); // Randomly assign input points into bins. Bin k has 2**k = 1,2,4,8,... and starts at index 2**k-1 = 0,1,3,7,... // We fill points into bins as sequentially as possible to maximize cache coherence. const int bins = integer_log(n); Array<int> bin_counts(bins); for (int i=0;i<n;i++) { int j = (int)random_permute(n,key,i); const int bin = min(integer_log(j+1),bins-1); j = (1<<bin)-1+bin_counts[bin]++; X[j] = Perturbed2(i,Xin[i]); } // Spatially sort each bin down to clusters of size 64. const int leaf_size = 64; for (int bin=0;bin<bins;bin++) { const int start = (1<<bin)-1, end = bin==bins-1?n:start+(1<<bin); assert(bin_counts[bin]==end-start); spatial_sort(X.slice(start,end),leaf_size,new_<Random>(key+bin)); } // Add 3 sentinel points at infinity X[n+0] = Perturbed2(n+0,EV(-bound,-bound)); X[n+1] = Perturbed2(n+1,EV( bound, 0) ); X[n+2] = Perturbed2(n+2,EV(-bound, bound)); return X; }
static void spatial_sort(RawArray<Perturbed2> X, const int leaf_size, Random& random) { const int n = X.size(); if (n<=leaf_size) return; // We determine the subdivision axis using inexact computation, which is okay since neither the result nor // the asymptotic worst case complexity depends upon any properties of the spatial_sort whatsoever. const Box<EV> box = bounding_box(X.project<EV,&Perturbed2::value_>()); const int axis = box.sizes().argmax(); // We use exact arithmetic to perform the partition, which is important in case many points are coincident const int mid = axis==0 ? spatial_partition<0>(X,random) : spatial_partition<1>(X,random); // Recursely sort both halves spatial_sort(X.slice(0,mid),leaf_size,random); spatial_sort(X.slice(mid,n),leaf_size,random); }
int main() { std::vector<Point_3> points; Point_3 p; while(std::cin >> p){ points.push_back(p); } Timer timer; timer.start(); int N = 0; for(int i = 0; i < 5; i++){ spatial_sort(points.begin(), points.end()); } timer.stop(); std::cerr << timer.time() << " sec" << std::endl; return 0; }