From bd489b1c2c76a7ee84105db758839c4d47ffcbcb Mon Sep 17 00:00:00 2001 From: Siyuan Zhou Date: Tue, 10 Mar 2015 16:12:08 -0400 Subject: SERVER-9220 allow more than two values in the coordinate-array when using 2dsphere index --- src/mongo/db/geo/geoparser.cpp | 20 +++++++++---------- src/mongo/db/geo/geoparser_test.cpp | 39 ++++++++++++++++++++++++------------- 2 files changed, 36 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/mongo/db/geo/geoparser.cpp b/src/mongo/db/geo/geoparser.cpp index 8b8c3aebb63..5fd1c86a741 100644 --- a/src/mongo/db/geo/geoparser.cpp +++ b/src/mongo/db/geo/geoparser.cpp @@ -108,11 +108,11 @@ namespace mongo { return Status::OK(); } - static Status parseGeoJSONCoodinate(const BSONElement& elem, S2Point* out) { + static Status parseGeoJSONCoordinate(const BSONElement& elem, S2Point* out) { if (Array != elem.type()) { return BAD_VALUE("GeoJSON coordinates must be an array"); } Point p; - // Check the object has and only has 2 numbers. - Status status = parseFlatPoint(elem, &p); + // GeoJSON allows extra elements, e.g. altitude. + Status status = parseFlatPoint(elem, &p, true); if (!status.isOK()) return status; status = coordToPoint(p.x, p.y, out); @@ -120,13 +120,13 @@ namespace mongo { } // "coordinates": [ [100.0, 0.0], [101.0, 1.0] ] - static Status parseArrayOfCoodinates(const BSONElement& elem, vector* out) { + static Status parseArrayOfCoordinates(const BSONElement& elem, vector* out) { if (Array != elem.type()) { return BAD_VALUE("GeoJSON coordinates must be an array of coordinates"); } BSONObjIterator it(elem.Obj()); // Iterate all coordinates in array while (it.more()) { S2Point p; - Status status = parseGeoJSONCoodinate(it.next(), &p); + Status status = parseGeoJSONCoordinate(it.next(), &p); if (!status.isOK()) return status; out->push_back(p); } @@ -168,7 +168,7 @@ namespace mongo { // Parse the array of vertices of a loop. BSONElement coordinateElt = it.next(); vector points; - status = parseArrayOfCoodinates(coordinateElt, &points); + status = parseArrayOfCoordinates(coordinateElt, &points); if (!status.isOK()) return status; // Check if the loop is closed. @@ -269,7 +269,7 @@ namespace mongo { Status status = Status::OK(); string err; - status = parseArrayOfCoodinates(coordinates.front(), &exteriorVertices); + status = parseArrayOfCoordinates(coordinates.front(), &exteriorVertices); if (!status.isOK()) return status; status = isLoopClosed(exteriorVertices, coordinates.front()); @@ -346,7 +346,7 @@ namespace mongo { // Or a line in "coordinates" field of GeoJSON MultiLineString static Status parseGeoJSONLineCoordinates(const BSONElement& elem, S2Polyline* out) { vector vertices; - Status status = parseArrayOfCoodinates(elem, &vertices); + Status status = parseArrayOfCoordinates(elem, &vertices); if (!status.isOK()) return status; eraseDuplicatePoints(&vertices); @@ -425,7 +425,7 @@ namespace mongo { if (!status.isOK()) return status; // "coordinates" - status = parseFlatPoint(obj[GEOJSON_COORDINATES], &out->oldPoint); + status = parseFlatPoint(obj[GEOJSON_COORDINATES], &out->oldPoint, true); if (!status.isOK()) return status; // Projection @@ -478,7 +478,7 @@ namespace mongo { out->points.clear(); BSONElement coordElt = obj.getFieldDotted(GEOJSON_COORDINATES); - status = parseArrayOfCoodinates(coordElt, &out->points); + status = parseArrayOfCoordinates(coordElt, &out->points); if (!status.isOK()) return status; if (0 == out->points.size()) diff --git a/src/mongo/db/geo/geoparser_test.cpp b/src/mongo/db/geo/geoparser_test.cpp index fd863447563..2387696b7be 100644 --- a/src/mongo/db/geo/geoparser_test.cpp +++ b/src/mongo/db/geo/geoparser_test.cpp @@ -73,7 +73,7 @@ namespace { fromjson("{'type':'Point', 'coordhats': [40, -5]}"), &point)); ASSERT_NOT_OK(GeoParser::parseGeoJSONPoint( fromjson("{'type':'Point', 'coordinates': 40}"), &point)); - ASSERT_NOT_OK(GeoParser::parseGeoJSONPoint( + ASSERT_OK(GeoParser::parseGeoJSONPoint( fromjson("{'type':'Point', 'coordinates': [40, -5, 7]}"), &point)); // Make sure lat is in range @@ -105,7 +105,8 @@ namespace { ASSERT_OK(GeoParser::parseGeoJSONLine( fromjson("{'type':'LineString', 'coordinates':[[180,-90], [-180,90]]}"), &polyline)); ASSERT_NOT_OK(GeoParser::parseGeoJSONLine( - fromjson("{'type':'LineString', 'coordinates':[[180.1,-90], [-180.1,90]]}"), &polyline)); + fromjson("{'type':'LineString', 'coordinates':[[180.1,-90], [-180.1,90]]}"), + &polyline)); ASSERT_NOT_OK(GeoParser::parseGeoJSONLine( fromjson("{'type':'LineString', 'coordinates':[[0,-91], [0,90]]}"), &polyline)); ASSERT_NOT_OK(GeoParser::parseGeoJSONLine( @@ -118,22 +119,27 @@ namespace { fromjson("{'type':'LineString', 'coordinates':[['chicken','little']]}"), &polyline)); ASSERT_NOT_OK(GeoParser::parseGeoJSONLine( fromjson("{'type':'LineString', 'coordinates':[1,2, 3, 4]}"), &polyline)); - ASSERT_NOT_OK(GeoParser::parseGeoJSONLine( - fromjson("{'type':'LineString', 'coordinates':[[1,2, 3], [3,4, 5], [5,6]]}"), &polyline)); + ASSERT_OK(GeoParser::parseGeoJSONLine( + fromjson("{'type':'LineString', 'coordinates':[[1,2, 3], [3,4, 5], [5,6]]}"), + &polyline)); } TEST(GeoParser, parseGeoJSONPolygon) { PolygonWithCRS polygon; ASSERT_OK(GeoParser::parseGeoJSONPolygon( - fromjson("{'type':'Polygon', 'coordinates':[ [[0,0],[5,0],[5,5],[0,5],[0,0]] ]}"), &polygon)); + fromjson("{'type':'Polygon', 'coordinates':[ [[0,0],[5,0],[5,5],[0,5],[0,0]] ]}"), + &polygon)); // No out of bounds points ASSERT_NOT_OK(GeoParser::parseGeoJSONPolygon( - fromjson("{'type':'Polygon', 'coordinates':[ [[0,0],[5,0],[5,91],[0,5],[0,0]] ]}"), &polygon)); + fromjson("{'type':'Polygon', 'coordinates':[ [[0,0],[5,0],[5,91],[0,5],[0,0]] ]}"), + &polygon)); ASSERT_OK(GeoParser::parseGeoJSONPolygon( - fromjson("{'type':'Polygon', 'coordinates':[ [[0,0],[180,0],[5,5],[0,5],[0,0]] ]}"), &polygon)); + fromjson("{'type':'Polygon', 'coordinates':[ [[0,0],[180,0],[5,5],[0,5],[0,0]] ]}"), + &polygon)); ASSERT_NOT_OK(GeoParser::parseGeoJSONPolygon( - fromjson("{'type':'Polygon', 'coordinates':[ [[0,0],[181,0],[5,5],[0,5],[0,0]] ]}"), &polygon)); + fromjson("{'type':'Polygon', 'coordinates':[ [[0,0],[181,0],[5,5],[0,5],[0,0]] ]}"), + &polygon)); // And one with a hole. ASSERT_OK(GeoParser::parseGeoJSONPolygon( fromjson("{'type':'Polygon', 'coordinates':[ [[0,0],[5,0],[5,5],[0,5],[0,0]]," @@ -145,7 +151,10 @@ namespace { // First point must be the same as the last. ASSERT_NOT_OK(GeoParser::parseGeoJSONPolygon( fromjson("{'type':'Polygon', 'coordinates':[ [[1,2],[3,4],[5,6]] ]}"), &polygon)); - + // Extra elements are allowed + ASSERT_OK(GeoParser::parseGeoJSONPolygon( + fromjson("{'type':'Polygon', 'coordinates':[ [[0,0,0,0],[5,0,0],[5,5,1]," + " [0,5],[0,0]] ]}"), &polygon)); // Test functionality of polygon PointWithCRS point; @@ -211,17 +220,21 @@ namespace { ASSERT_NOT_OK(GeoParser::parseGeoJSONPoint(point4, &point)); PolygonWithCRS polygon; - BSONObj polygon1 = fromjson("{'type':'Polygon', 'coordinates':[ [[0,0],[5,0],[5,5],[0,5],[0,0]]," + BSONObj polygon1 = fromjson("{'type':'Polygon', 'coordinates':[ " + "[[0,0],[5,0],[5,5],[0,5],[0,0]]," " [[1,1],[1,4],[4,4],[4,1],[1,1]] ]," + goodCRS1 + "}"); ASSERT_OK(GeoParser::parseGeoJSONPolygon(polygon1, &polygon)); - BSONObj polygon2 = fromjson("{'type':'Polygon', 'coordinates':[ [[0,0],[5,0],[5,5],[0,5],[0,0]]," + BSONObj polygon2 = fromjson("{'type':'Polygon', 'coordinates':[ " + "[[0,0],[5,0],[5,5],[0,5],[0,0]]," " [[1,1],[1,4],[4,4],[4,1],[1,1]] ]," + badCRS2 + "}"); ASSERT_NOT_OK(GeoParser::parseGeoJSONPolygon(polygon2, &polygon)); LineWithCRS line; - BSONObj line1 = fromjson("{'type':'LineString', 'coordinates':[[1,2], [3,4], [5,6]]," + goodCRS2 + "}"); + BSONObj line1 = fromjson("{'type':'LineString', 'coordinates':[[1,2], [3,4], [5,6]]," + + goodCRS2 + "}"); ASSERT_OK(GeoParser::parseGeoJSONLine(line1, &line)); - BSONObj line2 = fromjson("{'type':'LineString', 'coordinates':[[1,2], [3,4], [5,6]]," + badCRS1 + "}"); + BSONObj line2 = fromjson("{'type':'LineString', 'coordinates':[[1,2], [3,4], [5,6]]," + + badCRS1 + "}"); ASSERT_NOT_OK(GeoParser::parseGeoJSONLine(line2, &line)); } -- cgit v1.2.1