Gnash  0.8.11dev
Range2d.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
3 // Free Software Foundation, Inc
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 
19 //
20 // Original author: Sandro Santilli <strk@keybit.net>
21 //
22 
23 #ifndef GNASH_RANGE2D_H
24 #define GNASH_RANGE2D_H
25 
26 #include <ostream>
27 #include <limits>
28 #include <algorithm>
29 #include <cassert> // for inlines
30 #include <cmath> // for floor / ceil
31 #include <cstdint>
32 
33 namespace gnash {
34 
35 namespace geometry {
36 
38 enum RangeKind {
41 
44 
48  //
53 };
54 
55 namespace detail {
56  template <typename U> struct Promote { typedef U type; };
57  template <> struct Promote<float> { typedef double type; };
58  template <> struct Promote<int> { typedef std::int64_t type; };
59  template <> struct Promote<unsigned int> { typedef std::uint64_t type; };
60 }
61 
63 //
76 template <typename T>
77 class Range2d
78 {
79 public:
80 
82  template <typename U>
83  friend std::ostream& operator<< (std::ostream& os, const Range2d<U>& rect);
84 
86  //
91  template <typename U>
92  friend bool operator== (const Range2d<U>& r1, const Range2d<U>& r2);
93 
95  //
100  template <typename U>
101  friend bool operator!= (const Range2d<U>& r1, const Range2d<U>& r2);
102 
104  //
107  template <typename U> friend Range2d<U>
108  Intersection(const Range2d<U>& r1, const Range2d<U>& r2);
109 
111  template <typename U> friend Range2d<U>
112  Union(const Range2d<U>& r1, const Range2d<U>& r2);
113 
115  //
123  :
124  _xmin(T()),
125  _xmax(T()),
126  _ymin(T()),
127  _ymax(T())
128  {
129  switch ( kind )
130  {
131  case worldRange:
132  setWorld();
133  break;
134  case nullRange:
135  setNull();
136  break;
137  default:
138  case finiteRange:
139  break;
140  }
141  }
142 
144  //
151  Range2d(T xmin, T ymin, T xmax, T ymax)
152  :
153  _xmin(xmin),
154  _xmax(xmax),
155  _ymin(ymin),
156  _ymax(ymax)
157  {
158  // use the default ctor to make a NULL Range2d
159  assert(_xmin <= _xmax);
160  assert(_ymin <= _ymax);
161  // .. or should we raise an exception .. ?
162  }
163 
165  template <typename U>
166  Range2d(const Range2d<U>& from)
167  {
168  if ( from.isWorld() ) {
169  setWorld();
170  } else if ( from.isNull() ) {
171  setNull();
172  } else {
173  _xmin = roundMin(from.getMinX());
174  _ymin = roundMin(from.getMinY());
175  _xmax = roundMax(from.getMaxX());
176  _ymax = roundMax(from.getMaxY());
177  }
178  }
179 
181  bool isNull() const
182  {
183  return _xmax < _xmin;
184  }
185 
187  //
191  {
192  _xmin = std::numeric_limits<T>::max();
193  _xmax = std::numeric_limits<T>::min();
194  _ymin = 0;
195  _ymax = 0;
196  return *this;
197  }
198 
200  bool isWorld() const
201  {
202  return _xmax == std::numeric_limits<T>::max()
203  && _xmin == std::numeric_limits<T>::min();
204  }
205 
207  //
210  bool isFinite() const
211  {
212  return ( ! isNull() && ! isWorld() );
213  }
214 
216  //
225  {
226  _xmin = std::numeric_limits<T>::min();
227  _xmax = std::numeric_limits<T>::max();
228  _ymin = 0;
229  _ymax = 0;
230  return *this;
231  }
232 
236  //
240  template <typename U>
241  bool contains(U x, U y) const
242  {
243  if ( isNull() ) return false;
244  if ( isWorld() ) return true;
245  if (x < _xmin || x > _xmax || y < _ymin || y > _ymax)
246  {
247  return false;
248  }
249  return true;
250  }
251 
254  //
262  bool contains(const Range2d<T>& other) const
263  {
264  if ( isNull() || other.isNull() ) return false;
265  if ( isWorld() ) return true;
266  if ( other.isWorld() ) return false;
267 
268  return _xmin <= other._xmin &&
269  _xmax >= other._xmax &&
270  _ymin <= other._ymin &&
271  _ymax >= other._ymax;
272  }
273 
277  //
281  bool intersects(const Range2d<T>& other) const
282  {
283  if ( isNull() || other.isNull() ) return false;
284  if ( isWorld() || other.isWorld() ) return true;
285 
286  if ( _xmin > other._xmax ) return false;
287  if ( _xmax < other._xmin ) return false;
288  if ( _ymin > other._ymax ) return false;
289  if ( _ymax < other._ymin ) return false;
290  return true;
291  }
292 
294  //
298  {
299  // A WORLD range already enclose every point
300  if ( isWorld() ) return *this;
301 
302  if ( isNull() )
303  {
304  setTo(x,y);
305  }
306  else
307  {
308  _xmin = std::min(_xmin, x);
309  _ymin = std::min(_ymin, y);
310  _xmax = std::max(_xmax, x);
311  _ymax = std::max(_ymax, y);
312  }
313 
314  return *this;
315  }
316 
318  //
322  {
323  // A WORLD range already enclose every point
324  if ( isWorld() ) return *this;
325 
326  expandTo(x-radius, y);
327  expandTo(x+radius, y);
328 
329  expandTo(x, y-radius);
330  expandTo(x, y+radius);
331 
332  return *this;
333  }
334 
336  //
340  {
341  _xmin = _xmax = x;
342  _ymin = _ymax = y;
343  return *this;
344  }
345 
347  //
353  //
356  Range2d<T>& setTo(T xmin, T ymin, T xmax, T ymax)
357  {
358  _xmin = xmin;
359  _xmax = xmax;
360  _ymin = ymin;
361  _ymax = ymax;
362 
363  // use the default ctor to make a NULL Range2d
364  assert(_xmin <= _xmax);
365  assert(_ymin <= _ymax);
366 
367  return *this;
368  }
369 
371  //
374  T width() const
375  {
376  assert ( ! isWorld() );
377  if ( isNull() ) return 0;
378  return _xmax-_xmin;
379  }
380 
382  //
385  T height() const
386  {
387  assert ( ! isWorld() );
388  if ( isNull() ) return 0;
389  return _ymax-_ymin;
390  }
391 
393  //
401  Range2d<T>& shiftX(T offset)
402  {
403  if ( isNull() || isWorld() ) return *this;
404  _xmin += offset;
405  _xmax += offset;
406  return *this;
407  }
408 
410  //
418  Range2d<T>& shiftY(T offset)
419  {
420  if ( isNull() || isWorld() ) return *this;
421  _ymin += offset;
422  _ymax += offset;
423  return *this;
424  }
425 
427  Range2d<T>& scaleX(float factor)
428  {
429  return scale(factor, 1);
430  }
431 
433  Range2d<T>& scaleY(float factor)
434  {
435  return scale(1, factor);
436  }
437 
439  //
471  Range2d<T>& scale(float xfactor, float yfactor)
472  {
473  assert(xfactor >= 0 && yfactor >= 0);
474 
475  if ( ! isFinite() ) return *this;
476 
477  if ( xfactor == 0 || yfactor == 0 )
478  {
479  return setNull();
480  }
481 
482  if ( xfactor != 1 )
483  {
484  _xmin = scaleMin(_xmin, xfactor);
485  _xmax = scaleMax(_xmax, xfactor);
486  assert(_xmin <= _xmax); // in case of overflow...
487  }
488 
489  if ( yfactor != 1 )
490  {
491  _ymin = scaleMin(_ymin, yfactor);
492  _ymax = scaleMax(_ymax, yfactor);
493  assert(_ymin <= _ymax); // in case of overflow...
494  }
495 
496  return *this;
497  }
498 
500  Range2d<T>& scale(float factor)
501  {
502  return scale(factor, factor);
503  }
504 
506  //
520  Range2d<T>& growBy(T amount)
521  {
522  if ( isNull() || isWorld() || amount==0 ) return *this;
523 
524  // NOTE: this trigger a compiler warning when T is an
525  // unsigned type (Coverity CID 1154656 -
526  // logically dead code)
527  if ( amount < 0 ) return shrinkBy(-amount);
528 
529  T newxmin = _xmin - amount;
530  if (newxmin > _xmin ) return setWorld();
531  else _xmin = newxmin;
532 
533  T newxmax = _xmax + amount;
534  if (newxmax < _xmax ) return setWorld();
535  else _xmax = newxmax;
536 
537  T newymin = _ymin - amount;
538  if (newymin > _ymin ) return setWorld();
539  else _ymin = newymin;
540 
541  T newymax = _ymax + amount;
542  if (newymax < _ymax ) return setWorld();
543  else _ymax = newymax;
544 
545  return *this;
546 
547  }
548 
550  //
574  {
575  if ( isNull() || isWorld() || amount==0 ) return *this;
576 
577  // NOTE: this trigger a compiler warning when T is an
578  // unsigned type (Coverity CID 1154655 -
579  // logically dead code)
580  if ( amount < 0 ) return growBy(-amount);
581 
582  // Turn this range into the NULL range
583  // if any dimension collapses.
584  // Don't use width() and height() to
585  // avoid superflous checks.
586 
587  if ( _xmax - _xmin <= amount ) return setNull();
588  if ( _ymax - _ymin <= amount ) return setNull();
589 
590  _xmin += amount;
591  _ymin += amount;
592  _xmax -= amount;
593  _ymax -= amount;
594 
595  return *this;
596 
597  }
598 
600  //
603  T getMinX() const
604  {
605  assert ( isFinite() );
606  return _xmin;
607  }
608 
610  //
613  T getMaxX() const
614  {
615  assert ( isFinite() );
616  return _xmax;
617  }
618 
620  //
623  T getMinY() const
624  {
625  assert ( isFinite() );
626  return _ymin;
627  }
628 
630  //
633  T getMaxY() const
634  {
635  assert ( isFinite() );
636  return _ymax;
637  }
638 
639 
641  //
642  typename detail::Promote<T>::type
643  getArea() const {
644  assert ( !isWorld() );
645  if ( isNull() ) return 0;
646  return static_cast<typename detail::Promote<T>::type>(_xmax - _xmin)
647  * (_ymax - _ymin);
648  // this implementation is for float types, see specialization below
649  // for ints...
650  }
651 
653  //
657  void expandTo(const Range2d<T>& r)
658  {
659  if ( r.isNull() )
660  {
661  // the given range will add nothing
662  return;
663  }
664 
665  if ( isNull() )
666  {
667  // being null ourself, we'll equal the given range
668  *this = r;
669  return;
670  }
671 
672  if ( isWorld() || r.isWorld() )
673  {
674  // union with world is always world...
675  setWorld();
676  return;
677  }
678 
679  _xmin = std::min(_xmin, r._xmin);
680  _xmax = std::max(_xmax, r._xmax);
681  _ymin = std::min(_ymin, r._ymin);
682  _ymax = std::max(_ymax, r._ymax);
683 
684  }
685 
686 private:
687 
688  T _xmin, _xmax, _ymin, _ymax;
689 
690  T scaleMin(T min, float scale) const {
691  return roundMin(static_cast<float>(min) * scale);
692  }
693 
694  T scaleMax(T max, float scale) const {
695  return roundMax(static_cast<float>(max) * scale);
696  }
697 
698  T roundMin(float v) const {
699  return static_cast<T>(v);
700  }
701 
702  T roundMax(float v) const {
703  return static_cast<T>(v);
704  }
705 
706 
707 };
708 
709 template <typename T> inline std::ostream&
710 operator<< (std::ostream& os, const Range2d<T>& rect)
711 {
712  if ( rect.isNull() ) return os << "Null range";
713  if ( rect.isWorld() ) return os << "World range";
714 
715  return os << "Finite range (" << rect._xmin << "," << rect._ymin
716  << " " << rect._xmax << "," << rect._ymax << ")";
717 }
718 
719 template <typename T> inline bool
720 operator== (const Range2d<T>& r1, const Range2d<T>& r2)
721 {
722  // These checks are needed becase
723  // we don't initialize *all* memebers
724  // when setting to Null or World
725 
726  if ( r1.isNull() ) return r2.isNull();
727  if ( r2.isNull() ) return r1.isNull();
728  if ( r1.isWorld() ) return r2.isWorld();
729  if ( r2.isWorld() ) return r1.isWorld();
730 
731  return r1._xmin == r2._xmin && r1._ymin == r2._ymin &&
732  r1._xmax == r2._xmax && r1._ymax == r2._ymax;
733 }
734 
735 template <typename T> inline bool
736 operator!= (const Range2d<T>& r1, const Range2d<T>& r2)
737 {
738  return ! ( r1 == r2 );
739 }
740 
742 template <typename T> inline bool
743 Intersect(const Range2d<T>& r1, const Range2d<T>& r2)
744 {
745  return r1.intersects(r2);
746 }
747 
749 template <typename T> inline Range2d<T>
750 Union(const Range2d<T>& r1, const Range2d<T>& r2)
751 {
752  Range2d<T> ret = r1;
753  ret.expandTo(r2);
754  return ret;
755 }
756 
758 //
761 template <typename T> inline Range2d<T>
762 Intersection(const Range2d<T>& r1, const Range2d<T>& r2)
763 {
764  if ( r1.isNull() || r2.isNull() ) {
765  // NULL ranges intersect nothing
766  return Range2d<T>(nullRange);
767  }
768 
769  if ( r1.isWorld() ) {
770  // WORLD range intersect everything
771  return r2;
772  }
773 
774  if ( r2.isWorld() ) {
775  // WORLD range intersect everything
776  return r1;
777  }
778 
779  if ( ! r1.intersects(r2) ) {
780  // No intersection results in a NULL range
781  return Range2d<T>(nullRange);
782  }
783 
784  return Range2d<T> (
785  std::max(r1._xmin, r2._xmin), // xmin
786  std::max(r1._ymin, r2._ymin), // ymin
787  std::min(r1._xmax, r2._xmax), // xmax
788  std::min(r1._ymax, r2._ymax) // ymax
789  );
790 
791 }
792 
794 //
797 template<> inline int
798 Range2d<int>::roundMin(float min) const
799 {
800  return static_cast<int>(std::floor(min));
801 }
802 
804 //
807 template<> inline unsigned int
808 Range2d<unsigned int>::roundMin(float min) const
809 {
810  return static_cast<unsigned int>(std::floor(min));
811 }
812 
814 //
817 template<> inline int
818 Range2d<int>::roundMax(float max) const
819 {
820  return static_cast<int>(std::ceil(max));
821 }
822 
824 //
827 template<> inline unsigned int
828 Range2d<unsigned int>::roundMax(float max) const
829 {
830  return static_cast<unsigned int>(std::ceil(max));
831 }
832 
834 //
837 template<> inline
840 {
841  assert ( !isWorld() );
842  if ( isNull() ) return 0;
843  return static_cast<detail::Promote<int>::type>(_xmax - _xmin + 1) *
844  (_ymax - _ymin + 1);
845 }
846 
848 //
851 template<> inline
854 {
855  assert ( isFinite() );
856  return static_cast<detail::Promote<unsigned int>::type>(_xmax - _xmin + 1) *
857  (_ymax - _ymin + 1);
858 }
859 
860 
861 } // namespace gnash::geometry
862 } // namespace gnash
863 
864 #endif // GNASH_RANGE2D_H
865 
866 
867 // Local Variables:
868 // mode: C++
869 // indent-tabs-mode: t
870 // End:
Range2d< T > & shiftY(T offset)
Shift this Range2dangle vertically.
Definition: Range2d.h:418
U type
Definition: Range2d.h:56
bool operator==(const Range2d< T > &r1, const Range2d< T > &r2)
Definition: Range2d.h:720
A NULL range is a range enclosing NO points.
Definition: Range2d.h:43
bool isFinite() const
Returns true if this is a finite Range2d.
Definition: Range2d.h:210
std::uint64_t type
Definition: Range2d.h:59
bool isNull() const
Returns true if this is the NULL Range2d.
Definition: Range2d.h:181
detail::Promote< T >::type getArea() const
Get area (width*height)
Definition: Range2d.h:643
T height() const
Return height this Range2dangle.
Definition: Range2d.h:385
Range2d< T > & setNull()
Set the Range2d to the NULL value.
Definition: Range2d.h:190
A WORLD range2d is a range including all points on the plane.
Definition: Range2d.h:52
T getMinY() const
Get min Y ordinate.
Definition: Range2d.h:623
Definition: Range2d.h:56
v
Definition: test.py:11
T width() const
Return width this Range2d.
Definition: Range2d.h:374
Anonymous namespace for callbacks, local functions, event handlers etc.
Definition: dbus_ext.cpp:40
T getMaxY() const
Get max Y ordinate.
Definition: Range2d.h:633
2d Range template class
Definition: Range2d.h:77
bool contains(const Range2d< T > &other) const
Return true if this rectangle contains the given rectangle.
Definition: Range2d.h:262
Range2d< T > Union(const Range2d< T > &r1, const Range2d< T > &r2)
Return a rectangle being the union of the two rectangles.
Definition: Range2d.h:750
Definition: GnashKey.h:164
Range2d< T > & setTo(T x, T y)
Set ourself to bound the given point.
Definition: Range2d.h:339
Range2d< T > Intersection(const Range2d< T > &r1, const Range2d< T > &r2)
Return a rectangle being the intersetion of the two rectangles.
Definition: Range2d.h:762
Range2d< T > & scale(float xfactor, float yfactor)
Scale this Range2d.
Definition: Range2d.h:471
bool Intersect(const Range2d< T > &r1, const Range2d< T > &r2)
Return true of the two ranges intersect (boundaries included)
Definition: Range2d.h:743
Range2d< T > & expandToCircle(T x, T y, T radius)
Expand this Range2d to enclose the given circle.
Definition: Range2d.h:321
T getMaxX() const
Get max X ordinate.
Definition: Range2d.h:613
bool isFinite(double d)
Definition: GnashNumeric.h:47
Range2d< T > & scaleY(float factor)
Scale this Range2d vertically.
Definition: Range2d.h:433
Range2d(T xmin, T ymin, T xmax, T ymax)
Construct a finite Range2d with the given values.
Definition: Range2d.h:151
std::int64_t type
Definition: Range2d.h:58
std::int32_t x
Definition: BitmapData_as.cpp:434
RangeKind
Kinds of a range.
Definition: Range2d.h:38
Range2d< T > & expandTo(T x, T y)
Expand this Range2d to enclose the given point.
Definition: Range2d.h:297
Range2d< T > & shiftX(T offset)
Shift this Range2dangle horizontally.
Definition: Range2d.h:401
bool isWorld() const
Returns true if this is the WORLD Range2d.
Definition: Range2d.h:200
Definition: GnashKey.h:133
Range2d< T > & scaleX(float factor)
Scale this Range2d horizontally.
Definition: Range2d.h:427
Range2d(const Range2d< U > &from)
Templated copy constructor, for casting between range types.
Definition: Range2d.h:166
Definition: GnashKey.h:132
Range2d< T > & growBy(T amount)
Grow this range by the given amout in all directions.
Definition: Range2d.h:520
std::int32_t y
Definition: BitmapData_as.cpp:435
Range2d< T > & setWorld()
Set the Range2d to the WORLD value.
Definition: Range2d.h:224
Range2d< T > & setTo(T xmin, T ymin, T xmax, T ymax)
Set coordinates to given values.
Definition: Range2d.h:356
Range2d(RangeKind kind=nullRange)
Construct a Range2d of the given kind.
Definition: Range2d.h:122
Range2d< T > & shrinkBy(T amount)
Shirnk this range by the given amout in all directions.
Definition: Range2d.h:573
Valid range, using finite values.
Definition: Range2d.h:40
double type
Definition: Range2d.h:57
T getMinX() const
Get min X ordinate.
Definition: Range2d.h:603
Range2d< T > & scale(float factor)
Scale this Range2d in both directions with the same factor.
Definition: Range2d.h:500
bool contains(U x, U y) const
Return true if this rectangle contains the point with given coordinates (boundaries are inclusive)...
Definition: Range2d.h:241
void expandTo(const Range2d< T > &r)
Expand this range to include the given Range2d.
Definition: Range2d.h:657
bool operator!=(const Range2d< T > &r1, const Range2d< T > &r2)
Definition: Range2d.h:736
bool intersects(const Range2d< T > &other) const
Return true if this rectangle intersects the point with given coordinates (boundaries are inclusive)...
Definition: Range2d.h:281