1 // This is core/vgl/vgl_vector_2d.h
2 #ifndef vgl_vector_2d_h_
3 #define vgl_vector_2d_h_
4 //:
5 // \file
6 // \brief direction vector in Euclidean 2D space
7 // \author Peter Vanroose
8 // \date 27 June, 2001
9 //
10 // \verbatim
11 // Modifications
12 // 2001-07-05 Peter Vanroose Added orthogonal(); operator* now accepts double
13 // 2009-05-21 Peter Vanroose istream operator>> re-implemented
14 // \endverbatim
15
16 #include <iosfwd>
17 #ifdef _MSC_VER
18 # include <vcl_msvc_warnings.h>
19 #endif
20
21 //----------------------------------------------------------------------
22
23 //: Direction vector in Euclidean 2D space, templated by type of element
24 // (typically float or double). A vgl_vector_2d<T> represents the
25 // difference (or connecting vector) between two vgl_point_2d<T>s.
26 //
27 // Use this class to do arithmetic (adding and scaling) in 2d geometric space.
28 //
29 template <class T>
30 class vgl_vector_2d
31 {
32 public:
33 T x_; // Data is public
34 T y_;
x()35 inline T x() const { return x_; }
y()36 inline T y() const { return y_; }
37
38 //: Creates the vector (0,0) of zero length.
vgl_vector_2d()39 inline vgl_vector_2d () : x_(0) , y_(0) {}
40
41 //: Creates the vector \a (x,y).
vgl_vector_2d(T vx,T vy)42 inline vgl_vector_2d (T vx, T vy) : x_(vx) , y_(vy) {}
43
44 //: Casting Constructor
45 vgl_vector_2d(vgl_vector_2d<T> const&) = default;
46
47 template<typename Other>
vgl_vector_2d(vgl_vector_2d<Other> const & other)48 explicit vgl_vector_2d(vgl_vector_2d<Other> const& other)
49 : x_(other.x()), y_(other.y()) {}
50
51 #if 0 // The defaults do exactly what they should do...
52 //: Copy constructor
53 inline vgl_vector_2d (vgl_vector_2d<T> const& v) : x_(v.x()) , y_(v.y()) {}
54 //: Assignment operator
55 inline vgl_vector_2d<T>& operator=(vgl_vector_2d<T> const& v) {
56 x_=v.x(); y_=v.y(); return *this; }
57 //: Destructor
58 inline ~vgl_vector_2d () {}
59 #endif
60
61 //: Assignment
set(T vx,T vy)62 inline void set(T vx, T vy) { x_=vx; y_=vy; }
63
64 //: Comparison
65 inline bool operator==(vgl_vector_2d<T>const& v)const{return x_==v.x()&&y_==v.y();}
66 inline bool operator!=(vgl_vector_2d<T>const& v)const{return !operator==(v);}
67
68 //: Return the length of this vector.
69 double length() const; // return sqrt( x()*x()+y()*y() );
70
71 //: Return the squared length of this vector.
sqr_length()72 inline T sqr_length() const { return x()*x()+y()*y(); }
73
74 //: Read from stream, possibly with formatting
75 // Either just reads two blank-separated numbers,
76 // or reads two comma-separated numbers,
77 // or reads two numbers in parenthesized form "(123, 321)"
78 std::istream& read(std::istream& is);
79 };
80
81 #define v vgl_vector_2d<T>
82
83 // +-+-+ vector_2d simple I/O +-+-+
84
85 //: Write "<vgl_vector_2d x,y> " to stream
86 // \relatesalso vgl_vector_2d
87 template <class T> std::ostream& operator<<(std::ostream& s, v const& p);
88
89 //: Read from stream, possibly with formatting
90 // Either just reads two blank-separated numbers,
91 // or reads two comma-separated numbers,
92 // or reads two numbers in parenthesized form "(123, 321)"
93 // \relatesalso vgl_vector_2d
94 template <class T> std::istream& operator>>(std::istream& s, v& p);
95
96
97 // +-+-+ vector_2d geometry and algebra +-+-+
98
99 //: Return the length of a vector.
100 // \relatesalso vgl_vector_2d
length(v const & a)101 template <class T> inline double length(v const& a) { return a.length(); }
102
103 //: Return the squared length of a vector.
104 // \relatesalso vgl_vector_2d
sqr_length(v const & a)105 template <class T> inline T sqr_length(v const& a) { return a.sqr_length(); }
106
107 //: c=a+b: add two vectors.
108 // \relatesalso vgl_vector_2d
109 template <class T> inline v operator+(v const& a, v const& b) { return v(a.x()+b.x(), a.y()+b.y()); }
110
111 //: c=a-b: subtract two vectors.
112 // \relatesalso vgl_vector_2d
113 template <class T> inline v operator-(v const& a, v const& b) { return v(a.x()-b.x(), a.y()-b.y()); }
114
115 //: a+=b: add b to a and return a.
116 // \relatesalso vgl_vector_2d
117 template <class T> inline v& operator+=(v& a, v const& b) { a.x_+=b.x_; a.y_+=b.y_; return a; }
118
119 //: a-=b: subtract b from a and return a.
120 // \relatesalso vgl_vector_2d
121 template <class T> inline v& operator-=(v& a, v const& b) { a.x_-=b.x_; a.y_-=b.y_; return a; }
122
123 //: +b: unary plus operator (no-op).
124 // \relatesalso vgl_vector_2d
125 template <class T> inline v operator+(v const& b) { return b; }
126
127 //: -a: unary minus operator (additive inverse).
128 // \relatesalso vgl_vector_2d
129 template <class T> inline v operator-(v const& b) { return v(-b.x(), -b.y()); }
130
131 //: c=f*b: return a scaled version of the vector.
132 // \relatesalso vgl_vector_2d
133 template <class T> inline v operator*(double s, v const& b) { return v(T(s*b.x()), T(s*b.y())); }
134
135 //: c=a*f: return a scaled version of the vector.
136 // \relatesalso vgl_vector_2d
137 template <class T> inline v operator*(v const& a, double s) { return v(T(a.x()*s), T(a.y()*s)); }
138
139 //: c=b/f: return an inversely scaled version of the vector (scale must be nonzero).
140 // Note that the argument type is double, not T, to avoid rounding errors
141 // when type T has no multiplicative inverses (like T=int).
142 // \relatesalso vgl_vector_2d
143 template <class T> inline v operator/(v const& a, double s) { return v(T(a.x()/s), T(a.y()/s)); }
144
145 //: a*=f: scale the vector.
146 // \relatesalso vgl_vector_2d
147 template <class T> inline v& operator*=(v& a, double s) { a.set(T(a.x()*s), T(a.y()*s)); return a; }
148
149 //: a/=f: inversely scale the vector (scale must be nonzero).
150 // \relatesalso vgl_vector_2d
151 template <class T> inline v& operator/=(v& a, double s) { a.set(T(a.x()/s), T(a.y()/s)); return a; }
152
153 //: dot product or inner product of two vectors.
154 // \relatesalso vgl_vector_2d
dot_product(v const & a,v const & b)155 template <class T> inline T dot_product(v const& a, v const& b) { return a.x()*b.x()+a.y()*b.y(); }
156
157 //: dot product or inner product of two vectors.
158 // \relatesalso vgl_vector_2d
inner_product(v const & a,v const & b)159 template <class T> inline T inner_product(v const& a, v const& b) { return a.x()*b.x()+a.y()*b.y(); }
160
161 //: cross product of two vectors (area of enclosed parallellogram).
162 // \relatesalso vgl_vector_2d
cross_product(v const & a,v const & b)163 template <class T> inline T cross_product(v const& a, v const& b) { return a.x()*b.y()-a.y()*b.x(); }
164
165 //: cosine of the angle between two vectors.
166 // \relatesalso vgl_vector_2d
cos_angle(v const & a,v const & b)167 template <class T> inline double cos_angle(v const& a, v const& b) { return inner_product(a,b)/(a.length()*b.length()); }
168
169 //: smallest angle between two vectors (in radians, between 0 and Pi).
170 // \relatesalso vgl_vector_2d
171 template <class T> double angle(v const& a, v const& b); // return acos(cos_angle(a,b));
172
173 //: signed angle between two vectors (in radians, between -Pi and Pi).
174 // return the rotation angle to go from `a' to `b'
175 // \relatesalso vgl_vector_2d
176 template <class T> double signed_angle(v const& a, v const& b);
177
178 //: are two vectors orthogonal, i.e., is their dot product zero?
179 // If the third argument is specified, it is taken as the "tolerance", i.e.
180 // in that case this function returns true if the vectors are almost orthogonal.
181 // \relatesalso vgl_vector_2d
182 template <class T> bool orthogonal(v const& a, v const& b, double eps=0.0);
183
184 //: are two vectors parallel, i.e., is one a scalar multiple of the other?
185 // If the third argument is specified, it is taken as the "tolerance", i.e.
186 // in that case this function returns true if the vectors are almost parallel.
187 // \relatesalso vgl_vector_2d
188 template <class T> bool parallel(v const& a, v const& b, double eps=0.0);
189
190 //: f=a/b: return the ratio of two vectors, if they are parallel.
191 // (If not, return a "least squares" approximation.)
192 // Note that the return type is double, not T, since the ratio of e.g.
193 // two vgl_vector_2d<int> need not be an int.
194 // \relatesalso vgl_vector_2d
195 template <class T> inline double operator/(v const& a, v const& b)
196 { return dot_product(a,b)/(double)dot_product(b,b); }
197
198 //: Normalise by dividing through by the length, thus returning a length 1 vector.
199 // If a is zero length, return (0,0).
200 // \relatesalso vgl_vector_2d
normalize(v & a)201 template <class T> inline v& normalize(v& a) { double l=a.length(); return l?a/=l:a; }
202
203 //: Return a normalised version of a.
204 // If a is zero length, return (0,0).
205 // \relatesalso vgl_vector_2d
normalized(v const & a)206 template <class T> inline v normalized(v const& a) { double l=a.length(); return l?a/l:a; }
207
208 //: Return a CCW rotated version of a (angle in radian)
209 // \relatesalso vgl_vector_2d
210 template <class T> v rotated(v const& a, double angle);
211
212 #undef v
213
214 #define VGL_VECTOR_2D_INSTANTIATE(T) extern "please include vgl/vgl_vector_2d.hxx first"
215
216 #endif // vgl_vector_2d_h_
217