static NValue polygonFromText(const std::string &wkt, bool doValidation) { // Discard whitespace, but return commas or parentheses as tokens Tokenizer tokens(wkt, boost::char_separator<char>(" \f\n\r\t\v", ",()")); Tokenizer::iterator it = tokens.begin(); Tokenizer::iterator end = tokens.end(); if (! boost::iequals(*it, "polygon")) { throwInvalidWktPoly("does not start with POLYGON keyword"); } ++it; if (! boost::iequals(*it, "(")) { throwInvalidWktPoly("missing left parenthesis after POLYGON keyword"); } ++it; bool is_shell = true; std::size_t length = Polygon::serializedLengthNoLoops(); std::vector<std::unique_ptr<S2Loop> > loops; while (it != end) { loops.push_back(std::unique_ptr<S2Loop>(new S2Loop())); readLoop(is_shell, wkt, it, end, loops.back().get()); // Only the first loop is a shell. is_shell = false; length += Loop::serializedLength(loops.back()->num_vertices()); if (*it == ",") { ++it; } else if (*it == ")") { ++it; break; } else { throwInvalidWktPoly("unexpected token: '" + (*it) + "'"); } } if (it != end) { // extra stuff after input throwInvalidWktPoly("unrecognized input after WKT: '" + (*it) + "'"); } NValue nval = ValueFactory::getUninitializedTempGeographyValue(length); char* storage = const_cast<char*>(ValuePeeker::peekObjectValue(nval)); Polygon poly; poly.init(&loops); // polygon takes ownership of loops here. if (doValidation) { std::stringstream validReason; if (!poly.IsValid(&validReason) || isMultiPolygon(poly, &validReason)) { throwInvalidWktPoly(validReason.str()); } } SimpleOutputSerializer output(storage, length); poly.saveToBuffer(output); return nval; }
template<> NValue NValue::callUnary<FUNC_VOLT_VALIDATE_POLYGON>() const { assert(getValueType() == VALUE_TYPE_GEOGRAPHY); if (isNull()) { return NValue::getNullValue(VALUE_TYPE_BOOLEAN); } // Be optimistic. bool returnval = true; // Extract the polygon and check its validity. Polygon poly; poly.initFromGeography(getGeographyValue()); if (!poly.IsValid() || isMultiPolygon(poly)) { returnval = false; } return ValueFactory::getBooleanValue(returnval); }
template<> NValue NValue::callUnary<FUNC_VOLT_POLYGON_INVALID_REASON>() const { assert(getValueType() == VALUE_TYPE_GEOGRAPHY); if (isNull()) { return NValue::getNullValue(VALUE_TYPE_VARCHAR); } // Extract the polygon and check its validity. std::stringstream msg; Polygon poly; poly.initFromGeography(getGeographyValue()); if (poly.IsValid(&msg)) { isMultiPolygon(poly, &msg); } std::string res (msg.str()); if (res.size() == 0) { res = std::string("Valid Polygon"); } return getTempStringValue(res.c_str(),res.length()); }
bool GeoParser::isGeometryCollection(const BSONObj &obj) { BSONElement type = obj.getFieldDotted(GEOJSON_TYPE); if (type.eoo() || (String != type.type())) { return false; } if (GEOJSON_TYPE_GEOMETRY_COLLECTION != type.String()) { return false; } BSONElement coordElt = obj.getFieldDotted(GEOJSON_GEOMETRIES); if (coordElt.eoo() || (Array != coordElt.type())) { return false; } const vector<BSONElement>& coordinates = coordElt.Array(); if (0 == coordinates.size()) { return false; } for (size_t i = 0; i < coordinates.size(); ++i) { if (coordinates[i].eoo() || (Object != coordinates[i].type())) { return false; } BSONObj obj = coordinates[i].Obj(); if (!isGeoJSONPoint(obj) && !isLine(obj) && !isGeoJSONPolygon(obj) && !isMultiPoint(obj) && !isMultiPolygon(obj) && !isMultiLine(obj)) { return false; } } return true; }
bool GeoParser::parseGeometryCollection(const BSONObj &obj, GeometryCollection *out) { BSONElement coordElt = obj.getFieldDotted(GEOJSON_GEOMETRIES); const vector<BSONElement>& geometries = coordElt.Array(); for (size_t i = 0; i < geometries.size(); ++i) { const BSONObj& geoObj = geometries[i].Obj(); if (isGeoJSONPoint(geoObj)) { PointWithCRS point; if (!parsePoint(geoObj, &point)) { return false; } out->points.push_back(point); } else if (isLine(geoObj)) { out->lines.mutableVector().push_back(new LineWithCRS()); if (!parseLine(geoObj, out->lines.vector().back())) { return false; } } else if (isGeoJSONPolygon(geoObj)) { out->polygons.mutableVector().push_back(new PolygonWithCRS()); if (!parsePolygon(geoObj, out->polygons.vector().back())) { return false; } } else if (isMultiPoint(geoObj)) { out->multiPoints.mutableVector().push_back(new MultiPointWithCRS()); if (!parseMultiPoint(geoObj, out->multiPoints.mutableVector().back())) { return false; } } else if (isMultiPolygon(geoObj)) { out->multiPolygons.mutableVector().push_back(new MultiPolygonWithCRS()); if (!parseMultiPolygon(geoObj, out->multiPolygons.mutableVector().back())) { return false; } } else { verify(isMultiLine(geoObj)); out->multiLines.mutableVector().push_back(new MultiLineWithCRS()); if (!parseMultiLine(geoObj, out->multiLines.mutableVector().back())) { return false; } } } return true; }