This is hpoint3a.c in view mode; [Download] [Up]
/* * hpoint3a.c: linear algebra routines for hpoints */ #include <math.h> #include <stdio.h> #include "hg4.h" #include "point3.h" #include "hpoint3.h" #include "hplane3.h" #include "hline3.h" #include "transform3.h" #include "tolerance.h" /* inner product of R4 */ HPt3Coord HPt3R40Dot(HPoint3 *a, HPoint3 *b) { return a->x*b->x + a->y*b->y + a->z*b->z + a->w*b->w; } /* inner product of R(3,1) */ HPt3Coord HPt3R31Dot(HPoint3 *a, HPoint3 *b) { return a->x*b->x + a->y*b->y + a->z*b->z - a->w*b->w; } /* inner product of R(3,0) */ HPt3Coord HPt3R30Dot(HPoint3 *a, HPoint3 *b) { double w2 = a->w*b->w; if (w2 == 1.0 || w2 == 0.0) return a->x*b->x + a->y*b->y + a->z*b->z; else return (a->x*b->x + a->y*b->y + a->z*b->z) / w2; } HPt3Coord HPt3SpaceDot(HPoint3 *a, HPoint3 *b, int space) { switch (space) { case TM_EUCLIDEAN: default: return HPt3R30Dot(a,b); break; case TM_HYPERBOLIC: return HPt3R31Dot(a,b); break; case TM_SPHERICAL: return HPt3R40Dot(a,b); break; } } /* normalize a point a in R4 so that <a,a> = 1 */ void HPt3R40Normalize(HPoint3 *a) { float len = sqrt( (double)(HPt3R40Dot(a,a)) ); if (len > 0) { len = 1 / len; a->x *= len; a->y *= len; a->z *= len; a->w *= len; } } /* normalize a point a in R(3,1) so that <a,a> = sign(<a,a>) */ void HPt3R31Normalize(HPoint3 *a) { float len = sqrt( fabs( (double)(HPt3R31Dot(a,a)) ) ); if (len > 0) { len = 1 / len; a->x *= len; a->y *= len; a->z *= len; a->w *= len; } } /* normalize a point a in R(3,0) so that <a,a> = 1 */ void HPt3R30Normalize(HPoint3 *a) { float len = sqrt( (double)(HPt3R30Dot(a,a)) ); if (len > 0) { len = 1 / len; a->x *= len; a->y *= len; a->z *= len; } } void HPt3SpaceNormalize(HPoint3 *a, int space) { switch (space) { case TM_EUCLIDEAN: default: HPt3R30Normalize(a); break; case TM_HYPERBOLIC: HPt3R31Normalize(a); break; case TM_SPHERICAL: HPt3R40Normalize(a); break; } } HPt3Coord HPt3HypDistance(HPoint3 *a, HPoint3 *b) { float aa, bb, ab; aa = HPt3R31Dot(a,a); bb = HPt3R31Dot(b,b); ab = HPt3R31Dot(a,b); return acosh( fabs(ab / sqrt( aa * bb ) )); } HPt3Coord HPt3Distance( a, b ) HPoint3 *a, *b; { float dx, dy, dz; float w1w2; w1w2 = a->w * b->w; if( w1w2 == 0. ) return 0.; dx = b->w * a->x - b->x * a->w; dy = b->w * a->y - b->y * a->w; dz = b->w * a->z - b->z * a->w; return (sqrt( dx*dx + dy*dy + dz*dz )) / w1w2; } HPt3Coord HPt3SphDistance(HPoint3 *a, HPoint3 *b) { return acos( HPt3R40Dot(a,b) / sqrt( HPt3R40Dot(a,a) * HPt3R40Dot(b,b) ) ); } HPt3Coord HPt3SpaceDistance(HPoint3 *a, HPoint3 *b, int space) { switch (space) { case TM_EUCLIDEAN: default: return HPt3Distance(a,b); break; case TM_HYPERBOLIC: return HPt3HypDistance(a,b); break; case TM_SPHERICAL: return HPt3SphDistance(a,b); break; } } void HPt3Sub(HPoint3 *a, HPoint3 *b, HPoint3 *aminusb) { aminusb->x = a->x - b->x; aminusb->y = a->y - b->y; aminusb->z = a->z - b->z; aminusb->w = a->w - b->w; } void HPt3Scale(HPt3Coord s, HPoint3 *a, HPoint3 *sa) { sa->x = s * a->x; sa->y = s * a->y; sa->z = s * a->z; sa->w = s * a->w; } void HPt3GramSchmidt(HPoint3 *base, HPoint3 *v) { HPt3SpaceGramSchmidt(base, v, TM_EUCLIDEAN); } void HPt3HypGramSchmidt(HPoint3 *base, HPoint3 *v) { HPt3SpaceGramSchmidt(base, v, TM_HYPERBOLIC); } void HPt3SphGramSchmidt(HPoint3 *base, HPoint3 *v) { HPt3SpaceGramSchmidt(base, v, TM_SPHERICAL); } /* Modifies v to arrange that <base,v> = 0, i.e. v is a tangent vector based at base */ void HPt3SpaceGramSchmidt(HPoint3 *base, HPoint3 *v, int space) { HPt3Coord d,e; HPoint3 tmp; d = HPt3SpaceDot(base,v,space); e = HPt3SpaceDot(base,base,space); if (e == 0.0) { fprintf(stderr, "GramSchmidt: invalid base point.\n"); e = 1.0; } HPt3Scale((HPt3Coord)(d / e), base, &tmp); HPt3Sub(v, &tmp, v); } #if 0 /* This stuff doesn't compile yet; in progress: */ HPt3Coord HPt3Angle(HPoint3 *base, HPoint3 *v1, HPoint3 *v2) { /* * I'm not sure that this will work in the euclidean case!!! mbp */ return HPt3SpaceAngle(base, v1, v2, TM_EUCLIDEAN); } HPt3Coord HPt3HypAngle(HPoint3 *base, HPoint3 *v1, HPoint3 *v2) { return HPt3SpaceAngle(base, v1, v2, TM_HYPERBOLIC); } HPt3Coord HPt3SphAngle(HPoint3 *base, HPoint3 *v1, HPoint3 *v2) { return HPt3SpaceAngle(base, v1, v2, TM_SPHERICAL); } HPt3Coord HPt3SpaceAngle(HPoint3 *base, HPoint3 *v1, HPoint3 *v2, int space) { double d, n; HPoint3 v1n = *v1; HPoint3 v2n = *v2; HPt3SpaceGramSchmidt(base, &v1n, space); HPt3SpaceGramSchmidt(base, &v2n, space); d = HPt3SpaceDot(&v1n,&v1n,space) * HPt3SpaceDot(&v2n,&v2n,space); if (d <= 0.0) { fprintf(stderr,"HPt3SpaceAngle: invalid denominator\n"); return 0.0; } n = HPt3SpaceDot(&v1n, &v2n, space); return acos( n / sqrt(d) ); } #endif
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.