vgl_homg_point_3d.h
Go to the documentation of this file.
1 // This is core/vgl/vgl_homg_point_3d.h
2 #ifndef vgl_homg_point_3d_h_
3 #define vgl_homg_point_3d_h_
4 //:
5 // \file
6 // \brief point in projective 3D space
7 // \author Don HAMILTON, Peter TU
8 //
9 // \verbatim
10 // Modifications
11 // Peter Vanroose - 4 July 2001 - Added geometric interface like vgl_point_3d
12 // Peter Vanroose - 2 July 2001 - Added constructor from 3 planes
13 // Peter Vanroose - 1 July 2001 - Renamed data to x_ y_ z_ w_ and inlined constructors
14 // Peter Vanroose - 27 June 2001 - Implemented operator==
15 // Peter Vanroose - 15 July 2002 - Added coplanar()
16 // Guillaume Mersch- 10 Feb 2009 - bug fix in coplanar()
17 // \endverbatim
18 
19 #include <iosfwd>
20 #include <vgl/vgl_point_3d.h>
21 #include <vgl/vgl_fwd.h> // forward declare vgl_homg_plane_3d
22 #ifdef _MSC_VER
23 # include <vcl_msvc_warnings.h>
24 #endif
25 #include <cassert>
26 
27 //: Represents a homogeneous 3D point
28 template <class Type>
30 {
31  // the data associated with this point
32  Type x_;
33  Type y_;
34  Type z_;
35  Type w_;
36 
37  public:
38 
39  // Constructors/Initializers/Destructor------------------------------------
40 
41  //: Default constructor with (0,0,0,1)
42  inline vgl_homg_point_3d() : x_(0), y_(0), z_(0), w_((Type)1) {}
43 
44  //: Construct from three (nonhomogeneous) or four (homogeneous) Types.
45  inline vgl_homg_point_3d(Type px, Type py, Type pz, Type pw = (Type)1)
46  : x_(px), y_(py), z_(pz), w_(pw) {}
47 
48  //: Construct from homogeneous 4-array.
49  inline vgl_homg_point_3d(const Type v[4]) : x_(v[0]), y_(v[1]), z_(v[2]), w_(v[3]) {}
50 
51  //: Construct point at infinity from direction vector.
52  inline vgl_homg_point_3d(vgl_vector_3d<Type>const& v) : x_(v.x()), y_(v.y()), z_(v.z()), w_(0) {}
53 
54  //: Construct from (non-homogeneous) vgl_point_3d<Type>
55  inline explicit vgl_homg_point_3d(vgl_point_3d<Type> const& p)
56  : x_(p.x()), y_(p.y()), z_(p.z()), w_((Type)1) {}
57 
58  //: Construct from 3 planes (intersection).
60  vgl_homg_plane_3d<Type> const& l2,
61  vgl_homg_plane_3d<Type> const& l3);
62 
63 #if 0
64  // Default copy constructor
65  inline vgl_homg_point_3d(const vgl_homg_point_3d<Type>& that)
66  : x_(that.x()), y_(that.y()), z_(that.z()), w_(that.w()) {}
67 
68  // Destructor
69  inline ~vgl_homg_point_3d() {}
70 
71  // Default assignment operator
72  inline vgl_homg_point_3d<Type>& operator=(const vgl_homg_point_3d<Type>& that)
73  {
74  set(that.x(),that.y(),that.z(),that.w());
75  return *this;
76  }
77 #endif
78 
79  //: the comparison operator
80  bool operator==(vgl_homg_point_3d<Type> const& other) const;
81  inline bool operator!=(vgl_homg_point_3d<Type>const& other)const{return !operator==(other);}
82 
83  // Data Access-------------------------------------------------------------
84 
85  inline Type x() const { return x_; }
86  inline Type y() const { return y_; }
87  inline Type z() const { return z_; }
88  inline Type w() const { return w_; }
89 
90  //: Set \a x,y,z,w
91  // Note that it does not make sense to set \a x, \a y, \a z or \a w individually.
92  inline void set(Type px, Type py, Type pz, Type pw = (Type)1)
93  { x_=px; y_=py; z_=pz; w_=pw; }
94 
95  inline void set(Type const p[4]) { x_=p[0]; y_=p[1]; z_=p[2]; w_=p[3]; }
96 
97  //: Return true iff the point is at infinity (an ideal point).
98  // The method checks whether |w| <= tol * max(|x|,|y|,|z|)
99  inline bool ideal(Type tol = (Type)0) const
100  {
101 #define vgl_Abs(x) ((x)<0?-(x):(x)) // avoid #include of vcl_cmath.h AND vcl_cstdlib.h
102  return vgl_Abs(w()) <= tol * vgl_Abs(x()) ||
103  vgl_Abs(w()) <= tol * vgl_Abs(y()) ||
104  vgl_Abs(w()) <= tol * vgl_Abs(z());
105 #undef vgl_Abs
106  }
107 
108  inline bool get_nonhomogeneous(double& vx, double& vy, double& vz) const
109  {
110  if (w() == 0)
111  {
112 #ifdef DEBUG
113  std::cerr << "vgl_homg_point_3d::get_nonhomogeneous - point at infinity\n";
114 #endif
115  return false;
116  }
117 
118  double hw = 1.0/w();
119 
120  vx = x() * hw;
121  vy = y() * hw;
122  vz = z() * hw;
123 
124  return true;
125  }
126 
127  inline bool rescale_w(Type new_w = Type(1))
128  {
129  if (w() == 0)
130  return false;
131 
132  x_ = x() * new_w / w();
133  y_ = y() * new_w / w();
134  z_ = z() * new_w / w();
135  w_ = new_w;
136 
137  return true;
138  }
139 };
140 
141 // +-+-+ point_3d simple I/O +-+-+
142 
143 //: Write "<vgl_homg_point_3d (x,y,z,w) >" to stream
144 // \relatesalso vgl_homg_point_3d
145 template <class Type>
146 std::ostream& operator<<(std::ostream& s, vgl_homg_point_3d<Type> const& p);
147 
148 //: Read x y z w from stream
149 // \relatesalso vgl_homg_point_3d
150 template <class Type>
151 std::istream& operator>>(std::istream& s, vgl_homg_point_3d<Type>& p);
152 
153 // +-+-+ homg_point_3d arithmetic +-+-+
154 
155 //: Return true iff the point is at infinity (an ideal point).
156 // The method checks whether |w| <= tol * max(|x|,|y|,|z|)
157 // \relatesalso vgl_homg_point_3d
158 template <class Type> inline
159 bool is_ideal(vgl_homg_point_3d<Type> const& p, Type tol = (Type)0) { return p.ideal(tol); }
160 
161 //: Return true iff the 4 points are coplanar, i.e., they belong to a common plane
162 // \relatesalso vgl_homg_point_3d
163 template <class Type> inline
165  vgl_homg_point_3d<Type> const& p2,
166  vgl_homg_point_3d<Type> const& p3,
167  vgl_homg_point_3d<Type> const& p4)
168 {
169  return ((p1.x()*p2.y()-p1.y()*p2.x())*p3.z()
170  +(p3.x()*p1.y()-p3.y()*p1.x())*p2.z()
171  +(p2.x()*p3.y()-p2.y()*p3.x())*p1.z())*p4.w()
172  -((p4.x()*p1.y()-p4.y()*p1.x())*p2.z()
173  +(p2.x()*p4.y()-p2.y()*p4.x())*p1.z()
174  +(p1.x()*p2.y()-p1.y()*p2.x())*p4.z())*p3.w()
175  +((p3.x()*p4.y()-p3.y()*p4.x())*p1.z()
176  +(p1.x()*p3.y()-p1.y()*p3.x())*p4.z()
177  +(p4.x()*p1.y()-p4.y()*p1.x())*p3.z())*p2.w()
178  -((p2.x()*p3.y()-p2.y()*p3.x())*p4.z()
179  +(p4.x()*p2.y()-p4.y()*p2.x())*p3.z()
180  +(p3.x()*p4.y()-p3.y()*p4.x())*p2.z())*p1.w() == 0;
181 }
182 
183 //: The difference of two points is the vector from second to first point
184 // This function is only valid if the points are not at infinity.
185 // \relatesalso vgl_homg_point_3d
186 template <class Type> inline
188  vgl_homg_point_3d<Type> const& p2)
189 {
190  assert(p1.w() && p2.w());
191  return vgl_vector_3d<Type>(p1.x()/p1.w()-p2.x()/p2.w(),
192  p1.y()/p1.w()-p2.y()/p2.w(),
193  p1.z()/p1.w()-p2.z()/p2.w());
194 }
195 
196 //: Adding a vector to a point gives a new point at the end of that vector
197 // If the point is at infinity, nothing happens.
198 // Note that vector + point is not defined! It's always point + vector.
199 // \relatesalso vgl_homg_point_3d
200 template <class Type> inline
202  vgl_vector_3d<Type> const& v)
203 {
204  return vgl_homg_point_3d<Type>(p.x()+v.x()*p.w(),
205  p.y()+v.y()*p.w(),
206  p.z()+v.z()*p.w(), p.w());
207 }
208 
209 //: Adding a vector to a point gives the point at the end of that vector
210 // If the point is at infinity, nothing happens.
211 // \relatesalso vgl_homg_point_3d
212 template <class Type> inline
214  vgl_vector_3d<Type> const& v)
215 {
216  p.set(p.x()+v.x()*p.w(),p.y()+v.y()*p.w(),p.z()+v.z()*p.w(),p.w()); return p;
217 }
218 
219 //: Subtracting a vector from a point is the same as adding the inverse vector
220 // \relatesalso vgl_homg_point_3d
221 template <class Type> inline
223  vgl_vector_3d<Type> const& v)
224 { return p + (-v); }
225 
226 //: Subtracting a vector from a point is the same as adding the inverse vector
227 // \relatesalso vgl_homg_point_3d
228 template <class Type> inline
230  vgl_vector_3d<Type> const& v)
231 { return p += (-v); }
232 
233 // +-+-+ homg_point_3d geometry +-+-+
234 
235 //: cross ratio of four collinear points
236 // This number is projectively invariant, and it is the coordinate of p4
237 // in the reference frame where p2 is the origin (coordinate 0), p3 is
238 // the unity (coordinate 1) and p1 is the point at infinity.
239 // This cross ratio is often denoted as ((p1, p2; p3, p4)) (which also
240 // equals ((p3, p4; p1, p2)) or ((p2, p1; p4, p3)) or ((p4, p3; p2, p1)) )
241 // and is calculated as
242 // \verbatim
243 // p1 - p3 p2 - p3 (p1-p3)(p2-p4)
244 // ------- : -------- = --------------
245 // p1 - p4 p2 - p4 (p1-p4)(p2-p3)
246 // \endverbatim
247 // If three of the given points coincide, the cross ratio is not defined.
248 //
249 // In this implementation, a least-squares result is calculated when the
250 // points are not exactly collinear.
251 //
252 // \relatesalso vgl_homg_point_3d
253 template <class T>
254 double cross_ratio(vgl_homg_point_3d<T>const& p1, vgl_homg_point_3d<T>const& p2,
255  vgl_homg_point_3d<T>const& p3, vgl_homg_point_3d<T>const& p4);
256 
257 //: Are three points collinear, i.e., do they lie on a common line?
258 // \relatesalso vgl_homg_point_3d
259 template <class Type>
260 bool collinear(vgl_homg_point_3d<Type> const& p1,
261  vgl_homg_point_3d<Type> const& p2,
262  vgl_homg_point_3d<Type> const& p3);
263 
264 //: Return the relative distance to p1 wrt p1-p2 of p3.
265 // The three points should be collinear and p2 should not equal p1.
266 // This is the coordinate of p3 in the affine 1D reference frame (p1,p2).
267 // If p3=p1, the ratio is 0; if p1=p3, the ratio is 1.
268 // The mid point of p1 and p2 has ratio 0.5.
269 // Note that the return type is double, not Type, since the ratio of e.g.
270 // two vgl_vector_3d<int> need not be an int.
271 // \relatesalso vgl_homg_point_3d
272 template <class Type> inline
274  vgl_homg_point_3d<Type> const& p2,
275  vgl_homg_point_3d<Type> const& p3)
276 { return (p3-p1)/(p2-p1); }
277 
278 //: Return the point at a given ratio wrt two other points.
279 // By default, the mid point (ratio=0.5) is returned.
280 // Note that the third argument is Type, not double, so the midpoint of e.g.
281 // two vgl_homg_point_3d<int> is not a valid concept. But the reflection point
282 // of p2 wrt p1 is: in that case f=-1.
283 // \relatesalso vgl_homg_point_3d
284 template <class Type> inline
286  vgl_homg_point_3d<Type> const& p2,
287  Type f = (Type)0.5)
288 { return p1 + f*(p2-p1); }
289 
290 
291 //: Return the point at the centre of gravity of two given points.
292 // Identical to midpoint(p1,p2).
293 // Invalid when both points are at infinity.
294 // If only one point is at infinity, that point is returned. inline
295 // \relatesalso vgl_homg_point_3d
296 template <class Type> inline
298  vgl_homg_point_3d<Type> const& p2)
299 {
300  return vgl_homg_point_3d<Type>(p1.x()*p2.w() + p2.x()*p1.w() ,
301  p1.y()*p2.w() + p2.y()*p1.w() ,
302  p1.z()*p2.w() + p2.z()*p1.w() ,
303  p1.w()*p2.w()*2 );
304 }
305 
306 //: Return the point at the centre of gravity of a set of given points.
307 // There are no rounding errors when Type is e.g. int, if all w() are 1.
308 // \relatesalso vgl_homg_point_3d
309 template <class Type> inline
311 {
312  int n=v.size();
313  assert(n>0); // it is *not* correct to return the point (0,0) when n==0.
314  Type x = 0, y = 0, z = 0;
315  for (int i=0; i<n; ++i)
316  x+=v[i].x()/v[i].w(), y+=v[i].y()/v[i].w(), z+=v[i].z()/v[i].w();
317  return vgl_homg_point_3d<Type>(x,y,z,(Type)n);
318 }
319 
320 #define VGL_HOMG_POINT_3D_INSTANTIATE(T) extern "please include vgl/vgl_homg_point_3d.hxx first"
321 
322 #endif // vgl_homg_point_3d_h_
vgl_homg_point_1d< T > centre(vgl_homg_point_1d< T > const &p1, vgl_homg_point_1d< T > const &p2)
Return the point at the centre of gravity of two given points.
bool rescale_w(Type new_w=Type(1))
vgl_homg_point_3d(const Type v[4])
Construct from homogeneous 4-array.
vgl_homg_point_3d(Type px, Type py, Type pz, Type pw=(Type) 1)
Construct from three (nonhomogeneous) or four (homogeneous) Types.
vgl_homg_point_1d< T > & operator-=(vgl_homg_point_1d< T > &p, T v)
Subtracting a number from a point is the same as adding the inverse number.
vgl_homg_point_3d(vgl_vector_3d< Type >const &v)
Construct point at infinity from direction vector.
bool get_nonhomogeneous(double &vx, double &vy, double &vz) const
Represents a homogeneous 3D plane.
Definition: vgl_fwd.h:22
void set(Type const p[4])
double cross_ratio(vgl_homg_point_1d< T >const &p1, vgl_homg_point_1d< T >const &p2, vgl_homg_point_1d< T >const &p3, vgl_homg_point_1d< T >const &p4)
cross ratio of four points.
Represents a cartesian 3D point.
Definition: vgl_fwd.h:11
vgl_homg_point_1d< T > & operator+=(vgl_homg_point_1d< T > &p, T v)
Adding a number to a 1-D point translates that point.
#define vgl_Abs(x)
std::ostream & operator<<(std::ostream &s, vgl_orient_box_3d< Type > const &p)
Write box to stream.
Represents a homogeneous 3D point.
Definition: vgl_fwd.h:9
bool operator!=(vgl_homg_point_3d< Type >const &other) const
#define v
Definition: vgl_vector_2d.h:74
bool collinear(l const &l1, vgl_homg_point_3d< Type > const &p)
Does a line pass through a point, i.e., are the point and the line collinear?.
a point in 3D nonhomogeneous space
vgl_homg_point_3d(vgl_point_3d< Type > const &p)
Construct from (non-homogeneous) vgl_point_3d<Type>.
vgl_homg_point_1d< T > operator+(vgl_homg_point_1d< T > const &p, T v)
Adding a number to a 1-D point translates that point.
double ratio(vgl_homg_point_1d< T > const &p1, vgl_homg_point_1d< T > const &p2, vgl_homg_point_1d< T > const &p3)
Return the relative distance to p1 wrt p1-p2 of p3.
bool is_ideal(l const &line, T tol=(T) 0)
Return true iff line is the line at infinity.
bool coplanar(l const &l1, l const &l2)
Are two lines coplanar, i.e., do they intersect?.
bool operator==(vgl_homg_point_3d< Type > const &other) const
the comparison operator.
std::istream & operator>>(std::istream &is, vgl_orient_box_3d< Type > &p)
Read box from stream.
void set(Type px, Type py, Type pz, Type pw=(Type) 1)
Set x,y,z,w.
vgl_homg_point_3d()
Default constructor with (0,0,0,1).
bool ideal(Type tol=(Type) 0) const
Return true iff the point is at infinity (an ideal point).
vgl_homg_point_1d< T > midpoint(vgl_homg_point_1d< T > const &p1, vgl_homg_point_1d< T > const &p2, T f=0.5)
Return the point at a given ratio wrt two other points.
T operator-(vgl_homg_point_1d< T > const &p1, vgl_homg_point_1d< T > const &p2)
The difference of two points is the distance between the two.