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;
    }
Beispiel #3
0
 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);
 }
Beispiel #4
0
 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);
 }