summaryrefslogtreecommitdiff
path: root/src/mongo/db/geo/geoparser.cpp
diff options
context:
space:
mode:
authorSiyuan Zhou <siyuan.zhou@mongodb.com>2014-07-21 14:36:17 -0400
committerSiyuan Zhou <siyuan.zhou@mongodb.com>2014-08-12 17:04:40 -0400
commitcd5c001c43b295ad601b0004f9c31f9d454f5d04 (patch)
tree72e6279b18ebb7272eac033af74a822ba8e8dd76 /src/mongo/db/geo/geoparser.cpp
parent712768556e72d1756995c6a7b020b875fb9d6ea9 (diff)
downloadmongo-cd5c001c43b295ad601b0004f9c31f9d454f5d04.tar.gz
SERVER-14510 Custom CRS for strict winding order enforcement
Add big polygon parsing and query.
Diffstat (limited to 'src/mongo/db/geo/geoparser.cpp')
-rw-r--r--src/mongo/db/geo/geoparser.cpp77
1 files changed, 72 insertions, 5 deletions
diff --git a/src/mongo/db/geo/geoparser.cpp b/src/mongo/db/geo/geoparser.cpp
index 6efecc3ec58..658e145efb1 100644
--- a/src/mongo/db/geo/geoparser.cpp
+++ b/src/mongo/db/geo/geoparser.cpp
@@ -153,7 +153,9 @@ namespace mongo {
}
static bool parseGeoJSONPolygonCoordinates(const vector<BSONElement>& coordinates,
- const BSONObj &sourceObject, S2Polygon *out) {
+ const BSONObj &sourceObject,
+ S2Polygon *out) {
+
const vector<BSONElement>& exteriorRing = coordinates[0].Array();
vector<S2Point> exteriorVertices;
if (!parsePoints(exteriorRing, &exteriorVertices)) { return false; }
@@ -206,6 +208,38 @@ namespace mongo {
return polyBuilder.AssemblePolygon(out, NULL);
}
+ static bool parseBigSimplePolygonCoordinates(const vector<BSONElement>& coordinates,
+ const BSONObj &sourceObject,
+ BigSimplePolygon *out) {
+
+ // Only one loop is allowed in a BigSimplePolygon
+ if (coordinates.size() != 1)
+ return false;
+
+ const vector<BSONElement>& exteriorRing = coordinates[0].Array();
+
+ vector<S2Point> exteriorVertices;
+ if (!parsePoints(exteriorRing, &exteriorVertices))
+ return false;
+
+ eraseDuplicatePoints(&exteriorVertices);
+
+ // The last point is duplicated. We drop it, since S2Loop expects no
+ // duplicate points
+ exteriorVertices.resize(exteriorVertices.size() - 1);
+
+ // S2 Polygon loops must have 3 vertices
+ if (exteriorVertices.size() < 3)
+ return false;
+
+ auto_ptr<S2Loop> loop(new S2Loop(exteriorVertices));
+ if (!loop->IsValid())
+ return false;
+
+ out->Init(loop.release());
+ return true;
+ }
+
static bool parseLegacyPoint(const BSONObj &obj, Point *out) {
BSONObjIterator it(obj);
BSONElement x = it.next();
@@ -326,7 +360,7 @@ namespace mongo {
BSONElement x = it.next();
BSONElement y = it.next();
out->oldPoint.x = x.Number();
- out->oldPoint.y = y.Number();
+ out->oldPoint.y = y.Number();
out->crs = FLAT;
} else if (isGeoJSONPoint(obj)) {
const vector<BSONElement>& coords = obj.getFieldDotted(GEOJSON_COORDINATES).Array();
@@ -401,8 +435,22 @@ namespace mongo {
bool GeoParser::parsePolygon(const BSONObj &obj, PolygonWithCRS *out) {
if (isGeoJSONPolygon(obj)) {
const vector<BSONElement>& coordinates = obj.getFieldDotted(GEOJSON_COORDINATES).Array();
- if (!parseGeoJSONPolygonCoordinates(coordinates, obj, &out->polygon)) { return false; }
- out->crs = SPHERE;
+
+ if (!parseGeoJSONCRS(obj, &out->crs))
+ return false;
+
+ if (out->crs == SPHERE) {
+ out->s2Polygon.reset(new S2Polygon());
+ if (!parseGeoJSONPolygonCoordinates(coordinates, obj, out->s2Polygon.get())) {
+ return false;
+ }
+ }
+ else if (out->crs == STRICT_SPHERE) {
+ out->bigPolygon.reset(new BigSimplePolygon());
+ if (!parseBigSimplePolygonCoordinates(coordinates, obj, out->bigPolygon.get())) {
+ return false;
+ }
+ }
} else {
BSONObjIterator typeIt(obj);
BSONElement type = typeIt.next();
@@ -580,7 +628,26 @@ namespace mongo {
// see http://portal.opengeospatial.org/files/?artifact_id=24045
// and http://spatialreference.org/ref/epsg/4326/
// and http://www.geojson.org/geojson-spec.html#named-crs
- return ("urn:ogc:def:crs:OGC:1.3:CRS84" == name) || ("EPSG:4326" == name);
+ return ("urn:ogc:def:crs:OGC:1.3:CRS84" == name) || ("EPSG:4326" == name) ||
+ ("urn:mongodb:strictwindingcrs:EPSG:4326" == name);
+ }
+
+ bool GeoParser::parseGeoJSONCRS(const BSONObj& obj, CRS* crs) {
+
+ dassert(crsIsOK(obj));
+
+ *crs = SPHERE;
+
+ if (!obj["crs"].eoo()) {
+ const string name = obj["crs"].Obj()["properties"].Obj()["name"].String();
+
+ if (name == "urn:mongodb:strictwindingcrs:EPSG:4326")
+ *crs = STRICT_SPHERE;
+ else
+ *crs = SPHERE;
+ }
+
+ return true;
}
bool GeoParser::isCap(const BSONObj &obj) {