28 #define LINE_TEM template <class num> inline
29 #define LINE_FUN Line2d<num>
47 mutable bool updateRequired;
49 static const num eps = 1e-5;
56 Line2d(num p0x, num p0y, num p1x, num p1y);
58 void set(num p0x, num p0y, num p1x, num p1y);
104 inline const num Length()
const {
if(updateRequired)
calcValues();
return length;}
105 inline const num Angle()
const {
if(updateRequired)
calcValues();
return dir.angle();}
109 inline num Length()
const {
return (p1-p0).length();}
110 inline num Angle()
const {
return (p1-p0).angle();}
141 updateRequired =
true;
152 updateRequired =
true;
163 updateRequired =
true;
168 LINE_FUN::Line2d(num p0x, num p0y, num p1x, num p1y)
174 updateRequired =
true;
185 updateRequired =
true;
190 void LINE_FUN::set(num p0x, num p0y, num p1x, num p1y)
196 updateRequired =
true;
201 void LINE_FUN::calcValues()
const
203 length = (p1-p0).length();
204 dir = (p1-p0)/length;
206 updateRequired =
false;
213 if(updateRequired) calcValues();
217 num dist = fabs(perp.dot(p-p0));
218 num locationOnLine = dir.dot(p-p0);
220 if(locationOnLine<0.0 && endcaps){
221 return (p-p0).length();
222 }
else if(locationOnLine>length && endcaps){
223 return (p-p1).length();
232 if(updateRequired) calcValues();
237 if(intersects(p,rayDir) || extendLine){
238 num sinTheta = dir.cross(rayDir.
norm());
239 result = fabs(perp.dot(p-p0)/sinTheta);
244 printf(
"Fail2! %d %f %f %f\n",(intersects(p,rayDir) || extendLine)?1:0,dir.cross(rayDir.
norm()), perp.dot(p-p0), result);
254 if(updateRequired) calcValues();
262 if(intersects(p,heading,
false) || extendLine){
263 num sinTheta = dir.cross(heading.
norm());
264 result = fabs(perp.dot(p-p0)/sinTheta);
269 printf(
"Fail1! %d %f %f %f\n",(intersects(p,heading,
false) || extendLine)?1:0,dir.cross(heading.
norm()), perp.dot(p-p0), result);
279 if(updateRequired) calcValues();
283 num d = dir.dot(p-p0);
284 if((d>=0.0 && d<=length) || !endcaps){
286 return ( (p-p0) - dir*d );
300 if(updateRequired) calcValues();
304 num location = (p-p0).dot(dir);
305 return (location>-margin && location<length+margin);
312 if(updateRequired) calcValues();
319 return ( (extendL1 || (perp.dot(p2-p0)*perp.dot(p3-p0)<=eps)) && (extendL0 || ((p3-p2).perpdot(p0-p2)*(p3-p2).perpdot(p1-p2)<=eps)) );
321 return ( (extendL1 || (perp.dot(p2-p0)*perp.dot(p3-p0)<0.0)) && (extendL0 || ((p3-p2).perpdot(p0-p2)*(p3-p2).perpdot(p1-p2)<0.0)) );
328 if(updateRequired) calcValues();
334 num den = dir.y*dir2.x - dir.x*dir2.y;
335 num ua = (dir.y*(p0.x-p2.x) - dir.x*(p0.y-p2.y))/den;
338 num position0 = dir.
dot(p-p0);
339 num position1 = dir2.dot(p-p2);
342 if( (!extendL0 && (position0<0.0 || position0>length)) || (!extendL1 && (sq(position1)>(p3-p2).sqlength())) )
349 bool LINE_FUN::intersects(
Line2d<num> l2,
bool extendL0,
bool extendL1,
bool touch)
352 if(updateRequired) calcValues();
359 return ( (extendL1 || (perp.dot(l2.P0()-p0)*perp.dot(l2.P1()-p0)<=eps)) && (extendL0 || (l2.Perp().dot(p0-l2.P0())*l2.Perp().dot(p1-l2.P0())<=eps)) );
361 return ( (extendL1 || (perp.dot(l2.P0()-p0)*perp.dot(l2.P1()-p0)<-eps)) && (extendL0 || (l2.Perp().dot(p0-l2.P0())*l2.Perp().dot(p1-l2.P0())<-eps)) );
368 if(updateRequired) calcValues();
378 return ( v0.
cross(rayDir)>=0.0 && v1.
cross(rayDir) <= 0.0 );
380 return ( v0.
cross(rayDir)>eps && v1.
cross(rayDir) < -eps );
387 if(updateRequired) calcValues();
394 return intersects(p, heading,
false);
401 if(updateRequired) calcValues();
407 num den = dir.y*dir2.x - dir.x*dir2.y;
408 num ua = (dir.y*(p0.x-p2.x) - dir.x*(p0.y-p2.y))/den;
411 num position0 = dir.
dot(p-p0);
412 num position1 = dir2.dot(p-p2);
414 if( (!extendL0 && (position0<0.0 || position0>length)) || (!extendL1 && (sq(position1)>(p3-p2).sqlength())) )
424 if(updateRequired) calcValues();
431 num den = dir.y*dir2.x - dir.x*dir2.y;
432 num ua = (dir.y*(p0.x-p02.x) - dir.x*(p0.y-p02.y))/den;
435 num position0 = dir.
dot(p-p0);
436 num position1 = dir2.dot(p-p02);
438 if( (!extendL0 && (position0<0.0 || position0>length)) || (!extendL1 && (position1<0.0 || position1>l1.Length())) )
448 if(updateRequired) calcValues();
461 if(updateRequired) calcValues();
472 if(updateRequired) calcValues();
476 return (dir*p.x + perp*p.y);
480 char* LINE_FUN::ToString(
char* str)
482 snprintf(str,64,
"(%8.3f,%8.3f) - (%8.3f,%8.3f)",V2COMP(p0),V2COMP(p1));
486 #define LINE_UNARY_OPERATOR_SCALAR(op) \
488 Line2d<num>& LINE_FUN::operator op (num f) \
492 updateRequired = true; \
496 LINE_UNARY_OPERATOR_SCALAR(*=)
497 LINE_UNARY_OPERATOR_SCALAR(/=)
499 #define LINE_BINARY_OPERATOR_SCALAR(op) \
501 Line2d<num> LINE_FUN::operator op (num f) const\
503 GVector::vector2d<num> p0_ = p0 op f; \
504 GVector::vector2d<num> p1_ = p1 op f; \
505 return(Line2d<num>(p0_,p1_)); \
508 LINE_BINARY_OPERATOR_SCALAR(*)
509 LINE_BINARY_OPERATOR_SCALAR(/)
511 #define LINE_BINARY_OPERATOR_VECTOR(op) \
513 Line2d<num> LINE_FUN::operator op (GVector::vector2d<num> v) const\
515 GVector::vector2d<num> p0_ = p0 op v; \
516 GVector::vector2d<num> p1_ = p1 op v; \
517 return(Line2d<num>(p0_,p1_)); \
520 LINE_BINARY_OPERATOR_VECTOR(+)
521 LINE_BINARY_OPERATOR_VECTOR(-)
523 #define LINE_UNARY_OPERATOR_VECTOR(op) \
525 Line2d<num>& LINE_FUN::operator op (GVector::vector2d<num> v) \
529 updateRequired = true; \
533 LINE_UNARY_OPERATOR_VECTOR(+=)
534 LINE_UNARY_OPERATOR_VECTOR(-=)
Line2d< num > operator+(GVector::vector2d< num > v) const
returns this line translated by vector v
Line2d< num > operator/(num f) const
returns this line scaled by 1/f
num distFromLine1(GVector::vector2d< num > p, num rayDir, bool extendLine)
Calculate distance of p along the direction angle rayDir from this line.
Line2d< num > operator*(num f) const
returns this line scaled by f
char * ToString(char *str)
Returns a string formated representation of the line.
GVector::vector2d< num > intersectTest(GVector::vector2d< num > p2, GVector::vector2d< num > p3, bool &intersects, bool extendL0, bool extendL1)
Checks if the current line intersects the line joining p2 and p3, and if so, returns the point of int...
Line2d< num > & operator/=(num f)
scales this line by 1/f
Line2d< num > rotate(GVector::vector2d< num > p, num angle)
Rotates the line about point p by given angle.
GVector::vector2d< num > project_out(GVector::vector2d< num > p)
Projects point p from the coordinate frame attached to the line segment to global coordinates...
Line2d< num > & operator+=(GVector::vector2d< num > v)
translates this line by vector v
num distFromLine(GVector::vector2d< num > p, GVector::vector2d< num > rayDir, bool extendLine)
Calculate distance of p along the direction rayDir from this line.
Line2d< num > & operator*=(num f)
scales this line by f
GVector::vector2d< num > intersection(Line2d< num > l1, bool extendL0, bool extendL1)
Return the point of intersection of two lines.
bool intersects(GVector::vector2d< num > v, bool extendL0, bool extendL1)
Return true if the ray v from origin intersects this line.
num cross(const vector2d< num > p) const MustUseResult
return z component of 3D cross product on 2D vectors. right handed.
void calcValues() const
Calculate derived values (dir, perp, angle)
vector2d< num > norm() const MustUseResult
return a unit length vector in the same direction
GVector::vector2d< num > perpFromLine(GVector::vector2d< num > p, bool endcaps)
Returns a vector perpendicular to the line, starting from the line, terminating at p...
bool intersects(Line2d< num > l1, bool extendL0, bool extendL1, bool touch)
Return true if the line l1 intersects this line. If touch==true then touching counts as intersection...
vector2d< num > perp() const MustUseResult
return the perpendicular of a vector (i.e. rotated 90 deg counterclockwise)
void heading(num angle)
make a unit vector at given angle
num dot(const vec p) const MustUseResult
return dot product of vector with p
GVector::vector2d< num > project_in(GVector::vector2d< num > p)
Projects point p into the coordinate frame attached to the line segment, where the x axis is in the d...
num closestDistFromLine(GVector::vector2d< num > p, bool endcaps)
Calculate closest distance of p from this line.
bool liesAlongside(GVector::vector2d< num > p, num margin=0.0)
Returns true if p lies along side this line.