1 #ifndef __GEOM_ALGO_H__
2 #define __GEOM_ALGO_H__
13 return(fabs((x1 - x0).norm().perpdot(p - x0)));
23 n = (x1 - x0).perp().
norm();
25 return(n.
dot(p - x0));
56 if(fabs(dn) < EPSILON)
return(a0);
58 t = -dot(a0-b0,n) / dn;
88 return(angle_mod((a-b).angle() - (c-b).angle()));
106 da = a.
dot(p1 + p2) * 0.5;
107 db = b.
dot(p2 + p3) * 0.5;
118 num det = a.x * b.y - a.y * b.x;
119 if(fabs(det) < EPSILON)
return(
false);
121 cen.x = ( b.y*da + -a.y*db) / det;
122 cen.y = (-b.x*da + a.x*db) / det;
129 printf(
"%f %f, %f %f\n",
140 template <
class vector>
141 vector interpolate(
const vector x0,
const vector x1,
double t)
144 return(x0 + (x1-x0)*t);
147 template <
class vector>
148 vector point_on_line(
const vector x0,
const vector x1,
const vector p)
162 if(l < EPSILON)
return(p);
165 r = x0 + sx * (f / l);
169 template <
class vector>
170 vector point_on_segment(
const vector x0,
const vector x1,
const vector p)
180 if(f <= 0.0)
return(x0);
183 if(f >= l)
return(x1);
185 r = x0 + sx * (f / l);
191 template <
class vector>
192 double point_on_segment_t(
const vector x0,
const vector x1,
const vector p)
204 if (f <= 0)
return 0.0;
205 else if(f >= l)
return 1.0;
211 template <
class vector>
212 double distance_to_segment(
const vector x0,
const vector x1,
const vector p)
221 if(f <= 0.0)
return(distance(x0,p));
224 if(f >= l)
return(distance(x1,p));
226 r = x0 + sx * (f / l);
228 return(distance(r,p));
231 template <
class vector>
232 double closest_point_time(
const vector x1,
const vector v1,
233 const vector x2,
const vector v2)
241 if(sl < EPSILON)
return(0.0);
243 t = -v.dot(x1 - x2) / sl;
244 if(t < 0.0)
return(0.0);
258 template <
class vector>
259 double distance_seg_to_seg(vector s1a,vector s1b,vector s2a,vector s2b)
263 vector u = s1b - s1a;
264 vector v = s2b - s2a;
265 vector w = s1a - s2a;
272 float sc, sN, sD = D;
273 float tc, tN, tD = D;
276 printf(
"SegDist (%f,%f)-(%f,%f) to (%f,%f)-(%f,%f) a=%f b=%f\n",
277 V2COMP(s1a),V2COMP(s1b),V2COMP(s2a),V2COMP(s2b),
281 if((a < EPSILON) || (b < EPSILON)){
282 if((a < EPSILON) && (b < EPSILON)){
283 return(dist(s1a,s2a));
284 }
else if(a < EPSILON){
285 return(distance_to_segment(s2a,s2b,s1a));
287 return(distance_to_segment(s1a,s1b,s2a));
327 }
else if((-d + b) > a){
339 sc = (fabs(sN) < EPSILON)? 0.0 : sN / sD;
340 tc = (fabs(tN) < EPSILON)? 0.0 : tN / tD;
343 dp = w + u*sc - v*tc;
350 template <
class vector>
351 double ray_plane_intersect(vector pOrigin,vector pNormal,
352 vector rOrigin,vector rVector)
355 return((dot(pNormal,pOrigin) - dot(pNormal,rOrigin)) /
356 dot(pNormal,rVector));
384 template <
class vector,
class real>
385 real ray_sphere_intersect(vector rO, vector rV,vector sO,real sR)
393 real d = sR*sR - (c*c - v*v);
396 if(d < 0.0)
return(-1.0);
402 template <
class vector,
class real>
403 real ray_stretched_circle_intersect(vector rO, vector rV,vector sO,real sR, vector stretchH)
423 real t1=ray_sphere_intersect(rO, rV,sO+stretchH,sR);
431 real t2=ray_sphere_intersect(rO, rV,sO-stretchH,sR);
433 if (found==
false || t2 < t) {
443 vector perp=(stretchH.perp()).norm(sR);
445 real t3=ray_plane_intersect(sO+perp,perp,rO,rV);
447 if (found==
false || t3 < t) {
448 vector ptmp=(rO+(rV*t3));
450 if ((ptmp - (sO+perp)).sqlength() < stretchH.sqlength()) {
460 real t4=ray_plane_intersect(sO+perp,perp,rO,rV);
462 if (found==
false || t4 < t) {
463 vector ptmp=(rO+(rV*t4));
465 if ((ptmp - (sO+perp)).sqlength() < stretchH.sqlength()) {
477 template <
class vector,
class real>
478 bool CircleTangentDir(vector cen,real rad,vector p,
479 vector &left,vector &right)
487 d2 = delta.sqlength();
490 if(t < 0)
return(
false);
494 basis.set(l/d2,rad/d2);
498 left = basis.project_out(delta);
500 right = basis.project_out(delta);
505 template <
class vector,
class real>
506 bool CircleTangent(vector cen,real rad,vector p,
507 vector &left,vector &right)
515 d2 = delta.sqlength();
518 if(t < 0)
return(
false);
522 basis.set(l/d2,rad/d2);
526 left = basis.project_out(delta)*l;
528 right = basis.project_out(delta)*l;
537 template <
class vector,
class real>
538 vector LineMidpointAngular(
const vector &p0,
const vector &p1,real &dist)
540 vector dir = (p0.norm() + p1.norm()).norm();
541 vector pn = (p1 - p0).norm();
542 dist = pn.perpdot(p0) / pn.perpdot(dir);
void set(num nx, num ny)
set the components of the vector
num angle() const MustUseResult
calculate the clockwise angle from <1,0>
void normalize()
normalize to unit length in place
num sqlength() const MustUseResult
calculate squared Euclidean length (faster than length())
vector2d< num > norm() const MustUseResult
return a unit length vector in the same direction
vector2d< num > rotate(const double a) const MustUseResult
return vector rotated by angle a
num dot(const vec p) const MustUseResult
return dot product of vector with p