This is spheremisc.c in view mode; [Download] [Up]
#include <stdio.h> #include <math.h> #include "geom.h" #include "geomclass.h" #include "transform.h" #include "sphereP.h" #include "hpoint3.h" #ifndef FUDGE #define FUDGE 1e-6 #endif void SphereMinMax(Sphere *sphere, HPoint3 *min, HPoint3 *max) { Geom *bbox; bbox = GeomBound((Geom *)sphere, TM_IDENTITY); BBoxMinMax((BBox *)bbox, min, max); GeomDelete(bbox); HPt3Normalize(min, min); HPt3Normalize(max, max); } void SphereCenter(Sphere *sphere, HPoint3 *center) { *center = sphere->center; } float SphereRadius(Sphere *sphere) { return sphere->radius; } void SphereSwitchSpace(Sphere *sphere, int space) { Transform T; sphere->space = space; TmScale(sphere->axis, sphere->radius, sphere->radius, sphere->radius); TmSpaceTranslate(T, sphere->center.x, sphere->center.y, sphere->center.z, sphere->space); GeomTransform((Geom*)sphere, T); } Sphere *SphereUnion3(Sphere *a, Sphere *b, Sphere *dest) { Sphere *sphere; int space; HPoint3 center, diff; float radius, mag_diff; if (a == NULL && b == NULL) return NULL; space = (a != NULL) ? a->space : b->space; if (dest == NULL) dest = (Sphere *)GeomCreate("sphere", CR_SPACE, space, CR_END); if (a == NULL || b == NULL) { if (a == NULL) { radius = b->radius; center = b->center; space = b->space; } else if (b == NULL) { radius = a->radius; center = a->center; space = a->space; } GeomSet((Geom*)dest, CR_RADIUS, radius, CR_CENTER, ¢er, CR_SPACE, space, CR_END); } else { if (a->space != b->space) OOGLError(1, "Uniting two spheres existing in different spaces."); space = a->space; if (space != TM_EUCLIDEAN) OOGLError(1, "SphereUnion3 currently only works reliably in\n%s", "Euclidean space."); HPt3Sub(&b->center, &a->center, &diff); Pt3Unit((Point3*)&diff); center.x = b->center.x + diff.x*b->radius; center.y = b->center.y + diff.y*b->radius; center.z = b->center.z + diff.z*b->radius; center.w = 1.0; GeomSet((Geom*)dest, CR_RADIUS, a->radius, CR_CENTER, &a->center, CR_END); SphereAddHPt3(dest, ¢er, TM_IDENTITY); } return dest; } void SphereEncompassBounds(Sphere *sphere, HPoint3 *points) { int i, j; float span, maxspan; HPoint3 *d1, *d2, center; d1 = d2 = &points[0]; maxspan = 0.0; for (i = 0; i < 6; i++) for (j = i+1; j < 6; j++) { span = HPt3SpaceDistance(&points[i], &points[j], sphere->space); if (span > maxspan) { maxspan = span; d1 = &points[i]; d2 = &points[j]; } } /* Find the midpoint here - this will not work in non-Euclidean space */ center.x = (d1->x + d2->x) / 2.0; center.y = (d1->y + d2->y) / 2.0; center.z = (d1->z + d2->z) / 2.0; center.w = 1.0; GeomSet((Geom *)sphere, CR_RADIUS, maxspan / 2.0, CR_CENTER, ¢er, CR_END); } int SphereAddHPt3(Sphere *sphere, HPoint3 *point, Transform T) { float radius, old_to_p, old_to_new; Point3 direction; HPoint3 center, newpoint; HPt3Transform(T, point, &newpoint); old_to_p = HPt3SpaceDistance(&newpoint, &sphere->center, sphere->space); if (old_to_p > sphere->radius) { radius = (sphere->radius + old_to_p) / 2.0; old_to_new = old_to_p - radius; center.x = sphere->center.x + (newpoint.x - sphere->center.x)*old_to_new / old_to_p; center.y = sphere->center.y + (newpoint.y - sphere->center.y)*old_to_new / old_to_p; center.z = sphere->center.z + (newpoint.z - sphere->center.z)*old_to_new / old_to_p; center.w = 1.0; GeomSet((Geom *)sphere, CR_RADIUS, radius, CR_CENTER, ¢er, CR_END); return 1; } else return 0; } int SphereAddHPt3N(Sphere *sphere, HPoint3 *point, int n, Transform T) { int i, ans = 0; for (i = 0; i < n; i++) ans |= SphereAddHPt3(sphere, &point[i], T); return ans; } void SphereEncompassHPt3N(Sphere *sphere, HPoint3 *point, int n, Transform T) { int i; HPoint3 spanPts[6]; if (!n) return; for (i = 0; i < 6; i++) spanPts[i] = point[0]; MaxDimensionalSpanN(spanPts, point, n); HPt3TransformN(T, spanPts, spanPts, 6); SphereEncompassBounds(sphere, spanPts); SphereAddHPt3N(sphere, point, n, T); } /* 0 has min x, 1 has max x, 2 has min y... */ void MaxDimensionalSpan(HPoint3 *spanPts, HPoint3 *point) { if (point->x < spanPts[0].x) spanPts[0] = *point; else if (point->x > spanPts[1].x) spanPts[1] = *point; if (point->y < spanPts[2].y) spanPts[2] = *point; else if (point->y > spanPts[3].y) spanPts[3] = *point; if (point->z < spanPts[4].z) spanPts[4] = *point; else if (point->z > spanPts[5].z) spanPts[5] = *point; } void MaxDimensionalSpanN(HPoint3 *spanPts, HPoint3 *points, int n) { int i; for (i = 0; i < n; i++) { if (points[i].x < spanPts[0].x) spanPts[0] = points[i]; else if (points[i].x > spanPts[1].x) spanPts[1] = points[i]; if (points[i].y < spanPts[2].y) spanPts[2] = points[i]; else if (points[i].y > spanPts[3].y) spanPts[3] = points[i]; if (points[i].z < spanPts[4].z) spanPts[4] = points[i]; else if (points[i].z > spanPts[5].z) spanPts[5] = points[i]; } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.