diff options
Diffstat (limited to 'dep/g3dlite/include/G3D/Rect2D.h')
-rw-r--r-- | dep/g3dlite/include/G3D/Rect2D.h | 139 |
1 files changed, 97 insertions, 42 deletions
diff --git a/dep/g3dlite/include/G3D/Rect2D.h b/dep/g3dlite/include/G3D/Rect2D.h index 2fb58c50465..f72dd082ad8 100644 --- a/dep/g3dlite/include/G3D/Rect2D.h +++ b/dep/g3dlite/include/G3D/Rect2D.h @@ -1,12 +1,12 @@ /** - @file Rect2D.h + \file Rect2D.h - @maintainer Morgan McGuire, http://graphics.cs.williams.edu + \maintainer Morgan McGuire, http://graphics.cs.williams.edu - @created 2003-11-13 - @created 2009-11-16 + \created 2003-11-13 + \created 2011-06-16 - Copyright 2000-2009, Morgan McGuire. + Copyright 2000-2012, Morgan McGuire. All rights reserved. */ @@ -39,7 +39,7 @@ class Any; */ class Rect2D { private: - Vector2 min, max; + Point2 min, max; /** Returns true if the whole polygon is clipped. @@ -117,38 +117,60 @@ private: return false; } + /** Uninitialized constructor */ + Rect2D(bool b) {} public: /** \param any Must either Rect2D::xywh(#, #, #, #) or Rect2D::xyxy(#, #, #, #)*/ Rect2D(const Any& any); /** Converts the Rect2D to an Any. */ - operator Any() const; + Any toAny() const; - Rect2D() : min(0, 0), max(0, 0) {} + Rect2D(const Rect2D& r) : min(r.min), max(r.max) {} + + /** Creates the empty set rectangle. + */ + Rect2D() : min(fnan(), fnan()), max(fnan(), fnan()) {} + + static const Rect2D& empty(); + + /** Returns true if this is the empty set, which is distinct from a zero-area rectangle. */ + inline bool isEmpty() const { + return min.isNaN() && max.isNaN(); + } /** Creates a rectangle at 0,0 with the given width and height*/ Rect2D(const Vector2& wh) : min(0, 0), max(wh.x, wh.y) {} - /** Computes a rectangle that contains both @a a and @a b. - Note that even if @a or @b has zero area, its origin will be included.*/ - Rect2D(const Rect2D& a, const Rect2D& b) { - min = a.min.min(b.min); - max = a.max.max(b.max); + Vector2 extent() const { + if (isEmpty()) { + return Vector2::zero(); + } else { + return max - min; + } } /** @brief Uniformly random point on the interior */ - Vector2 randomPoint() const { - return Vector2(uniformRandom(0, max.x - min.x) + min.x, + Point2 randomPoint() const { + return Point2(uniformRandom(0, max.x - min.x) + min.x, uniformRandom(0, max.y - min.y) + min.y); } float width() const { - return max.x - min.x; + if (isEmpty()) { + return 0; + } else { + return max.x - min.x; + } } float height() const { - return max.y - min.y; + if (isEmpty()) { + return 0; + } else { + return max.y - min.y; + } } float x0() const { @@ -168,29 +190,33 @@ public: } /** Min, min corner */ - Vector2 x0y0() const { + Point2 x0y0() const { return min; } - Vector2 x1y0() const { - return Vector2(max.x, min.y); + Point2 x1y0() const { + return Point2(max.x, min.y); } - Vector2 x0y1() const { - return Vector2(min.x, max.y); + Point2 x0y1() const { + return Point2(min.x, max.y); } /** Max,max corner */ - Vector2 x1y1() const { + Point2 x1y1() const { return max; } /** Width and height */ Vector2 wh() const { - return max - min; + if (isEmpty()) { + return Vector2::zero(); + } else { + return max - min; + } } - Vector2 center() const { + Point2 center() const { return (max + min) * 0.5; } @@ -203,7 +229,7 @@ public: } Rect2D lerp(const Rect2D& other, float alpha) const { - Rect2D out; + Rect2D out(false); out.min = min.lerp(other.min, alpha); out.max = max.lerp(other.max, alpha); @@ -212,7 +238,7 @@ public: } static Rect2D xyxy(float x0, float y0, float x1, float y1) { - Rect2D r; + Rect2D r(false); r.min.x = G3D::min(x0, x1); r.min.y = G3D::min(y0, y1); @@ -222,8 +248,8 @@ public: return r; } - static Rect2D xyxy(const Vector2& v0, const Vector2& v1) { - Rect2D r; + static Rect2D xyxy(const Point2& v0, const Point2& v1) { + Rect2D r(false); r.min = v0.min(v1); r.max = v0.max(v1); @@ -235,7 +261,7 @@ public: return xyxy(x, y, x + w, y + h); } - static Rect2D xywh(const Vector2& v, const Vector2& w) { + static Rect2D xywh(const Point2& v, const Vector2& w) { return xyxy(v.x, v.y, v.x + w.x, v.y + w.y); } @@ -246,11 +272,13 @@ public: return xyxy(Vector2::inf(), Vector2::inf()); } - bool contains(const Vector2& v) const { + bool contains(const Point2& v) const { + // This will automatically return false if isEmpty() return (v.x >= min.x) && (v.y >= min.y) && (v.x <= max.x) && (v.y <= max.y); } bool contains(const Rect2D& r) const { + // This will automatically return false if isEmpty() return (min.x <= r.min.x) && (min.y <= r.min.y) && (max.x >= r.max.x) && (max.y >= r.max.y); } @@ -259,12 +287,14 @@ public: Note that two rectangles that are adjacent do not intersect because there is zero area to the overlap, even though one of them "contains" the corners of the other.*/ bool intersects(const Rect2D& r) const { + // This will automatically return false if isEmpty() return (min.x < r.max.x) && (min.y < r.max.y) && (max.x > r.min.x) && (max.y > r.min.y); } /** Like intersection, but counts the adjacent case as touching. */ bool intersectsOrTouches(const Rect2D& r) const { + // This will automatically return false if isEmpty() return (min.x <= r.max.x) && (min.y <= r.max.y) && (max.x >= r.min.x) && (max.y >= r.min.y); } @@ -273,6 +303,10 @@ public: return xyxy(min.x * s, min.y * s, max.x * s, max.y * s); } + Rect2D operator*(const Vector2& s) const { + return xyxy(min * s, max * s); + } + Rect2D operator/(float s) const { return xyxy(min / s, max / s); } @@ -297,21 +331,25 @@ public: return (min != other.min) || (max != other.max); } + void serialize(class BinaryOutput& b) const; + + void deserialize(class BinaryInput& b); + /** Returns the corners in the order: (min,min), (max,min), (max,max), (min,max). */ - Vector2 corner(int i) const { + Point2 corner(int i) const { debugAssert(i >= 0 && i < 4); switch (i & 3) { case 0: - return Vector2(min.x, min.y); + return Point2(min.x, min.y); case 1: - return Vector2(max.x, min.y); + return Point2(max.x, min.y); case 2: - return Vector2(max.x, max.y); + return Point2(max.x, max.y); case 3: - return Vector2(min.x, max.y); + return Point2(min.x, max.y); default: // Should never get here - return Vector2(0, 0); + return Point2(0, 0); } } @@ -345,6 +383,22 @@ public: return Rect2D::xywh(newX, newY, newW, newH); } + void merge(const Rect2D& other) { + if (isEmpty()) { + *this = other; + } else if (! other.isEmpty()) { + min = min.min(other.min); + max = max.max(other.max); + } + } + + /** Computes a rectangle that contains both @a a and @a b. + Note that even if @a or @b has zero area, its origin will be included.*/ + Rect2D(const Rect2D& a, const Rect2D& b) { + *this = a; + merge(b); + } + /** Clips so that the rightmost point of the outPoly is at rect.x1 (e.g. a 800x600 window produces rightmost point 799, not 800). The results are suitable for pixel rendering if iRounded. @@ -398,15 +452,16 @@ public: } /** - Returns the overlap region between the two rectangles. This may have zero area - if they do not intersect. See the two-Rect2D constructor for a way to compute - a union-like rectangle. + Returns the overlap region between the two rectangles. This may + have zero area if they do not intersect. See the two-Rect2D + constructor and merge() for a way to compute a union-like + rectangle. */ Rect2D intersect(const Rect2D& other) const { if (intersects(other)) { return Rect2D::xyxy(min.max(other.min), max.min(other.max)); - }else{ - return Rect2D::xywh(0, 0, 0, 0); + } else { + return empty(); } } }; |