Skip to content

Commit

Permalink
Add new MBTilesImageLayer and MBTilesElevationLayer
Browse files Browse the repository at this point in the history
  • Loading branch information
gwaldron committed Dec 5, 2018
1 parent 62fe743 commit 2250b7b
Show file tree
Hide file tree
Showing 8 changed files with 925 additions and 20 deletions.
5 changes: 4 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,12 @@ FIND_PACKAGE(GDAL)
FIND_PACKAGE(GEOS)
FIND_PACKAGE(Sqlite3)
FIND_PACKAGE(Poco)

FIND_PACKAGE(LevelDB)

IF(SQLITE3_FOUND)
ADD_DEFINITIONS(-DOSGEARTH_HAVE_MBTILES)
ENDIF(SQLITE3_FOUND)

SET (WITH_STATIC_ROCKSDB FALSE CACHE BOOL "Use static library of RocksDB")

IF(MINGW)
Expand Down
13 changes: 13 additions & 0 deletions src/osgEarth/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ SET(LIB_PUBLIC_HEADERS
MemCache
MetaTile
Metrics
MBTiles
ModelLayer
ModelSource
NativeProgramAdapter
Expand Down Expand Up @@ -326,6 +327,7 @@ set(TARGET_SRC
Memory.cpp
MetaTile.cpp
Metrics.cpp
MBTiles.cpp
MimeTypes.cpp
ModelLayer.cpp
ModelSource.cpp
Expand Down Expand Up @@ -404,10 +406,16 @@ ADD_LIBRARY(

INCLUDE_DIRECTORIES(${GDAL_INCLUDE_DIR} ${CURL_INCLUDE_DIR} ${OSG_INCLUDE_DIR} )

# TinyXML support?
IF (TINYXML_FOUND)
INCLUDE_DIRECTORIES(${TINYXML_INCLUDE_DIR})
ENDIF (TINYXML_FOUND)

# MBTiles support?
IF(SQLITE3_FOUND)
INCLUDE_DIRECTORIES(${SQLITE3_INCLUDE_DIR})
ENDIF(SQLITE3_FOUND)

IF (WIN32)
LINK_EXTERNAL(${LIB_NAME} ${TARGET_EXTERNAL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${MATH_LIBRARY} )
ELSE(WIN32)
Expand All @@ -431,4 +439,9 @@ IF (TINYXML_FOUND)
message(STATUS ${output})
ENDIF (TINYXML_FOUND)

# MBTiles links to sqlite3
IF (SQLITE3_FOUND)
LINK_WITH_VARIABLES(${LIB_NAME} SQLITE3_LIBRARY)
ENDIF(SQLITE3_FOUND)

INCLUDE(ModuleInstall OPTIONAL)
294 changes: 294 additions & 0 deletions src/osgEarth/MBTiles
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2018 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 <http://www.gnu.org/licenses/>
*/

#ifndef OSGEARTH_MBTILES_H
#define OSGEARTH_MBTILES_H

#include <osgEarth/Common>
#include <osgEarth/ImageLayer>
#include <osgEarth/ElevationLayer>
#include <osgEarth/URI>

/**
* MBTiles - MapBox tile storage specification using SQLite3
* https://github.com/mapbox/mbtiles-spec
*/

//! Namespace for internal driver classes
namespace osgEarth { namespace MBTiles
{
/**
* Underlying driver that does the actual I/O
*/
class OSGEARTH_EXPORT Driver
{
public:
Status open(
const URI& uri,
osg::ref_ptr<const Profile>& profile,
const std::string& format,
DataExtentList& dataExtents,
const osgDB::Options* readOptions);

ReadResult read(
const TileKey& key,
ProgressCallback* progress,
const osgDB::Options* readOptions) const;

bool write(
const TileKey& key,
osg::Image* image,
ProgressCallback* progress);

private:
void* _db;
unsigned _minLevel;
unsigned _maxLevel;
osg::ref_ptr< osg::Image> _emptyImage;
osg::ref_ptr<osgDB::ReaderWriter> _rw;
osg::ref_ptr<osgDB::Options> _dbOptions;
osg::ref_ptr<osgDB::BaseCompressor> _compressor;
std::string _tileFormat;
bool _forceRGB;

// because no one knows if/when sqlite3 is threadsafe.
mutable Threading::Mutex _mutex;

bool getMetaData(const std::string& name, std::string& value);
bool putMetaData(const std::string& name, const std::string& value);
bool createTables();
void computeLevelsNow();
};

/**
* Base class that mixes in the options with a base Layer class.
*/
template<typename BASE>
class OSGEARTH_EXPORT MBTilesLayerOptions : public BASE
{
public:
META_LayerOptions(osgEarth, MBTilesLayerOptions, BASE);

//! Location of the MBTiles database
optional<URI>& url() { return _filename; }
const optional<URI>& url() const { return _filename; }

//! Format of the imagery in the MBTiles file (jpeg, png, etc)
optional<std::string>& format() { return _format; }
const optional<std::string>& format() const { return _format; }

//! Whether to compress the data. This isn't necessary for formats that
//! are already compressed, like JPEG
optional<bool>& compress() { return _compress; }
const optional<bool>& compress() const { return _compress; }

//! Whether or not to automatically compute the valid levels of the MBTiles file.
//! By default this is true and will scan the table to determine the min/max.
//! This can take time when first loading the file so if you know the levels of your file
//! up front you can set this to false and just use the min_level max_level settings
//! of the tile source.
optional<bool>& computeLevels() { return _computeLevels; }
const optional<bool>& computeLevels() const { return _computeLevels; }

public:
virtual inline Config getConfig() const;

private:
inline void fromConfig(const Config& conf);
optional<URI> _filename;
optional<std::string> _format;
optional<bool> _computeLevels;
optional<bool> _compress;
};
} }

//........................................................................

namespace osgEarth
{
/**
* Serialization options for a TMS image layer.
*/
typedef MBTiles::MBTilesLayerOptions<ImageLayerOptions> MBTilesImageLayerOptions;

/**
* Image layer connected to a TMS (Tile Map Service) facility
*/
class OSGEARTH_EXPORT MBTilesImageLayer : public ImageLayer
{
public:
META_Layer(
osgEarth,
MBTilesImageLayer,
MBTilesImageLayerOptions,
ImageLayer,
MBTilesImage);

public:
//! Base URL of TileCache endpoint
void setURL(const URI& value) { options().url() = value; }
const URI& getURL() const { return options().url().get(); }

//! Data format to request from the service
void setFormat(const std::string& value) { options().format() = value; }
const std::string& getFormat() const { return options().format().get(); }

//! Whether to compress the data. This isn't necessary for formats that
//! are already compressed, like JPEG
void setCompress(bool value) { options().compress() = value; }
bool getCompress() const { return options().compress().get(); }

//! Whether or not to automatically compute the valid levels of the MBTiles file.
//! By default this is true and will scan the table to determine the min/max.
//! This can take time when first loading the file so if you know the levels of your file
//! up front you can set this to false and just use the min_level max_level settings
//! of the tile source.
void setComputeLevels(bool value) { options().computeLevels() = value; }
bool getComputeLevels() const { return options().computeLevels().get(); }

public: // Layer

//! Establishes a connection to the database
virtual const Status& open();

//! Creates a raster image for the given tile key
virtual GeoImage createImageImplementation(const TileKey& key, ProgressCallback* progress) const;

protected: // Layer

//! Called by constructors
virtual void init();

protected:

//! Destructor
virtual ~MBTilesImageLayer() { }

private:
void* _database;
unsigned _minLevel;
unsigned _maxLevel;
osg::ref_ptr< osg::Image> _emptyImage;
osg::ref_ptr<osgDB::ReaderWriter> _rw;
osg::ref_ptr<osgDB::Options> _dbOptions;
osg::ref_ptr<osgDB::BaseCompressor> _compressor;
std::string _tileFormat;
bool _forceRGB;

// because no one knows if/when sqlite3 is threadsafe.
mutable Threading::Mutex _mutex;

bool getMetaData(const std::string& name, std::string& value);
bool putMetaData(const std::string& name, const std::string& value);
bool createTables();
void computeLevels();
};


/**
* Serialization options for a TMS elevation layer.
*/
typedef MBTiles::MBTilesLayerOptions<ElevationLayerOptions> MBTilesElevationLayerOptions;

/**
* Elevation layer connected to a TMS (Tile Map Service) facility
*/
class OSGEARTH_EXPORT MBTilesElevationLayer : public ElevationLayer
{
public:
META_Layer(
osgEarth,
MBTilesElevationLayer,
MBTilesElevationLayerOptions,
ElevationLayer,
MBTilesElevation);

//! Base URL of TileCache endpoint
void setURL(const URI& value) { options().url() = value; }
const URI& getURL() const { return options().url().get(); }

//! Data format to request from the service
void setFormat(const std::string& value) { options().format() = value; }
const std::string& getFormat() const { return options().format().get(); }

//! Whether to compress the data. This isn't necessary for formats that
//! are already compressed, like JPEG
void setCompress(bool value) { options().compress() = value; }
bool getCompress() const { return options().compress().get(); }

//! Whether or not to automatically compute the valid levels of the MBTiles file.
//! By default this is true and will scan the table to determine the min/max.
//! This can take time when first loading the file so if you know the levels of your file
//! up front you can set this to false and just use the min_level max_level settings
//! of the tile source.
void setComputeLevels(bool value) { options().computeLevels() = value; }
bool getComputeLevels() const { return options().computeLevels().get(); }

public: // Layer

//! Establishes a connection to the TMS repository
virtual const Status& open();

//! Creates a heightfield for the given tile key
virtual GeoHeightField createHeightFieldImplementation(const TileKey& key, ProgressCallback* progress) const;

protected: // Layer

//! Called by constructors
virtual void init();

protected:

//! Destructor
virtual ~MBTilesElevationLayer() { }

private:
osg::ref_ptr<MBTilesImageLayer> _imageLayer;
};
} // namespace osgEarth

OSGEARTH_SPECIALIZE_CONFIG(osgEarth::MBTilesImageLayerOptions);
OSGEARTH_SPECIALIZE_CONFIG(osgEarth::MBTilesElevationLayerOptions);

// template inlines ......................................................

namespace osgEarth
{
template<typename BASE>
void MBTiles::MBTilesLayerOptions<BASE>::fromConfig(const Config& conf)
{
conf.get("filename", _filename);
conf.get("url", _filename); // compat for consistency with other drivers
conf.get("format", _format);
conf.get("compute_levels", _computeLevels);
conf.get("compress", _compress);
}

template<typename BASE>
Config MBTiles::MBTilesLayerOptions<BASE>::getConfig() const
{
osgEarth::Config conf = BASE::getConfig();
conf.set("filename", _filename);
conf.set("format", _format);
conf.set("compute_levels", _computeLevels);
conf.set("compress", _compress);
return conf;
}
}
#endif // OSGEARTH_MBTILES_H
Loading

0 comments on commit 2250b7b

Please sign in to comment.