1*219b2ee8SDavid du Colombier #include <u.h> 2*219b2ee8SDavid du Colombier #include <libc.h> 3*219b2ee8SDavid du Colombier #include <libg.h> 4*219b2ee8SDavid du Colombier #include <geometry.h> 5*219b2ee8SDavid du Colombier /* 6*219b2ee8SDavid du Colombier * Routines whose names end in 3 work on points in Affine 3-space. 7*219b2ee8SDavid du Colombier * They ignore w in all arguments and produce w=1 in all results. 8*219b2ee8SDavid du Colombier * Routines whose names end in 4 work on points in Projective 3-space. 9*219b2ee8SDavid du Colombier */ 10*219b2ee8SDavid du Colombier Point3 add3(Point3 a, Point3 b){ 11*219b2ee8SDavid du Colombier return (Point3){a.x+b.x, a.y+b.y, a.z+b.z, 1.}; 12*219b2ee8SDavid du Colombier } 13*219b2ee8SDavid du Colombier Point3 sub3(Point3 a, Point3 b){ 14*219b2ee8SDavid du Colombier return (Point3){a.x-b.x, a.y-b.y, a.z-b.z, 1.}; 15*219b2ee8SDavid du Colombier } 16*219b2ee8SDavid du Colombier Point3 neg3(Point3 a){ 17*219b2ee8SDavid du Colombier return (Point3){-a.x, -a.y, -a.z, 1.}; 18*219b2ee8SDavid du Colombier } 19*219b2ee8SDavid du Colombier Point3 div3(Point3 a, double b){ 20*219b2ee8SDavid du Colombier return (Point3){a.x/b, a.y/b, a.z/b, 1.}; 21*219b2ee8SDavid du Colombier } 22*219b2ee8SDavid du Colombier Point3 mul3(Point3 a, double b){ 23*219b2ee8SDavid du Colombier return (Point3){a.x*b, a.y*b, a.z*b, 1.}; 24*219b2ee8SDavid du Colombier } 25*219b2ee8SDavid du Colombier int eqpt3(Point3 p, Point3 q){ 26*219b2ee8SDavid du Colombier return p.x==q.x && p.y==q.y && p.z==q.z; 27*219b2ee8SDavid du Colombier } 28*219b2ee8SDavid du Colombier /* 29*219b2ee8SDavid du Colombier * Are these points closer than eps, in a relative sense 30*219b2ee8SDavid du Colombier */ 31*219b2ee8SDavid du Colombier int closept3(Point3 p, Point3 q, double eps){ 32*219b2ee8SDavid du Colombier return 2.*dist3(p, q)<eps*(len3(p)+len3(q)); 33*219b2ee8SDavid du Colombier } 34*219b2ee8SDavid du Colombier double dot3(Point3 p, Point3 q){ 35*219b2ee8SDavid du Colombier return p.x*q.x+p.y*q.y+p.z*q.z; 36*219b2ee8SDavid du Colombier } 37*219b2ee8SDavid du Colombier Point3 cross3(Point3 p, Point3 q){ 38*219b2ee8SDavid du Colombier return (Point3){p.y*q.z-p.z*q.y, p.z*q.x-p.x*q.z, p.x*q.y-p.y*q.x, 1.}; 39*219b2ee8SDavid du Colombier } 40*219b2ee8SDavid du Colombier double len3(Point3 p){ 41*219b2ee8SDavid du Colombier return sqrt(p.x*p.x+p.y*p.y+p.z*p.z); 42*219b2ee8SDavid du Colombier } 43*219b2ee8SDavid du Colombier double dist3(Point3 p, Point3 q){ 44*219b2ee8SDavid du Colombier p.x-=q.x; 45*219b2ee8SDavid du Colombier p.y-=q.y; 46*219b2ee8SDavid du Colombier p.z-=q.z; 47*219b2ee8SDavid du Colombier return sqrt(p.x*p.x+p.y*p.y+p.z*p.z); 48*219b2ee8SDavid du Colombier } 49*219b2ee8SDavid du Colombier Point3 unit3(Point3 p){ 50*219b2ee8SDavid du Colombier double len=sqrt(p.x*p.x+p.y*p.y+p.z*p.z); 51*219b2ee8SDavid du Colombier return (Point3){p.x/len, p.y/len, p.z/len, 1.}; 52*219b2ee8SDavid du Colombier } 53*219b2ee8SDavid du Colombier Point3 midpt3(Point3 p, Point3 q){ 54*219b2ee8SDavid du Colombier return (Point3){.5*(p.x+q.x), .5*(p.y+q.y), .5*(p.z+q.z), 1.}; 55*219b2ee8SDavid du Colombier } 56*219b2ee8SDavid du Colombier Point3 lerp3(Point3 p, Point3 q, double alpha){ 57*219b2ee8SDavid du Colombier return (Point3){p.x+(q.x-p.x)*alpha, p.y+(q.y-p.y)*alpha, p.z+(q.z-p.z)*alpha, 1.}; 58*219b2ee8SDavid du Colombier } 59*219b2ee8SDavid du Colombier /* 60*219b2ee8SDavid du Colombier * Reflect point p in the line joining p0 and p1 61*219b2ee8SDavid du Colombier */ 62*219b2ee8SDavid du Colombier Point3 reflect3(Point3 p, Point3 p0, Point3 p1){ 63*219b2ee8SDavid du Colombier Point3 a, b; 64*219b2ee8SDavid du Colombier a=sub3(p, p0); 65*219b2ee8SDavid du Colombier b=sub3(p1, p0); 66*219b2ee8SDavid du Colombier return add3(a, mul3(b, 2*dot3(a, b)/dot3(b, b))); 67*219b2ee8SDavid du Colombier } 68*219b2ee8SDavid du Colombier /* 69*219b2ee8SDavid du Colombier * Return the nearest point on segment [p0,p1] to point testp 70*219b2ee8SDavid du Colombier */ 71*219b2ee8SDavid du Colombier Point3 nearseg3(Point3 p0, Point3 p1, Point3 testp){ 72*219b2ee8SDavid du Colombier double num, den; 73*219b2ee8SDavid du Colombier Point3 q, r; 74*219b2ee8SDavid du Colombier q=sub3(p1, p0); 75*219b2ee8SDavid du Colombier r=sub3(testp, p0); 76*219b2ee8SDavid du Colombier num=dot3(q, r);; 77*219b2ee8SDavid du Colombier if(num<=0) return p0; 78*219b2ee8SDavid du Colombier den=dot3(q, q); 79*219b2ee8SDavid du Colombier if(num>=den) return p1; 80*219b2ee8SDavid du Colombier return add3(p0, mul3(q, num/den)); 81*219b2ee8SDavid du Colombier } 82*219b2ee8SDavid du Colombier /* 83*219b2ee8SDavid du Colombier * distance from point p to segment [p0,p1] 84*219b2ee8SDavid du Colombier */ 85*219b2ee8SDavid du Colombier #define SMALL 1e-8 /* what should this value be? */ 86*219b2ee8SDavid du Colombier double pldist3(Point3 p, Point3 p0, Point3 p1){ 87*219b2ee8SDavid du Colombier Point3 d, e; 88*219b2ee8SDavid du Colombier double dd, de, dsq; 89*219b2ee8SDavid du Colombier d=sub3(p1, p0); 90*219b2ee8SDavid du Colombier e=sub3(p, p0); 91*219b2ee8SDavid du Colombier dd=dot3(d, d); 92*219b2ee8SDavid du Colombier de=dot3(d, e); 93*219b2ee8SDavid du Colombier if(dd<SMALL*SMALL) return len3(e); 94*219b2ee8SDavid du Colombier dsq=dot3(e, e)-de*de/dd; 95*219b2ee8SDavid du Colombier if(dsq<SMALL*SMALL) return 0; 96*219b2ee8SDavid du Colombier return sqrt(dsq); 97*219b2ee8SDavid du Colombier } 98*219b2ee8SDavid du Colombier /* 99*219b2ee8SDavid du Colombier * vdiv3(a, b) is the magnitude of the projection of a onto b 100*219b2ee8SDavid du Colombier * measured in units of the length of b. 101*219b2ee8SDavid du Colombier * vrem3(a, b) is the component of a perpendicular to b. 102*219b2ee8SDavid du Colombier */ 103*219b2ee8SDavid du Colombier double vdiv3(Point3 a, Point3 b){ 104*219b2ee8SDavid du Colombier return (a.x*b.x+a.y*b.y+a.z*b.z)/(b.x*b.x+b.y*b.y+b.z*b.z); 105*219b2ee8SDavid du Colombier } 106*219b2ee8SDavid du Colombier Point3 vrem3(Point3 a, Point3 b){ 107*219b2ee8SDavid du Colombier double quo=(a.x*b.x+a.y*b.y+a.z*b.z)/(b.x*b.x+b.y*b.y+b.z*b.z); 108*219b2ee8SDavid du Colombier return (Point3){a.x-b.x*quo, a.y-b.y*quo, a.z-b.z*quo, 1.}; 109*219b2ee8SDavid du Colombier } 110*219b2ee8SDavid du Colombier /* 111*219b2ee8SDavid du Colombier * Compute face (plane) with given normal, containing a given point 112*219b2ee8SDavid du Colombier */ 113*219b2ee8SDavid du Colombier Point3 pn2f3(Point3 p, Point3 n){ 114*219b2ee8SDavid du Colombier return (Point3){n.x, n.y, n.z, -dot3(p, n)}; 115*219b2ee8SDavid du Colombier } 116*219b2ee8SDavid du Colombier /* 117*219b2ee8SDavid du Colombier * Compute face containing three points 118*219b2ee8SDavid du Colombier */ 119*219b2ee8SDavid du Colombier Point3 ppp2f3(Point3 p0, Point3 p1, Point3 p2){ 120*219b2ee8SDavid du Colombier Point3 p01, p02; 121*219b2ee8SDavid du Colombier p01=sub3(p1, p0); 122*219b2ee8SDavid du Colombier p02=sub3(p2, p0); 123*219b2ee8SDavid du Colombier return pn2f3(p0, cross3(p01, p02)); 124*219b2ee8SDavid du Colombier } 125*219b2ee8SDavid du Colombier /* 126*219b2ee8SDavid du Colombier * Compute point common to three faces. 127*219b2ee8SDavid du Colombier * Cramer's rule, yuk. 128*219b2ee8SDavid du Colombier */ 129*219b2ee8SDavid du Colombier Point3 fff2p3(Point3 f0, Point3 f1, Point3 f2){ 130*219b2ee8SDavid du Colombier double det, x, y, z; 131*219b2ee8SDavid du Colombier det=dot3(f0, cross3(f1, f2)); 132*219b2ee8SDavid du Colombier if(fabs(det)<SMALL) return (Point3){0,0,0,0}; /* parallel planes, bogus answer */ 133*219b2ee8SDavid du Colombier x=f0.w*(f2.y*f1.z-f1.y*f2.z)+f1.w*(f0.y*f2.z-f2.y*f0.z)+f2.w*(f1.y*f0.z-f0.y*f1.z); 134*219b2ee8SDavid du Colombier y=f0.w*(f2.z*f1.x-f1.z*f2.x)+f1.w*(f0.z*f2.x-f2.z*f0.x)+f2.w*(f1.z*f0.x-f0.z*f1.x); 135*219b2ee8SDavid du Colombier z=f0.w*(f2.x*f1.y-f1.x*f2.y)+f1.w*(f0.x*f2.y-f2.x*f0.y)+f2.w*(f1.x*f0.y-f0.x*f1.y); 136*219b2ee8SDavid du Colombier return (Point3){x/det, y/det, z/det, 1.}; 137*219b2ee8SDavid du Colombier } 138*219b2ee8SDavid du Colombier /* 139*219b2ee8SDavid du Colombier * pdiv4 does perspective division to convert a projective point to affine coordinates. 140*219b2ee8SDavid du Colombier */ 141*219b2ee8SDavid du Colombier Point3 pdiv4(Point3 a){ 142*219b2ee8SDavid du Colombier if(a.w==0) return a; 143*219b2ee8SDavid du Colombier return (Point3){a.x/a.w, a.y/a.w, a.z/a.w, 1.}; 144*219b2ee8SDavid du Colombier } 145*219b2ee8SDavid du Colombier Point3 add4(Point3 a, Point3 b){ 146*219b2ee8SDavid du Colombier return (Point3){a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w}; 147*219b2ee8SDavid du Colombier } 148*219b2ee8SDavid du Colombier Point3 sub4(Point3 a, Point3 b){ 149*219b2ee8SDavid du Colombier return (Point3){a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w}; 150*219b2ee8SDavid du Colombier } 151