void _imd_calc_bounds(iIMDShape *s, Vector3f *p, int size) { int32_t xmax, ymax, zmax, count; double dx, dy, dz, rad_sq, rad, old_to_p_sq, old_to_p, old_to_new; double xspan, yspan, zspan, maxspan; Vector3f dia1, dia2, cen; Vector3f vxmin(0, 0, 0), vymin(0, 0, 0), vzmin(0, 0, 0), vxmax(0, 0, 0), vymax(0, 0, 0), vzmax(0, 0, 0); s->max.x = s->max.y = s->max.z = -FP12_MULTIPLIER; s->min.x = s->min.y = s->min.z = FP12_MULTIPLIER; vxmax.x = vymax.y = vzmax.z = -FP12_MULTIPLIER; vxmin.x = vymin.y = vzmin.z = FP12_MULTIPLIER; // set up bounding data for minimum number of vertices for (count = 0; count < size; p++, count++) { if (p->x > s->max.x) { s->max.x = p->x; } if (p->x < s->min.x) { s->min.x = p->x; } if (p->y > s->max.y) { s->max.y = p->y; } if (p->y < s->min.y) { s->min.y = p->y; } if (p->z > s->max.z) { s->max.z = p->z; } if (p->z < s->min.z) { s->min.z = p->z; } // for tight sphere calculations if (p->x < vxmin.x) { vxmin.x = p->x; vxmin.y = p->y; vxmin.z = p->z; } if (p->x > vxmax.x) { vxmax.x = p->x; vxmax.y = p->y; vxmax.z = p->z; } if (p->y < vymin.y) { vymin.x = p->x; vymin.y = p->y; vymin.z = p->z; } if (p->y > vymax.y) { vymax.x = p->x; vymax.y = p->y; vymax.z = p->z; } if (p->z < vzmin.z) { vzmin.x = p->x; vzmin.y = p->y; vzmin.z = p->z; } if (p->z > vzmax.z) { vzmax.x = p->x; vzmax.y = p->y; vzmax.z = p->z; } } // no need to scale an IMD shape (only FSD) xmax = MAX(s->max.x, -s->min.x); ymax = MAX(s->max.y, -s->min.y); zmax = MAX(s->max.z, -s->min.z); s->radius = MAX(xmax, MAX(ymax, zmax)); s->sradius = sqrtf(xmax * xmax + ymax * ymax + zmax * zmax); // START: tight bounding sphere // set xspan = distance between 2 points xmin & xmax (squared) dx = vxmax.x - vxmin.x; dy = vxmax.y - vxmin.y; dz = vxmax.z - vxmin.z; xspan = dx * dx + dy * dy + dz * dz; // same for yspan dx = vymax.x - vymin.x; dy = vymax.y - vymin.y; dz = vymax.z - vymin.z; yspan = dx * dx + dy * dy + dz * dz; // and ofcourse zspan dx = vzmax.x - vzmin.x; dy = vzmax.y - vzmin.y; dz = vzmax.z - vzmin.z; zspan = dx * dx + dy * dy + dz * dz; // set points dia1 & dia2 to maximally seperated pair // assume xspan biggest dia1 = vxmin; dia2 = vxmax; maxspan = xspan; if (yspan > maxspan) { maxspan = yspan; dia1 = vymin; dia2 = vymax; } if (zspan > maxspan) { dia1 = vzmin; dia2 = vzmax; } // dia1, dia2 diameter of initial sphere cen.x = (dia1.x + dia2.x) / 2.; cen.y = (dia1.y + dia2.y) / 2.; cen.z = (dia1.z + dia2.z) / 2.; // calc initial radius dx = dia2.x - cen.x; dy = dia2.y - cen.y; dz = dia2.z - cen.z; rad_sq = dx * dx + dy * dy + dz * dz; rad = sqrt((double)rad_sq); // second pass (find tight sphere) for (p = s->points; p < s->points + s->npoints; p++) { dx = p->x - cen.x; dy = p->y - cen.y; dz = p->z - cen.z; old_to_p_sq = dx * dx + dy * dy + dz * dz; // do r**2 first if (old_to_p_sq > rad_sq) { // this point outside current sphere old_to_p = sqrt((double)old_to_p_sq); // radius of new sphere rad = (rad + old_to_p) / 2.; // rad**2 for next compare rad_sq = rad * rad; old_to_new = old_to_p - rad; // centre of new sphere cen.x = (rad * cen.x + old_to_new * p->x) / old_to_p; cen.y = (rad * cen.y + old_to_new * p->y) / old_to_p; cen.z = (rad * cen.z + old_to_new * p->z) / old_to_p; } } s->ocen = cen; // END: tight bounding sphere }
static bool _imd_load_points( const char **ppFileData, iIMDShape *s ) { Vector3f *p = NULL; int32_t xmax, ymax, zmax; double dx, dy, dz, rad_sq, rad, old_to_p_sq, old_to_p, old_to_new; double xspan, yspan, zspan, maxspan; Vector3f dia1, dia2, cen; Vector3f vxmin(0, 0, 0), vymin(0, 0, 0), vzmin(0, 0, 0), vxmax(0, 0, 0), vymax(0, 0, 0), vzmax(0, 0, 0); //load the points then pass through a second time to setup bounding datavalues s->points = (Vector3f*)malloc(sizeof(Vector3f) * s->npoints); if (s->points == NULL) { return false; } // Read in points and remove duplicates (!) if ( ReadPoints( ppFileData, s ) == false ) { free(s->points); s->points = NULL; return false; } s->max.x = s->max.y = s->max.z = -FP12_MULTIPLIER; s->min.x = s->min.y = s->min.z = FP12_MULTIPLIER; vxmax.x = vymax.y = vzmax.z = -FP12_MULTIPLIER; vxmin.x = vymin.y = vzmin.z = FP12_MULTIPLIER; // set up bounding data for minimum number of vertices for (p = s->points; p < s->points + s->npoints; p++) { if (p->x > s->max.x) { s->max.x = p->x; } if (p->x < s->min.x) { s->min.x = p->x; } if (p->y > s->max.y) { s->max.y = p->y; } if (p->y < s->min.y) { s->min.y = p->y; } if (p->z > s->max.z) { s->max.z = p->z; } if (p->z < s->min.z) { s->min.z = p->z; } // for tight sphere calculations if (p->x < vxmin.x) { vxmin.x = p->x; vxmin.y = p->y; vxmin.z = p->z; } if (p->x > vxmax.x) { vxmax.x = p->x; vxmax.y = p->y; vxmax.z = p->z; } if (p->y < vymin.y) { vymin.x = p->x; vymin.y = p->y; vymin.z = p->z; } if (p->y > vymax.y) { vymax.x = p->x; vymax.y = p->y; vymax.z = p->z; } if (p->z < vzmin.z) { vzmin.x = p->x; vzmin.y = p->y; vzmin.z = p->z; } if (p->z > vzmax.z) { vzmax.x = p->x; vzmax.y = p->y; vzmax.z = p->z; } } // no need to scale an IMD shape (only FSD) xmax = MAX(s->max.x, -s->min.x); ymax = MAX(s->max.y, -s->min.y); zmax = MAX(s->max.z, -s->min.z); s->radius = MAX(xmax, MAX(ymax, zmax)); s->sradius = sqrtf(xmax*xmax + ymax*ymax + zmax*zmax); // START: tight bounding sphere // set xspan = distance between 2 points xmin & xmax (squared) dx = vxmax.x - vxmin.x; dy = vxmax.y - vxmin.y; dz = vxmax.z - vxmin.z; xspan = dx*dx + dy*dy + dz*dz; // same for yspan dx = vymax.x - vymin.x; dy = vymax.y - vymin.y; dz = vymax.z - vymin.z; yspan = dx*dx + dy*dy + dz*dz; // and ofcourse zspan dx = vzmax.x - vzmin.x; dy = vzmax.y - vzmin.y; dz = vzmax.z - vzmin.z; zspan = dx*dx + dy*dy + dz*dz; // set points dia1 & dia2 to maximally seperated pair // assume xspan biggest dia1 = vxmin; dia2 = vxmax; maxspan = xspan; if (yspan > maxspan) { maxspan = yspan; dia1 = vymin; dia2 = vymax; } if (zspan > maxspan) { dia1 = vzmin; dia2 = vzmax; } // dia1, dia2 diameter of initial sphere cen.x = (dia1.x + dia2.x) / 2.; cen.y = (dia1.y + dia2.y) / 2.; cen.z = (dia1.z + dia2.z) / 2.; // calc initial radius dx = dia2.x - cen.x; dy = dia2.y - cen.y; dz = dia2.z - cen.z; rad_sq = dx*dx + dy*dy + dz*dz; rad = sqrt((double)rad_sq); // second pass (find tight sphere) for (p = s->points; p < s->points + s->npoints; p++) { dx = p->x - cen.x; dy = p->y - cen.y; dz = p->z - cen.z; old_to_p_sq = dx*dx + dy*dy + dz*dz; // do r**2 first if (old_to_p_sq>rad_sq) { // this point outside current sphere old_to_p = sqrt((double)old_to_p_sq); // radius of new sphere rad = (rad + old_to_p) / 2.; // rad**2 for next compare rad_sq = rad*rad; old_to_new = old_to_p - rad; // centre of new sphere cen.x = (rad*cen.x + old_to_new*p->x) / old_to_p; cen.y = (rad*cen.y + old_to_new*p->y) / old_to_p; cen.z = (rad*cen.z + old_to_new*p->z) / old_to_p; } } s->ocen = cen; // END: tight bounding sphere return true; }