Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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