00001 #ifndef LINE_H_IS_INCLUDED
00002 #define LINE_H_IS_INCLUDED
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "mlib/global.H"
00012
00013 namespace mlib {
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 template <class L, class P, class V>
00032 class Line {
00033
00034 public:
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 Line() {}
00045
00046
00047
00048
00049
00050 Line(const P& p, const V& v) : _point ( p), _vector(v) {}
00051
00052
00053
00054
00055 Line(const P& p1, const P& p2) : _point (p1), _vector(p2-p1) {}
00056
00057
00058
00059
00060
00061
00062 const P& point () const { return _point; }
00063 P& point () { return _point; }
00064 const V& vector() const { return _vector; }
00065 V& vector() { return _vector; }
00066
00067
00068
00069
00070
00071
00072
00073 bool is_valid() const { return !_vector.is_null(); }
00074
00075
00076
00077 P endpt () const { return _point + _vector; }
00078
00079
00080
00081 P midpt () const { return _point + _vector*0.5; }
00082
00083
00084 double length() const { return _vector.length(); }
00085
00086
00087
00088
00089
00090
00091
00092 bool operator==(const Line<L,P,V>& l) const {
00093 return (l._point == _point && l._vector == _vector);
00094 }
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 double dist(const P& p) const { return project(p).dist(p); }
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 P project(const P& p) const {
00117 V vn(_vector.normalized());
00118 return _point + ((p-_point)*vn) *vn;
00119 }
00120
00121
00122
00123
00124 P project_to_seg(const P& p) const {
00125 double vv = _vector.length_sqrd();
00126 if (vv < epsAbsSqrdMath())
00127 return _point;
00128 return _point + (_vector * clamp(((p - _point)*_vector)/vv, 0.0, 1.0));
00129 }
00130
00131
00132
00133
00134 P project_to_seg(const L& l) const {
00135 return project_to_seg(intersect(l));
00136 }
00137
00138
00139
00140
00141
00142
00143
00144 P reflection(const P& p) const {
00145 Line temp(p,project(p));
00146 temp.vector() *= 2.0;
00147
00148 return temp.endpt();
00149
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 P intersect(const L& l) const {
00163 const P& A = point();
00164 const P& B = l.point();
00165 const V Y = vector().normalized();
00166 const V W = l.vector().normalized();
00167 const V BA = B-A;
00168 const double vw = Y*W;
00169 const double vba= Y*BA;
00170 const double wba= W*BA;
00171 const double det = vw*vw - 1.0;
00172
00173 if (fabs(det) < gEpsAbsMath) {
00174 return A;
00175 }
00176
00177 const double as = (vw*wba - vba)/det;
00178 const P AP = A + as*Y;
00179
00180 return AP;
00181 }
00182
00183
00184
00185
00186
00187 bool intersect_segs(const L& l, P& inter) const {
00188 P ap = intersect(l);
00189 P bp = l.intersect(*((L*)this));
00190 if (ap.is_equal(bp)) {
00191 inter = ap;
00192
00193
00194 double len1 = vector().length();
00195 double len2 = l.vector().length();
00196 double dot1 = (ap - point()) * vector() / len1;
00197 if (dot1 <= len1 && dot1 >= 0) {
00198 double dot2 = (ap - l.point()) * l.vector() / len2;
00199 if (dot2 <= len2 && dot2 >= 0)
00200 return 1;
00201 }
00202 }
00203 return 0;
00204 }
00205
00206
00207
00208
00209
00210 bool intersect_seg_line(const L& l, P& inter) const {
00211 P ap = intersect(l);
00212 P bp = l.intersect(*((L*)this));
00213 if (ap.is_equal(bp)) {
00214 inter = ap;
00215
00216
00217 double len1 = vector().length();
00218 double dot1 = (ap - point()) * vector() / len1;
00219 if (dot1 <= len1 && dot1 >= 0) {
00220 return 1;
00221 }
00222 }
00223 return 0;
00224 }
00225
00226
00227
00228
00229 bool intersect_segs(const L& l) const {
00230 P foo;
00231 return intersect_segs(l, foo);
00232 }
00233
00234
00235
00236 protected:
00237
00238 P _point;
00239 V _vector;
00240
00241 };
00242
00243 }
00244
00245
00246 #include "std/iostream.H"
00247
00248
00249 namespace mlib {
00250
00251
00252
00253 template <class L, class P, class V>
00254 ostream& operator<<(ostream& os, const Line<L,P,V>& l)
00255 {
00256 return os << "Line("<<l.point()<<","<<l.vector()<<")";
00257 }
00258
00259 }
00260
00261 #endif // LINE_H_IS_INCLUDED
00262
00263
00264