Example #1
0
    void GeoParser::parseGeoJSONPolygon(const BSONObj& obj, S2Polygon* out) {
        const vector<BSONElement>& coordinates =
            obj.getFieldDotted(GEOJSON_COORDINATES).Array();

        const vector<BSONElement>& exteriorRing = coordinates[0].Array();
        vector<S2Point> exteriorVertices;
        parsePoints(exteriorRing, &exteriorVertices);

        S2PolygonBuilderOptions polyOptions;
        polyOptions.set_validate(true);
        S2PolygonBuilder polyBuilder(polyOptions);
        S2Loop exteriorLoop(exteriorVertices);
        if (exteriorLoop.is_hole()) {
            exteriorLoop.Invert();
        }
        polyBuilder.AddLoop(&exteriorLoop);

        // Subsequent arrays of coordinates are interior rings/holes.
        for (size_t i = 1; i < coordinates.size(); ++i) {
            vector<S2Point> holePoints;
            parsePoints(coordinates[i].Array(), &holePoints);
            // Interior rings are clockwise.
            S2Loop holeLoop(holePoints);
            if (!holeLoop.is_hole()) {
                holeLoop.Invert();
            }
            polyBuilder.AddLoop(&holeLoop);
        }

        polyBuilder.AssemblePolygon(out, NULL);
    }
Example #2
0
    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);
    }
Example #3
0
    void GeoParser::parseGeoJSONPolygon(const BSONObj& obj, S2Polygon* out) {
        const vector<BSONElement>& coordinates =
            obj.getFieldDotted(GEOJSON_COORDINATES).Array();

        const vector<BSONElement>& exteriorRing = coordinates[0].Array();
        vector<S2Point> exteriorVertices;
        parsePoints(exteriorRing, &exteriorVertices);
        // The last point is duplicated.  We drop it, since S2Loop expects no
        // duplicate points
        exteriorVertices.resize(exteriorVertices.size() - 1);

        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();
        }
        uassert(16693, "Exterior shell of polygon is invalid: " + obj.toString(),
                exteriorLoop.IsValid());
        polyBuilder.AddLoop(&exteriorLoop);

        // Subsequent arrays of coordinates are interior rings/holes.
        for (size_t i = 1; i < coordinates.size(); ++i) {
            vector<S2Point> holePoints;
            parsePoints(coordinates[i].Array(), &holePoints);
            // Drop the duplicated last point.
            holePoints.resize(holePoints.size() - 1);
            // Interior rings are clockwise.
            S2Loop holeLoop(holePoints);
            holeLoop.Normalize();
            uassert(16694, "Interior hole of polygon is invalid: " + obj.toString(),
                    holeLoop.IsValid());
            if (!holeLoop.is_hole()) {
                holeLoop.Invert();
            }
            polyBuilder.AddLoop(&holeLoop);
        }

        uassert(16695, "Couldn't assemble polygon: " + obj.toString(),
                polyBuilder.AssemblePolygon(out, NULL));
    }
Example #4
0
    void GeoParser::parseLegacyPolygon(const BSONObj &obj, S2Polygon *out) {
        vector<S2Point> points;

        BSONObjIterator coordIt(obj);
        while (coordIt.more()) {
            BSONElement coord = coordIt.next();
            S2Point point;
            parseLegacyPoint(coord.Obj(), &point);
            points.push_back(point);
        }
        points.push_back(points[0]);

        S2PolygonBuilderOptions polyOptions;
        polyOptions.set_validate(true);
        S2PolygonBuilder polyBuilder(polyOptions);
        S2Loop exteriorLoop(points);
        if (exteriorLoop.is_hole()) {
            exteriorLoop.Invert();
        }
        polyBuilder.AddLoop(&exteriorLoop);
        polyBuilder.AssemblePolygon(out, NULL);
    }