static bool parseGeoJSONPolygonCoordinates(const vector<BSONElement>& coordinates, const BSONObj &sourceObject, S2Polygon *out) { 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; } S2PolygonBuilderOptions polyOptions; polyOptions.set_validate(true); // Don't silently eliminate duplicate edges. polyOptions.set_xor_edges(false); S2PolygonBuilder polyBuilder(polyOptions); S2Loop exteriorLoop(exteriorVertices); exteriorLoop.Normalize(); if (exteriorLoop.is_hole()) { exteriorLoop.Invert(); } if (!exteriorLoop.IsValid()) { return false; } polyBuilder.AddLoop(&exteriorLoop); // Subsequent arrays of coordinates are interior rings/holes. for (size_t i = 1; i < coordinates.size(); ++i) { vector<S2Point> holePoints; if (!parsePoints(coordinates[i].Array(), &holePoints)) { return false; } eraseDuplicatePoints(&holePoints); // Drop the duplicated last point. holePoints.resize(holePoints.size() - 1); // S2 Polygon loops must have 3 vertices if (holePoints.size() < 3) { return false; } // Interior rings are clockwise. S2Loop holeLoop(holePoints); holeLoop.Normalize(); if (!holeLoop.IsValid()) { return false; } if (!holeLoop.is_hole()) { if (!exteriorLoop.Contains(&holeLoop)) { return false; } holeLoop.Invert(); } else { // It's already clockwise; we need to invert once to check that it's contained in // the shell, then invert again. holeLoop.Invert(); if (!exteriorLoop.Contains(&holeLoop)) { return false; } holeLoop.Invert(); } polyBuilder.AddLoop(&holeLoop); } 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 isValidLineString(const vector<BSONElement>& coordinateArray) { if (coordinateArray.size() < 2) { return false; } if (!isArrayOfCoordinates(coordinateArray)) { return false; } vector<S2Point> vertices; if (!parsePoints(coordinateArray, &vertices)) { return false; } eraseDuplicatePoints(&vertices); return S2Polyline::IsValid(vertices); }
bool GeoParser::parseLine(const BSONObj& obj, LineWithCRS* out) { vector<S2Point> vertices; if (!parsePoints(obj.getFieldDotted(GEOJSON_COORDINATES).Array(), &vertices)) { return false; } eraseDuplicatePoints(&vertices); out->line.Init(vertices); out->crs = SPHERE; return true; }
bool GeoParser::isGeoJSONLineString(const BSONObj& obj) { BSONElement type = obj.getFieldDotted(GEOJSON_TYPE); if (type.eoo() || (String != type.type())) { return false; } if (GEOJSON_TYPE_LINESTRING != type.String()) { return false; } if (!crsIsOK(obj)) { warning() << "Invalid CRS: " << obj.toString() << endl; return false; } BSONElement coordElt = obj.getFieldDotted(GEOJSON_COORDINATES); if (coordElt.eoo() || (Array != coordElt.type())) { return false; } const vector<BSONElement>& coordinateArray = coordElt.Array(); if (coordinateArray.size() < 2) { return false; } if (!isArrayOfCoordinates(coordinateArray)) { return false; } vector<S2Point> vertices; parsePoints(obj.getFieldDotted(GEOJSON_COORDINATES).Array(), &vertices); eraseDuplicatePoints(&vertices); return S2Polyline::IsValid(vertices); }
void GeoParser::parseGeoJSONLineString(const BSONObj& obj, S2Polyline* out) { vector<S2Point> vertices; parsePoints(obj.getFieldDotted(GEOJSON_COORDINATES).Array(), &vertices); eraseDuplicatePoints(&vertices); out->Init(vertices); }