iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Rectangle.H
Go to the documentation of this file.
1 /*! @file
2  @author Randolph Voorhies
3  @copyright GNU Public License (GPL v3)
4  @section License
5  @verbatim
6  // ////////////////////////////////////////////////////////////////////////
7  // The iLab Neuromorphic Robotics Toolkit (NRT) //
8  // Copyright 2010-2012 by the University of Southern California (USC) //
9  // and the iLab at USC. //
10  // //
11  // iLab - University of Southern California //
12  // Hedco Neurociences Building, Room HNB-10 //
13  // Los Angeles, Ca 90089-2520 - USA //
14  // //
15  // See http://ilab.usc.edu for information about this project. //
16  // ////////////////////////////////////////////////////////////////////////
17  // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18  // //
19  // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20  // redistribute it and/or modify it under the terms of the GNU General //
21  // Public License as published by the Free Software Foundation, either //
22  // version 3 of the License, or (at your option) any later version. //
23  // //
24  // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25  // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27  // PURPOSE. See the GNU General Public License for more details. //
28  // //
29  // You should have received a copy of the GNU General Public License //
30  // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31  // <http://www.gnu.org/licenses/>. //
32  // ////////////////////////////////////////////////////////////////////////
33  @endverbatim */
34 
35 
36 #ifndef INCLUDE_NRT_CORE_GEOMETRY_RECTANGLE_H
37 #define INCLUDE_NRT_CORE_GEOMETRY_RECTANGLE_H
38 
39 #include <nrt/Core/Geometry/Dims.H>
40 #include <nrt/Core/Geometry/Line.H>
41 #include <nrt/External/cereal/access.hpp>
42 #include <array>
43 
44 namespace nrt
45 {
46  //! A basic rectangle class
47  /*! This is a shorthand class to represent a 2D rectangle, as defined by top, left, bottom and right coordinates. The
48  goal of this object is not to have to check if left < right, etc... for each function using a Rectangle. The object
49  checks for that at its creation, and is always internally coherent. Image convention: top < bottom, left < right.
50 
51  There is often some ambiguity about how to represent the left-right and top-bottom ranges involved in a
52  rectangle. Imagine a pixel grid like this:
53 
54 @verbatim
55  +---+---+---+---+
56  | | | | |
57  | | | | |
58  +---+---+---+---+
59  | | | | |
60  | | | | |
61  +---+---+---+---+
62  | | | | |
63  | | | | |
64  +---+---+---+---+
65  | | | | |
66  | | | | |
67  +---+---+---+---+
68 @endverbatim
69 
70  If we want a Rectangle that covers this whole 4x4 grid, how should we represent the coordinates? Clearly the upper
71  left corner is (0,0), but what about the bottom right corner? One answer would be that the lower right corner is
72  (4,4), in which we imagine the coordinate numbers falling between the cracks of the pixels:
73 
74 @verbatim
75  . 0...1...2...3...4
76  0 +---+---+---+---+
77  . | | | | |
78  . | | | | |
79  1 +---+---+---+---+
80  . | | | | |
81  . | | | | |
82  2 +---+---+---+---+
83  . | | | | |
84  . | | | | |
85  3 +---+---+---+---+
86  . | | | | |
87  . | | | | |
88  4 +---+---+---+---+
89 @endverbatim
90 
91  Another answer is that the lower right corner should be labeled as (3,3), if we envision the coordinate numbers
92  labeling the pixel centers, and this approach is more natural if we want to draw a line just inside the border of
93  the rectangle as shown by the '*' here:
94 
95 @verbatim
96  . ..0...1...2...3..
97  . +---+---+---+---+
98  0 |***|***|***|***|
99  . |***|***|***|***|
100  . +---+---+---+---+
101  1 |***| | |***|
102  . |***| | |***|
103  . +---+---+---+---+
104  2 |***| | |***|
105  . |***| | |***|
106  . +---+---+---+---+
107  3 |***|***|***|***|
108  . |***|***|***|***|
109  . +---+---+---+---+
110 @endverbatim
111 
112  In the Rectangle class we support both approaches; the (4,4) coords are called 'outer' coordinates and corresponding
113  functions have a 'O' suffix (bottomO(), rightO(), and tlbrO()), while the (3,3) coords are called 'inner'
114  coordinates and corresponding functions have an 'I' suffix (bottomI(), rightI(), and tlbrI()).
115 
116  The internal representation of Rectangle is based on outer coordinates, but this has no effect on users of the class
117  who are free to user whichever of inner or outer coords are more convenient for their purposes.
118 
119  Outer coordinates are more natural for uniformly scaling a rectangle up or down by a factor. For example, if we want
120  to scale the 4x4 rect up by a factor of 2 giving an 8x8 rect, then in outer coords we just do newright=right*2=4*2=8
121  and newbottom=bottom*2=4*2=8. But with inner coords we can't just multiply by 2: the inner bottom-right coords are
122  (3,3), and if we scale those by 2 we get (6,6) which represents a 7x7 rectangle rather than the correct 8x8
123  result.
124 
125  \ingroup geometry */
126  template <class T>
127  class Rectangle
128  {
129  public:
130  //! Uninitialized constructor, topleft = (0,0) and bottom-right=(0,0)
131  explicit Rectangle();
132 
133  //! Build a Rectangle from a top-left corner and some dims
134  explicit Rectangle(Point2D<T> const & topLeft, Dims<T> const & dims);
135 
136  //! Build a Rectangle from the top left and bottom right corners
137  explicit Rectangle(Point2D<T> const & topLeft, Point2D<T> const & bottomRight);
138 
139  //! Build a Rectangle from a center point and some dims
140  static Rectangle<T> centerDims(Point2D<T> const & center, Dims<T> const & dims);
141 
142  //! Build a Rectangle from 4 coordinates (top, left, inner-bottom, inner-right)
143  static Rectangle<T> tlbrI(T tt, T ll, T bb, T rr);
144 
145  //! Build a Rectangle from 4 coordinates (top, left, outer-bottom, outer-right)
146  static Rectangle<T> tlbrO(T tt, T ll, T bb, T rr);
147 
148  //! Build a Rectangle which defines the smallest bounding box around the given group of points
149  /*! \note The returned Rectangle contains the extremal points on its borders (see dims() for more) */
150  static Rectangle<T> bounds(std::vector<Point2D<T> > const & points);
151 
152  //! Copy constructor
153  Rectangle(Rectangle<T> const & rect) = default;
154 
155  //! Move constructor
156  Rectangle(Rectangle<T> && rect) = default;
157 
158  //! Conversion copy constructor, uses nrt::clamped_convert<T,U> internally
159  template <class U>
160  explicit Rectangle(Rectangle<U> const & rect);
161 
162  //! Assignment
163  Rectangle<T> & operator=(Rectangle<T> const & other) = default;
164 
165  //! Move assignment
166  Rectangle<T> & operator=(Rectangle<T> && other) = default;
167 
168  //! Get the Rectangle's dims
169  /*! The dimensions returned by this method are such that the bottomRight corner lies <i>on</i> the border. This
170  means that if you want to allocate e.g. an Image to contain this Rectangle, the Image's dimensions should be 1
171  larger than the Rectangle. */
172  Dims<T> dims() const;
173 
174  //! Get the Rectangle's width
175  T width() const;
176 
177  //! Get the Rectangle's height
178  T height() const;
179 
180  //! Get the Rectangle's area
181  T area() const;
182 
183  //! Get the Rectangle's aspect ratio (width/height)
184  float aspectRatio() const;
185 
186  //! Get the Rectangle's center
187  Point2D<T> center() const;
188 
189  //! Get a grid of points uniformly distributed inside the rectangle
190  /*! PointClass must have a constructor that takes two arguments of type nrt::promote<T, float>::type for x and
191  y. For example, nrt::Point2D<typename nrt::promote<T, float>::type> */
192  template <class PointClass = nrt::Point2D<typename nrt::promote<T, float>::type> >
193  void getGridOfPoints(T const margin, T const nx, T const ny, std::vector<PointClass> & points) const;
194 
195  //! Is this the Point contained in the Rectangle?
196  /*! \note Boundaries are included in this check */
197  template <class U>
198  bool contains(Point2D<U> const & p) const;
199 
200  //! check if this Rectangle contains another
201  /*! \note The boundaries are allowed to coincide, such that by this definition a rectangle "contains" itself. */
202  template <class U>
203  bool contains(Rectangle<U> const & r) const;
204 
205  //! Check that rectangle entirely fits inside the specified Dims
206  /*! This is the same as checking that the intersection of our rectangls with a rectangle of top-left at (0,0) and
207  the given dims is our rectangle itself. Useful to check whether a Rectangle is fully inside an Image. */
208  template <class U>
209  bool inside(Dims<U> const & dims) const;
210 
211  T top() const; //!< Get (inner) top coordinate
212  T bottomI() const; //!< Get inner bottom coordinate (=top+height-1)
213  T bottomO() const; //!< Get outer bottom coordinate (=top+height)
214  T left() const; //!< Get (inner) left coordinate
215  T rightI() const; //!< Get inner right coordinate (=left+width-1)
216  T rightO() const; //!< Get outer right coordinate (=left+width)
217 
218  Point2D<T> topLeft() const; //!< Get (outer) top left corner point
219  Point2D<T> topRight() const; //!< Get (outer) top right corner point
220  Point2D<T> bottomLeft() const; //!< Get (outer) bottom left corner point
221  Point2D<T> bottomRight() const; //!< Get (outer) bottom right corner point
222  Point2D<T> topRightI() const; //!< Get (inner) top right corner point
223  Point2D<T> bottomLeftI() const; //!< Get (inner) bottom left corner point
224  Point2D<T> bottomRightI() const; //!< Get (inner) bottom right corner point
225 
226  //! Set this rectangle as the intersection of itself and another Rectangle
227  void intersect(Rectangle<T> const & rect);
228 
229  //! Return the intersection of this Rectangle and another Rectangle
230  /*! \see intersect() */
231  Rectangle<T> intersected(Rectangle<T> const & rect) const;
232 
233  //! Set this rectangle as the union of itself and another Rectangle (note: "union" is a reserved word)
234  void unite(Rectangle<T> const & rect);
235 
236  //! Return the union of this Rectangle and another Rectangle
237  /*! \see unite() */
238  Rectangle<T> united(Rectangle<T> const & rect) const;
239 
240  //! Compute the overlap as (the area of the intersection) / (the area of the union)
241  double overlapRatio(Rectangle<T> const & rect) const;
242 
243  //! Return vector of vertices of this Rectangle (convention is clockwise from top-left)
244  std::vector<Point2D<T> > vertices() const;
245 
246  //! Clip the line so that it is contained within the Rectangle
247  /*! @todo Implement one of the many very fast line-rectangle clipping algorithms around */
248  Line<T> clip(Line<T> const & line) const;
249 
250  private:
251  //! Private constructor; use the tlbrO() pseudo-constructor if you want to call this publicly
252  Rectangle(T tt, T ll, T bbO, T rrO);
253 
254  T itsT, itsL, itsBO, itsRO;
255 
256  protected:
257  template <class Archive> void serialize(Archive& ar)
258  {
259  ar( itsT, itsL, itsBO, itsRO );
260  }
261  friend class cereal::access;
262 
263  private:
264  void make_valid();
265  };
266 
267  //! Human-readable output to a stream: outputs [TopLeft: xxx, Dims: xxx]
268  /*! \relates Rectangle */
269  template <class T>
270  std::ostream& operator<<(std::ostream &out, Rectangle<T> const & r);
271 
272  //! Return a scaled version of the source object
273  /*! \note This does \e not have the same effect as the multiplication or division operators, which scale everything,
274  while here we only scale the object size without scaling its center coordinates.
275  \relates Rectangle */
276  template <class T>
277  Rectangle<T> scale(Rectangle<T> const & src, double const factor);
278 
279  //! Return a rotated version of the source object, about its center by a given angle in radians
280  /*! \relates Rectangle */
281  //template <class T>
282  //RotatedRectangle<T> rotate(Rectangle<T> const & src, double const angle);
283 
284  //! Return a rotated version of the source object, about the given point and by a given angle in radians
285  /*! \relates Rectangle */
286  //template <class T>
287  //RotatedRectangle<T> rotateAbout(Rectangle<T> const & src, Point2D<T> const & p, double const angle);
288 
289  //! Operator overload for Rectangle<T> == Rectangle<T>
290  /*! \relates Rectangle */
291  template <class T>
292  bool operator==(Rectangle<T> const & lhs, Rectangle<T> const & rhs);
293 
294  //! Operator overload for Rectangle<T> != Rectangle<T>
295  /*! \relates Rectangle */
296  template <class T>
297  bool operator!=(Rectangle<T> const & lhs, Rectangle<T> const & rhs);
298 
299  //! Operator overload for Rectangle<T> + Point2D<T>
300  /*! \relates Rectangle */
301  template <class T>
302  Rectangle<T> operator+(Rectangle<T> const & lhs, Point2D<T> const & rhs);
303 
304  //! Operator overload for Point2D<T> + Rectangle<T>
305  /*! \relates Rectangle */
306  template <class T>
307  Rectangle<T> operator+(Point2D<T> const & lhs, Rectangle<T> const & rhs);
308 
309  //! Operator overload for Rectangle<T> - Point2D<T>
310  /*! \relates Rectangle */
311  template <class T>
312  Rectangle<T> operator-(Rectangle<T> const & lhs, nrt::Point2D<T> const & rhs);
313 
314  //! Operator overload for Point2D<T> - Rectangle<T>
315  /*! \relates Rectangle */
316  template <class T>
317  Rectangle<T> operator-(Point2D<T> const & lhs, Rectangle<T> const & rhs);
318 
319  //! Operator overload for Rectangle<T> * double
320  /*! \relates Rectangle */
321  template <class T>
322  Rectangle<T> operator*(Rectangle<T> const & lhs, double const rhs);
323 
324  //! Operator overload for double * Rectangle<T>
325  /*! \relates Rectangle */
326  template <class T>
327  Rectangle<T> operator*(double const lhs, Rectangle<T> const & rhs);
328 
329  //! Operator overload for Rectangle<T> / double
330  /*! \relates Rectangle */
331  template <class T>
332  Rectangle<T> operator/(Rectangle<T> const & lhs, double const rhs);
333 
334  //! Operator overload for Rectangle<T> *= double
335  /*! \relates Rectangle */
336  template <class T>
337  Rectangle<T> & operator*=(Rectangle<T> & lhs, double const rhs);
338 
339  //! Operator overload for Rectangle<T> /= double
340  /*! \relates Rectangle */
341  template <class T>
342  Rectangle<T> & operator/=(Rectangle<T> & lhs, double const rhs);
343 
344  //! Operator overload for Rectangle<T> += Point2D<T>
345  /*! \relates Rectangle */
346  template <class T>
347  Rectangle<T> & operator+=(Rectangle<T> & lhs, Point2D<T> const & rhs);
348 
349  //! Operator overload for Rectangle<T> -= Point2D<T>
350  /*! \relates Rectangle */
351  template <class T>
352  Rectangle<T> & operator-=(Rectangle<T> & lhs, Point2D<T> const & rhs);
353 }
354 
355 // Include inlined implementation details that are of no interest to the end user
357 
358 // Include explicit instantiations that are of no interest to the end user
360 
361 #endif // INCLUDE_NRT_CORE_GEOMETRY_RECTANGLE_H