/* -*-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 */ #ifndef OSGEARTH_MAPBOXGL_IMAGE_LAYER #define OSGEARTH_MAPBOXGL_IMAGE_LAYER 1 #include #include #include #include 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 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 expression) : _expression(std::move(expression)), _isConstant(false) { } void setConstant(T constant) { _constant = std::move(constant); _isConstant = true; } void setExpression(PropertyExpression 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 _expression; bool _isConstant = true; }; // https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#paint-property class Paint { public: Paint(); const PropertyValue& backgroundColor() const; PropertyValue& backgroundColor(); const PropertyValue& backgroundOpacity() const; PropertyValue& backgroundOpacity(); const PropertyValue& fillColor() const; PropertyValue& fillColor(); const optional& fillPattern() const; optional& fillPattern(); const PropertyValue& lineColor() const; PropertyValue& lineColor(); const PropertyValue& lineWidth() const; PropertyValue& lineWidth(); const optional& textField() const; optional& textField(); const optional& textFont() const; optional& textFont(); const PropertyValue& textColor() const; PropertyValue& textColor(); const PropertyValue& textHaloColor() const; PropertyValue& textHaloColor(); const PropertyValue& textSize() const; PropertyValue& textSize(); const optional& textAnchor() const; optional& textAnchor(); const optional& iconImage() const; optional& iconImage(); const optional& visibility() const; optional& visibility(); private: //Background PropertyValue _backgroundColor = PropertyValue(Color::Transparent); PropertyValue _backgroundOpacity = PropertyValue(1.0f); // Fill optional _fillAntialias; PropertyValue _fillColor = PropertyValue(Color("#000000")); PropertyValue _fillOpacity = PropertyValue(1.0f); optional _fillPattern; // Line PropertyValue _lineColor = PropertyValue(Color::Green); PropertyValue _lineWidth = PropertyValue(1.0f); // Text optional _textField; optional _textFont; PropertyValue _textColor = PropertyValue(Color::Black); PropertyValue _textHaloColor = PropertyValue(Color::Transparent); PropertyValue _textSize = PropertyValue(16.0f); optional _textAnchor; // Icon optional _iconImage; optional _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