home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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
-