summaryrefslogtreecommitdiff
path: root/src/third_party/s2/s2r2rect.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/s2/s2r2rect.h')
-rw-r--r--src/third_party/s2/s2r2rect.h205
1 files changed, 205 insertions, 0 deletions
diff --git a/src/third_party/s2/s2r2rect.h b/src/third_party/s2/s2r2rect.h
new file mode 100644
index 00000000000..fab55e76da8
--- /dev/null
+++ b/src/third_party/s2/s2r2rect.h
@@ -0,0 +1,205 @@
+// Copyright 2005 Google Inc. All Rights Reserved.
+
+#ifndef UTIL_GEOMETRY_S2R2RECT_H_
+#define UTIL_GEOMETRY_S2R2RECT_H_
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "r1interval.h"
+#include "s2region.h"
+#include "util/math/vector2-inl.h"
+
+class S2CellId;
+class S2Cell;
+
+// TODO: Create an r2.h and move this definition into it.
+typedef Vector2_d R2Point;
+
+// This class is a stopgap measure that allows some of the S2 spherical
+// geometry machinery to be applied to planar geometry. An S2R2Rect
+// represents a closed axis-aligned rectangle in the (x,y) plane, but it also
+// happens to be a subtype of S2Region, which means that you can use an
+// S2RegionCoverer to approximate it as a collection of S2CellIds.
+//
+// With respect to the S2Cell decomposition, an S2R2Rect is interpreted as a
+// region of (s,t)-space on face 0. In particular, the rectangle [0,1]x[0,1]
+// corresponds to the S2CellId that covers all of face 0. This means that
+// only rectangles that are subsets of [0,1]x[0,1] can be approximated using
+// the S2RegionCoverer interface.
+//
+// The S2R2Rect class is also a convenient way to find the (s,t)-region
+// covered by a given S2CellId (see the FromCell and FromCellId methods).
+//
+// TODO: If the geometry library is extended to have better support for planar
+// geometry, then this class should no longer be necessary.
+//
+// This class is intended to be copied by value as desired. It uses
+// the default copy constructor and assignment operator, however it is
+// not a "plain old datatype" (POD) because it has virtual functions.
+class S2R2Rect : public S2Region {
+ public:
+ // Construct a rectangle from the given lower-left and upper-right points.
+ inline S2R2Rect(R2Point const& lo, R2Point const& hi);
+
+ // Construct a rectangle from the given intervals in x and y. The two
+ // intervals must either be both empty or both non-empty.
+ inline S2R2Rect(R1Interval const& x, R1Interval const& y);
+
+ // Construct a rectangle that corresponds to the boundary of the given cell
+ // is (s,t)-space. Such rectangles are always a subset of [0,1]x[0,1].
+ static S2R2Rect FromCell(S2Cell const& cell);
+ static S2R2Rect FromCellId(S2CellId const& id);
+
+ // Construct a rectangle from a center point and size in each dimension.
+ // Both components of size should be non-negative, i.e. this method cannot
+ // be used to create an empty rectangle.
+ static S2R2Rect FromCenterSize(R2Point const& center,
+ R2Point const& size);
+
+ // Convenience method to construct a rectangle containing a single point.
+ static S2R2Rect FromPoint(R2Point const& p);
+
+ // Convenience method to construct the minimal bounding rectangle containing
+ // the two given points. This is equivalent to starting with an empty
+ // rectangle and calling AddPoint() twice. Note that it is different than
+ // the S2R2Rect(lo, hi) constructor, where the first point is always
+ // used as the lower-left corner of the resulting rectangle.
+ static S2R2Rect FromPointPair(R2Point const& p1, R2Point const& p2);
+
+ // Accessor methods.
+ R1Interval const& x() const { return x_; }
+ R1Interval const& y() const { return y_; }
+ R1Interval *mutable_x() { return &x_; }
+ R1Interval *mutable_y() { return &y_; }
+ R2Point lo() const { return R2Point(x_.lo(), y_.lo()); }
+ R2Point hi() const { return R2Point(x_.hi(), y_.hi()); }
+
+ // The canonical empty rectangle. Use is_empty() to test for empty
+ // rectangles, since they have more than one representation.
+ static inline S2R2Rect Empty();
+
+ // Return true if the rectangle is valid, which essentially just means
+ // that if the bound for either axis is empty then both must be.
+ inline bool is_valid() const;
+
+ // Return true if the rectangle is empty, i.e. it contains no points at all.
+ inline bool is_empty() const;
+
+ // Return the k-th vertex of the rectangle (k = 0,1,2,3) in CCW order.
+ // Vertex 0 is in the lower-left corner.
+ R2Point GetVertex(int k) const;
+
+ // Return the center of the rectangle in (x,y)-space
+ // (in general this is not the center of the region on the sphere).
+ R2Point GetCenter() const;
+
+ // Return the width and height of this rectangle in (x,y)-space. Empty
+ // rectangles have a negative width and height.
+ R2Point GetSize() const;
+
+ // Return true if the rectangle contains the given point. Note that
+ // rectangles are closed regions, i.e. they contain their boundary.
+ bool Contains(R2Point const& p) const;
+
+ // Return true if and only if the given point is contained in the interior
+ // of the region (i.e. the region excluding its boundary).
+ bool InteriorContains(R2Point const& p) const;
+
+ // Return true if and only if the rectangle contains the given other
+ // rectangle.
+ bool Contains(S2R2Rect const& other) const;
+
+ // Return true if and only if the interior of this rectangle contains all
+ // points of the given other rectangle (including its boundary).
+ bool InteriorContains(S2R2Rect const& other) const;
+
+ // Return true if this rectangle and the given other rectangle have any
+ // points in common.
+ bool Intersects(S2R2Rect const& other) const;
+
+ // Return true if and only if the interior of this rectangle intersects
+ // any point (including the boundary) of the given other rectangle.
+ bool InteriorIntersects(S2R2Rect const& other) const;
+
+ // Increase the size of the bounding rectangle to include the given point.
+ // The rectangle is expanded by the minimum amount possible.
+ void AddPoint(R2Point const& p);
+
+ // Return a rectangle that contains all points whose x-distance from this
+ // rectangle is at most margin.x(), and whose y-distance from this rectangle
+ // is at most margin.y(). Note that any expansion of an empty interval
+ // remains empty, and both components of the given margin must be
+ // non-negative.
+ S2R2Rect Expanded(R2Point const& margin) const;
+
+ // Return the smallest rectangle containing the union of this rectangle and
+ // the given rectangle.
+ S2R2Rect Union(S2R2Rect const& other) const;
+
+ // Return the smallest rectangle containing the intersection of this
+ // rectangle and the given rectangle.
+ S2R2Rect Intersection(S2R2Rect const& other) const;
+
+ // Return true if two rectangles contains the same set of points.
+ inline bool operator==(S2R2Rect const& other) const;
+
+ // Return true if the x- and y-intervals of the two rectangles are the same
+ // up to the given tolerance (see r1interval.h for details).
+ bool ApproxEquals(S2R2Rect const& other, double max_error = 1e-15) const;
+
+ // Return the unit-length S2Point corresponding to the given point "p" in
+ // the (s,t)-plane. "p" need not be restricted to the range [0,1]x[0,1].
+ static S2Point ToS2Point(R2Point const& p);
+
+ ////////////////////////////////////////////////////////////////////////
+ // S2Region interface (see s2region.h for details):
+
+ virtual S2R2Rect* Clone() const;
+ virtual S2Cap GetCapBound() const;
+ virtual S2LatLngRect GetRectBound() const;
+ virtual bool VirtualContainsPoint(S2Point const& p) const {
+ return Contains(p); // The same as Contains() below, just virtual.
+ }
+ bool Contains(S2Point const& p) const;
+ virtual bool Contains(S2Cell const& cell) const;
+ virtual bool MayIntersect(S2Cell const& cell) const;
+ virtual void Encode(Encoder* const encoder) const {
+ S2LOG(FATAL) << "Unimplemented";
+ }
+ virtual bool Decode(Decoder* const decoder) { return false; }
+
+ private:
+ R1Interval x_;
+ R1Interval y_;
+};
+
+inline S2R2Rect::S2R2Rect(R2Point const& lo, R2Point const& hi)
+ : x_(lo.x(), hi.x()), y_(lo.y(), hi.y()) {
+ DCHECK(is_valid());
+}
+
+inline S2R2Rect::S2R2Rect(R1Interval const& x, R1Interval const& y)
+ : x_(x), y_(y) {
+ DCHECK(is_valid());
+}
+
+inline S2R2Rect S2R2Rect::Empty() {
+ return S2R2Rect(R1Interval::Empty(), R1Interval::Empty());
+}
+
+inline bool S2R2Rect::is_valid() const {
+ // The x/y ranges must either be both empty or both non-empty.
+ return x_.is_empty() == y_.is_empty();
+}
+
+inline bool S2R2Rect::is_empty() const {
+ return x_.is_empty();
+}
+
+inline bool S2R2Rect::operator==(S2R2Rect const& other) const {
+ return x_ == other.x_ && y_ == other.y_;
+}
+
+ostream& operator<<(ostream& os, S2R2Rect const& r);
+
+#endif // UTIL_GEOMETRY_S2R2RECT_H_