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); }
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); }
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)); }
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); }
void OverlayOp::computeOverlay(int opCode) //throw(TopologyException *) { // copy points from input Geometries. // This ensures that any Point geometries // in the input are considered for inclusion in the result set copyPoints(0); copyPoints(1); // node the input Geometries delete (*arg)[0]->computeSelfNodes(li,false); delete (*arg)[1]->computeSelfNodes(li,false); #if DEBUG cerr<<"OverlayOp::computeOverlay: computed SelfNodes"<<endl; #endif // compute intersections between edges of the two input geometries delete (*arg)[0]->computeEdgeIntersections((*arg)[1],li,true); #if DEBUG cerr<<"OverlayOp::computeOverlay: computed EdgeIntersections"<<endl; cerr<<"OverlayOp::computeOverlay: li: "<<li->toString()<<endl; #endif vector<Edge*> baseSplitEdges; (*arg)[0]->computeSplitEdges(&baseSplitEdges); (*arg)[1]->computeSplitEdges(&baseSplitEdges); // add the noded edges to this result graph insertUniqueEdges(&baseSplitEdges); computeLabelsFromDepths(); replaceCollapsedEdges(); //Debug.println(edgeList); // debugging only //NodingValidator nv = new NodingValidator(edgeList.getEdges()); //nv.checkValid(); graph->addEdges(edgeList->getEdges()); // this can throw TopologyException * computeLabelling(); //Debug.printWatch(); labelIncompleteNodes(); //Debug.printWatch(); //nodeMap.print(System.out); /* * The ordering of building the result Geometries is important. * Areas must be built before lines, which must be built * before points. * This is so that lines which are covered by areas are not * included explicitly, and similarly for points. */ findResultAreaEdges(opCode); cancelDuplicateResultEdges(); PolygonBuilder polyBuilder(geomFact,cga); // might throw a TopologyException * polyBuilder.add(graph); vector<Geometry*> *gv=polyBuilder.getPolygons(); size_t gvSize=gv->size(); resultPolyList=new vector<Polygon*>(gvSize); for(size_t i=0; i<gvSize; ++i) { (*resultPolyList)[i]=(Polygon*)(*gv)[i]; } delete gv; LineBuilder lineBuilder(this,geomFact,ptLocator); resultLineList=lineBuilder.build(opCode); PointBuilder pointBuilder(this,geomFact,ptLocator); resultPointList=pointBuilder.build(opCode); // gather the results from all calculations into a single // Geometry for the result set resultGeom=computeGeometry(resultPointList,resultLineList,resultPolyList); #if USE_ELEVATION_MATRIX elevationMatrix->elevate(resultGeom); #endif // USE_ELEVATION_MATRIX }