/* -*-c++-*- */ /* osgEarth - Geospatial SDK for OpenSceneGraph * Copyright 2020 Pelican Mapping * http://osgearth.org * * osgEarth is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see */ #ifndef OSGEARTH_TMS_H #define OSGEARTH_TMS_H #include #include #include #include /** * TMS (TileMapService) * https://wiki.osgeo.org/wiki/Tile_Map_Service_Specification */ //! TMS namespace contains TMS support classes used to the Layers namespace osgEarth { namespace TMS { class OSGEARTH_EXPORT TileFormat { public: TileFormat(); /** dtor */ virtual ~TileFormat() { } /** *Gets the width of a tile */ unsigned int getWidth() const {return _width;} /** *Sets the width of a tile */ void setWidth(unsigned int width) {_width = width;} /** *Gets the height of a tile */ unsigned int getHeight() const {return _height;} /** *Sets the height of a tile */ void setHeight(unsigned int height) {_height = height;} /** *Gets the mime type of a tile */ const std::string& getMimeType() const {return _mimeType;} /** *Sets the mime type of a tile */ void setMimeType(const std::string& mimeType) {_mimeType = mimeType;} /** *Gets the extension of a tile */ const std::string& getExtension() const {return _extension;} /** *Sets the extension of a tile */ void setExtension(const std::string& extension) {_extension = extension;} protected: unsigned int _width; unsigned int _height; std::string _mimeType; std::string _extension; }; /** * TMS tile set. A collection of tiled images at a given zoom level. */ class OSGEARTH_EXPORT TileSet { public: TileSet(); /** dtor */ virtual ~TileSet() { } /** *Gets the reference link for this TileSet. */ const std::string& getHref() const {return _href;} /** *Sets the reference link for this TileSet. */ void setHref( const std::string &href) {_href = href;} /** *Gets the units per pixel for this TileSet. */ double getUnitsPerPixel() const {return _unitsPerPixel;} /** *Sets the units per pixel for this TileSet. */ void setUnitsPerPixel(double unitsPerPixel) {_unitsPerPixel = unitsPerPixel;} /** *Gets the zoom level of this TileSet. */ unsigned int getOrder() const {return _order;} /** *Sets the zoom level of this TileSet. */ void setOrder( int order ) {_order = order;} protected: std::string _href; double _unitsPerPixel; unsigned int _order; }; /** *A TMS tile map */ class OSGEARTH_EXPORT TileMap : public osg::Referenced { public: enum ProfileType { TYPE_UNKNOWN, TYPE_GEODETIC, TYPE_MERCATOR, TYPE_LOCAL }; TileMap(); /** dtor */ virtual ~TileMap() { } /** *Gets the tile map service for this TileMap */ const std::string& getTileMapService() const {return _tileMapService;} /** *Sets the tile map service for this TileMap */ void setTileMapService(const std::string& tileMapService) {_tileMapService = tileMapService;} /** *Gets the version of this TileMap */ const std::string& getVersion() const {return _version;} /** *Sets the version of this TileMap */ void setVersion(const std::string& version) {_version = version;} /** *Gets the title of this TileMap */ const std::string& getTitle() const {return _title;} /** *Sets the title of this TileMap */ void setTitle(const std::string& title) {_title = title;} /** *Gets the abstract of this TileMap */ const std::string& getAbstract() const {return _abstract;} /** *Sets the abstract of this TileMap */ void setAbstract(const std::string& value) {_abstract = value;} /** *Gets the spatial reference of this TileMap */ const std::string& getSRS() const {return _srs;} /** *Sets the spatial reference of this TileMap */ void setSRS(const std::string& srs) {_srs = srs;} /** *Gets the vertical spatial reference of this TileMap */ const std::string& getVerticalSRS() const { return _vsrs; } /** *Sets the vertical spatial reference of this TileMap */ void setVerticalSRS(const std::string& vsrs) { _vsrs = vsrs; } /** *Gets the filename that this TileMap was loaded from */ const std::string& getFilename() const {return _filename;} /** *Sets the filename that this TileMap was loaded from */ void setFilename(const std::string& filename) {_filename = filename;} /** *Gets the minimum zoom level that this TileMap has valid data for */ unsigned int getMinLevel() const {return _minLevel;} /** *Gets the maximum level that this TileMap has valid data for */ unsigned int getMaxLevel() const {return _maxLevel;} /** *Computes the minimum and maximum levels of valid data for this TileMap */ void computeMinMaxLevel(); /** *Computes the number of tiles at level 0 from the existing TileSets */ void computeNumTiles(); /** *Gets the x coordinate of the origin of this TileMap */ double getOriginX() const {return _originX;} /** *Sets the x coordinate of the origin of this TileMap */ void setOriginX(double x) {_originX = x;} /** *Gets the y coordinate of the origin of this TileMap */ double getOriginY() const {return _originY;} /** *Sets the y coordinate of the origin of this TileMap */ void setOriginY(double y) {_originY = y;} /** * Sets the timestamp of the TimeMap, i.e. the last modified time */ void setTimeStamp(TimeStamp t) { _timestamp = t; } /** * Gets the timestap of the TileMap */ TimeStamp getTimeStamp() const { return _timestamp; } /** *Sets the origin of this TileMap * *@param x * The origin's x coordinate *@param y * The origin's y coordinate */ void setOrigin(double x, double y); /** *Gets the extents of this TileMap *@param minX * The minimum x coordinate of the extents *@param minY * The minimum y coordinate of the extents *@param maxX * The maximum x coordinate of the extents *@param maxY * The maximum y coordinate of the extents */ void getExtents( double &minX, double &minY, double &maxX, double &maxY) const; /** *Sets the extents of this TileMap *@param minX * The minimum x coordinate of the extents *@param minY * The minimum y coordinate of the extents *@param maxX * The maximum x coordinate of the extents *@param maxY * The maximum y coordinate of the extents */ void setExtents( double minX, double minY, double maxX, double maxY); /** *Gets the number of tiles wide at lod 0 */ unsigned int getNumTilesWide() const { return _numTilesWide; } /** *Sets the number of tiles wide at lod 0 */ void setNumTilesWide(unsigned int w) { _numTilesWide = w; } /** *Gets the number of tiles high at lod 0 */ unsigned int getNumTilesHigh() const { return _numTilesHigh; } /** *Sets the number of tiles high at lod 0 */ void setNumTilesHigh(unsigned int h) {_numTilesHigh = h;} ProfileType getProfileType() const {return _profile_type;} void setProfileType( ProfileType type ) {_profile_type = type;} const Profile* createProfile() const; /** Gets the TileFormat for this TileMap */ TileFormat& getFormat() {return _format;} /** Gets the TileFormat for this TileMap */ const TileFormat& getFormat() const {return _format;} /** A list of TileSets */ typedef std::vector TileSetList; /** Gets the TileSets for this TileMap */ TileSetList& getTileSets() {return _tileSets;} /** Gets the TileSets for this TileMap */ const TileSetList& getTileSets() const {return _tileSets;} DataExtentList& getDataExtents() { return _dataExtents;} const DataExtentList& getDataExtents() const { return _dataExtents;} /** *Gets a URL string that can be used to retrieve the image for the given TileKey *@param tileKey * The TileKey to get the URL for. *@param invertY * If false, treat tile 0,0 as the lower left tile in the the map. If true, treat 0,0 as the top left tile in the map. *@returns * The URL if the data intersects the TileKey. */ std::string getURL(const osgEarth::TileKey& tileKey, bool invertY); /** *Determines whether or not the given TileKey intersects the TileMap */ bool intersectsKey(const osgEarth::TileKey& tileKey); /** *Automatically generates a number of TileSets */ void generateTileSets(unsigned int numLevels = 20); /** * Creates a TileMap corresponding to one of osgEarth's built-in profile types */ static TileMap* create( const std::string& url, const Profile* profile, const DataExtentList& dataExtents, const std::string& format, int tile_width, int tile_height ); protected: std::string _tileMapService; std::string _version; std::string _title; std::string _abstract; std::string _srs; std::string _vsrs; double _originX, _originY; double _minX, _minY, _maxX, _maxY; TileSetList _tileSets; TileFormat _format; std::string _filename; unsigned int _minLevel; unsigned int _maxLevel; unsigned int _numTilesWide; unsigned int _numTilesHigh; ProfileType _profile_type; TimeStamp _timestamp; DataExtentList _dataExtents; }; class OSGEARTH_EXPORT TileMapReaderWriter { public: static TileMap* read( const URI& location, const osgDB::ReaderWriter::Options* options ); static TileMap* read( std::istream &in ); static TileMap* read( const Config& conf ); static void write(const TileMap* tileMap, const std::string& location); static void write(const TileMap* tileMap, std::ostream& output); private: TileMapReaderWriter(); TileMapReaderWriter(const TileMapReaderWriter &tmr); /** dtor */ virtual ~TileMapReaderWriter() { } }; /** * An entry in a TileMapService's list of TileMaps. */ struct OSGEARTH_EXPORT TileMapEntry { TileMapEntry( const std::string& _title, const std::string& _href, const std::string& _srs, const std::string& _profile); std::string title; std::string href; std::string srs; std::string profile; }; typedef std::list< TileMapEntry > TileMapEntryList; /** * Reads a list of TileMapEntry's from a server. Useful for displaying a list of layers to the user */ class OSGEARTH_EXPORT TileMapServiceReader { public: /** * Reads a list of TileMapEntry's from a server * @param location * A URL to the TMS service URL like http://server.com/tiles/1.0.0/ */ static bool read( const std::string &location, const osgDB::ReaderWriter::Options* options, TileMapEntryList& tileMaps ); static bool read( const Config& conf, TileMapEntryList& tileMaps); private: TileMapServiceReader(); TileMapServiceReader( const TileMapServiceReader& rhs ); }; /** * Underlying TMS driver that does the actual TMS I/O */ class OSGEARTH_EXPORT Driver { public: Status open( const URI& uri, osg::ref_ptr& profile, const std::string& format, bool isCoverage, DataExtentList& out_dataExtents, const osgDB::Options* readOptions); void close(); ReadResult read( const URI& uri, const TileKey& key, bool invertY, ProgressCallback* progress, const osgDB::Options* readOptions) const; bool write( const URI& uri, const TileKey& key, const osg::Image* image, bool invertY, ProgressCallback* progress, const osgDB::Options* writeOptions) const; private: osg::ref_ptr _tileMap; osg::ref_ptr _writer; bool _forceRGBWrites; bool _isCoverage; bool resolveWriter(const std::string& format); }; /** * Serializable TMS options */ class OSGEARTH_EXPORT Options { public: OE_OPTION(URI, url); OE_OPTION(std::string, tmsType); OE_OPTION(std::string, format); static Config getMetadata(); void readFrom(const Config& conf); void writeTo(Config&) const; }; } } namespace osgEarth { /** * Image layer connected to a TMS (Tile Map Service) facility */ class OSGEARTH_EXPORT TMSImageLayer : public ImageLayer { public: // serialization class OSGEARTH_EXPORT Options : public ImageLayer::Options, public TMS::Options { public: META_LayerOptions(osgEarth, Options, ImageLayer::Options); virtual Config getConfig() const; private: void fromConfig(const Config& conf); }; public: META_Layer(osgEarth, TMSImageLayer, Options, ImageLayer, TMSImage); public: //! Base URL for TMS requests void setURL(const URI& value); const URI& getURL() const; //! Options TMS "type"; only possible setting is "google" which will //! invert the Y axis for tile indices void setTMSType(const std::string& value); const std::string& getTMSType() const; //! Data format to request from the service void setFormat(const std::string& value); const std::string& getFormat() const; public: // Layer //! Establishes a connection to the TMS repository virtual Status openImplementation() override; virtual Status closeImplementation() override; //! Creates a raster image for the given tile key virtual GeoImage createImageImplementation(const TileKey& key, ProgressCallback* progress) const override; //! Writes a raster image for he given tile key (if open for writing) virtual Status writeImageImplementation(const TileKey& key, const osg::Image* image, ProgressCallback* progress) const override; protected: // Layer //! Called by constructors virtual void init() override; virtual bool isWritingSupported() const override { return true; } protected: //! Destructor virtual ~TMSImageLayer() { } private: TMS::Driver _driver; mutable ReadWriteMutex _mutex; }; /** * Elevation layer connected to a TMS (Tile Map Service) facility */ class OSGEARTH_EXPORT TMSElevationLayer : public ElevationLayer { public: // serialization class OSGEARTH_EXPORT Options : public ElevationLayer::Options, public TMS::Options { public: META_LayerOptions(osgEarth, Options, ElevationLayer::Options); virtual Config getConfig() const; private: void fromConfig(const Config& conf); }; public: META_Layer(osgEarth, TMSElevationLayer, Options, ElevationLayer, TMSElevation); //! Base URL for TMS requests void setURL(const URI& value); const URI& getURL() const; //! Options TMS "type"; only possible setting is "google" which will //! invert the Y axis for tile indices void setTMSType(const std::string& value); const std::string& getTMSType() const; //! Data format to request from the service void setFormat(const std::string& value); const std::string& getFormat() const; public: // Layer //! Establishes a connection to the TMS repository virtual Status openImplementation() override; virtual Status closeImplementation() override; //! Creates a heightfield for the given tile key virtual GeoHeightField createHeightFieldImplementation(const TileKey& key, ProgressCallback* progress) const override; //! Writes a raster image for he given tile key (if open for writing) virtual Status writeHeightFieldImplementation(const TileKey& key, const osg::HeightField* hf, ProgressCallback* progress) const override; protected: // Layer //! Called by constructors virtual void init() override; virtual bool isWritingSupported() const override { return true; } protected: //! Destructor virtual ~TMSElevationLayer() { } private: osg::ref_ptr _imageLayer; }; } // namespace osgEarth OSGEARTH_SPECIALIZE_CONFIG(osgEarth::TMSImageLayer::Options); OSGEARTH_SPECIALIZE_CONFIG(osgEarth::TMSElevationLayer::Options); #endif // OSGEARTH_TMS_H