std::string createURL(const Symbology::Query& query) { if (query.tileKey().isSet()) { const TileKey &key = query.tileKey().get(); unsigned int tileX = key.getTileX(); unsigned int tileY = key.getTileY(); unsigned int level = key.getLevelOfDetail(); // TFS follows the same protocol as TMS, with the origin in the lower left of the profile. // osgEarth TileKeys are upper left origin, so we need to invert the tilekey to request the correct key. unsigned int numRows, numCols; key.getProfile()->getNumTiles(key.getLevelOfDetail(), numCols, numRows); tileY = numRows - tileY - 1; std::stringstream buf; std::string path = osgDB::getFilePath(_options.url()->full()); buf << path << "/" << level << "/" << tileX << "/" << tileY << "." << _options.format().get(); OE_DEBUG << "TFS url " << buf.str() << std::endl; return buf.str(); } return ""; }
std::string createURL(const Symbology::Query& query) { if (query.tileKey().isSet()) { std::stringstream buf; std::string path = osgDB::getFilePath(_options.url()->full()); buf << path << "/" << query.tileKey().get().getLevelOfDetail() << "/" << query.tileKey().get().getTileX() << "/" << query.tileKey().get().getTileY() << "." << _options.format().get(); OE_DEBUG << "TFS url " << buf.str() << std::endl; return buf.str(); } return ""; }
std::string createURL(const Symbology::Query& query) { std::stringstream buf; buf << _options.url()->full() << "?SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature"; buf << "&TYPENAME=" << _typeName; std::string outputFormat = "geojson"; if (_options.outputFormat().isSet()) outputFormat = _options.outputFormat().get(); buf << "&OUTPUTFORMAT=" << outputFormat; if (_options.maxFeatures().isSet()) { buf << "&MAXFEATURES=" << _options.maxFeatures().get(); } if (query.tileKey().isSet()) { buf << "&Z=" << query.tileKey().get().getLevelOfDetail() << "&X=" << query.tileKey().get().getTileX() << "&Y=" << query.tileKey().get().getTileY(); } else if (query.bounds().isSet()) { double buffer = *_options.buffer(); buf << "&BBOX=" << std::setprecision(16) << query.bounds().get().xMin() - buffer << "," << query.bounds().get().yMin() - buffer << "," << query.bounds().get().xMax() + buffer << "," << query.bounds().get().yMax() + buffer; } std::string str; str = buf.str(); return str; }
std::string createURL(const Symbology::Query& query) { std::stringstream buf; buf << _options.url().get() << "?SERVICE=WFS&VERSION=1.0.0&REQUEST=getfeature"; buf << "&TYPENAME=" << _options.typeName().get(); std::string outputFormat = "geojson"; if (_options.outputFormat().isSet()) outputFormat = _options.outputFormat().get(); buf << "&OUTPUTFORMAT=" << outputFormat; if (_options.maxFeatures().isSet()) { buf << "&MAXFEATURES=" << _options.maxFeatures().get(); } if (query.tileKey().isSet()) { buf << "&Z=" << query.tileKey().get().getLevelOfDetail() << "&X=" << query.tileKey().get().getTileX() << "&Y=" << query.tileKey().get().getTileY(); } else if (query.bounds().isSet()) { buf << "&BBOX=" << query.bounds().get().xMin() << "," << query.bounds().get().yMin() << "," << query.bounds().get().xMax() << "," << query.bounds().get().yMax(); } return buf.str(); }
std::string createURL(const Symbology::Query& query) { if (query.tileKey().isSet()) { const TileKey& key = query.tileKey().get(); unsigned int tileX = key.getTileX(); unsigned int tileY = key.getTileY(); unsigned int level = key.getLevelOfDetail(); // attempt to verify that the request is within the first and max level // of the data source. const FeatureProfile* fp = getFeatureProfile(); if (fp && fp->getTiled()) { if (fp->getFirstLevel() > level || fp->getMaxLevel() < level) { return ""; } } // TFS follows the same protocol as TMS, with the origin in the lower left of the profile. // osgEarth TileKeys are upper left origin, so we need to invert the tilekey to request the correct key. if (_options.invertY() == false) { unsigned int numRows, numCols; key.getProfile()->getNumTiles(key.getLevelOfDetail(), numCols, numRows); tileY = numRows - tileY - 1; } std::stringstream buf; std::string path = osgDB::getFilePath(_options.url()->full()); buf << path << "/" << level << "/" << tileX << "/" << tileY << "." << _options.format().get(); return buf.str(); } return ""; }
std::string createURL(const Symbology::Query& query) { std::stringstream buf; buf << _options.url()->full() << "?SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature"; buf << "&TYPENAME=" << _options.typeName().get(); std::string outputFormat = "geojson"; if (_options.outputFormat().isSet()) outputFormat = _options.outputFormat().get(); buf << "&OUTPUTFORMAT=" << outputFormat; if (_options.maxFeatures().isSet()) { buf << "&MAXFEATURES=" << _options.maxFeatures().get(); } if (query.tileKey().isSet()) { unsigned int tileX = query.tileKey().get().getTileX(); unsigned int tileY = query.tileKey().get().getTileY(); unsigned int level = query.tileKey().get().getLevelOfDetail(); // Tiled WFS follows the same protocol as TMS, with the origin in the lower left of the profile. // osgEarth TileKeys are upper left origin, so we need to invert the tilekey to request the correct key. unsigned int numRows, numCols; query.tileKey().get().getProfile()->getNumTiles(level, numCols, numRows); tileY = numRows - tileY - 1; buf << "&Z=" << level << "&X=" << tileX << "&Y=" << tileY; } else if (query.bounds().isSet()) { double buffer = *_options.buffer(); buf << "&BBOX=" << std::setprecision(16) << query.bounds().get().xMin() - buffer << "," << query.bounds().get().yMin() - buffer << "," << query.bounds().get().xMax() + buffer << "," << query.bounds().get().yMax() + buffer; } std::string str; str = buf.str(); return str; }
std::string createURL(const Symbology::Query& query) { std::stringstream buf; buf << _options.url()->full() << "?SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature"; buf << "&TYPENAME=" << _options.typeName().get(); std::string outputFormat = "geojson"; if (_options.outputFormat().isSet()) outputFormat = _options.outputFormat().get(); buf << "&OUTPUTFORMAT=" << outputFormat; if (_options.maxFeatures().isSet()) { buf << "&MAXFEATURES=" << _options.maxFeatures().get(); } if (query.tileKey().isSet()) { unsigned int tileX = query.tileKey().get().getTileX(); unsigned int tileY = query.tileKey().get().getTileY(); unsigned int level = query.tileKey().get().getLevelOfDetail(); #if 0 unsigned int numRows, numCols; query.tileKey().get().getProfile()->getNumTiles(level, numCols, numRows); tileY = numRows - tileY - 1; #endif buf << "&Z=" << level << "&X=" << tileX << "&Y=" << tileY; } else if (query.bounds().isSet()) { double buffer = *_options.buffer(); buf << "&BBOX=" << std::setprecision(16) << query.bounds().get().xMin() - buffer << "," << query.bounds().get().yMin() - buffer << "," << query.bounds().get().xMax() + buffer << "," << query.bounds().get().yMax() + buffer; } std::string str; str = buf.str(); return str; }
FeatureCursorOGR::FeatureCursorOGR(OGRDataSourceH dsHandle, OGRLayerH layerHandle, const FeatureProfile* profile, const Symbology::Query& query, const FeatureFilterList& filters ) : _dsHandle( dsHandle ), _layerHandle( layerHandle ), _resultSetHandle( 0L ), _profile( profile ), _query( query ), _filters( filters ), _chunkSize( 500 ), _nextHandleToQueue( 0L ), _spatialFilter( 0L ) { //_resultSetHandle = _layerHandle; { OGR_SCOPED_LOCK; std::string expr; std::string from = OGR_FD_GetName( OGR_L_GetLayerDefn( _layerHandle )); from = std::string("'") + from + std::string("'"); if ( query.expression().isSet() ) { // build the SQL: allow the Query to include either a full SQL statement or // just the WHERE clause. expr = query.expression().value(); // if the expression is just a where clause, expand it into a complete SQL expression. std::string temp = expr; std::transform( temp.begin(), temp.end(), temp.begin(), ::tolower ); bool complete = temp.find( "select" ) == 0; if ( temp.find( "select" ) != 0 ) { std::stringstream buf; buf << "SELECT * FROM " << from << " WHERE " << expr; std::string bufStr; bufStr = buf.str(); expr = bufStr; } } else { std::stringstream buf; buf << "SELECT * FROM " << from; expr = buf.str(); } // if there's a spatial extent in the query, build the spatial filter: if ( query.bounds().isSet() ) { OGRGeometryH ring = OGR_G_CreateGeometry( wkbLinearRing ); OGR_G_AddPoint(ring, query.bounds()->xMin(), query.bounds()->yMin(), 0 ); OGR_G_AddPoint(ring, query.bounds()->xMin(), query.bounds()->yMax(), 0 ); OGR_G_AddPoint(ring, query.bounds()->xMax(), query.bounds()->yMax(), 0 ); OGR_G_AddPoint(ring, query.bounds()->xMax(), query.bounds()->yMin(), 0 ); OGR_G_AddPoint(ring, query.bounds()->xMin(), query.bounds()->yMin(), 0 ); _spatialFilter = OGR_G_CreateGeometry( wkbPolygon ); OGR_G_AddGeometryDirectly( _spatialFilter, ring ); // note: "Directly" above means _spatialFilter takes ownership if ring handle } _resultSetHandle = OGR_DS_ExecuteSQL( _dsHandle, expr.c_str(), _spatialFilter, 0L ); if ( _resultSetHandle ) { OGR_L_ResetReading( _resultSetHandle ); } } readChunk(); }
FeatureCursorOGR::FeatureCursorOGR(OGRDataSourceH dsHandle, OGRLayerH layerHandle, const FeatureSource* source, const FeatureProfile* profile, const Symbology::Query& query, const FeatureFilterList& filters ) : _source ( source ), _dsHandle ( dsHandle ), _layerHandle ( layerHandle ), _resultSetHandle ( 0L ), _spatialFilter ( 0L ), _query ( query ), _chunkSize ( 500 ), _nextHandleToQueue( 0L ), _profile ( profile ), _filters ( filters ) { { OGR_SCOPED_LOCK; std::string expr; std::string from = OGR_FD_GetName( OGR_L_GetLayerDefn( _layerHandle )); std::string driverName = OGR_Dr_GetName( OGR_DS_GetDriver( dsHandle ) ); // Quote the layer name if it is a shapefile, so we can handle any weird filenames like those with spaces or hyphens. // Or quote any layers containing spaces for PostgreSQL if (driverName == "ESRI Shapefile" || from.find(" ") != std::string::npos) { std::string delim = "'"; //Use single quotes by default if (driverName.compare("PostgreSQL") == 0) { //PostgreSQL uses double quotes as identifier delimeters delim = "\""; } from = delim + from + delim; } if ( query.expression().isSet() ) { // build the SQL: allow the Query to include either a full SQL statement or // just the WHERE clause. expr = query.expression().value(); // if the expression is just a where clause, expand it into a complete SQL expression. std::string temp = expr; std::transform( temp.begin(), temp.end(), temp.begin(), ::tolower ); //bool complete = temp.find( "select" ) == 0; if ( temp.find( "select" ) != 0 ) { std::stringstream buf; buf << "SELECT * FROM " << from << " WHERE " << expr; std::string bufStr; bufStr = buf.str(); expr = bufStr; } } else { std::stringstream buf; buf << "SELECT * FROM " << from; expr = buf.str(); } //Include the order by clause if it's set if (query.orderby().isSet()) { std::string orderby = query.orderby().value(); std::string temp = orderby; std::transform( temp.begin(), temp.end(), temp.begin(), ::tolower ); if ( temp.find( "order by" ) != 0 ) { std::stringstream buf; buf << "ORDER BY " << orderby; std::string bufStr; bufStr = buf.str(); orderby = buf.str(); } expr += (" " + orderby ); } // if there's a spatial extent in the query, build the spatial filter: if ( query.bounds().isSet() ) { OGRGeometryH ring = OGR_G_CreateGeometry( wkbLinearRing ); OGR_G_AddPoint(ring, query.bounds()->xMin(), query.bounds()->yMin(), 0 ); OGR_G_AddPoint(ring, query.bounds()->xMin(), query.bounds()->yMax(), 0 ); OGR_G_AddPoint(ring, query.bounds()->xMax(), query.bounds()->yMax(), 0 ); OGR_G_AddPoint(ring, query.bounds()->xMax(), query.bounds()->yMin(), 0 ); OGR_G_AddPoint(ring, query.bounds()->xMin(), query.bounds()->yMin(), 0 ); _spatialFilter = OGR_G_CreateGeometry( wkbPolygon ); OGR_G_AddGeometryDirectly( _spatialFilter, ring ); // note: "Directly" above means _spatialFilter takes ownership if ring handle } OE_DEBUG << LC << "SQL: " << expr << std::endl; _resultSetHandle = OGR_DS_ExecuteSQL( _dsHandle, expr.c_str(), _spatialFilter, 0L ); if ( _resultSetHandle ) { OGR_L_ResetReading( _resultSetHandle ); } } readChunk(); }