// "buckytree" (c)2007 Bryan McNett. All Rights Reserved. // bmcnett at gmail dot com // sort an array of spheres in O(NlogN) time. // determine which intersect a sphere in O(logN)? time, // requiring no spatial index // the database contains "minimum" values for each convex hull plane, // and the search query contains "maximum" values. // the search query is a convex hull. // the ABC of plane equation[i] goes in basis[i] // and the D goes in hull[i] #include #include #include #define AABB #define EXPLICIT_SPATIAL_INDEX // not required, but vastly improves rejection rate #define DIMENSIONS 3 #ifdef AABB #define DIRECTIONS (DIMENSIONS*2) // AABB is easier to understand #else #define DIRECTIONS (DIMENSIONS+1) // simplex ( triangle, tetrahedron ) is more space-efficient #endif struct vector { float v[DIMENSIONS]; }; struct sphere { vector center; float radius; }; struct hull { float plane[DIRECTIONS]; }; // for 3D AABB, this is [ max(x), max(-x), max(y), max(-y), max(z), max(-z) ] vector basis[DIRECTIONS] #if DIMENSIONS == 3 = { #if defined(AABB) {{ 1, 0, 0 }}, {{ -1, 0, 0 }}, {{ 0, 1, 0 }}, {{ 0, -1, 0 }}, {{ 0, 0, 1 }}, {{ 0, 0, -1 }} #else {{ 0.000, 0.000, 1.000 }}, {{ 0.943, 0.000, -0.333 }}, {{ -0.471, 0.816, -0.333 }}, {{ -0.471, -0.816, -0.333 }} #endif // defined(AABB) } #endif // DIMENSIONS == 3 ; float dot( const vector& a, const vector& b ) { float result = a.v[0] * b.v[0]; for( int i=1; iplane[direction] < dot( median->center, basis[direction] ) - median->radius ) return; // reject median and far side of plane #ifdef EXPLICIT_SPATIAL_INDEX // simulate the rejections made by an explicit spatial index int i; for( i=0; iplane[i] < dot( median->center, basis[i] ) - median->radius ) break; if( i == DIRECTIONS ) #endif { ++tests; if( intersects( query_sphere, *median ) ) *results++ = median; } buckysearch( results, median+1, end, query, (direction+1)%DIRECTIONS ); } // search an array of spheres for those that intersect a target sphere in O(logN)? time // void buckysearch( sphere**& results, sphere* begin, sphere* end, sphere* query ) { query_sphere = *query; hull query_maximum; for( int i=0; icenter, basis[i] ) + query->radius; buckysearch( results, begin, end, &query_maximum, 0 ); } #define SPHERES 50000 #define ITERATIONS 500000 int main( int argc, char* argv[] ) { std::ofstream out( "out.txt", std::ios_base::app ); out << "bounding shape: " << #ifdef AABB "AABB" #else "simplex" #endif << std::endl; out << "spatial index: " << #ifdef EXPLICIT_SPATIAL_INDEX "explicit" #else "implicit" #endif << std::endl; sphere database[SPHERES]; srand( 0xCAFEBABE ); for( int i=0; i