summaryrefslogtreecommitdiff
path: root/src/mongo/db/geo/big_polygon.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/geo/big_polygon.cpp')
-rw-r--r--src/mongo/db/geo/big_polygon.cpp298
1 files changed, 146 insertions, 152 deletions
diff --git a/src/mongo/db/geo/big_polygon.cpp b/src/mongo/db/geo/big_polygon.cpp
index fb496bfa96e..f50bdf1ae37 100644
--- a/src/mongo/db/geo/big_polygon.cpp
+++ b/src/mongo/db/geo/big_polygon.cpp
@@ -35,197 +35,191 @@
namespace mongo {
- using std::unique_ptr;
- using std::vector;
+using std::unique_ptr;
+using std::vector;
- BigSimplePolygon::BigSimplePolygon() {
- }
-
- // Caller should ensure loop is valid.
- BigSimplePolygon::BigSimplePolygon(S2Loop* loop) :
- _loop(loop), _isNormalized(loop->IsNormalized()) {
- }
+BigSimplePolygon::BigSimplePolygon() {}
- BigSimplePolygon::~BigSimplePolygon() {
- }
+// Caller should ensure loop is valid.
+BigSimplePolygon::BigSimplePolygon(S2Loop* loop)
+ : _loop(loop), _isNormalized(loop->IsNormalized()) {}
- void BigSimplePolygon::Init(S2Loop* loop) {
- _loop.reset(loop);
- _isNormalized = loop->IsNormalized();
- _borderLine.reset();
- _borderPoly.reset();
- }
+BigSimplePolygon::~BigSimplePolygon() {}
- double BigSimplePolygon::GetArea() const {
- return _loop->GetArea();
- }
+void BigSimplePolygon::Init(S2Loop* loop) {
+ _loop.reset(loop);
+ _isNormalized = loop->IsNormalized();
+ _borderLine.reset();
+ _borderPoly.reset();
+}
- bool BigSimplePolygon::Contains(const S2Polygon& polygon) const {
- const S2Polygon& polyBorder = GetPolygonBorder();
+double BigSimplePolygon::GetArea() const {
+ return _loop->GetArea();
+}
- if (_isNormalized) {
- // Polygon border is the same as the loop
- return polyBorder.Contains(&polygon);
- }
+bool BigSimplePolygon::Contains(const S2Polygon& polygon) const {
+ const S2Polygon& polyBorder = GetPolygonBorder();
- // Polygon border is the complement of the loop
- //
- // Return true iff big polygon's complement (polyBorder) doesn't intersect with polygon.
- // We don't guarantee whether the points on border are contained or not.
- return !polyBorder.Intersects(&polygon);
+ if (_isNormalized) {
+ // Polygon border is the same as the loop
+ return polyBorder.Contains(&polygon);
}
- bool BigSimplePolygon::Contains(const S2Polyline& line) const {
- //
- // A line is contained within a loop if the result of subtracting the loop from the line is
- // nothing.
- //
- // Also, a line is contained within a loop if the result of clipping the line to the
- // complement of the loop is nothing.
- //
- // If we can't subtract the loop itself using S2, we clip (intersect) to the inverse. Every
- // point in S2 is contained in exactly one of these loops.
- //
- // TODO: Polygon borders are actually kind of weird, and this is somewhat inconsistent with
- // Intersects(). A point might Intersect() a boundary exactly, but not be Contain()ed
- // within the Polygon. Think the right thing to do here is custom intersection functions.
- //
- const S2Polygon& polyBorder = GetPolygonBorder();
+ // Polygon border is the complement of the loop
+ //
+ // Return true iff big polygon's complement (polyBorder) doesn't intersect with polygon.
+ // We don't guarantee whether the points on border are contained or not.
+ return !polyBorder.Intersects(&polygon);
+}
- OwnedPointerVector<S2Polyline> clippedOwned;
- vector<S2Polyline*>& clipped = clippedOwned.mutableVector();
-
- if (_isNormalized) {
- // Polygon border is the same as the loop
- polyBorder.SubtractFromPolyline(&line, &clipped);
- return clipped.size() == 0;
- }
- else {
- // Polygon border is the complement of the loop
- polyBorder.IntersectWithPolyline(&line, &clipped);
- return clipped.size() == 0;
- }
+bool BigSimplePolygon::Contains(const S2Polyline& line) const {
+ //
+ // A line is contained within a loop if the result of subtracting the loop from the line is
+ // nothing.
+ //
+ // Also, a line is contained within a loop if the result of clipping the line to the
+ // complement of the loop is nothing.
+ //
+ // If we can't subtract the loop itself using S2, we clip (intersect) to the inverse. Every
+ // point in S2 is contained in exactly one of these loops.
+ //
+ // TODO: Polygon borders are actually kind of weird, and this is somewhat inconsistent with
+ // Intersects(). A point might Intersect() a boundary exactly, but not be Contain()ed
+ // within the Polygon. Think the right thing to do here is custom intersection functions.
+ //
+ const S2Polygon& polyBorder = GetPolygonBorder();
+
+ OwnedPointerVector<S2Polyline> clippedOwned;
+ vector<S2Polyline*>& clipped = clippedOwned.mutableVector();
+
+ if (_isNormalized) {
+ // Polygon border is the same as the loop
+ polyBorder.SubtractFromPolyline(&line, &clipped);
+ return clipped.size() == 0;
+ } else {
+ // Polygon border is the complement of the loop
+ polyBorder.IntersectWithPolyline(&line, &clipped);
+ return clipped.size() == 0;
}
+}
- bool BigSimplePolygon::Contains(S2Point const& point) const {
- return _loop->Contains(point);
- }
+bool BigSimplePolygon::Contains(S2Point const& point) const {
+ return _loop->Contains(point);
+}
- bool BigSimplePolygon::Intersects(const S2Polygon& polygon) const {
- // If the loop area is at most 2*Pi, treat it as a simple Polygon.
- if (_isNormalized) {
- const S2Polygon& polyBorder = GetPolygonBorder();
- return polyBorder.Intersects(&polygon);
- }
-
- // The loop area is greater than 2*Pi, so it intersects a polygon (even with holes) if it
- // intersects any of the top-level polygon loops, since any valid polygon is less than
- // a hemisphere.
- //
- // Intersecting a polygon hole requires that the loop must have intersected the containing
- // loop - topology ftw.
- //
- // Another approach is to check polyBorder doesn't contain polygon, but the following
- // approach is cheaper.
-
- // Iterate over all the top-level polygon loops
- for (int i = 0; i < polygon.num_loops(); i = polygon.GetLastDescendant(i) + 1) {
- const S2Loop* polyLoop = polygon.loop(i);
- if (_loop->Intersects(polyLoop))
- return true;
- }
-
- return false;
+bool BigSimplePolygon::Intersects(const S2Polygon& polygon) const {
+ // If the loop area is at most 2*Pi, treat it as a simple Polygon.
+ if (_isNormalized) {
+ const S2Polygon& polyBorder = GetPolygonBorder();
+ return polyBorder.Intersects(&polygon);
}
- bool BigSimplePolygon::Intersects(const S2Polyline& line) const {
- //
- // A loop intersects a line if line intersects the loop border or, if it doesn't, either
- // line is contained in the loop, or line is disjoint with the loop. So checking any
- // vertex of the line is sufficient.
- //
- // TODO: Make a general Polygon/Line relation tester which uses S2 primitives
- //
- return GetLineBorder().Intersects(&line) || _loop->Contains(line.vertex(0));
- }
+ // The loop area is greater than 2*Pi, so it intersects a polygon (even with holes) if it
+ // intersects any of the top-level polygon loops, since any valid polygon is less than
+ // a hemisphere.
+ //
+ // Intersecting a polygon hole requires that the loop must have intersected the containing
+ // loop - topology ftw.
+ //
+ // Another approach is to check polyBorder doesn't contain polygon, but the following
+ // approach is cheaper.
- bool BigSimplePolygon::Intersects(S2Point const& point) const {
- return Contains(point);
+ // Iterate over all the top-level polygon loops
+ for (int i = 0; i < polygon.num_loops(); i = polygon.GetLastDescendant(i) + 1) {
+ const S2Loop* polyLoop = polygon.loop(i);
+ if (_loop->Intersects(polyLoop))
+ return true;
}
- void BigSimplePolygon::Invert() {
- _loop->Invert();
- _isNormalized = _loop->IsNormalized();
- }
+ return false;
+}
- const S2Polygon& BigSimplePolygon::GetPolygonBorder() const {
- if (_borderPoly)
- return *_borderPoly;
+bool BigSimplePolygon::Intersects(const S2Polyline& line) const {
+ //
+ // A loop intersects a line if line intersects the loop border or, if it doesn't, either
+ // line is contained in the loop, or line is disjoint with the loop. So checking any
+ // vertex of the line is sufficient.
+ //
+ // TODO: Make a general Polygon/Line relation tester which uses S2 primitives
+ //
+ return GetLineBorder().Intersects(&line) || _loop->Contains(line.vertex(0));
+}
- unique_ptr<S2Loop> cloned(_loop->Clone());
+bool BigSimplePolygon::Intersects(S2Point const& point) const {
+ return Contains(point);
+}
- // Any loop in polygon should be than a hemisphere (2*Pi).
- cloned->Normalize();
+void BigSimplePolygon::Invert() {
+ _loop->Invert();
+ _isNormalized = _loop->IsNormalized();
+}
- OwnedPointerVector<S2Loop> loops;
- loops.mutableVector().push_back(cloned.release());
- _borderPoly.reset(new S2Polygon(&loops.mutableVector()));
+const S2Polygon& BigSimplePolygon::GetPolygonBorder() const {
+ if (_borderPoly)
return *_borderPoly;
- }
- const S2Polyline& BigSimplePolygon::GetLineBorder() const {
- if (_borderLine)
- return *_borderLine;
+ unique_ptr<S2Loop> cloned(_loop->Clone());
- vector<S2Point> points;
- int numVertices = _loop->num_vertices();
- for (int i = 0; i <= numVertices; ++i) {
- // vertex() maps "numVertices" to 0 internally, so we don't have to deal with
- // the index out of range.
- points.push_back(_loop->vertex(i));
- }
+ // Any loop in polygon should be than a hemisphere (2*Pi).
+ cloned->Normalize();
- _borderLine.reset(new S2Polyline(points));
+ OwnedPointerVector<S2Loop> loops;
+ loops.mutableVector().push_back(cloned.release());
+ _borderPoly.reset(new S2Polygon(&loops.mutableVector()));
+ return *_borderPoly;
+}
+const S2Polyline& BigSimplePolygon::GetLineBorder() const {
+ if (_borderLine)
return *_borderLine;
- }
- BigSimplePolygon* BigSimplePolygon::Clone() const {
- return new BigSimplePolygon(_loop->Clone());
+ vector<S2Point> points;
+ int numVertices = _loop->num_vertices();
+ for (int i = 0; i <= numVertices; ++i) {
+ // vertex() maps "numVertices" to 0 internally, so we don't have to deal with
+ // the index out of range.
+ points.push_back(_loop->vertex(i));
}
- S2Cap BigSimplePolygon::GetCapBound() const {
- return _loop->GetCapBound();
- }
+ _borderLine.reset(new S2Polyline(points));
- S2LatLngRect BigSimplePolygon::GetRectBound() const {
- return _loop->GetRectBound();
- }
+ return *_borderLine;
+}
- bool BigSimplePolygon::Contains(const S2Cell& cell) const {
- return _loop->Contains(cell);
- }
+BigSimplePolygon* BigSimplePolygon::Clone() const {
+ return new BigSimplePolygon(_loop->Clone());
+}
- bool BigSimplePolygon::MayIntersect(const S2Cell& cell) const {
- return _loop->MayIntersect(cell);
- }
+S2Cap BigSimplePolygon::GetCapBound() const {
+ return _loop->GetCapBound();
+}
- bool BigSimplePolygon::VirtualContainsPoint(const S2Point& p) const {
- return _loop->VirtualContainsPoint(p);
- }
+S2LatLngRect BigSimplePolygon::GetRectBound() const {
+ return _loop->GetRectBound();
+}
- void BigSimplePolygon::Encode(Encoder* const encoder) const {
- invariant(false);
- }
+bool BigSimplePolygon::Contains(const S2Cell& cell) const {
+ return _loop->Contains(cell);
+}
- bool BigSimplePolygon::Decode(Decoder* const decoder) {
- invariant(false);
- }
+bool BigSimplePolygon::MayIntersect(const S2Cell& cell) const {
+ return _loop->MayIntersect(cell);
+}
- bool BigSimplePolygon::DecodeWithinScope(Decoder* const decoder) {
- invariant(false);
- }
+bool BigSimplePolygon::VirtualContainsPoint(const S2Point& p) const {
+ return _loop->VirtualContainsPoint(p);
+}
+
+void BigSimplePolygon::Encode(Encoder* const encoder) const {
+ invariant(false);
+}
+bool BigSimplePolygon::Decode(Decoder* const decoder) {
+ invariant(false);
}
+bool BigSimplePolygon::DecodeWithinScope(Decoder* const decoder) {
+ invariant(false);
+}
+}