void calcBoundingSphere(double *center, double *radius, FaceList *fl){ double maxDistance = 0.0; for( int i = 0; i < fl->vc-1; i++ ){ for(int j = i + 1; j < fl->vc; j++){ double *a = fl->vertices[i]; double *b = fl->vertices[j]; double distance = vecSquaredDistanceBetween3d(a, b); if( distance > maxDistance){ midpoint(center, a, b); *radius = sqrt(distance) * 0.5; maxDistance = distance; } } } }
void calcRitterBoundingSphere(double* center, double* radius, FaceList *fl){ /* An Efficient Bounding Sphere by Jack Ritter from "Graphics Gems", Academic Press, 1990 p. 301-303, code: p. 723-725 */ int count = 0; double x_min, x_max, y_min, y_max, z_min, z_max; int px_min, px_max, py_min, py_max, pz_min, pz_max; double *p; // Intialize // Select a point in the mesh as an arbitrary starting point. p = fl->vertices[0]; px_min = px_max = py_min = py_max = pz_min = pz_max = 0; x_min = x_max = p[0]; y_min = y_max = p[1]; z_min = z_max = p[2]; // Find 6 minima & maxima points for( int i = 0; i < fl->vc; i++ ){ p = fl->vertices[i]; if( p[0] < x_min ){ x_min = p[0]; px_min = i; } if( p[0] > x_max ){ x_max = p[0]; px_max = i; } if( p[1] < y_min ){ y_min = p[1]; py_min = i; } if( p[1] > y_max ){ y_max = p[1]; py_max = i; } if( p[2] < z_min ){ z_min = p[2]; pz_min = i; } if( p[2] > z_max ){ z_max = p[2]; pz_max = i; } } // end for // Find the distance between the extremal values double x_span_dist = vecSquaredDistanceBetween3d(fl->vertices[px_max], fl->vertices[px_min]); double y_span_dist = vecSquaredDistanceBetween3d(fl->vertices[py_max], fl->vertices[py_min]); double z_span_dist = vecSquaredDistanceBetween3d(fl->vertices[pz_max], fl->vertices[pz_min]); // Find the maximally separated pair; dia1 & dia2 double max_span_dist = x_span_dist; int dia1, dia2; dia1 = px_min; dia2 = px_max; if( y_span_dist > max_span_dist ){ max_span_dist = y_span_dist; dia1 = py_min; dia2 = py_max; } if( z_span_dist > max_span_dist ){ dia1 = pz_min; dia2 = pz_max; } // dia1 and dia2 define the diameter of the intial sphere // calculate the center of the sphere double _center[3]; midpoint(_center, fl->vertices[dia1], fl->vertices[dia2]); // Calculate the length of the radius double radius_sq_dist = vecSquaredDistanceBetween3d(fl->vertices[dia2], _center); double radius_dist = sqrt(radius_sq_dist); // Incrementally grow the sphere to include all points for( int i = 0; i < fl->vc; i++ ){ double test_sq_dist = vecSquaredDistanceBetween3d(fl->vertices[i], _center); if( test_sq_dist > radius_sq_dist ){ // the current (ith) point is outside the sphere double test_dist = sqrt(test_sq_dist); // calculate the radius of the new sphere radius_dist = (radius_dist + test_dist) * 0.5; radius_sq_dist = SQR(radius_dist); // calculate the center of the new sphere double old_to_new_dist = test_dist - radius_dist; for(int j = 0; j < 3; j++){ _center[j] = (radius_dist * _center[j] + old_to_new_dist * fl->vertices[i][j]) / test_dist; } count++; } } // end for *radius = radius_dist; for(int j = 0; j < 3; j++){ center[j] = _center[j]; } //printf("Grew the sphere %d times\n", count); }