442 lines
12 KiB
Plaintext
442 lines
12 KiB
Plaintext
|
/* -*-c++-*- */
|
||
|
/* osgEarth - Dynamic map generation toolkit 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 <http://www.gnu.org/licenses/>
|
||
|
*/
|
||
|
#ifndef OSGEARTH_MAPBOXGL_IMAGE_LAYER
|
||
|
#define OSGEARTH_MAPBOXGL_IMAGE_LAYER 1
|
||
|
|
||
|
#include <osgEarth/ImageLayer>
|
||
|
#include <osgEarth/FeatureSource>
|
||
|
#include <osgEarth/JsonUtils>
|
||
|
#include <osgEarth/MapboxGLGlyphManager>
|
||
|
|
||
|
|
||
|
namespace osgEarth
|
||
|
{
|
||
|
namespace MapBoxGL
|
||
|
{
|
||
|
template< class T >
|
||
|
class Stop
|
||
|
{
|
||
|
public:
|
||
|
Stop(float z, T v) :
|
||
|
zoom(z),
|
||
|
value(std::move(v))
|
||
|
{
|
||
|
}
|
||
|
|
||
|
T value;
|
||
|
float zoom;
|
||
|
};
|
||
|
|
||
|
template<typename T>
|
||
|
inline T lerp(float t, const T& a, const T& b)
|
||
|
{
|
||
|
return (T)(a + (b - a) * t);
|
||
|
}
|
||
|
|
||
|
template<>
|
||
|
inline GeoPoint lerp(float t, const GeoPoint& a, const GeoPoint& b)
|
||
|
{
|
||
|
return a.interpolate(b, t);
|
||
|
}
|
||
|
|
||
|
template< class T >
|
||
|
class PropertyExpression
|
||
|
{
|
||
|
using StopType = Stop< T >;
|
||
|
|
||
|
public:
|
||
|
PropertyExpression() = default;
|
||
|
const std::vector< StopType >& stops() const {
|
||
|
return _stops;
|
||
|
}
|
||
|
|
||
|
std::vector< StopType >& stops() {
|
||
|
return _stops;
|
||
|
}
|
||
|
|
||
|
T evalute(float zoom) const
|
||
|
{
|
||
|
if (_stops.empty())
|
||
|
{
|
||
|
return T();
|
||
|
}
|
||
|
else if (zoom <= _stops[0].zoom)
|
||
|
{
|
||
|
return _stops[0].value;
|
||
|
}
|
||
|
else if (zoom >= _stops.back().zoom)
|
||
|
{
|
||
|
return _stops.back().value;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (unsigned int i = 0; i < _stops.size(); ++i)
|
||
|
{
|
||
|
const StopType& a = _stops[i];
|
||
|
const StopType& b = _stops[i + 1];
|
||
|
if (a.zoom <= zoom && b.zoom >= zoom)
|
||
|
{
|
||
|
// Normalize the value between 0 and 1 for interpolation.
|
||
|
float t = (zoom - a.zoom) / (b.zoom - a.zoom);
|
||
|
auto val = lerp(t, a.value, b.value);
|
||
|
return val;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return T();
|
||
|
}
|
||
|
|
||
|
|
||
|
private:
|
||
|
float _base = 1.0f;
|
||
|
std::vector< StopType > _stops;
|
||
|
};
|
||
|
|
||
|
template< class T >
|
||
|
class PropertyValue
|
||
|
{
|
||
|
public:
|
||
|
PropertyValue() = default;
|
||
|
|
||
|
PropertyValue(T constant) :
|
||
|
_constant(std::move(constant)),
|
||
|
_isConstant(true)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
PropertyValue(PropertyExpression<T> expression) :
|
||
|
_expression(std::move(expression)),
|
||
|
_isConstant(false)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void setConstant(T constant)
|
||
|
{
|
||
|
_constant = std::move(constant);
|
||
|
_isConstant = true;
|
||
|
}
|
||
|
|
||
|
void setExpression(PropertyExpression<T> expression)
|
||
|
{
|
||
|
_expression = std::move(expression);
|
||
|
_isConstant = false;
|
||
|
}
|
||
|
|
||
|
bool isConstant() const
|
||
|
{
|
||
|
return _isConstant;
|
||
|
}
|
||
|
|
||
|
bool isExpression() const
|
||
|
{
|
||
|
return !_isConstant;
|
||
|
}
|
||
|
|
||
|
T evaluate(float zoom) const
|
||
|
{
|
||
|
if (_isConstant)
|
||
|
{
|
||
|
return _constant;
|
||
|
}
|
||
|
return _expression.evalute(zoom);
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
T _constant;
|
||
|
PropertyExpression<T> _expression;
|
||
|
bool _isConstant = true;
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
// https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#paint-property
|
||
|
class Paint
|
||
|
{
|
||
|
public:
|
||
|
Paint();
|
||
|
|
||
|
const PropertyValue<Color>& backgroundColor() const;
|
||
|
PropertyValue<Color>& backgroundColor();
|
||
|
|
||
|
const PropertyValue<float>& backgroundOpacity() const;
|
||
|
PropertyValue<float>& backgroundOpacity();
|
||
|
|
||
|
const PropertyValue<Color>& fillColor() const;
|
||
|
PropertyValue<Color>& fillColor();
|
||
|
|
||
|
const optional<std::string>& fillPattern() const;
|
||
|
optional<std::string>& fillPattern();
|
||
|
|
||
|
const PropertyValue<Color>& lineColor() const;
|
||
|
PropertyValue<Color>& lineColor();
|
||
|
|
||
|
const PropertyValue<float>& lineWidth() const;
|
||
|
PropertyValue<float>& lineWidth();
|
||
|
|
||
|
const optional<std::string>& textField() const;
|
||
|
optional<std::string>& textField();
|
||
|
|
||
|
const optional<std::string>& textFont() const;
|
||
|
optional<std::string>& textFont();
|
||
|
|
||
|
const PropertyValue<Color>& textColor() const;
|
||
|
PropertyValue<Color>& textColor();
|
||
|
|
||
|
const PropertyValue<Color>& textHaloColor() const;
|
||
|
PropertyValue<Color>& textHaloColor();
|
||
|
|
||
|
const PropertyValue<float>& textSize() const;
|
||
|
PropertyValue<float>& textSize();
|
||
|
|
||
|
const optional<std::string>& textAnchor() const;
|
||
|
optional<std::string>& textAnchor();
|
||
|
|
||
|
const optional<std::string>& iconImage() const;
|
||
|
optional<std::string>& iconImage();
|
||
|
|
||
|
const optional<std::string>& visibility() const;
|
||
|
optional<std::string>& visibility();
|
||
|
|
||
|
|
||
|
private:
|
||
|
|
||
|
//Background
|
||
|
PropertyValue<Color> _backgroundColor = PropertyValue<Color>(Color::Transparent);
|
||
|
PropertyValue<float> _backgroundOpacity = PropertyValue<float>(1.0f);
|
||
|
|
||
|
// Fill
|
||
|
optional<bool> _fillAntialias;
|
||
|
PropertyValue<Color> _fillColor = PropertyValue<Color>(Color("#000000"));
|
||
|
PropertyValue<float> _fillOpacity = PropertyValue<float>(1.0f);
|
||
|
optional<std::string> _fillPattern;
|
||
|
|
||
|
// Line
|
||
|
PropertyValue<Color> _lineColor = PropertyValue<Color>(Color::Green);
|
||
|
|
||
|
PropertyValue<float> _lineWidth = PropertyValue<float>(1.0f);
|
||
|
|
||
|
// Text
|
||
|
optional<std::string> _textField;
|
||
|
optional<std::string> _textFont;
|
||
|
PropertyValue<Color> _textColor = PropertyValue<Color>(Color::Black);
|
||
|
PropertyValue<Color> _textHaloColor = PropertyValue<Color>(Color::Transparent);
|
||
|
PropertyValue<float> _textSize = PropertyValue<float>(16.0f);
|
||
|
optional<std::string> _textAnchor;
|
||
|
|
||
|
// Icon
|
||
|
optional<std::string> _iconImage;
|
||
|
|
||
|
optional<std::string> _visibility;
|
||
|
|
||
|
|
||
|
};
|
||
|
|
||
|
class OSGEARTH_EXPORT StyleSheet
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
class Source
|
||
|
{
|
||
|
public:
|
||
|
Source();
|
||
|
|
||
|
const std::string& attribution() const;
|
||
|
std::string& attribution();
|
||
|
|
||
|
const std::string& url() const;
|
||
|
std::string& url();
|
||
|
|
||
|
const std::string& type() const;
|
||
|
std::string& type();
|
||
|
|
||
|
const std::string& name() const;
|
||
|
std::string& name();
|
||
|
|
||
|
const std::vector< std::string >& tiles() const;
|
||
|
std::vector< std::string >& tiles();
|
||
|
|
||
|
FeatureSource* featureSource();
|
||
|
const FeatureSource* featureSource() const;
|
||
|
|
||
|
void loadFeatureSource(const std::string& styleSheetURI, const osgDB::Options* options);
|
||
|
|
||
|
|
||
|
private:
|
||
|
|
||
|
|
||
|
std::string _attribution;
|
||
|
std::string _url;
|
||
|
std::string _type;
|
||
|
std::string _name;
|
||
|
|
||
|
std::vector< std::string > _tiles;
|
||
|
|
||
|
osg::ref_ptr< FeatureSource > _featureSource;
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
class FilterExpression
|
||
|
{
|
||
|
public:
|
||
|
Json::Value _filter;
|
||
|
};
|
||
|
|
||
|
class Layer
|
||
|
{
|
||
|
public:
|
||
|
Layer();
|
||
|
|
||
|
const std::string& id() const;
|
||
|
std::string& id();
|
||
|
|
||
|
const std::string& source() const;
|
||
|
std::string& source();
|
||
|
|
||
|
const std::string& sourceLayer() const;
|
||
|
std::string& sourceLayer();
|
||
|
|
||
|
const std::string& type() const;
|
||
|
std::string& type();
|
||
|
|
||
|
|
||
|
const unsigned int& minZoom() const;
|
||
|
unsigned int& minZoom();
|
||
|
|
||
|
const unsigned int& maxZoom() const;
|
||
|
unsigned int& maxZoom();
|
||
|
|
||
|
Paint& paint();
|
||
|
const Paint& paint() const;
|
||
|
|
||
|
FilterExpression& filter();
|
||
|
const FilterExpression& filter() const;
|
||
|
|
||
|
private:
|
||
|
std::string _id;
|
||
|
std::string _source;
|
||
|
std::string _sourceLayer;
|
||
|
std::string _type;
|
||
|
unsigned int _minZoom = 0;
|
||
|
unsigned int _maxZoom = 24;
|
||
|
Paint _paint;
|
||
|
FilterExpression _filter;
|
||
|
};
|
||
|
|
||
|
const std::string& version() const;
|
||
|
|
||
|
const std::string& name() const;
|
||
|
|
||
|
const URI& glyphs() const;
|
||
|
|
||
|
const URI& sprite() const;
|
||
|
|
||
|
|
||
|
std::vector< Layer >& layers();
|
||
|
const std::vector< Layer >& layers() const;
|
||
|
|
||
|
std::vector< Source >& sources();
|
||
|
const std::vector< Source >& sources() const;
|
||
|
|
||
|
const ResourceLibrary* spriteLibrary() const;
|
||
|
|
||
|
static StyleSheet load(const URI& location, const osgDB::Options* options);
|
||
|
|
||
|
StyleSheet();
|
||
|
|
||
|
private:
|
||
|
|
||
|
std::string _version;
|
||
|
std::string _name;
|
||
|
URI _sprite;
|
||
|
URI _glyphs;
|
||
|
|
||
|
std::vector< Source > _sources;
|
||
|
std::vector< Layer > _layers;
|
||
|
|
||
|
osg::ref_ptr< ResourceLibrary > _spriteLibrary;
|
||
|
static ResourceLibrary* loadSpriteLibrary(const URI& sprite);
|
||
|
};
|
||
|
}
|
||
|
|
||
|
|
||
|
class OSGEARTH_EXPORT MapBoxGLImageLayer : public osgEarth::ImageLayer
|
||
|
{
|
||
|
public: // serialization
|
||
|
class OSGEARTH_EXPORT Options : public ImageLayer::Options {
|
||
|
public:
|
||
|
META_LayerOptions(osgEarth, Options, ImageLayer::Options);
|
||
|
OE_OPTION(URI, url);
|
||
|
OE_OPTION(std::string, key);
|
||
|
OE_OPTION(bool, disableText);
|
||
|
OE_OPTION(float, pixelScale);
|
||
|
virtual Config getConfig() const;
|
||
|
private:
|
||
|
void fromConfig( const Config& conf );
|
||
|
};
|
||
|
|
||
|
public:
|
||
|
META_Layer(osgEarth, MapBoxGLImageLayer, Options, osgEarth::ImageLayer, MapboxGLImage);
|
||
|
|
||
|
//! URL of the style url
|
||
|
void setURL(const URI& value);
|
||
|
const URI& getURL() const;
|
||
|
|
||
|
//! API key
|
||
|
void setKey(const std::string& value);
|
||
|
const std::string& getKey() const;
|
||
|
|
||
|
void setDisableText(const bool& value);
|
||
|
const bool& getDisableText() const;
|
||
|
|
||
|
void setPixelScale(const float& value);
|
||
|
const float& getPixelScale() const;
|
||
|
|
||
|
// Opens the layer and returns a status
|
||
|
virtual Status openImplementation();
|
||
|
|
||
|
virtual GeoImage createImageImplementation(const TileKey& key, ProgressCallback* progress) const;
|
||
|
|
||
|
protected: // Layer
|
||
|
|
||
|
// Called by Map when it adds this layer
|
||
|
virtual void addedToMap(const class Map*);
|
||
|
|
||
|
// Called by Map when it removes this layer
|
||
|
virtual void removedFromMap(const class Map*);
|
||
|
|
||
|
// post-ctor initialization
|
||
|
virtual void init();
|
||
|
|
||
|
|
||
|
protected:
|
||
|
|
||
|
virtual ~MapBoxGLImageLayer() { }
|
||
|
|
||
|
osg::observer_ptr< const osgEarth::Map > _map;
|
||
|
MapBoxGL::StyleSheet _styleSheet;
|
||
|
osg::ref_ptr< MapboxGLGlyphManager > _glyphManager;
|
||
|
};
|
||
|
} // namespace osgEarth
|
||
|
|
||
|
OSGEARTH_SPECIALIZE_CONFIG(osgEarth::MapBoxGLImageLayer::Options);
|
||
|
|
||
|
#endif // OSGEARTH_MAPBOXGL_IMAGE_LAYER
|