00001 #ifndef VEC2_H_IS_INCLUDED
00002 #define VEC2_H_IS_INCLUDED
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <cmath>
00012 #include "mlib/global.H"
00013 #include "mlib/point3.H"
00014
00015 namespace mlib {
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 template <class V>
00028 class Vec2 {
00029
00030 protected:
00031
00032 double _x, _y;
00033
00034 public:
00035
00036
00037
00038
00039 Vec2() : _x(0) , _y(0) {}
00040 Vec2(double x, double y) : _x(x) , _y(y) {}
00041
00042
00043
00044
00045
00046
00047 typedef double value_type;
00048 static int dim() { return 2; }
00049
00050
00051
00052
00053
00054
00055 V operator + (const V &v) const { return V(_x+v._x, _y+v._y); }
00056 V operator - (const V &v) const { return V(_x-v._x, _y-v._y); }
00057 double operator * (const V &v) const { return _x*v._x+_y*v._y; }
00058 V operator - () const { return V(-_x, -_y); }
00059
00060 V operator * (double s) const { return V(_x*s, _y*s); }
00061 V operator / (double s) const { return V(_x/s, _y/s); }
00062
00063 void operator +=(const V &v) { _x += v._x; _y += v._y; }
00064 void operator -=(const V &v) { _x -= v._x; _y -= v._y; }
00065 void operator *=(double s) { _x *= s; _y *= s; }
00066 void operator /=(double s) { _x /= s; _y /= s; }
00067
00068
00069
00070
00071
00072
00073 double operator [](int index) const { return (&_x)[index]; }
00074 double& operator [](int index) { return (&_x)[index]; }
00075
00076
00077
00078
00079
00080
00081 double length () const { return sqrt(_x*_x+_y*_y); }
00082 double length_sqrd () const { return _x*_x+_y*_y; }
00083
00084 bool is_exact_null() const { return _x == 0 && _y == 0; }
00085
00086
00087 bool is_null (double epsSqrdMath = epsNorSqrdMath()) const {
00088 return length_sqrd() <= epsSqrdMath;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097 V normalized () const;
00098
00099
00100 V perpend () const { return V(-_y, _x); }
00101
00102
00103
00104
00105
00106
00107 double dist (const V &v) const { return (*this-v).length(); }
00108 double dist_sqrd (const V &v) const { return (*this-v).length_sqrd(); }
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 double signed_angle(const V&) const;
00119
00120
00121
00122 double angle(const V& v) const;
00123
00124
00125 inline double tlen(const V &b) const {
00126 double bb = b.length_sqrd();
00127 return isZero(bb) ? 0 : (*this * b)/bb;
00128 }
00129
00130
00131 inline V projected(const V &b) const { return b * tlen(b); }
00132
00133
00134 inline V orthogonalized(const V &b) const { return *this - projected(b); }
00135
00136
00137
00138
00139
00140
00141 bool is_equal (const V &v, double epsSqrd = epsNorSqrdMath()) const
00142 { return dist_sqrd(v)<=epsSqrd;}
00143 bool is_parallel(const V&) const;
00144
00145
00146
00147
00148
00149
00150 bool operator ==(const V &v) const { return v._x == _x && v._y == _y;}
00151 bool operator !=(const V &v) const { return v._x != _x || v._y != _y;}
00152
00153
00154
00155 };
00156
00157 }
00158
00159
00160
00161 template<class V>
00162 inline V
00163 mlib::Vec2<V>::normalized() const
00164 {
00165 const double l = length();
00166 return (l > gEpsZeroMath ? V(_x/l, _y/l) : V(0,0));
00167 }
00168
00169 template<class V>
00170 inline double
00171 mlib::Vec2<V>::signed_angle(const V& v) const
00172 {
00173
00174
00175 const V v1 = normalized();
00176 const V v2 = v.normalized();
00177
00178
00179 return Sign(det(v1,v2)) * Acos(v1*v2);
00180 }
00181
00182 template<class V>
00183 inline double
00184 mlib::Vec2<V>::angle(const V& v) const
00185 {
00186
00187 return fabs(signed_angle(v));
00188
00189 }
00190
00191 template<class V>
00192 inline bool
00193 mlib::Vec2<V>::is_parallel(const V &v) const
00194 {
00195 const V a = normalized();
00196 const V b = v.normalized();
00197
00198 if (a.is_exact_null() || b.is_exact_null())
00199 return false;
00200
00201 return (a-b).length_sqrd() <= epsNorSqrdMath() ||
00202 (a+b).length_sqrd() <= epsNorSqrdMath();
00203 }
00204
00205
00206
00207 namespace mlib {
00208
00209
00210
00211
00212 template <class V>
00213 inline double
00214 det(const Vec2<V>& v1, const Vec2<V>& v2)
00215 {
00216
00217 return v1[0]*v2[1]-v1[1]*v2[0];
00218
00219 }
00220
00221
00222
00223 template <class V>
00224 inline ostream &
00225 operator <<(ostream &os, const Vec2<V>& v)
00226 {
00227 return os <<"{"<<v[0]<<","<<v[1]<<"}";
00228 }
00229
00230
00231
00232 template <typename V>
00233 inline V
00234 operator*(double s, const Vec2<V> &v)
00235 {
00236 return v*s;
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246 template <class V>
00247 inline double
00248 line_angle(const V& v1, const V& v2)
00249 {
00250
00251 double a = v1.angle(v2);
00252 return (a <= M_PI_2) ? a : (M_PI - a);
00253
00254 }
00255
00256 }
00257
00258 #endif // VEC2_H_IS_INCLUDED
00259
00260