1 // This is core/vgl/vgl_vector_3d.h
2 #ifndef vgl_vector_3d_h_
3 #define vgl_vector_3d_h_
4 //:
5 // \file
6 // \brief direction vector in Euclidean 3D 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 3D space, templated by type of element
24 // (typically float or double).  A vgl_vector_3d<T> represents the
25 // difference (or connecting vector) between two vgl_point_3d<T>s.
26 //
27 // Use this class to do arithmetic (adding and scaling) in 3d geometric space.
28 //
29 template <class T>
30 class vgl_vector_3d
31 {
32  public:
33   T x_; // Data is public
34   T y_;
35   T z_;
x()36   inline T x() const { return x_; }
y()37   inline T y() const { return y_; }
z()38   inline T z() const { return z_; }
39 
40   //: Creates the vector (0,0,0) of zero length.
vgl_vector_3d()41   inline vgl_vector_3d() : x_(0) , y_(0) , z_(0) {}
42 
43   //: Creates the vector \a (vx,vy,vz).
vgl_vector_3d(T vx,T vy,T vz)44   inline vgl_vector_3d(T vx, T vy, T vz) : x_(vx) , y_(vy) , z_(vz) {}
45 
46   //: Creates the vector \a (vx,vy,vz).
vgl_vector_3d(const T v[3])47   inline vgl_vector_3d(const T v[3]) : x_(v[0]), y_(v[1]), z_(v[2]) {}
48 
49   //: Casting constructors
50   vgl_vector_3d(vgl_vector_3d<T> const&) = default;
51 
52   template<typename Other>
vgl_vector_3d(vgl_vector_3d<Other> const & other)53   explicit vgl_vector_3d(vgl_vector_3d<Other> const& other)
54     : x_(other.x()), y_(other.y()), z_(other.z()) {}
55 
56 #if 0 // The defaults do exactly what they should do...
57   //: Copy constructor
58   inline vgl_vector_3d (vgl_vector_3d<T>const&v):x_(v.x()),y_(v.y()),z_(v.z()){}
59   //: Assignment operator
60   inline vgl_vector_3d<T>& operator=(vgl_vector_3d<T> const& v) {
61     x_=v.x(); y_=v.y(); z_=v.z(); return *this; }
62   //: Destructor
63   inline ~vgl_vector_3d () {}
64 #endif
65 
66   //: Assignment
set(T vx,T vy,T vz)67   inline void set(T vx, T vy, T vz) { x_=vx; y_=vy; z_=vz; }
68 
69   //: Set \a x, \a y and \a z
set(T const v[3])70   inline void set (T const v[3]) { x_ = v[0]; y_ = v[1]; z_ = v[2]; }
71 
72   //: Comparison
73   inline bool operator==(vgl_vector_3d<T>const& v) const {
74     return x_==v.x() && y_==v.y() && z_==v.z(); }
75   inline bool operator!=(vgl_vector_3d<T>const& v)const{return !operator==(v);}
76 
77   //: Return the length of this vector.
78   double length() const; // return sqrt( sqr_length() );
79 
80   //: Return the squared length of this vector.
sqr_length()81   inline T sqr_length() const { return x()*x()+y()*y()+z()*z(); }
82 
83 
84   //: One-parameter family of unit vectors that are orthogonal to *this, v(s).
85   // To get two orthogonal vectors call this function twice with s=0 and
86   // s=0.25 for example.
87   // \param s 0<=s<=1, v(0)==v(1)
88   // \note This function is not continuous near z==0. (Under the Hairy Ball
89   // theorem no such smooth function can exist.)
90   // \note This vector need not be normalized but it should have non-zero length.
91   // \deprecated Use global function orthogonal_vectors(vgl_vector_3d<T > const& a, double s) instead.
92   vgl_vector_3d<T> orthogonal_vectors(double s) const;
93 
94   //: Read from stream, possibly with formatting
95   //  Either just reads three blank-separated numbers,
96   //  or reads three comma-separated numbers,
97   //  or reads three numbers in parenthesized form "(123, 321, 567)"
98   // \relatesalso vgl_point_3d
99   std::istream& read(std::istream& is);
100 };
101 
102 #define v vgl_vector_3d<T>
103 
104 //  +-+-+ vector_3d simple I/O +-+-+
105 
106 //: Write "<vgl_vector_3d x,y,z> " to stream
107 // \relatesalso vgl_vector_3d
108 template <class T> std::ostream&  operator<<(std::ostream& s, v const& p);
109 
110 //: Read from stream, possibly with formatting
111 //  Either just reads three blank-separated numbers,
112 //  or reads three comma-separated numbers,
113 //  or reads three numbers in parenthesized form "(123, 321, 567)"
114 // \relatesalso vgl_vector_3d
115 template <class T> std::istream& operator>>(std::istream& s, v& p);
116 
117 
118 //  +-+-+ vector_3d geometry and algebra +-+-+
119 
120 //: Return the length of a vector.
121 // \relatesalso vgl_vector_3d
length(v const & a)122 template <class T> inline double length(v const& a) { return a.length(); }
123 
124 //: Return the squared length of a vector.
125 // \relatesalso vgl_vector_3d
sqr_length(v const & a)126 template <class T> inline T sqr_length(v const& a) { return a.sqr_length(); }
127 
128 //: c=a+b: add two vectors.
129 // \relatesalso vgl_vector_3d
130 template <class T> inline v      operator+(v const& a, v const& b) { return v(a.x()+b.x(), a.y()+b.y(), a.z()+b.z()); }
131 
132 //: c=a-b: subtract two vectors.
133 // \relatesalso vgl_vector_3d
134 template <class T> inline v      operator-(v const& a, v const& b) { return v(a.x()-b.x(), a.y()-b.y(), a.z()-b.z()); }
135 
136 //: a+=b: add b to a and return a.
137 // \relatesalso vgl_vector_3d
138 template <class T> inline v&     operator+=(v& a, v const& b) { a.x_+=b.x_; a.y_+=b.y_; a.z_+=b.z_; return a; }
139 
140 //: a-=b: subtract b from a and return a.
141 // \relatesalso vgl_vector_3d
142 template <class T> inline v&     operator-=(v& a, v const& b) { a.x_-=b.x_; a.y_-=b.y_; a.z_-=b.z_; return a; }
143 
144 //: +b: unary plus operator (no-op).
145 // \relatesalso vgl_vector_3d
146 template <class T> inline v      operator+(v const& b) { return b; }
147 
148 //: -a: unary minus operator (additive inverse).
149 // \relatesalso vgl_vector_3d
150 template <class T> inline v      operator-(v const& b) { return v(-b.x(), -b.y(), -b.z()); }
151 
152 //: c=f*b: return a scaled version of the vector.
153 // \relatesalso vgl_vector_3d
154 template <class T> inline v      operator*(double s, v const& b) { return v(T(s*b.x()), T(s*b.y()), T(s*b.z())); }
155 
156 //: c=a*f: return a scaled version of the vector.
157 // \relatesalso vgl_vector_3d
158 template <class T> inline v      operator*(v const& a, double s) { return v(T(a.x()*s), T(a.y()*s), T(a.z()*s)); }
159 
160 //: c=b/f: return an inversely scaled version of the vector (scale must be nonzero).
161 //  Note that the argument type is double, not T, to avoid rounding errors
162 //  when type T has no multiplicative inverses (like T=int).
163 // \relatesalso vgl_vector_3d
164 template <class T> inline v      operator/(v const& a, double s) { return v(T(a.x()/s), T(a.y()/s), T(a.z()/s)); }
165 
166 //: a*=f: scale the vector.
167 // \relatesalso vgl_vector_3d
168 template <class T> inline v&     operator*=(v& a, double s) { a.set(T(a.x()*s), T(a.y()*s), T(a.z()*s)); return a; }
169 
170 //: a/=f: inversely scale the vector (scale must be nonzero).
171 // \relatesalso vgl_vector_3d
172 template <class T> inline v&     operator/=(v& a, double s) { a.set(T(a.x()/s), T(a.y()/s), T(a.z()/s)); return a; }
173 
174 //: dot product or inner product of two vectors.
175 // \relatesalso vgl_vector_3d
dot_product(v const & a,v const & b)176 template <class T> inline T      dot_product(v const& a, v const& b) { return a.x()*b.x()+a.y()*b.y()+a.z()*b.z(); }
177 
178 //: dot product or inner product of two vectors.
179 // \relatesalso vgl_vector_3d
inner_product(v const & a,v const & b)180 template <class T> inline T      inner_product(v const& a, v const& b) { return a.x()*b.x()+a.y()*b.y()+a.z()*b.z(); }
181 
182 //: cross product of two vectors (is orthogonal to both)
183 // \relatesalso vgl_vector_3d
cross_product(v const & a,v const & b)184 template <class T> inline v      cross_product(v const& a, v const& b)
185 { return v(a.y()*b.z()-a.z()*b.y(), a.z()*b.x()-a.x()*b.z(), a.x()*b.y()-a.y()*b.x()); }
186 
187 //: cosine of the angle between two vectors.
188 // \relatesalso vgl_vector_3d
cos_angle(v const & a,v const & b)189 template <class T> inline double cos_angle(v const& a, v const& b) { return inner_product(a,b)/(a.length()*b.length()); }
190 
191 //: smallest angle between two vectors (in radians, between 0 and Pi).
192 // \relatesalso vgl_vector_3d
193 template <class T>        double angle(v const& a, v const& b); // return acos(cos_angle(a,b));
194 
195 //: are two vectors orthogonal, i.e., is their dot product zero?
196 // If the third argument is specified, it is taken as the "tolerance", i.e.
197 // in that case this function returns true if the vectors are almost orthogonal.
198 // \relatesalso vgl_vector_3d
199 template <class T>        bool orthogonal(v const& a, v const& b, double eps=0.0);
200 
201 //: are two vectors parallel, i.e., is one a scalar multiple of the other?
202 // If the third argument is specified, it is taken as the "tolerance", i.e.
203 // in that case this function returns true if the vectors are almost parallel.
204 // \relatesalso vgl_vector_3d
205 template <class T>        bool parallel(v const& a, v const& b, double eps=0.0);
206 
207 //: f=a/b: return the ratio of two vectors, if they are parallel.
208 //  (If not, return a "least squares" approximation.)
209 //  Note that the return type is double, not T, since the ratio of e.g.
210 //  two vgl_vector_3d<int> need not be an int.
211 // \relatesalso vgl_vector_3d
212 template <class T> inline double operator/(v const& a, v const& b)
213 { return dot_product(a,b)/(double)dot_product(b,b); }
214 
215 //: Normalise by dividing through by the length, thus returning a length 1 vector.
216 //  If a is zero length, return (0,0).
217 // \relatesalso vgl_vector_3d
normalize(v & a)218 template <class T> inline v&     normalize(v& a) { double l=a.length(); return l?a/=l:a; }
219 
220 //: Return a normalised version of a.
221 //  If a is zero length, return (0,0).
222 // \relatesalso vgl_vector_3d
normalized(v const & a)223 template <class T> inline v      normalized(v const& a) { double l=a.length(); return l?a/l:a; }
224 
225 //: One-parameter family of unit vectors that are orthogonal to \a a, v(s).
226 // To get two orthogonal vectors call this function twice with s=0 and
227 // s=0.25 for example.
228 // \param s 0<=s<=1, v(0)==v(1)
229 // \note This function is not continuous near z==0. (Under the Hairy Ball
230 // theorem no such smooth function can exist.)
231 // \note This vector need not be normalized but it should have non-zero length.
232 template <class T> v             orthogonal_vectors(v const& a, double s);
233 
234 #undef v
235 
236 #define VGL_VECTOR_3D_INSTANTIATE(T) extern "please include vgl/vgl_vector_3d.hxx first"
237 
238 #endif // vgl_vector_3d_h_
239