1 // This is core/vgl/vgl_point_2d.h
2 #ifndef vgl_point_2d_h
3 #define vgl_point_2d_h
4 //:
5 // \file
6 // \brief a point in 2D nonhomogeneous space
7 // \author Don Hamilton, Peter Tu
8 //
9 // \verbatim
10 //  Modifications
11 //   29 June 2001 Peter Vanroose moved arithmetic operators to new vgl_vector_2d
12 //    2 July 2001 Peter Vanroose implemented constructor from homg point
13 //   21 May  2009 Peter Vanroose istream operator>> re-implemented
14 // \endverbatim
15 
16 #include <iosfwd>
17 #include <vector>
18 #ifdef _MSC_VER
19 #  include <vcl_msvc_warnings.h>
20 #endif
21 #include "vgl_fwd.h" // declare vgl_homg_point_2d and vgl_line_2d
22 #include "vgl_vector_2d.h"
23 #include <cassert>
24 
25 //: Represents a cartesian 2D point
26 template <class Type>
27 class vgl_point_2d
28 {
29   // the data associated with this point
30   Type x_;
31   Type y_;
32 
33  public:
34 
35   // Constructors/Initializers/Destructor------------------------------------
36 
37   //: Default constructor
38   inline vgl_point_2d () = default;
39 
40   //: Construct from two Types.
vgl_point_2d(Type px,Type py)41   inline vgl_point_2d (Type px, Type py) : x_(px), y_(py) {}
42 
43   //: Construct from 2-array.
vgl_point_2d(Type const v[2])44   inline vgl_point_2d (Type const v[2]) : x_(v[0]), y_(v[1]) {}
45 
46   //: Construct from homogeneous point
47   vgl_point_2d (vgl_homg_point_2d<Type> const& p);
48 
49   //: Construct from 2 lines (intersection).
50   vgl_point_2d (vgl_line_2d<Type> const& l1,
51                 vgl_line_2d<Type> const& l2);
52 
53   //: Casting constructors
54   vgl_point_2d(vgl_point_2d<Type> const&) = default;
55 
56   template<typename Other>
vgl_point_2d(vgl_point_2d<Other> const & other)57   explicit vgl_point_2d(vgl_point_2d<Other> const& other)
58     : x_(other.x()), y_(other.y()) {}
59 
60 #if 0 // The compiler defaults for these are doing what they should do:
61   //: Copy constructor
62   inline vgl_point_2d(vgl_point_2d<Type> const& p) : x_(p.x()), y_(p.y()) {}
63   //: Destructor
64   inline ~vgl_point_2d () {}
65   //: Assignment
66   inline vgl_point_2d<Type>& operator=(const vgl_point_2d<Type>& p)
67   { x_ = p.x(); y_ = p.y(); return *this; }
68 #endif
69 
70   //: Test for equality
71   inline bool operator==(vgl_point_2d<Type>const& p) const
72   { return this==&p || (x_==p.x() && y_==p.y()); }
73   inline bool operator!=(vgl_point_2d<Type>const& p)const
74   { return !operator==(p); }
75 
76   // Data Access-------------------------------------------------------------
77 
x()78   inline Type &x() {return x_;}
y()79   inline Type &y() {return y_;}
80 
x()81   inline Type x() const {return x_;}
y()82   inline Type y() const {return y_;}
83 
84   //: Set \a x and \a y
85   //  Note that \a x and \a y can also be set individually.
set(Type px,Type py)86   inline void set (Type px, Type py){ x_ = px; y_ = py; }
87   //: Set \a x and \a y
88   //  Note that \a x and \a y can also be set individually.
set(Type const p[2])89   inline void set (Type const p[2]) { x_ = p[0]; y_ = p[1]; }
90 
91   //: Return true iff the point is at infinity (an ideal point).
92   //  Always returns false.
93   inline bool ideal(Type = (Type)0) const { return false; }
94 
95   //: Read from stream, possibly with formatting
96   //  Either just reads two blank-separated numbers,
97   //  or reads two comma-separated numbers,
98   //  or reads two numbers in parenthesized form "(123, 321)"
99   std::istream& read(std::istream& is);
100 };
101 
102 //  +-+-+ point_2d simple I/O +-+-+
103 
104 //: Write "<vgl_point_2d x,y>" to stream
105 // \relatesalso vgl_point_2d
106 template <class Type>
107 std::ostream&  operator<<(std::ostream& s, vgl_point_2d<Type> const& p);
108 
109 //: Read from stream, possibly with formatting
110 //  Either just reads two blank-separated numbers,
111 //  or reads two comma-separated numbers,
112 //  or reads two numbers in parenthesized form "(123, 321)"
113 // \relatesalso vgl_point_2d
114 template <class Type>
115 std::istream&  operator>>(std::istream& s, vgl_point_2d<Type>& p);
116 
117 //  +-+-+ point_2d arithmetic +-+-+
118 
119 //: Return true iff the point is at infinity (an ideal point).
120 //  Always returns false.
121 template <class Type> inline
122 bool is_ideal(vgl_point_2d<Type> const&, Type = 0) { return false; }
123 
124 //: The difference of two points is the vector from second to first point
125 // \relatesalso vgl_point_2d
126 template <class Type> inline
127 vgl_vector_2d<Type> operator-(vgl_point_2d<Type> const& p1,
128                               vgl_point_2d<Type> const& p2)
129 { return vgl_vector_2d<Type>(p1.x()-p2.x(), p1.y()-p2.y()); }
130 
131 //: Adding a vector to a point gives a new point at the end of that vector
132 // Note that vector + point is not defined!  It's always point + vector.
133 // \relatesalso vgl_point_2d
134 template <class Type> inline
135 vgl_point_2d<Type> operator+(vgl_point_2d<Type> const& p,
136                              vgl_vector_2d<Type> const& v)
137 { return vgl_point_2d<Type>(p.x()+v.x(), p.y()+v.y()); }
138 
139 //: Adding a vector to a point gives the point at the end of that vector
140 // \relatesalso vgl_point_2d
141 template <class Type> inline
142 vgl_point_2d<Type>& operator+=(vgl_point_2d<Type>& p,
143                                vgl_vector_2d<Type> const& v)
144 { p.set(p.x()+v.x(), p.y()+v.y()); return p; }
145 
146 //: Subtracting a vector from a point is the same as adding the inverse vector
147 // \relatesalso vgl_point_2d
148 template <class Type> inline
149 vgl_point_2d<Type> operator-(vgl_point_2d<Type> const& p,
150                              vgl_vector_2d<Type> const& v)
151 { return p + (-v); }
152 
153 //: Subtracting a vector from a point is the same as adding the inverse vector
154 // \relatesalso vgl_point_2d
155 template <class Type> inline
156 vgl_point_2d<Type>& operator-=(vgl_point_2d<Type>& p,
157                                vgl_vector_2d<Type> const& v)
158 { return p += (-v); }
159 
160 //  +-+-+ point_2d geometry +-+-+
161 
162 //: cross ratio of four collinear points
163 // This number is projectively invariant, and it is the coordinate of p4
164 // in the reference frame where p2 is the origin (coordinate 0), p3 is
165 // the unity (coordinate 1) and p1 is the point at infinity.
166 // This cross ratio is often denoted as ((p1, p2; p3, p4)) (which also
167 // equals ((p3, p4; p1, p2)) or ((p2, p1; p4, p3)) or ((p4, p3; p2, p1)) )
168 // and is calculated as
169 //  \verbatim
170 //                      p1 - p3   p2 - p3      (p1-p3)(p2-p4)
171 //                      ------- : --------  =  --------------
172 //                      p1 - p4   p2 - p4      (p1-p4)(p2-p3)
173 // \endverbatim
174 // If three of the given points coincide, the cross ratio is not defined.
175 //
176 // In this implementation, a least-squares result is calculated when the
177 // points are not exactly collinear.
178 //
179 // \relatesalso vgl_point_2d
180 template <class T>
181 double cross_ratio(vgl_point_2d<T>const& p1, vgl_point_2d<T>const& p2,
182                    vgl_point_2d<T>const& p3, vgl_point_2d<T>const& p4);
183 
184 //: Are three points collinear, i.e., do they lie on a common line?
185 // \relatesalso vgl_point_2d
186 template <class Type> inline
collinear(vgl_point_2d<Type> const & p1,vgl_point_2d<Type> const & p2,vgl_point_2d<Type> const & p3)187 bool collinear(vgl_point_2d<Type> const& p1,
188                vgl_point_2d<Type> const& p2,
189                vgl_point_2d<Type> const& p3)
190 { return parallel(p1-p2, p1-p3); }
191 
192 //: Return the relative distance to p1 wrt p1-p2 of p3.
193 //  The three points should be collinear and p2 should not equal p1.
194 //  This is the coordinate of p3 in the affine 1D reference frame (p1,p2).
195 //  If p3=p1, the ratio is 0; if p1=p3, the ratio is 1.
196 //  The mid point of p1 and p2 has ratio 0.5.
197 //  Note that the return type is double, not Type, since the ratio of e.g.
198 //  two vgl_vector_2d<int> need not be an int.
199 // \relatesalso vgl_point_2d
200 template <class Type> inline
ratio(vgl_point_2d<Type> const & p1,vgl_point_2d<Type> const & p2,vgl_point_2d<Type> const & p3)201 double ratio(vgl_point_2d<Type> const& p1,
202              vgl_point_2d<Type> const& p2,
203              vgl_point_2d<Type> const& p3)
204 { return (p3-p1)/(p2-p1); }
205 
206 //: Return the point at a given ratio wrt two other points.
207 //  By default, the mid point (ratio=0.5) is returned.
208 //  Note that the third argument is Type, not double, so the midpoint of e.g.
209 //  two vgl_point_2d<int> is not a valid concept.  But the reflection point
210 //  of p2 wrt p1 is: in that case f=-1.
211 // \relatesalso vgl_point_2d
212 template <class Type> inline
213 vgl_point_2d<Type> midpoint(vgl_point_2d<Type> const& p1,
214                             vgl_point_2d<Type> const& p2,
215                             Type f = (Type)0.5)
216 {
217   return vgl_point_2d<Type>((Type)((1-f)*p1.x() + f*p2.x()),
218                             (Type)((1-f)*p1.y() + f*p2.y()));
219 }
220 
221 
222 //: Return the point at the centre of gravity of two given points.
223 // Identical to midpoint(p1,p2).
224 // \relatesalso vgl_point_2d
225 template <class Type> inline
centre(vgl_point_2d<Type> const & p1,vgl_point_2d<Type> const & p2)226 vgl_point_2d<Type> centre(vgl_point_2d<Type> const& p1,
227                           vgl_point_2d<Type> const& p2)
228 {
229   return vgl_point_2d<Type>((p1.x() + p2.x())/2 ,
230                             (p1.y() + p2.y())/2 );
231 }
232 
233 //: Return the point at the centre of gravity of three given points.
234 // \relatesalso vgl_point_2d
235 template <class Type> inline
centre(vgl_point_2d<Type> const & p1,vgl_point_2d<Type> const & p2,vgl_point_2d<Type> const & p3)236 vgl_point_2d<Type> centre(vgl_point_2d<Type> const& p1,
237                           vgl_point_2d<Type> const& p2,
238                           vgl_point_2d<Type> const& p3)
239 {
240   return vgl_point_2d<Type>((p1.x() + p2.x() + p3.x())/3 ,
241                             (p1.y() + p2.y() + p3.y())/3 );
242 }
243 
244 //: Return the point at the centre of gravity of four given points.
245 // \relatesalso vgl_point_2d
246 template <class Type> inline
centre(vgl_point_2d<Type> const & p1,vgl_point_2d<Type> const & p2,vgl_point_2d<Type> const & p3,vgl_point_2d<Type> const & p4)247 vgl_point_2d<Type> centre(vgl_point_2d<Type> const& p1,
248                           vgl_point_2d<Type> const& p2,
249                           vgl_point_2d<Type> const& p3,
250                           vgl_point_2d<Type> const& p4)
251 {
252   return vgl_point_2d<Type>((p1.x() + p2.x() + p3.x() + p4.x())/4 ,
253                             (p1.y() + p2.y() + p3.y() + p4.y())/4 );
254 }
255 
256 //: Return the point at the centre of gravity of a set of given points.
257 // Beware of possible rounding errors when Type is e.g. int.
258 // \relatesalso vgl_point_2d
259 template <class Type> inline
centre(std::vector<vgl_point_2d<Type>> const & v)260 vgl_point_2d<Type> centre(std::vector<vgl_point_2d<Type> > const& v)
261 {
262   int n=v.size();
263   assert(n>0); // it is *not* correct to return the point (0,0) when n==0.
264   Type x = 0, y = 0;
265   for (int i=0; i<n; ++i) x+=v[i].x(), y+=v[i].y();
266   return vgl_point_2d<Type>(x/n,y/n);
267 }
268 
269 #define VGL_POINT_2D_INSTANTIATE(T) extern "please include vgl/vgl_point_2d.hxx first"
270 
271 #endif // vgl_point_2d_h
272