iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RectangleImpl.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 // ######################################################################
37 template <class T> inline
39 {
40  if (itsBO < itsT) std::swap(itsT, itsBO);
41  if (itsRO < itsL) std::swap(itsL, itsRO);
42 }
43 
44 // ######################################################################
45 template <class T> inline
47  itsT(0), itsL(0), itsBO(0), itsRO(0)
48 { }
49 
50 // ######################################################################
51 template <class T> template <class U> inline
53  itsT(nrt::clamped_convert<T,U>(rect.top())),
54  itsL(nrt::clamped_convert<T,U>(rect.left())),
55  itsBO(nrt::clamped_convert<T,U>(rect.bottomO())),
56  itsRO(nrt::clamped_convert<T,U>(rect.rightO()))
57 {
58  this->make_valid();
59 }
60 
61 // ######################################################################
62 template <class T> inline
64  itsT(tl.y()), itsL(tl.x()), itsBO(tl.y() + dims.height()), itsRO(tl.x() + dims.width())
65 { }
66 
67 // ######################################################################
68 template <class T> inline
70  itsT(tl.y()), itsL(tl.x()), itsBO(br.y()), itsRO(br.x())
71 {
72  this->make_valid();
73 }
74 
75 // ######################################################################
76 template <class T> inline
78 {
79  return nrt::Rectangle<T>(nrt::Point2D<T>(center.x()-dims.width()/T(2), center.y()-dims.height()/T(2)), dims);
80 }
81 
82 // ######################################################################
83 template <class T> inline
84 nrt::Rectangle<T>::Rectangle(T tt, T ll, T bbO, T rrO)
85 {
86  if (bbO - tt < 0) { itsT = bbO; itsBO = tt; } else { itsT = tt; itsBO = bbO; }
87  if (rrO - ll < 0) { itsL = rrO; itsRO = ll; } else { itsL = ll; itsRO = rrO; }
88 }
89 
90 // ######################################################################
91 template <class T> inline
93 {
94  if (points.empty()) return nrt::Rectangle<T>();
95 
96  T top = points[0].y();
97  T bottom = points[0].y();
98  T left = points[0].x();
99  T right = points[0].x();
100  for (nrt::Point2D<T> const & p : points)
101  {
102  top = std::min(top, p.y());
103  bottom = std::max(bottom, p.y());
104  left = std::min(left, p.x());
105  right = std::max(right, p.x());
106  }
107  return nrt::Rectangle<T>::tlbrO(top, left, bottom, right);
108 }
109 
110 // ######################################################################
111 template <class T> inline
113 { return nrt::Rectangle<T>(tt, ll, bb+1, rr+1); }
114 
115 // ######################################################################
116 template <class T> inline
118 {
119  return nrt::Rectangle<T>(tt, ll, bb, rr);
120 }
121 
122 // ######################################################################
123 template <class T> inline
125 {
126  return nrt::Dims<T>(itsRO - itsL, itsBO - itsT);
127 }
128 
129 // ######################################################################
130 template <class T> inline
132 {
133  return itsRO - itsL;
134 }
135 
136 // ######################################################################
137 template <class T> inline
139 {
140  return itsBO - itsT;
141 }
142 
143 // ######################################################################
144 template <class T> inline
146 {
147  return width() * height();
148 }
149 
150 // ######################################################################
151 template <class T> inline
153 {
154  return float(width()) / float(height());
155 }
156 
157 // ######################################################################
158 template <class T> inline
160 {
161  return nrt::Point2D<T>(itsL+(itsRO-itsL)/T(2), itsT+(itsBO-itsT)/T(2));
162 }
163 
164 // ######################################################################
165 template <class T> template <class U> inline
167 {
168  return(p.x() >= itsL && p.x() < itsRO && p.y() >= itsT && p.y() < itsBO);
169 }
170 
171 // ######################################################################
172 template <class T> template <class U> inline
173 bool nrt::Rectangle<T>::inside(Dims<U> const & dims) const
174 {
175  return (itsL >= 0 && itsT >= 0 && itsRO <= dims.width() && itsBO <= dims.height());
176 }
177 
178 // ######################################################################
179 template <class T> template <class PointClass> inline
180 void nrt::Rectangle<T>::getGridOfPoints(T const margin, T const nx, T const ny, std::vector<PointClass> & points) const
181 {
182  typedef typename nrt::promote<T, float>::type TF;
183  TF minx, maxx, miny, maxy;
184 
185  if (width() < margin * 2.0F) { minx = center().x(); maxx = minx - 1.0F; }
186  else { minx = left() + margin; maxx = rightO() - margin; }
187 
188  if (height() < margin * 2.0F) { miny = center().y(); maxy = miny - 1.0F; }
189  else { miny = top() + margin; maxy = bottomO() - margin; }
190 
191  TF const stepx = (maxx - minx) / (nx - 1.0F), stepy = (maxy - miny) / (ny - 1.0F);
192  maxx += stepx * 0.1F; maxy += stepy * 0.1F; // avoid possible rounding issues
193 
194  for (TF x = minx; x <= maxx; x += stepx)
195  for (TF y = miny; y <= maxy; y += stepy)
196  points.push_back(PointClass(x, y));
197 }
198 
199 // ######################################################################
200 template <class T> template <class U> inline
202 {
203  return(r.left() >= itsL && r.top() >= itsT && r.rightO() <= itsRO && r.bottomO() <= itsBO);
204 }
205 
206 // ######################################################################
207 template <class T> inline
209 { return itsT; }
210 
211 // ######################################################################
212 template <class T> inline
214 { return itsBO-1; }
215 
216 // ######################################################################
217 template <class T> inline
219 { return itsBO; }
220 
221 // ######################################################################
222 template <class T> inline
224 { return itsL; }
225 
226 // ######################################################################
227 template <class T> inline
229 { return itsRO-1; }
230 
231 // ######################################################################
232 template <class T> inline
234 { return itsRO; }
235 
236 // ######################################################################
237 template <class T> inline
239 { return nrt::Point2D<T>(itsL, itsT); }
240 
241 // ######################################################################
242 template <class T> inline
244 { return nrt::Point2D<T>(itsRO, itsT); }
245 
246 // ######################################################################
247 template <class T> inline
249 { return nrt::Point2D<T>(itsL, itsBO); }
250 
251 // ######################################################################
252 template <class T> inline
254 { return nrt::Point2D<T>(itsRO, itsBO); }
255 
256 // ######################################################################
257 template <class T> inline
259 { return nrt::Point2D<T>(itsRO-1, itsT); }
260 
261 // ######################################################################
262 template <class T> inline
264 { return nrt::Point2D<T>(itsL, itsBO-1); }
265 
266 // ######################################################################
267 template <class T> inline
269 { return nrt::Point2D<T>(itsRO-1, itsBO-1); }
270 
271 // ######################################################################
272 template <class T> inline
274 {
275  const int l = std::max(itsL, rect.itsL);
276  const int r = std::min(itsRO, rect.itsRO);
277  const int t = std::max(itsT, rect.itsT);
278  const int b = std::min(itsBO, rect.itsBO);
279 
280  if (l >= r || t >= b) { *this = nrt::Rectangle<T>(); return; }
281 
282  *this = nrt::Rectangle<T>::tlbrO(t, l, b, r);
283 }
284 
285 // ######################################################################
286 template <class T> inline
288 {
289  nrt::Rectangle<T> r(*this);
290  r.intersect(rect);
291  return r;
292 }
293 
294 // ######################################################################
295 template <class T> inline
297 {
298  itsL = std::min(itsL, rect.itsL);
299  itsRO = std::max(itsRO, rect.itsRO);
300  itsT = std::min(itsT, rect.itsT);
301  itsBO = std::max(itsBO, rect.itsBO);
302 }
303 
304 // ######################################################################
305 template <class T> inline
307 {
308  nrt::Rectangle<T> r(*this);
309  r.unite(rect);
310  return r;
311 }
312 
313 // ######################################################################
314 template <class T> inline
316 {
317  nrt::Rectangle<T> ovR = this->intersected(rect);
318 
319  double ov = 0;
320  if (ovR.area())
321  {
322  // compute overlap as area of intersection / area of union
323  double ua = ((area()+1) + (rect.area()+1)) - ovR.area();
324  ov = double(ovR.area()) / ua;
325  }
326  return ov;
327 }
328 
329 // ######################################################################
330 template <class T> inline
331 std::vector<nrt::Point2D<T> > nrt::Rectangle<T>::vertices() const
332 {
333  return std::vector<nrt::Point2D<T> > { topLeft(), topRight(), bottomRight(), bottomLeft() };
334 }
335 
336 // ######################################################################
337 template <class T>
339 {
340  typedef typename nrt::promote<T, float>::type TF;
341 
342  // If the line lies within the rectangle then just return it
343  if (this->contains(line.p1()) && this->contains(line.p2())) return line;
344 
345  std::vector<std::shared_ptr<nrt::Point2D<TF> > > intersections {
346  nrt::Line<T>(topLeft(), topRightI()).template intersect<float>(line),
347  nrt::Line<T>(topRightI(), bottomRightI()).template intersect<float>(line),
348  nrt::Line<T>(bottomRightI(), bottomLeftI()).template intersect<float>(line),
349  nrt::Line<T>(bottomLeftI(), topLeft()).template intersect<float>(line)
350  };
351 
352  std::vector<nrt::Point2D<TF> > points;
353  for (std::shared_ptr<nrt::Point2D<TF> > intersect : intersections)
354  if (intersect && !std::count(points.begin(), points.end(), *intersect))
355  points.push_back(*intersect);
356 
357  if (points.size() == 2)
358  return nrt::Line<T>(nrt::Point2D<T>(points[0]), nrt::Point2D<T>(points[1]));
359  else if (points.size() == 1)
360  {
361  if (this->contains(line.p1())) return nrt::Line<T>(line.p1(), nrt::Point2D<T>(points[0]));
362  if (this->contains(line.p2())) return nrt::Line<T>(nrt::Point2D<T>(points[0]), line.p2());
363  }
364  return nrt::Line<T>();
365 }
366 
367 // ######################################################################
368 // Free function implementations
369 // ######################################################################
370 template <class T> inline
371 std::ostream & nrt::operator<<(std::ostream & out, nrt::Rectangle<T> const & r)
372 { return out << "[TopLeft: " << r.topLeft() << ", Dims: " << r.dims() << "]";}
373 
374 // ######################################################################
375 template <class T> inline
376 nrt::Rectangle<T> nrt::scale(nrt::Rectangle<T> const & src, double const factor)
377 { return nrt::Rectangle<T>::centerDims(src.center(), src.dims() * factor); }
378 
379 // ######################################################################
380 //template <class T> inline
381 //nrt::RotatedRectangle<T> nrt::rotate(nrt::Rectangle<T> const & src, double const angle)
382 //{ return nrt::RotatedRectangle<T>(src.center(), src.dims(), angle); }
383 
384 // ######################################################################
385 //template <class T> inline
386 //nrt::Rectangle<T> nrt::rotateAbout(nrt::Rectangle<T> const & src, nrt::Point2D<T> const & point, double const angle)
387 //{ return nrt::RotatedRectangle<T>(nrt::rotateAbout(src.center(), point, angle), src.dims(), angle); }
388 
389 // ######################################################################
390 template <class T> inline
391 bool nrt::operator==(nrt::Rectangle<T> const & lhs, nrt::Rectangle<T> const & rhs)
392 {
393  return (lhs.top() == rhs.top() && lhs.left() == rhs.left() &&
394  lhs.bottomO() == rhs.bottomO() && lhs.rightO() == rhs.rightO());
395 }
396 
397 // ######################################################################
398 template <class T> inline
399 bool nrt::operator!=(nrt::Rectangle<T> const & lhs, nrt::Rectangle<T> const & rhs)
400 { return ! (lhs == rhs); }
401 
402 // ######################################################################
403 template <class T> inline
405 { return nrt::Rectangle<T>(lhs.topLeft() + rhs, lhs.dims()); }
406 
407 // ######################################################################
408 template <class T> inline
410 { return nrt::Rectangle<T>(lhs + rhs.topLeft(), rhs.dims()); }
411 
412 // ######################################################################
413 template <class T> inline
415 { return nrt::Rectangle<T>(lhs.topLeft() - rhs, lhs.dims()); }
416 
417 // ######################################################################
418 template <class T> inline
420 { return nrt::Rectangle<T>(lhs - rhs.topLeft(), rhs.dims()); }
421 
422 // ######################################################################
423 template <class T> inline
424 nrt::Rectangle<T> nrt::operator*(nrt::Rectangle<T> const & lhs, double const rhs)
425 { return nrt::Rectangle<T>(lhs.topLeft() * rhs, lhs.bottomRight() * rhs); }
426 
427 // ######################################################################
428 template <class T> inline
429 nrt::Rectangle<T> nrt::operator*(double const lhs, nrt::Rectangle<T> const & rhs)
430 { return nrt::Rectangle<T>(lhs * rhs.topLeft(), lhs * rhs.bottomRight()); }
431 
432 // ######################################################################
433 template <class T> inline
434 nrt::Rectangle<T> nrt::operator/(nrt::Rectangle<T> const & lhs, double const rhs)
435 { return nrt::Rectangle<T>(lhs.topLeft() / rhs, lhs.bottomRight() / rhs); }
436 
437 // ######################################################################
438 template <class T> inline
439 nrt::Rectangle<T> & nrt::operator*=(nrt::Rectangle<T> & lhs, double const rhs)
440 { lhs = lhs * rhs; return lhs; }
441 
442 // ######################################################################
443 template <class T> inline
444 nrt::Rectangle<T> & nrt::operator/=(nrt::Rectangle<T> & lhs, double const rhs)
445 { lhs = lhs / rhs; return lhs; }
446 
447 // ######################################################################
448 template <class T> inline
450 { lhs = lhs + rhs; return lhs; }
451 
452 // ######################################################################
453 template <class T> inline
455 { lhs = lhs - rhs; return lhs; }
456