aboutsummaryrefslogtreecommitdiff
path: root/dep/g3dlite/include/G3D/Rect2D.h
diff options
context:
space:
mode:
Diffstat (limited to 'dep/g3dlite/include/G3D/Rect2D.h')
-rw-r--r--dep/g3dlite/include/G3D/Rect2D.h139
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();
}
}
};