From d4fcf5af1f3becfb25c8c602bfb9bda2e20cbcb6 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Fri, 3 Jul 2020 11:16:55 +0200 Subject: [PATCH 01/11] Hillshade layer improvements --- all/modules/layers/HillshadeRasterTileLayer.i | 6 +- all/modules/rastertiles/ElevationDecoder.i | 29 +++ .../rastertiles/MapBoxElevationDataDecoder.i | 30 +++ .../TerrariumElevationDataDecoder.i | 30 +++ .../PackageManagerValhallaRoutingService.i | 4 +- .../routing/ValhallaOfflineRoutingService.i | 4 +- .../layers/HillshadeRasterTileLayer.cpp | 192 +++++++++++++++--- all/native/layers/HillshadeRasterTileLayer.h | 33 ++- all/native/rastertiles/ElevationDecoder.cpp | 148 ++++++++++++++ all/native/rastertiles/ElevationDecoder.h | 52 +++++ .../MapBoxElevationDataDecoder.cpp | 27 +++ .../rastertiles/MapBoxElevationDataDecoder.h | 40 ++++ .../TerrariumElevationDataDecoder.cpp | 27 +++ .../TerrariumElevationDataDecoder.h | 40 ++++ all/native/renderers/TileRenderer.cpp | 23 ++- all/native/renderers/TileRenderer.h | 6 + .../PackageManagerValhallaRoutingService.cpp | 12 +- .../PackageManagerValhallaRoutingService.h | 6 + .../routing/ValhallaOfflineRoutingService.cpp | 12 +- .../routing/ValhallaOfflineRoutingService.h | 6 + all/native/routing/ValhallaRoutingProxy.cpp | 13 +- all/native/routing/ValhallaRoutingProxy.h | 5 +- 22 files changed, 705 insertions(+), 40 deletions(-) create mode 100644 all/modules/rastertiles/ElevationDecoder.i create mode 100644 all/modules/rastertiles/MapBoxElevationDataDecoder.i create mode 100644 all/modules/rastertiles/TerrariumElevationDataDecoder.i create mode 100644 all/native/rastertiles/ElevationDecoder.cpp create mode 100644 all/native/rastertiles/ElevationDecoder.h create mode 100644 all/native/rastertiles/MapBoxElevationDataDecoder.cpp create mode 100644 all/native/rastertiles/MapBoxElevationDataDecoder.h create mode 100644 all/native/rastertiles/TerrariumElevationDataDecoder.cpp create mode 100644 all/native/rastertiles/TerrariumElevationDataDecoder.h diff --git a/all/modules/layers/HillshadeRasterTileLayer.i b/all/modules/layers/HillshadeRasterTileLayer.i index ea243b0a9..335504249 100644 --- a/all/modules/layers/HillshadeRasterTileLayer.i +++ b/all/modules/layers/HillshadeRasterTileLayer.i @@ -3,7 +3,7 @@ %module HillshadeRasterTileLayer -!proxy_imports(carto::HillshadeRasterTileLayer, datasources.TileDataSource, graphics.Color, layers.RasterTileLayer) +!proxy_imports(carto::HillshadeRasterTileLayer, core.MapPos, core.MapPosVector, core.IntVector, datasources.TileDataSource, rastertiles.ElevationDecoder, graphics.Color, layers.RasterTileLayer) %{ #include "layers/HillshadeRasterTileLayer.h" @@ -15,13 +15,17 @@ %include %import "datasources/TileDataSource.i" +%import "rastertiles/ElevationDecoder.i" %import "graphics/Color.i" %import "layers/RasterTileLayer.i" +%import "core/IntVector.i" !polymorphic_shared_ptr(carto::HillshadeRasterTileLayer, layers.HillshadeRasterTileLayer) %attribute(carto::HillshadeRasterTileLayer, float, Contrast, getContrast, setContrast) %attribute(carto::HillshadeRasterTileLayer, float, HeightScale, getHeightScale, setHeightScale) +%attribute(carto::HillshadeRasterTileLayer, float, IlluminationDirection, getIlluminationDirection, setIlluminationDirection) +%attribute(carto::HillshadeRasterTileLayer, bool, IlluminationMapRotationEnabled, getIlluminationMapRotationEnabled, setIlluminationMapRotationEnabled) %attributeval(carto::HillshadeRasterTileLayer, carto::Color, ShadowColor, getShadowColor, setShadowColor) %attributeval(carto::HillshadeRasterTileLayer, carto::Color, HighlightColor, getHighlightColor, setHighlightColor) %std_exceptions(carto::HillshadeRasterTileLayer::HillshadeRasterTileLayer) diff --git a/all/modules/rastertiles/ElevationDecoder.i b/all/modules/rastertiles/ElevationDecoder.i new file mode 100644 index 000000000..1098f884c --- /dev/null +++ b/all/modules/rastertiles/ElevationDecoder.i @@ -0,0 +1,29 @@ +#ifndef _ELEVATIONDECODER_I +#define _ELEVATIONDECODER_I + +%module ElevationDecoder + +!proxy_imports(carto::ElevationDecoder, graphics.Color, core.MapPos, core.MapPosVector, core.IntVector, datasources.TileDataSource) + +%{ +#include "rastertiles/ElevationDecoder.h" +#include +%} + +%include +%include + +%import "graphics/Color.i" +%import "core/MapPos.i" +%import "datasources/TileDataSource.i" +%import "core/IntVector.i" + +!polymorphic_shared_ptr(carto::ElevationDecoder, rastertiles.ElevationDecoder) + +!standard_equals(carto::ElevationDecoder); +%ignore carto::ElevationDecoder::getColorComponentCoefficients; +%ignore carto::ElevationDecoder::getVectorTileScales; + +%include "rastertiles/ElevationDecoder.h" + +#endif diff --git a/all/modules/rastertiles/MapBoxElevationDataDecoder.i b/all/modules/rastertiles/MapBoxElevationDataDecoder.i new file mode 100644 index 000000000..51f4c5584 --- /dev/null +++ b/all/modules/rastertiles/MapBoxElevationDataDecoder.i @@ -0,0 +1,30 @@ +#ifndef _MAPBOXELEVATIONDATADECODER_I +#define _MAPBOXELEVATIONDATADECODER_I + +%module MapBoxElevationDataDecoder + +%module(directors="1") MapBoxElevationDataDecoder +!proxy_imports(carto::MapBoxElevationDataDecoder, graphics.Color, core.MapPos, core.MapPosVector, datasources.TileDataSource, rastertiles.ElevationDecoder) + +%{ +#include "rastertiles/MapBoxElevationDataDecoder.h" +#include +%} + +%include +%include + +%import "graphics/Color.i" +%import "rastertiles/ElevationDecoder.i" + +!polymorphic_shared_ptr(carto::MapBoxElevationDataDecoder, rastertiles.MapBoxElevationDataDecoder) +!standard_equals(carto::MapBoxElevationDataDecoder); + +%feature("director") carto::MapBoxElevationDataDecoder; + +%ignore carto::MapBoxElevationDataDecoder::getColorComponentCoefficients; +%ignore carto::MapBoxElevationDataDecoder::getVectorTileScales; + +%include "rastertiles/MapBoxElevationDataDecoder.h" + +#endif diff --git a/all/modules/rastertiles/TerrariumElevationDataDecoder.i b/all/modules/rastertiles/TerrariumElevationDataDecoder.i new file mode 100644 index 000000000..bc42fb65a --- /dev/null +++ b/all/modules/rastertiles/TerrariumElevationDataDecoder.i @@ -0,0 +1,30 @@ +#ifndef _TERRARIUMELEVATIONDATADECODER_I +#define _TERRARIUMELEVATIONDATADECODER_I + +%module TerrariumElevationDataDecoder + +%module(directors="1") TerrariumElevationDataDecoder +!proxy_imports(carto::TerrariumElevationDataDecoder, graphics.Color, core.MapPos, core.MapPosVector, datasources.TileDataSource, rastertiles.ElevationDecoder) + +%{ +#include "rastertiles/TerrariumElevationDataDecoder.h" +#include +%} + +%include +%include + +%import "graphics/Color.i" +%import "rastertiles/ElevationDecoder.i" + +!polymorphic_shared_ptr(carto::TerrariumElevationDataDecoder, rastertiles.TerrariumElevationDataDecoder) +!standard_equals(carto::TerrariumElevationDataDecoder); + +%feature("director") carto::TerrariumElevationDataDecoder; + +%ignore carto::TerrariumElevationDataDecoder::getColorComponentCoefficients; +%ignore carto::TerrariumElevationDataDecoder::getVectorTileScales; + +%include "rastertiles/TerrariumElevationDataDecoder.h" + +#endif diff --git a/all/modules/routing/PackageManagerValhallaRoutingService.i b/all/modules/routing/PackageManagerValhallaRoutingService.i index 1f428359c..90a89559a 100644 --- a/all/modules/routing/PackageManagerValhallaRoutingService.i +++ b/all/modules/routing/PackageManagerValhallaRoutingService.i @@ -5,7 +5,7 @@ #if defined(_CARTO_ROUTING_SUPPORT) && defined(_CARTO_VALHALLA_ROUTING_SUPPORT) && defined(_CARTO_PACKAGEMANAGER_SUPPORT) -!proxy_imports(carto::PackageManagerValhallaRoutingService, packagemanager.PackageManager, core.Variant, routing.RoutingService, routing.RoutingRequest, routing.RoutingResult, routing.RouteMatchingRequest, routing.RouteMatchingResult) +!proxy_imports(carto::PackageManagerValhallaRoutingService, packagemanager.PackageManager, core.Variant, routing.RoutingService, routing.RoutingRequest, routing.RoutingResult, routing.RouteMatchingRequest, routing.RouteMatchingResult, datasources.TileDataSource, rastertiles.ElevationDecoder) %{ #include "routing/PackageManagerValhallaRoutingService.h" @@ -20,6 +20,8 @@ %import "core/Variant.i" %import "routing/RoutingService.i" %import "packagemanager/PackageManager.i" +%import "datasources/TileDataSource.i" +%import "rastertiles/ElevationDecoder.i" !polymorphic_shared_ptr(carto::PackageManagerValhallaRoutingService, routing.PackageManagerValhallaRoutingService) diff --git a/all/modules/routing/ValhallaOfflineRoutingService.i b/all/modules/routing/ValhallaOfflineRoutingService.i index 227dbf819..614ea0a43 100644 --- a/all/modules/routing/ValhallaOfflineRoutingService.i +++ b/all/modules/routing/ValhallaOfflineRoutingService.i @@ -5,7 +5,7 @@ #if defined(_CARTO_ROUTING_SUPPORT) && defined(_CARTO_VALHALLA_ROUTING_SUPPORT) && defined(_CARTO_OFFLINE_SUPPORT) -!proxy_imports(carto::ValhallaOfflineRoutingService, core.Variant, routing.RoutingService, routing.RoutingRequest, routing.RoutingResult, routing.RouteMatchingRequest, routing.RouteMatchingResult) +!proxy_imports(carto::ValhallaOfflineRoutingService, core.Variant, routing.RoutingService, routing.RoutingRequest, routing.RoutingResult, routing.RouteMatchingRequest, routing.RouteMatchingResult, datasources.TileDataSource, rastertiles.ElevationDecoder) %{ #include "routing/ValhallaOfflineRoutingService.h" @@ -19,6 +19,8 @@ %import "core/Variant.i" %import "routing/RoutingService.i" +%import "datasources/TileDataSource.i" +%import "rastertiles/ElevationDecoder.i" !polymorphic_shared_ptr(carto::ValhallaOfflineRoutingService, routing.ValhallaOfflineRoutingService) diff --git a/all/native/layers/HillshadeRasterTileLayer.cpp b/all/native/layers/HillshadeRasterTileLayer.cpp index b54c97014..c34c6a00b 100644 --- a/all/native/layers/HillshadeRasterTileLayer.cpp +++ b/all/native/layers/HillshadeRasterTileLayer.cpp @@ -1,12 +1,16 @@ #include "HillshadeRasterTileLayer.h" -#include "graphics/Bitmap.h" #include "renderers/MapRenderer.h" #include "renderers/TileRenderer.h" #include "utils/Log.h" +#include "core/BinaryData.h" +#include "projections/EPSG3857.h" +#include "projections/Projection.h" #include #include +#include "graphics/Bitmap.h" + #include #include #include @@ -14,27 +18,90 @@ #include #include #include +#include + +namespace { + + + + std::array readTileBitmapColor(const std::shared_ptr& bitmap, int x, int y) { + x = std::max(0, std::min(x, (int)bitmap->getWidth() - 1)); + y = bitmap->getHeight() - 1 - std::max(0, std::min(y, (int)bitmap->getHeight() - 1)); + + switch (bitmap->getColorFormat()) { + case carto::ColorFormat::COLOR_FORMAT_GRAYSCALE: + { + std::uint8_t val = bitmap->getPixelData()[y * bitmap->getWidth() + x]; + return std::array { { val, val, val, 255 } }; + } + case carto::ColorFormat::COLOR_FORMAT_RGB: + { + const std::uint8_t* valPtr = &bitmap->getPixelData()[(y * bitmap->getWidth() + x) * 3]; + return std::array { { valPtr[0], valPtr[1], valPtr[2], 255 } }; + } + case carto::ColorFormat::COLOR_FORMAT_RGBA: + { + const std::uint8_t* valPtr = &bitmap->getPixelData()[(y * bitmap->getWidth() + x) * 4]; + return std::array { { valPtr[0], valPtr[1], valPtr[2], valPtr[3] } }; + } + default: + break; + } + return std::array { { 0, 0, 0, 0 } }; + } + + std::array readTileBitmapColor(const std::shared_ptr& bitmap, float x, float y) { + std::array result { { 0, 0, 0, 0 } }; + for (int dy = 0; dy < 2; dy++) { + for (int dx = 0; dx < 2; dx++) { + int x0 = static_cast(std::floor(x)); + int y0 = static_cast(std::floor(y)); + + std::array color = readTileBitmapColor(bitmap, x0 + dx, y0 + dy); + for (int i = 0; i < 4; i++) { + result[i] += color[i] * (dx == 0 ? x0 + 1.0f - x : x - x0) * (dy == 0 ? y0 + 1.0f - y : y - y0); + } + } + } + return std::array { { static_cast(result[0]), static_cast(result[1]), static_cast(result[2]), static_cast(result[3]) } }; + } + + int readPixelAltitude(const std::shared_ptr& tileBitmap, const carto::MapBounds& tileBounds, const carto::MapPos& pos, const std::array& components) { + int tileSize = tileBitmap->getWidth(); + float pixelX = (pos.getX() - tileBounds.getMin().getX()) / (tileBounds.getMax().getX() - tileBounds.getMin().getX()) * tileSize; + float pixelY = tileSize - (pos.getY() - tileBounds.getMin().getY()) / (tileBounds.getMax().getY() - tileBounds.getMin().getY()) * tileSize; + std::array interpolatedComponents = readTileBitmapColor(tileBitmap, pixelX - 0.5f, pixelY - 0.5f); + int altitude = std::round(components[0] * (float)interpolatedComponents[0] + components[1] * (float)interpolatedComponents[1] + components[2] * (float)interpolatedComponents[2] + components[3] * (float)interpolatedComponents[3]/255.0f); + return altitude; + } +} -namespace carto { +namespace carto +{ - HillshadeRasterTileLayer::HillshadeRasterTileLayer(const std::shared_ptr& dataSource) : - RasterTileLayer(dataSource), + HillshadeRasterTileLayer::HillshadeRasterTileLayer(const std::shared_ptr &dataSource, const std::shared_ptr &elevationDecoder) : RasterTileLayer(dataSource), + _elevationDecoder(elevationDecoder), _contrast(0.5f), _heightScale(1.0f), _shadowColor(0, 0, 0, 255), - _highlightColor(255, 255, 255, 255) + _highlightColor(255, 255, 255, 255), + _illuminationDirection(67), + _illuminationMapRotationEnabled(true) { } - - HillshadeRasterTileLayer::~HillshadeRasterTileLayer() { + + HillshadeRasterTileLayer::~HillshadeRasterTileLayer() + { } - - float HillshadeRasterTileLayer::getContrast() const { + + float HillshadeRasterTileLayer::getContrast() const + { std::lock_guard lock(_mutex); return _contrast; } - void HillshadeRasterTileLayer::setContrast(float contrast) { + void HillshadeRasterTileLayer::setContrast(float contrast) + { { std::lock_guard lock(_mutex); _contrast = std::min(1.0f, std::max(0.0f, contrast)); @@ -42,12 +109,14 @@ namespace carto { tilesChanged(false); } - float HillshadeRasterTileLayer::getHeightScale() const { + float HillshadeRasterTileLayer::getHeightScale() const + { std::lock_guard lock(_mutex); return _heightScale; } - void HillshadeRasterTileLayer::setHeightScale(float heightScale) { + void HillshadeRasterTileLayer::setHeightScale(float heightScale) + { { std::lock_guard lock(_mutex); _heightScale = heightScale; @@ -55,12 +124,14 @@ namespace carto { tilesChanged(false); } - Color HillshadeRasterTileLayer::getShadowColor() const { + Color HillshadeRasterTileLayer::getShadowColor() const + { std::lock_guard lock(_mutex); return _shadowColor; } - void HillshadeRasterTileLayer::setShadowColor(const Color& color) { + void HillshadeRasterTileLayer::setShadowColor(const Color &color) + { { std::lock_guard lock(_mutex); _shadowColor = color; @@ -68,12 +139,14 @@ namespace carto { redraw(); } - Color HillshadeRasterTileLayer::getHighlightColor() const { + Color HillshadeRasterTileLayer::getHighlightColor() const + { std::lock_guard lock(_mutex); return _highlightColor; } - void HillshadeRasterTileLayer::setHighlightColor(const Color& color) { + void HillshadeRasterTileLayer::setHighlightColor(const Color &color) + { { std::lock_guard lock(_mutex); _highlightColor = color; @@ -81,22 +154,55 @@ namespace carto { redraw(); } - bool HillshadeRasterTileLayer::onDrawFrame(float deltaSeconds, BillboardSorter& billboardSorter, const ViewState& viewState) { + float HillshadeRasterTileLayer::getIlluminationDirection() const + { + std::lock_guard lock(_mutex); + return _illuminationDirection; + } + void HillshadeRasterTileLayer::setIlluminationDirection(float direction) + { + { + std::lock_guard lock(_mutex); + _illuminationDirection = direction; + } + redraw(); + } + bool HillshadeRasterTileLayer::getIlluminationMapRotationEnabled() const + { + std::lock_guard lock(_mutex); + return _illuminationMapRotationEnabled; + } + void HillshadeRasterTileLayer::setIlluminationMapRotationEnabled(bool enabled) + { + { + std::lock_guard lock(_mutex); + _illuminationMapRotationEnabled = enabled; + } + redraw(); + } + + bool HillshadeRasterTileLayer::onDrawFrame(float deltaSeconds, BillboardSorter &billboardSorter, const ViewState &viewState) + { updateTileLoadListener(); - if (auto mapRenderer = getMapRenderer()) { + if (auto mapRenderer = getMapRenderer()) + { float opacity = getOpacity(); - if (opacity < 1.0f) { + if (opacity < 1.0f) + { mapRenderer->clearAndBindScreenFBO(Color(0, 0, 0, 0), false, false); } _tileRenderer->setRasterFilterMode(getRasterFilterMode()); _tileRenderer->setNormalMapShadowColor(getShadowColor()); _tileRenderer->setNormalMapHighlightColor(getHighlightColor()); + _tileRenderer->setNormalIlluminationDirection(getIlluminationDirection()); + _tileRenderer->setNormalIlluminationMapRotationEnabled(getIlluminationMapRotationEnabled()); bool refresh = _tileRenderer->onDrawFrame(deltaSeconds, viewState); - if (opacity < 1.0f) { + if (opacity < 1.0f) + { mapRenderer->blendAndUnbindScreenFBO(opacity); } @@ -104,8 +210,9 @@ namespace carto { } return false; } - - std::shared_ptr HillshadeRasterTileLayer::createVectorTile(const MapTile& tile, const std::shared_ptr& bitmap) const { + + std::shared_ptr HillshadeRasterTileLayer::createVectorTile(const MapTile &tile, const std::shared_ptr &bitmap) const + { std::uint8_t alpha = 0; std::array scales; { @@ -113,21 +220,22 @@ namespace carto { alpha = static_cast(_contrast * 255.0f); float exaggeration = tile.getZoom() < 2 ? 0.2f : tile.getZoom() < 5 ? 0.3f : 0.35f; float scale = 16 * _heightScale * static_cast(bitmap->getHeight() * std::pow(2.0, tile.getZoom() * (1 - exaggeration)) / 40075016.6855785); - scales = std::array { 65536 * scale, 256 * scale, scale, 0.0f }; + scales = _elevationDecoder->getVectorTileScales(); + std::transform(scales.begin(), scales.end(), scales.begin(), [&scale](float &c) { return c * scale; }); } - + // Build normal map from height map vt::TileId vtTileId(tile.getZoom(), tile.getX(), tile.getY()); std::shared_ptr rgbaBitmap = bitmap->getRGBABitmap(); - auto rgbaBitmapDataPtr = reinterpret_cast(rgbaBitmap->getPixelData().data()); + auto rgbaBitmapDataPtr = reinterpret_cast(rgbaBitmap->getPixelData().data()); std::vector rgbaBitmapData(rgbaBitmapDataPtr, rgbaBitmapDataPtr + rgbaBitmap->getWidth() * rgbaBitmap->getHeight()); auto vtBitmap = std::make_shared(rgbaBitmap->getWidth(), rgbaBitmap->getHeight(), std::move(rgbaBitmapData)); vt::NormalMapBuilder normalMapBuilder(scales, alpha); std::shared_ptr normalMap = normalMapBuilder.buildNormalMapFromHeightMap(vtTileId, vtBitmap); - auto normalMapDataPtr = reinterpret_cast(normalMap->data.data()); + auto normalMapDataPtr = reinterpret_cast(normalMap->data.data()); std::vector normalMapData(normalMapDataPtr, normalMapDataPtr + normalMap->data.size() * sizeof(std::uint32_t)); auto tileBitmap = std::make_shared(vt::TileBitmap::Type::NORMALMAP, vt::TileBitmap::Format::RGBA, normalMap->width, normalMap->height, std::move(normalMapData)); - + // Build vector tile from created normal map float tileSize = 256.0f; // 'normalized' tile size in pixels. Not really important std::shared_ptr tileBackground = std::make_shared(vt::Color(), std::shared_ptr()); @@ -135,7 +243,33 @@ namespace carto { vt::TileLayerBuilder tileLayerBuilder(vtTileId, 0, vtTransformer, tileSize, 1.0f); // Note: the size/scale argument is ignored tileLayerBuilder.addBitmap(tileBitmap); std::shared_ptr tileLayer = tileLayerBuilder.buildTileLayer(boost::optional(), vt::FloatFunction(1)); - return std::make_shared(vtTileId, tileSize, tileBackground, std::vector > { tileLayer }); + return std::make_shared(vtTileId, tileSize, tileBackground, std::vector>{tileLayer}); } -} + + std::shared_ptr HillshadeRasterTileLayer::getMapTileBitmap(const MapTile& mapTile) const { + std::shared_ptr tileData = _dataSource->loadTile(mapTile); + if (!tileData) { + Log::Error("HillshadeRasterTileLayer::getMapTileBitmap: Null tile data"); + return NULL; + } + + std::shared_ptr binaryData = tileData->getData(); + if (!binaryData) { + Log::Error("HillshadeRasterTileLayer::getMapTileBitmap: Null tile binary data"); + return NULL; + } + int size = binaryData->size(); + std::shared_ptr tileBitmap = Bitmap::CreateFromCompressed(binaryData); + return tileBitmap; + } + + int HillshadeRasterTileLayer::getElevation(MapPos &pos) const + { + return _elevationDecoder->getElevation(getDataSource(), pos); + } + std::vector HillshadeRasterTileLayer::getElevations(const std::vector poses) const + { + return _elevationDecoder->getElevations(getDataSource(), poses); + } +} // namespace carto diff --git a/all/native/layers/HillshadeRasterTileLayer.h b/all/native/layers/HillshadeRasterTileLayer.h index e11fcca42..1ef89c969 100644 --- a/all/native/layers/HillshadeRasterTileLayer.h +++ b/all/native/layers/HillshadeRasterTileLayer.h @@ -8,7 +8,9 @@ #define _CARTO_HILLSHADERASTERTILELAYER_H_ #include "graphics/Color.h" +#include "components/DirectorPtr.h" #include "layers/RasterTileLayer.h" +#include "rastertiles/ElevationDecoder.h" namespace carto { @@ -23,7 +25,7 @@ namespace carto { * Constructs a HillshadeRasterTileLayer object from a data source. * @param dataSource The data source from which this layer loads data. */ - explicit HillshadeRasterTileLayer(const std::shared_ptr& dataSource); + explicit HillshadeRasterTileLayer(const std::shared_ptr& dataSource, const std::shared_ptr& elevationDecoder); virtual ~HillshadeRasterTileLayer(); /** @@ -69,16 +71,45 @@ namespace carto { * @param color The new highlight color of the layer. */ void setHighlightColor(const Color& color); + /** + * Returns the illumination direction of the layer. + * @return direction in degrees. + */ + float getIlluminationDirection() const; + /** + * Sets the illumination direction. + * @param direction in degrees. + */ + void setIlluminationDirection(float direction); + /** + * Returns wheter the illumination direction should change with the map rotation. + * @return enabled + */ + bool getIlluminationMapRotationEnabled() const; + /** + * Sets wheter the illumination direction should change with the map rotation. + * @param enabled whether to enable or not. + */ + void setIlluminationMapRotationEnabled(bool enabled); + + int getElevation(MapPos& pos) const; + std::vector getElevations(const std::vector poses) const; protected: virtual bool onDrawFrame(float deltaSeconds, BillboardSorter& billboardSorter, const ViewState& viewState); virtual std::shared_ptr createVectorTile(const MapTile& tile, const std::shared_ptr& bitmap) const; + std::shared_ptr getMapTileBitmap(const MapTile& mapTile) const; + + const DirectorPtr _elevationDecoder; + float _contrast; float _heightScale; Color _shadowColor; Color _highlightColor; + float _illuminationDirection; + bool _illuminationMapRotationEnabled; }; } diff --git a/all/native/rastertiles/ElevationDecoder.cpp b/all/native/rastertiles/ElevationDecoder.cpp new file mode 100644 index 000000000..8b121c167 --- /dev/null +++ b/all/native/rastertiles/ElevationDecoder.cpp @@ -0,0 +1,148 @@ +#include "ElevationDecoder.h" +#include "datasources/TileDataSource.h" +#include "utils/Log.h" +#include "utils/TileUtils.h" +#include "core/MapBounds.h" +#include "core/MapTile.h" +#include "graphics/Bitmap.h" +#include "projections/EPSG3857.h" +#include "projections/Projection.h" + +#include +namespace { + + + + std::array readTileBitmapColor(const std::shared_ptr& bitmap, int x, int y) { + x = std::max(0, std::min(x, (int)bitmap->getWidth() - 1)); + y = bitmap->getHeight() - 1 - std::max(0, std::min(y, (int)bitmap->getHeight() - 1)); + + switch (bitmap->getColorFormat()) { + case carto::ColorFormat::COLOR_FORMAT_GRAYSCALE: + { + std::uint8_t val = bitmap->getPixelData()[y * bitmap->getWidth() + x]; + return std::array { { val, val, val, 255 } }; + } + case carto::ColorFormat::COLOR_FORMAT_RGB: + { + const std::uint8_t* valPtr = &bitmap->getPixelData()[(y * bitmap->getWidth() + x) * 3]; + return std::array { { valPtr[0], valPtr[1], valPtr[2], 255 } }; + } + case carto::ColorFormat::COLOR_FORMAT_RGBA: + { + const std::uint8_t* valPtr = &bitmap->getPixelData()[(y * bitmap->getWidth() + x) * 4]; + return std::array { { valPtr[0], valPtr[1], valPtr[2], valPtr[3] } }; + } + default: + break; + } + return std::array { { 0, 0, 0, 0 } }; + } + + std::array readTileBitmapColor(const std::shared_ptr& bitmap, float x, float y) { + std::array result { { 0, 0, 0, 0 } }; + for (int dy = 0; dy < 2; dy++) { + for (int dx = 0; dx < 2; dx++) { + int x0 = static_cast(std::floor(x)); + int y0 = static_cast(std::floor(y)); + + std::array color = readTileBitmapColor(bitmap, x0 + dx, y0 + dy); + for (int i = 0; i < 4; i++) { + result[i] += color[i] * (dx == 0 ? x0 + 1.0f - x : x - x0) * (dy == 0 ? y0 + 1.0f - y : y - y0); + } + } + } + return std::array { { static_cast(result[0]), static_cast(result[1]), static_cast(result[2]), static_cast(result[3]) } }; + } + + int readPixelAltitude(const std::shared_ptr& tileBitmap, const carto::MapBounds& tileBounds, const carto::MapPos& pos, const std::array& components) { + int tileSize = tileBitmap->getWidth(); + float pixelX = (pos.getX() - tileBounds.getMin().getX()) / (tileBounds.getMax().getX() - tileBounds.getMin().getX()) * tileSize; + float pixelY = tileSize - (pos.getY() - tileBounds.getMin().getY()) / (tileBounds.getMax().getY() - tileBounds.getMin().getY()) * tileSize; + std::array interpolatedComponents = readTileBitmapColor(tileBitmap, (int)pixelX, (int)pixelY); + int altitude = std::round(components[0] * (float)interpolatedComponents[0] + components[1] * (float)interpolatedComponents[1] + components[2] * (float)interpolatedComponents[2] + components[3] * (float)interpolatedComponents[3]/255.0f); + return altitude; + } +} +namespace carto +{ + ElevationDecoder::~ElevationDecoder() + { + } + + ElevationDecoder::ElevationDecoder() + { + } + float ElevationDecoder::decodeHeight(const Color &encodedHeight) const + { + // the 4th component is used to "translate" the result + const std::array components = getColorComponentCoefficients(); + return components[0] * encodedHeight.getR() + components[1] * encodedHeight.getG() + components[2] * encodedHeight.getB() + components[3] * encodedHeight.getA(); + } + std::shared_ptr ElevationDecoder::getMapTileBitmap(std::shared_ptr dataSource, const MapTile& mapTile) const { + std::shared_ptr tileData = dataSource->loadTile(mapTile); + if (!tileData) { + Log::Error("ElevationDecoder::getMapTileBitmap: Null tile data"); + return NULL; + } + + std::shared_ptr binaryData = tileData->getData(); + if (!binaryData) { + Log::Error("ElevationDecoder::getMapTileBitmap: Null tile binary data"); + return NULL; + } + std::shared_ptr tileBitmap = Bitmap::CreateFromCompressed(binaryData); + return tileBitmap; + } + int ElevationDecoder::getElevation(std::shared_ptr dataSource, const MapPos &pos) const + { + // we need to transform pos to dataSource projection + // TODO: how to check if pos is in Wgs84? + std::shared_ptr projection = dataSource->getProjection(); + MapPos dataSourcePos = projection->fromWgs84(pos); + + // The tile is flipped so to get the bitmap we need to flip it + MapTile mapTile = TileUtils::CalculateMapTile(dataSourcePos, dataSource->getMaxZoom(), projection); + MapTile flippedMapTile = mapTile.getFlipped(); + + std::shared_ptr tileBitmap = getMapTileBitmap(dataSource, flippedMapTile); + if (!tileBitmap) { + Log::Error("ElevationDecoder::getElevation: Null tile bitmap"); + return -1000000; + } + std::array components = getColorComponentCoefficients(); + return readPixelAltitude(tileBitmap, TileUtils::CalculateMapTileBounds(mapTile, projection), dataSourcePos, components); + } + std::vector ElevationDecoder::getElevations(std::shared_ptr dataSource, const std::vector poses) const + { + std::map>> indexedTiles; + std::vector results; + std::shared_ptr projection = dataSource->getProjection(); + std::array components = getColorComponentCoefficients(); + for (auto it = poses.begin(); it != poses.end(); it++) { + // TODO: how to check if pos is in Wgs84? + MapPos dataSourcePos = projection->fromWgs84(*it); + // The tile is flipped so to get the bitmap we need to flip it + MapTile mapTile = TileUtils::CalculateMapTile(dataSourcePos, dataSource->getMaxZoom(), projection); + MapTile flippedMapTile = mapTile.getFlipped(); + long long tileId = mapTile.getTileId(); + std::map>>::iterator iter(indexedTiles.lower_bound(tileId)); + Log::Debugf("ElevationDecoder::getElevations: %d, %d, %d, %d",it->getY(),it->getY(), tileId, iter == indexedTiles.end()); + if (iter == indexedTiles.end()) { + std::shared_ptr tileBitmap = getMapTileBitmap(dataSource, flippedMapTile); + MapBounds tileBounds = TileUtils::CalculateMapTileBounds(mapTile, projection); + std::pair> pair = std::make_pair(tileBounds, tileBitmap); + indexedTiles.insert(std::pair>>(iter->first, pair)); + int altitude = readPixelAltitude(tileBitmap, tileBounds, dataSourcePos, components); + results.push_back(altitude); + } else { + std::pair> pair = iter->second; + const std::shared_ptr& tileBitmap = pair.second; + const MapBounds& tileBounds = pair.first; + int altitude = readPixelAltitude(tileBitmap, tileBounds, dataSourcePos, components); + results.push_back(altitude); + } + } + return results; + } +} // namespace carto diff --git a/all/native/rastertiles/ElevationDecoder.h b/all/native/rastertiles/ElevationDecoder.h new file mode 100644 index 000000000..b6cc5b2f5 --- /dev/null +++ b/all/native/rastertiles/ElevationDecoder.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016 CartoDB. All rights reserved. + * Copying and using this code is allowed only according + * to license terms, as given in https://cartodb.com/terms/ + */ + +#ifndef _CARTO_ELEVATIONDECODER_H_ +#define _CARTO_ELEVATIONDECODER_H_ + +#include "graphics/Color.h" +#include "core/MapTile.h" +#include "core/MapPos.h" + +#include +#include +#include +#include +#include + +#include + +#include + +namespace carto { + class Bitmap; + class TileDataSource; + /** + * Abstract base class for raster elevation decoders. + */ + class ElevationDecoder { + public: + /** + * Constructs an ElevationDecoder. + */ + ElevationDecoder(); + virtual ~ElevationDecoder(); + + virtual float decodeHeight(const Color& encodedHeight) const; + virtual std::array getVectorTileScales() const = 0; + virtual std::array getColorComponentCoefficients() const = 0; + + int getElevation(std::shared_ptr dataSource, const MapPos &pos) const; + std::vector getElevations(std::shared_ptr dataSource, const std::vector poses) const; + + protected: + std::shared_ptr getMapTileBitmap(std::shared_ptr dataSource, const MapTile& mapTile) const; + + }; + +} + +#endif diff --git a/all/native/rastertiles/MapBoxElevationDataDecoder.cpp b/all/native/rastertiles/MapBoxElevationDataDecoder.cpp new file mode 100644 index 000000000..14efbeaea --- /dev/null +++ b/all/native/rastertiles/MapBoxElevationDataDecoder.cpp @@ -0,0 +1,27 @@ +#include "MapBoxElevationDataDecoder.h" + +namespace carto +{ + + MapBoxElevationDataDecoder::MapBoxElevationDataDecoder() : + ElevationDecoder() + { + } + + MapBoxElevationDataDecoder::~MapBoxElevationDataDecoder() + { + } + + std::array MapBoxElevationDataDecoder::getColorComponentCoefficients() const + { + return COMPONENTS; + } + + std::array MapBoxElevationDataDecoder::getVectorTileScales() const + { + return SCALES; + } + + const std::array MapBoxElevationDataDecoder::COMPONENTS = std::array{256 * 256 * 0.1f, 256 * 0.1f, 0.1f, -10000.0f}; + const std::array MapBoxElevationDataDecoder::SCALES = std::array{256 * 256, 256.0f, 1.0f, 0.0f}; +} // namespace carto diff --git a/all/native/rastertiles/MapBoxElevationDataDecoder.h b/all/native/rastertiles/MapBoxElevationDataDecoder.h new file mode 100644 index 000000000..7a6198a3f --- /dev/null +++ b/all/native/rastertiles/MapBoxElevationDataDecoder.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016 CartoDB. All rights reserved. + * Copying and using this code is allowed only according + * to license terms, as given in https://cartodb.com/terms/ + */ + +#ifndef _CARTO_MAPBOXELEVATIONDATADECODER_H_ +#define _CARTO_MAPBOXELEVATIONDATADECODER_H_ + +#include "rastertiles/ElevationDecoder.h" + +#include +#include +#include +#include + +namespace carto { + + /** + * A decoder for MapBox encoded elevation tiles + */ + class MapBoxElevationDataDecoder : public ElevationDecoder { + public: + /** + * Constructs a new MapBoxElevationDataDecoder. + */ + MapBoxElevationDataDecoder(); + virtual ~MapBoxElevationDataDecoder(); + + virtual std::array getVectorTileScales() const; + virtual std::array getColorComponentCoefficients() const; + + private : + static const std::array COMPONENTS; + static const std::array SCALES; + }; + +} + +#endif diff --git a/all/native/rastertiles/TerrariumElevationDataDecoder.cpp b/all/native/rastertiles/TerrariumElevationDataDecoder.cpp new file mode 100644 index 000000000..7f31cdf93 --- /dev/null +++ b/all/native/rastertiles/TerrariumElevationDataDecoder.cpp @@ -0,0 +1,27 @@ +#include "TerrariumElevationDataDecoder.h" + +namespace carto +{ + + TerrariumElevationDataDecoder::TerrariumElevationDataDecoder() : + ElevationDecoder() + { + } + + TerrariumElevationDataDecoder::~TerrariumElevationDataDecoder() + { + } + + std::array TerrariumElevationDataDecoder::getColorComponentCoefficients() const + { + return COMPONENTS; + } + + std::array TerrariumElevationDataDecoder::getVectorTileScales() const + { + return SCALES; + } + + const std::array TerrariumElevationDataDecoder::COMPONENTS = std::array{256.0f, 1.0f, 1.0f / 256, -32768.0f}; + const std::array TerrariumElevationDataDecoder::SCALES = std::array{256.0f, 1.0f, 1.0f / 256, -32768.0f}; +} // namespace carto diff --git a/all/native/rastertiles/TerrariumElevationDataDecoder.h b/all/native/rastertiles/TerrariumElevationDataDecoder.h new file mode 100644 index 000000000..cc93d02d2 --- /dev/null +++ b/all/native/rastertiles/TerrariumElevationDataDecoder.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016 CartoDB. All rights reserved. + * Copying and using this code is allowed only according + * to license terms, as given in https://cartodb.com/terms/ + */ + +#ifndef _CARTO_TERRARIUMELEVATIONDATADECODER_H_ +#define _CARTO_TERRARIUMELEVATIONDATADECODER_H_ + +#include "rastertiles/ElevationDecoder.h" + +#include +#include +#include +#include + +namespace carto { + + /** + * A decoder for Terrarium encoded elevation tiles + */ + class TerrariumElevationDataDecoder : public ElevationDecoder { + public: + /** + * Constructs a new TerrariumElevationDataDecoder. + */ + TerrariumElevationDataDecoder(); + virtual ~TerrariumElevationDataDecoder(); + + virtual std::array getVectorTileScales() const; + virtual std::array getColorComponentCoefficients() const; + + private : + static const std::array COMPONENTS; + static const std::array SCALES; + }; + +} + +#endif diff --git a/all/native/renderers/TileRenderer.cpp b/all/native/renderers/TileRenderer.cpp index eab05a66e..8f07a09f9 100644 --- a/all/native/renderers/TileRenderer.cpp +++ b/all/native/renderers/TileRenderer.cpp @@ -9,6 +9,7 @@ #include "renderers/utils/GLResourceManager.h" #include "renderers/utils/VTRenderer.h" #include "utils/Log.h" +#include "utils/Const.h" #include #include @@ -35,6 +36,9 @@ namespace carto { _horizontalLayerOffset(0), _viewDir(0, 0, 0), _mainLightDir(0, 0, 0), + _normalIlluminationMapRotationEnabled(false), + _normalIlluminationDirection(45), + _mapRotation(0), _tiles(), _mutex() { @@ -97,6 +101,15 @@ namespace carto { std::lock_guard lock(_mutex); _normalMapHighlightColor = color; } + void TileRenderer::setNormalIlluminationDirection(float direction) { + std::lock_guard lock(_mutex); + _normalIlluminationDirection = direction; + } + + void TileRenderer::setNormalIlluminationMapRotationEnabled(bool enabled) { + std::lock_guard lock(_mutex); + _normalIlluminationMapRotationEnabled = enabled; + } void TileRenderer::offsetLayerHorizontally(double offset) { std::lock_guard lock(_mutex); @@ -120,6 +133,8 @@ namespace carto { tileRenderer->setSubTileBlending(_subTileBlending); tileRenderer->setRasterFilterMode(_rasterFilterMode); + + _mapRotation = viewState.getRotation(); _viewDir = cglib::unit(viewState.getFocusPosNormal()); if (auto options = _options.lock()) { MapPos internalFocusPos = viewState.getProjectionSurface()->calculateMapPos(viewState.getFocusPos()); @@ -322,9 +337,15 @@ namespace carto { tileRenderer->setLightingShader3D(lightingShader3D); vt::GLTileRenderer::LightingShader lightingShaderNormalMap(false, LIGHTING_SHADER_NORMALMAP, [this](GLuint shaderProgram, const vt::ViewState& viewState) { + float azimuthal = _normalIlluminationDirection * Const::DEG_TO_RAD; + if (_normalIlluminationMapRotationEnabled) { + azimuthal -= _mapRotation * Const::DEG_TO_RAD; + } + MapVec viewDir = MapVec(std::cos(azimuthal), std::sin(azimuthal)); + cglib::vec3 cViewDir(viewDir.getX(), viewDir.getY(), 1); glUniform4f(glGetUniformLocation(shaderProgram, "u_shadowColor"), _normalMapShadowColor.getR() / 255.0f, _normalMapShadowColor.getG() / 255.0f, _normalMapShadowColor.getB() / 255.0f, _normalMapShadowColor.getA() / 255.0f); glUniform4f(glGetUniformLocation(shaderProgram, "u_highlightColor"), _normalMapHighlightColor.getR() / 255.0f, _normalMapHighlightColor.getG() / 255.0f, _normalMapHighlightColor.getB() / 255.0f, _normalMapHighlightColor.getA() / 255.0f); - glUniform3fv(glGetUniformLocation(shaderProgram, "u_lightDir"), 1, _mainLightDir.data()); + glUniform3fv(glGetUniformLocation(shaderProgram, "u_lightDir"), 1,cViewDir.data() ); }); tileRenderer->setLightingShaderNormalMap(lightingShaderNormalMap); } diff --git a/all/native/renderers/TileRenderer.h b/all/native/renderers/TileRenderer.h index 0842e5523..002b7c255 100644 --- a/all/native/renderers/TileRenderer.h +++ b/all/native/renderers/TileRenderer.h @@ -53,6 +53,8 @@ namespace carto { void setRasterFilterMode(vt::RasterFilterMode filterMode); void setNormalMapShadowColor(const Color& color); void setNormalMapHighlightColor(const Color& color); + void setNormalIlluminationMapRotationEnabled(bool enabled); + void setNormalIlluminationDirection(float direction); void offsetLayerHorizontally(double offset); @@ -89,6 +91,10 @@ namespace carto { double _horizontalLayerOffset; cglib::vec3 _viewDir; cglib::vec3 _mainLightDir; + double _normalIlluminationDirection; + bool _normalIlluminationMapRotationEnabled; + double _mapRotation; + std::map > _tiles; mutable std::mutex _mutex; diff --git a/all/native/routing/PackageManagerValhallaRoutingService.cpp b/all/native/routing/PackageManagerValhallaRoutingService.cpp index 18a55fff2..4703fdb76 100644 --- a/all/native/routing/PackageManagerValhallaRoutingService.cpp +++ b/all/native/routing/PackageManagerValhallaRoutingService.cpp @@ -6,6 +6,8 @@ #include "packagemanager/handlers/ValhallaRoutingPackageHandler.h" #include "projections/Projection.h" #include "routing/ValhallaRoutingProxy.h" +#include "datasources/TileDataSource.h" +#include "rastertiles/ElevationDecoder.h" #include "utils/Const.h" #include "utils/Log.h" @@ -19,7 +21,9 @@ namespace carto { _profile("pedestrian"), _configuration(ValhallaRoutingProxy::GetDefaultConfiguration()), _cachedPackageDatabases(), - _mutex() + _mutex(), + _elevationDataSource(), + _elevationDecoder() { if (!packageManager) { throw NullArgumentException("Null packageManager"); @@ -128,7 +132,7 @@ namespace carto { _cachedPackageDatabases = packageDatabases; } - result = ValhallaRoutingProxy::CalculateRoute(_cachedPackageDatabases, _profile, _configuration, request); + result = ValhallaRoutingProxy::CalculateRoute(_cachedPackageDatabases, _profile, _configuration, request, _elevationDataSource, _elevationDecoder); }); return result; @@ -148,6 +152,10 @@ namespace carto { // Impossible } + void PackageManagerValhallaRoutingService::connectElevationDataSource(const std::shared_ptr& dataSource, const std::shared_ptr& elevationDecoder) { + _elevationDataSource = dataSource; + _elevationDecoder = elevationDecoder; + } } #endif diff --git a/all/native/routing/PackageManagerValhallaRoutingService.h b/all/native/routing/PackageManagerValhallaRoutingService.h index 0ffd3898e..81d8990cc 100644 --- a/all/native/routing/PackageManagerValhallaRoutingService.h +++ b/all/native/routing/PackageManagerValhallaRoutingService.h @@ -23,6 +23,8 @@ namespace sqlite3pp { } namespace carto { + class TileDataSource; + class ElevationDecoder; /** * A routing service that uses routing packages from package manager. @@ -56,6 +58,8 @@ namespace carto { virtual std::shared_ptr calculateRoute(const std::shared_ptr& request) const; + void connectElevationDataSource(const std::shared_ptr& dataSource, const std::shared_ptr& elevationDecoder); + protected: class PackageManagerListener : public PackageManager::OnChangeListener { public: @@ -78,6 +82,8 @@ namespace carto { private: std::shared_ptr _packageManagerListener; + std::shared_ptr _elevationDataSource; + std::shared_ptr _elevationDecoder; }; } diff --git a/all/native/routing/ValhallaOfflineRoutingService.cpp b/all/native/routing/ValhallaOfflineRoutingService.cpp index 18982877d..689fd11d3 100644 --- a/all/native/routing/ValhallaOfflineRoutingService.cpp +++ b/all/native/routing/ValhallaOfflineRoutingService.cpp @@ -3,6 +3,8 @@ #include "ValhallaOfflineRoutingService.h" #include "components/Exceptions.h" #include "routing/ValhallaRoutingProxy.h" +#include "datasources/TileDataSource.h" +#include "rastertiles/ElevationDecoder.h" #include "utils/Const.h" #include "utils/Log.h" @@ -16,7 +18,9 @@ namespace carto { _database(), _profile("pedestrian"), _configuration(ValhallaRoutingProxy::GetDefaultConfiguration()), - _mutex() + _mutex(), + _elevationDataSource(), + _elevationDecoder() { _database.reset(new sqlite3pp::database()); if (_database->connect_v2(path.c_str(), SQLITE_OPEN_READONLY) != SQLITE_OK) { @@ -82,9 +86,13 @@ namespace carto { } std::lock_guard lock(_mutex); - return ValhallaRoutingProxy::CalculateRoute(std::vector > { _database }, _profile, _configuration, request); + return ValhallaRoutingProxy::CalculateRoute(std::vector > { _database }, _profile, _configuration, request, _elevationDataSource, _elevationDecoder); } + void ValhallaOfflineRoutingService::connectElevationDataSource(const std::shared_ptr& dataSource, const std::shared_ptr& elevationDecoder) { + _elevationDataSource = dataSource; + _elevationDecoder = elevationDecoder; + } } #endif diff --git a/all/native/routing/ValhallaOfflineRoutingService.h b/all/native/routing/ValhallaOfflineRoutingService.h index f4eb3a8b2..34dafeb1b 100644 --- a/all/native/routing/ValhallaOfflineRoutingService.h +++ b/all/native/routing/ValhallaOfflineRoutingService.h @@ -21,6 +21,8 @@ namespace sqlite3pp { } namespace carto { + class TileDataSource; + class ElevationDecoder; /** * An offline routing service that uses Valhalla routing tiles. @@ -55,11 +57,15 @@ namespace carto { virtual std::shared_ptr calculateRoute(const std::shared_ptr& request) const; + void connectElevationDataSource(const std::shared_ptr& dataSource, const std::shared_ptr& elevationDecoder); + private: std::shared_ptr _database; std::string _profile; Variant _configuration; mutable std::mutex _mutex; + std::shared_ptr _elevationDataSource; + std::shared_ptr _elevationDecoder; }; } diff --git a/all/native/routing/ValhallaRoutingProxy.cpp b/all/native/routing/ValhallaRoutingProxy.cpp index f0269c5c3..bdf2b6aaf 100644 --- a/all/native/routing/ValhallaRoutingProxy.cpp +++ b/all/native/routing/ValhallaRoutingProxy.cpp @@ -7,6 +7,8 @@ #include "components/Exceptions.h" #include "projections/Projection.h" #include "projections/EPSG3857.h" +#include "datasources/TileDataSource.h" +#include "rastertiles/ElevationDecoder.h" #include "routing/RoutingRequest.h" #include "routing/RoutingResult.h" #include "routing/RouteMatchingRequest.h" @@ -215,7 +217,8 @@ namespace carto { return ParseRouteMatchingResult(request->getProjection(), resultString); } - std::shared_ptr ValhallaRoutingProxy::CalculateRoute(const std::vector >& databases, const std::string& profile, const Variant& config, const std::shared_ptr& request) { + std::shared_ptr ValhallaRoutingProxy::CalculateRoute(const std::vector >& databases, const std::string& profile, const Variant& config, const std::shared_ptr& request, const std::shared_ptr& elevationDataSource, + const std::shared_ptr& elevationDecoder) { std::string resultString; try { std::stringstream ss; @@ -228,6 +231,14 @@ namespace carto { valhalla::ParseApi(SerializeRoutingRequest(profile, request), valhalla::Options::route, api); valhalla::loki::loki_worker_t lokiworker(configTree, reader); + if (elevationDecoder && elevationDataSource) { + auto lambdaGet = [elevationDecoder, elevationDataSource](const valhalla::midgard::PointLL& coords){ + const MapPos pos(coords.x(), coords.y()); + return elevationDecoder->getElevation(elevationDataSource, pos); + }; + auto objFunc = valhalla::skadi::GetHeightFunc(lambdaGet); + lokiworker.get_sample().set_get_func(objFunc); + } lokiworker.route(api); valhalla::thor::thor_worker_t thorworker(configTree, reader); thorworker.route(api); diff --git a/all/native/routing/ValhallaRoutingProxy.h b/all/native/routing/ValhallaRoutingProxy.h index b1bd22fd9..d34833f6e 100644 --- a/all/native/routing/ValhallaRoutingProxy.h +++ b/all/native/routing/ValhallaRoutingProxy.h @@ -27,6 +27,8 @@ namespace carto { class RoutingResult; class RouteMatchingRequest; class RouteMatchingResult; + class TileDataSource; + class ElevationDecoder; class ValhallaRoutingProxy { public: @@ -35,7 +37,8 @@ namespace carto { #ifdef _CARTO_VALHALLA_ROUTING_SUPPORT static std::shared_ptr MatchRoute(const std::vector >& databases, const std::string& profile, const Variant& config, const std::shared_ptr& request); - static std::shared_ptr CalculateRoute(const std::vector >& databases, const std::string& profile, const Variant& config, const std::shared_ptr& request); + static std::shared_ptr CalculateRoute(const std::vector >& databases, const std::string& profile, const Variant& config, const std::shared_ptr& request, const std::shared_ptr& elevationDataSource, + const std::shared_ptr& elevationDecoder); #endif static Variant GetDefaultConfiguration(); From 8955d228830f8a8a1b40c85023f8e2b8f973fa51 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Mon, 17 Aug 2020 10:52:18 +0200 Subject: [PATCH 02/11] fixed elevations decoding when the path is along multiple tiles --- all/native/rastertiles/ElevationDecoder.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/all/native/rastertiles/ElevationDecoder.cpp b/all/native/rastertiles/ElevationDecoder.cpp index 8b121c167..1bb1b3eb4 100644 --- a/all/native/rastertiles/ElevationDecoder.cpp +++ b/all/native/rastertiles/ElevationDecoder.cpp @@ -126,13 +126,12 @@ namespace carto MapTile mapTile = TileUtils::CalculateMapTile(dataSourcePos, dataSource->getMaxZoom(), projection); MapTile flippedMapTile = mapTile.getFlipped(); long long tileId = mapTile.getTileId(); - std::map>>::iterator iter(indexedTiles.lower_bound(tileId)); - Log::Debugf("ElevationDecoder::getElevations: %d, %d, %d, %d",it->getY(),it->getY(), tileId, iter == indexedTiles.end()); + std::map>>::iterator iter(indexedTiles.find(tileId)); if (iter == indexedTiles.end()) { std::shared_ptr tileBitmap = getMapTileBitmap(dataSource, flippedMapTile); MapBounds tileBounds = TileUtils::CalculateMapTileBounds(mapTile, projection); std::pair> pair = std::make_pair(tileBounds, tileBitmap); - indexedTiles.insert(std::pair>>(iter->first, pair)); + indexedTiles.insert(std::pair>>(tileId, pair)); int altitude = readPixelAltitude(tileBitmap, tileBounds, dataSourcePos, components); results.push_back(altitude); } else { From 472f5b948e8c113fc69a072f8599cb8791f3f60b Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Mon, 17 Aug 2020 14:49:44 +0200 Subject: [PATCH 03/11] removed valhalla height decoder for now No really addition value requires changes to the valhalla sources --- .../PackageManagerValhallaRoutingService.cpp | 12 ++---------- .../routing/PackageManagerValhallaRoutingService.h | 6 ------ .../routing/ValhallaOfflineRoutingService.cpp | 13 ++----------- all/native/routing/ValhallaOfflineRoutingService.h | 6 ------ all/native/routing/ValhallaRoutingProxy.cpp | 13 +------------ all/native/routing/ValhallaRoutingProxy.h | 3 +-- 6 files changed, 6 insertions(+), 47 deletions(-) diff --git a/all/native/routing/PackageManagerValhallaRoutingService.cpp b/all/native/routing/PackageManagerValhallaRoutingService.cpp index 4703fdb76..18a55fff2 100644 --- a/all/native/routing/PackageManagerValhallaRoutingService.cpp +++ b/all/native/routing/PackageManagerValhallaRoutingService.cpp @@ -6,8 +6,6 @@ #include "packagemanager/handlers/ValhallaRoutingPackageHandler.h" #include "projections/Projection.h" #include "routing/ValhallaRoutingProxy.h" -#include "datasources/TileDataSource.h" -#include "rastertiles/ElevationDecoder.h" #include "utils/Const.h" #include "utils/Log.h" @@ -21,9 +19,7 @@ namespace carto { _profile("pedestrian"), _configuration(ValhallaRoutingProxy::GetDefaultConfiguration()), _cachedPackageDatabases(), - _mutex(), - _elevationDataSource(), - _elevationDecoder() + _mutex() { if (!packageManager) { throw NullArgumentException("Null packageManager"); @@ -132,7 +128,7 @@ namespace carto { _cachedPackageDatabases = packageDatabases; } - result = ValhallaRoutingProxy::CalculateRoute(_cachedPackageDatabases, _profile, _configuration, request, _elevationDataSource, _elevationDecoder); + result = ValhallaRoutingProxy::CalculateRoute(_cachedPackageDatabases, _profile, _configuration, request); }); return result; @@ -152,10 +148,6 @@ namespace carto { // Impossible } - void PackageManagerValhallaRoutingService::connectElevationDataSource(const std::shared_ptr& dataSource, const std::shared_ptr& elevationDecoder) { - _elevationDataSource = dataSource; - _elevationDecoder = elevationDecoder; - } } #endif diff --git a/all/native/routing/PackageManagerValhallaRoutingService.h b/all/native/routing/PackageManagerValhallaRoutingService.h index 81d8990cc..0ffd3898e 100644 --- a/all/native/routing/PackageManagerValhallaRoutingService.h +++ b/all/native/routing/PackageManagerValhallaRoutingService.h @@ -23,8 +23,6 @@ namespace sqlite3pp { } namespace carto { - class TileDataSource; - class ElevationDecoder; /** * A routing service that uses routing packages from package manager. @@ -58,8 +56,6 @@ namespace carto { virtual std::shared_ptr calculateRoute(const std::shared_ptr& request) const; - void connectElevationDataSource(const std::shared_ptr& dataSource, const std::shared_ptr& elevationDecoder); - protected: class PackageManagerListener : public PackageManager::OnChangeListener { public: @@ -82,8 +78,6 @@ namespace carto { private: std::shared_ptr _packageManagerListener; - std::shared_ptr _elevationDataSource; - std::shared_ptr _elevationDecoder; }; } diff --git a/all/native/routing/ValhallaOfflineRoutingService.cpp b/all/native/routing/ValhallaOfflineRoutingService.cpp index 689fd11d3..82d845f68 100644 --- a/all/native/routing/ValhallaOfflineRoutingService.cpp +++ b/all/native/routing/ValhallaOfflineRoutingService.cpp @@ -3,8 +3,6 @@ #include "ValhallaOfflineRoutingService.h" #include "components/Exceptions.h" #include "routing/ValhallaRoutingProxy.h" -#include "datasources/TileDataSource.h" -#include "rastertiles/ElevationDecoder.h" #include "utils/Const.h" #include "utils/Log.h" @@ -18,9 +16,7 @@ namespace carto { _database(), _profile("pedestrian"), _configuration(ValhallaRoutingProxy::GetDefaultConfiguration()), - _mutex(), - _elevationDataSource(), - _elevationDecoder() + _mutex() { _database.reset(new sqlite3pp::database()); if (_database->connect_v2(path.c_str(), SQLITE_OPEN_READONLY) != SQLITE_OK) { @@ -86,12 +82,7 @@ namespace carto { } std::lock_guard lock(_mutex); - return ValhallaRoutingProxy::CalculateRoute(std::vector > { _database }, _profile, _configuration, request, _elevationDataSource, _elevationDecoder); - } - - void ValhallaOfflineRoutingService::connectElevationDataSource(const std::shared_ptr& dataSource, const std::shared_ptr& elevationDecoder) { - _elevationDataSource = dataSource; - _elevationDecoder = elevationDecoder; + return ValhallaRoutingProxy::CalculateRoute(std::vector > { _database }, _profile, _configuration, request); } } diff --git a/all/native/routing/ValhallaOfflineRoutingService.h b/all/native/routing/ValhallaOfflineRoutingService.h index 34dafeb1b..f4eb3a8b2 100644 --- a/all/native/routing/ValhallaOfflineRoutingService.h +++ b/all/native/routing/ValhallaOfflineRoutingService.h @@ -21,8 +21,6 @@ namespace sqlite3pp { } namespace carto { - class TileDataSource; - class ElevationDecoder; /** * An offline routing service that uses Valhalla routing tiles. @@ -57,15 +55,11 @@ namespace carto { virtual std::shared_ptr calculateRoute(const std::shared_ptr& request) const; - void connectElevationDataSource(const std::shared_ptr& dataSource, const std::shared_ptr& elevationDecoder); - private: std::shared_ptr _database; std::string _profile; Variant _configuration; mutable std::mutex _mutex; - std::shared_ptr _elevationDataSource; - std::shared_ptr _elevationDecoder; }; } diff --git a/all/native/routing/ValhallaRoutingProxy.cpp b/all/native/routing/ValhallaRoutingProxy.cpp index bdf2b6aaf..f0269c5c3 100644 --- a/all/native/routing/ValhallaRoutingProxy.cpp +++ b/all/native/routing/ValhallaRoutingProxy.cpp @@ -7,8 +7,6 @@ #include "components/Exceptions.h" #include "projections/Projection.h" #include "projections/EPSG3857.h" -#include "datasources/TileDataSource.h" -#include "rastertiles/ElevationDecoder.h" #include "routing/RoutingRequest.h" #include "routing/RoutingResult.h" #include "routing/RouteMatchingRequest.h" @@ -217,8 +215,7 @@ namespace carto { return ParseRouteMatchingResult(request->getProjection(), resultString); } - std::shared_ptr ValhallaRoutingProxy::CalculateRoute(const std::vector >& databases, const std::string& profile, const Variant& config, const std::shared_ptr& request, const std::shared_ptr& elevationDataSource, - const std::shared_ptr& elevationDecoder) { + std::shared_ptr ValhallaRoutingProxy::CalculateRoute(const std::vector >& databases, const std::string& profile, const Variant& config, const std::shared_ptr& request) { std::string resultString; try { std::stringstream ss; @@ -231,14 +228,6 @@ namespace carto { valhalla::ParseApi(SerializeRoutingRequest(profile, request), valhalla::Options::route, api); valhalla::loki::loki_worker_t lokiworker(configTree, reader); - if (elevationDecoder && elevationDataSource) { - auto lambdaGet = [elevationDecoder, elevationDataSource](const valhalla::midgard::PointLL& coords){ - const MapPos pos(coords.x(), coords.y()); - return elevationDecoder->getElevation(elevationDataSource, pos); - }; - auto objFunc = valhalla::skadi::GetHeightFunc(lambdaGet); - lokiworker.get_sample().set_get_func(objFunc); - } lokiworker.route(api); valhalla::thor::thor_worker_t thorworker(configTree, reader); thorworker.route(api); diff --git a/all/native/routing/ValhallaRoutingProxy.h b/all/native/routing/ValhallaRoutingProxy.h index d34833f6e..209ea5e18 100644 --- a/all/native/routing/ValhallaRoutingProxy.h +++ b/all/native/routing/ValhallaRoutingProxy.h @@ -37,8 +37,7 @@ namespace carto { #ifdef _CARTO_VALHALLA_ROUTING_SUPPORT static std::shared_ptr MatchRoute(const std::vector >& databases, const std::string& profile, const Variant& config, const std::shared_ptr& request); - static std::shared_ptr CalculateRoute(const std::vector >& databases, const std::string& profile, const Variant& config, const std::shared_ptr& request, const std::shared_ptr& elevationDataSource, - const std::shared_ptr& elevationDecoder); + static std::shared_ptr CalculateRoute(const std::vector >& databases, const std::string& profile, const Variant& config, const std::shared_ptr& request); #endif static Variant GetDefaultConfiguration(); From afc3679af4134ebcbafa43e4c31be4b19bb8a938 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Tue, 27 Oct 2020 17:41:11 +0100 Subject: [PATCH 04/11] refactoring to remove dependency on DataSource from ElevationDecoder --- all/modules/core/DoubleVector.i | 18 +++ all/modules/layers/HillshadeRasterTileLayer.i | 4 +- all/modules/rastertiles/ElevationDecoder.i | 5 +- .../layers/HillshadeRasterTileLayer.cpp | 59 +++++++- all/native/layers/HillshadeRasterTileLayer.h | 4 +- all/native/rastertiles/ElevationDecoder.cpp | 130 +----------------- all/native/rastertiles/ElevationDecoder.h | 12 +- 7 files changed, 79 insertions(+), 153 deletions(-) create mode 100644 all/modules/core/DoubleVector.i diff --git a/all/modules/core/DoubleVector.i b/all/modules/core/DoubleVector.i new file mode 100644 index 000000000..9b614c3a3 --- /dev/null +++ b/all/modules/core/DoubleVector.i @@ -0,0 +1,18 @@ +#ifndef _DOUBLEVECTOR_I +#define _DOUBLEVECTOR_I + +#pragma SWIG nowarn=302 + +%module DoubleVector + +%include + +!value_type(std::vector, core.DoubleVector) + +#ifdef SWIGOBJECTIVEC +%template(NTDoubleVector) std::vector; +#else +%template(DoubleVector) std::vector; +#endif + +#endif \ No newline at end of file diff --git a/all/modules/layers/HillshadeRasterTileLayer.i b/all/modules/layers/HillshadeRasterTileLayer.i index 335504249..7ba5fc306 100644 --- a/all/modules/layers/HillshadeRasterTileLayer.i +++ b/all/modules/layers/HillshadeRasterTileLayer.i @@ -3,7 +3,7 @@ %module HillshadeRasterTileLayer -!proxy_imports(carto::HillshadeRasterTileLayer, core.MapPos, core.MapPosVector, core.IntVector, datasources.TileDataSource, rastertiles.ElevationDecoder, graphics.Color, layers.RasterTileLayer) +!proxy_imports(carto::HillshadeRasterTileLayer, core.MapPos, core.MapPosVector, core.DoubleVector, datasources.TileDataSource, rastertiles.ElevationDecoder, graphics.Color, layers.RasterTileLayer) %{ #include "layers/HillshadeRasterTileLayer.h" @@ -18,7 +18,7 @@ %import "rastertiles/ElevationDecoder.i" %import "graphics/Color.i" %import "layers/RasterTileLayer.i" -%import "core/IntVector.i" +%import "core/DoubleVector.i" !polymorphic_shared_ptr(carto::HillshadeRasterTileLayer, layers.HillshadeRasterTileLayer) diff --git a/all/modules/rastertiles/ElevationDecoder.i b/all/modules/rastertiles/ElevationDecoder.i index 1098f884c..34a5dddf0 100644 --- a/all/modules/rastertiles/ElevationDecoder.i +++ b/all/modules/rastertiles/ElevationDecoder.i @@ -3,7 +3,7 @@ %module ElevationDecoder -!proxy_imports(carto::ElevationDecoder, graphics.Color, core.MapPos, core.MapPosVector, core.IntVector, datasources.TileDataSource) +!proxy_imports(carto::ElevationDecoder, graphics.Color) %{ #include "rastertiles/ElevationDecoder.h" @@ -14,9 +14,6 @@ %include %import "graphics/Color.i" -%import "core/MapPos.i" -%import "datasources/TileDataSource.i" -%import "core/IntVector.i" !polymorphic_shared_ptr(carto::ElevationDecoder, rastertiles.ElevationDecoder) diff --git a/all/native/layers/HillshadeRasterTileLayer.cpp b/all/native/layers/HillshadeRasterTileLayer.cpp index c34c6a00b..d420ef8c4 100644 --- a/all/native/layers/HillshadeRasterTileLayer.cpp +++ b/all/native/layers/HillshadeRasterTileLayer.cpp @@ -2,6 +2,7 @@ #include "renderers/MapRenderer.h" #include "renderers/TileRenderer.h" #include "utils/Log.h" +#include "utils/TileUtils.h" #include "core/BinaryData.h" #include "projections/EPSG3857.h" #include "projections/Projection.h" @@ -66,12 +67,12 @@ namespace { return std::array { { static_cast(result[0]), static_cast(result[1]), static_cast(result[2]), static_cast(result[3]) } }; } - int readPixelAltitude(const std::shared_ptr& tileBitmap, const carto::MapBounds& tileBounds, const carto::MapPos& pos, const std::array& components) { + double readPixelAltitude(const std::shared_ptr& tileBitmap, const carto::MapBounds& tileBounds, const carto::MapPos& pos, const std::array& components) { int tileSize = tileBitmap->getWidth(); float pixelX = (pos.getX() - tileBounds.getMin().getX()) / (tileBounds.getMax().getX() - tileBounds.getMin().getX()) * tileSize; float pixelY = tileSize - (pos.getY() - tileBounds.getMin().getY()) / (tileBounds.getMax().getY() - tileBounds.getMin().getY()) * tileSize; std::array interpolatedComponents = readTileBitmapColor(tileBitmap, pixelX - 0.5f, pixelY - 0.5f); - int altitude = std::round(components[0] * (float)interpolatedComponents[0] + components[1] * (float)interpolatedComponents[1] + components[2] * (float)interpolatedComponents[2] + components[3] * (float)interpolatedComponents[3]/255.0f); + int altitude = (double)(components[0] * (float)interpolatedComponents[0] + components[1] * (float)interpolatedComponents[1] + components[2] * (float)interpolatedComponents[2] + components[3] * (float)interpolatedComponents[3]/255.0f); return altitude; } } @@ -264,12 +265,56 @@ namespace carto return tileBitmap; } - int HillshadeRasterTileLayer::getElevation(MapPos &pos) const + double HillshadeRasterTileLayer::getElevation(const MapPos &pos) const { - return _elevationDecoder->getElevation(getDataSource(), pos); - } - std::vector HillshadeRasterTileLayer::getElevations(const std::vector poses) const + std::shared_ptr dataSource = getDataSource(); + // we need to transform pos to dataSource projection + // TODO: how to check if pos is in Wgs84? + std::shared_ptr projection = dataSource->getProjection(); + MapPos dataSourcePos = projection->fromWgs84(pos); + + // The tile is flipped so to get the bitmap we need to flip it + MapTile mapTile = TileUtils::CalculateMapTile(dataSourcePos, dataSource->getMaxZoom(), projection); + MapTile flippedMapTile = mapTile.getFlipped(); + + std::shared_ptr tileBitmap = getMapTileBitmap(flippedMapTile); + if (!tileBitmap) { + Log::Error("ElevationDecoder::getElevation: Null tile bitmap"); + return -1000000; + } + std::array components = _elevationDecoder->getColorComponentCoefficients(); + return readPixelAltitude(tileBitmap, TileUtils::CalculateMapTileBounds(mapTile, projection), dataSourcePos, components); + } + std::vector HillshadeRasterTileLayer::getElevations(const std::vector poses) const { - return _elevationDecoder->getElevations(getDataSource(), poses); + std::shared_ptr dataSource = getDataSource(); + std::map>> indexedTiles; + std::vector results; + std::shared_ptr projection = dataSource->getProjection(); + std::array components = _elevationDecoder->getColorComponentCoefficients(); + for (auto it = poses.begin(); it != poses.end(); it++) { + // TODO: how to check if pos is in Wgs84? + MapPos dataSourcePos = projection->fromWgs84(*it); + // The tile is flipped so to get the bitmap we need to flip it + MapTile mapTile = TileUtils::CalculateMapTile(dataSourcePos, dataSource->getMaxZoom(), projection); + MapTile flippedMapTile = mapTile.getFlipped(); + long long tileId = mapTile.getTileId(); + std::map>>::iterator iter(indexedTiles.find(tileId)); + if (iter == indexedTiles.end()) { + std::shared_ptr tileBitmap = getMapTileBitmap(flippedMapTile); + MapBounds tileBounds = TileUtils::CalculateMapTileBounds(mapTile, projection); + std::pair> pair = std::make_pair(tileBounds, tileBitmap); + indexedTiles.insert(std::pair>>(tileId, pair)); + double altitude = readPixelAltitude(tileBitmap, tileBounds, dataSourcePos, components); + results.push_back(altitude); + } else { + std::pair> pair = iter->second; + const std::shared_ptr& tileBitmap = pair.second; + const MapBounds& tileBounds = pair.first; + double altitude = readPixelAltitude(tileBitmap, tileBounds, dataSourcePos, components); + results.push_back(altitude); + } + } + return results; } } // namespace carto diff --git a/all/native/layers/HillshadeRasterTileLayer.h b/all/native/layers/HillshadeRasterTileLayer.h index 1ef89c969..25236dd36 100644 --- a/all/native/layers/HillshadeRasterTileLayer.h +++ b/all/native/layers/HillshadeRasterTileLayer.h @@ -92,8 +92,8 @@ namespace carto { */ void setIlluminationMapRotationEnabled(bool enabled); - int getElevation(MapPos& pos) const; - std::vector getElevations(const std::vector poses) const; + double getElevation(const MapPos& pos) const; + std::vector getElevations(const std::vector poses) const; protected: virtual bool onDrawFrame(float deltaSeconds, BillboardSorter& billboardSorter, const ViewState& viewState); diff --git a/all/native/rastertiles/ElevationDecoder.cpp b/all/native/rastertiles/ElevationDecoder.cpp index 1bb1b3eb4..c4b6ab0af 100644 --- a/all/native/rastertiles/ElevationDecoder.cpp +++ b/all/native/rastertiles/ElevationDecoder.cpp @@ -1,69 +1,9 @@ #include "ElevationDecoder.h" -#include "datasources/TileDataSource.h" #include "utils/Log.h" #include "utils/TileUtils.h" -#include "core/MapBounds.h" -#include "core/MapTile.h" -#include "graphics/Bitmap.h" -#include "projections/EPSG3857.h" -#include "projections/Projection.h" #include -namespace { - - - std::array readTileBitmapColor(const std::shared_ptr& bitmap, int x, int y) { - x = std::max(0, std::min(x, (int)bitmap->getWidth() - 1)); - y = bitmap->getHeight() - 1 - std::max(0, std::min(y, (int)bitmap->getHeight() - 1)); - - switch (bitmap->getColorFormat()) { - case carto::ColorFormat::COLOR_FORMAT_GRAYSCALE: - { - std::uint8_t val = bitmap->getPixelData()[y * bitmap->getWidth() + x]; - return std::array { { val, val, val, 255 } }; - } - case carto::ColorFormat::COLOR_FORMAT_RGB: - { - const std::uint8_t* valPtr = &bitmap->getPixelData()[(y * bitmap->getWidth() + x) * 3]; - return std::array { { valPtr[0], valPtr[1], valPtr[2], 255 } }; - } - case carto::ColorFormat::COLOR_FORMAT_RGBA: - { - const std::uint8_t* valPtr = &bitmap->getPixelData()[(y * bitmap->getWidth() + x) * 4]; - return std::array { { valPtr[0], valPtr[1], valPtr[2], valPtr[3] } }; - } - default: - break; - } - return std::array { { 0, 0, 0, 0 } }; - } - - std::array readTileBitmapColor(const std::shared_ptr& bitmap, float x, float y) { - std::array result { { 0, 0, 0, 0 } }; - for (int dy = 0; dy < 2; dy++) { - for (int dx = 0; dx < 2; dx++) { - int x0 = static_cast(std::floor(x)); - int y0 = static_cast(std::floor(y)); - - std::array color = readTileBitmapColor(bitmap, x0 + dx, y0 + dy); - for (int i = 0; i < 4; i++) { - result[i] += color[i] * (dx == 0 ? x0 + 1.0f - x : x - x0) * (dy == 0 ? y0 + 1.0f - y : y - y0); - } - } - } - return std::array { { static_cast(result[0]), static_cast(result[1]), static_cast(result[2]), static_cast(result[3]) } }; - } - - int readPixelAltitude(const std::shared_ptr& tileBitmap, const carto::MapBounds& tileBounds, const carto::MapPos& pos, const std::array& components) { - int tileSize = tileBitmap->getWidth(); - float pixelX = (pos.getX() - tileBounds.getMin().getX()) / (tileBounds.getMax().getX() - tileBounds.getMin().getX()) * tileSize; - float pixelY = tileSize - (pos.getY() - tileBounds.getMin().getY()) / (tileBounds.getMax().getY() - tileBounds.getMin().getY()) * tileSize; - std::array interpolatedComponents = readTileBitmapColor(tileBitmap, (int)pixelX, (int)pixelY); - int altitude = std::round(components[0] * (float)interpolatedComponents[0] + components[1] * (float)interpolatedComponents[1] + components[2] * (float)interpolatedComponents[2] + components[3] * (float)interpolatedComponents[3]/255.0f); - return altitude; - } -} namespace carto { ElevationDecoder::~ElevationDecoder() @@ -73,75 +13,11 @@ namespace carto ElevationDecoder::ElevationDecoder() { } - float ElevationDecoder::decodeHeight(const Color &encodedHeight) const + + double ElevationDecoder::decodeHeight(const Color &encodedHeight) const { // the 4th component is used to "translate" the result const std::array components = getColorComponentCoefficients(); - return components[0] * encodedHeight.getR() + components[1] * encodedHeight.getG() + components[2] * encodedHeight.getB() + components[3] * encodedHeight.getA(); - } - std::shared_ptr ElevationDecoder::getMapTileBitmap(std::shared_ptr dataSource, const MapTile& mapTile) const { - std::shared_ptr tileData = dataSource->loadTile(mapTile); - if (!tileData) { - Log::Error("ElevationDecoder::getMapTileBitmap: Null tile data"); - return NULL; - } - - std::shared_ptr binaryData = tileData->getData(); - if (!binaryData) { - Log::Error("ElevationDecoder::getMapTileBitmap: Null tile binary data"); - return NULL; - } - std::shared_ptr tileBitmap = Bitmap::CreateFromCompressed(binaryData); - return tileBitmap; - } - int ElevationDecoder::getElevation(std::shared_ptr dataSource, const MapPos &pos) const - { - // we need to transform pos to dataSource projection - // TODO: how to check if pos is in Wgs84? - std::shared_ptr projection = dataSource->getProjection(); - MapPos dataSourcePos = projection->fromWgs84(pos); - - // The tile is flipped so to get the bitmap we need to flip it - MapTile mapTile = TileUtils::CalculateMapTile(dataSourcePos, dataSource->getMaxZoom(), projection); - MapTile flippedMapTile = mapTile.getFlipped(); - - std::shared_ptr tileBitmap = getMapTileBitmap(dataSource, flippedMapTile); - if (!tileBitmap) { - Log::Error("ElevationDecoder::getElevation: Null tile bitmap"); - return -1000000; - } - std::array components = getColorComponentCoefficients(); - return readPixelAltitude(tileBitmap, TileUtils::CalculateMapTileBounds(mapTile, projection), dataSourcePos, components); - } - std::vector ElevationDecoder::getElevations(std::shared_ptr dataSource, const std::vector poses) const - { - std::map>> indexedTiles; - std::vector results; - std::shared_ptr projection = dataSource->getProjection(); - std::array components = getColorComponentCoefficients(); - for (auto it = poses.begin(); it != poses.end(); it++) { - // TODO: how to check if pos is in Wgs84? - MapPos dataSourcePos = projection->fromWgs84(*it); - // The tile is flipped so to get the bitmap we need to flip it - MapTile mapTile = TileUtils::CalculateMapTile(dataSourcePos, dataSource->getMaxZoom(), projection); - MapTile flippedMapTile = mapTile.getFlipped(); - long long tileId = mapTile.getTileId(); - std::map>>::iterator iter(indexedTiles.find(tileId)); - if (iter == indexedTiles.end()) { - std::shared_ptr tileBitmap = getMapTileBitmap(dataSource, flippedMapTile); - MapBounds tileBounds = TileUtils::CalculateMapTileBounds(mapTile, projection); - std::pair> pair = std::make_pair(tileBounds, tileBitmap); - indexedTiles.insert(std::pair>>(tileId, pair)); - int altitude = readPixelAltitude(tileBitmap, tileBounds, dataSourcePos, components); - results.push_back(altitude); - } else { - std::pair> pair = iter->second; - const std::shared_ptr& tileBitmap = pair.second; - const MapBounds& tileBounds = pair.first; - int altitude = readPixelAltitude(tileBitmap, tileBounds, dataSourcePos, components); - results.push_back(altitude); - } - } - return results; + return (double)(components[0] * encodedHeight.getR() + components[1] * encodedHeight.getG() + components[2] * encodedHeight.getB() + components[3] * encodedHeight.getA()); } } // namespace carto diff --git a/all/native/rastertiles/ElevationDecoder.h b/all/native/rastertiles/ElevationDecoder.h index b6cc5b2f5..b0ed766ee 100644 --- a/all/native/rastertiles/ElevationDecoder.h +++ b/all/native/rastertiles/ElevationDecoder.h @@ -8,8 +8,6 @@ #define _CARTO_ELEVATIONDECODER_H_ #include "graphics/Color.h" -#include "core/MapTile.h" -#include "core/MapPos.h" #include #include @@ -22,8 +20,6 @@ #include namespace carto { - class Bitmap; - class TileDataSource; /** * Abstract base class for raster elevation decoders. */ @@ -35,16 +31,10 @@ namespace carto { ElevationDecoder(); virtual ~ElevationDecoder(); - virtual float decodeHeight(const Color& encodedHeight) const; + virtual double decodeHeight(const Color& encodedHeight) const; virtual std::array getVectorTileScales() const = 0; virtual std::array getColorComponentCoefficients() const = 0; - int getElevation(std::shared_ptr dataSource, const MapPos &pos) const; - std::vector getElevations(std::shared_ptr dataSource, const std::vector poses) const; - - protected: - std::shared_ptr getMapTileBitmap(std::shared_ptr dataSource, const MapTile& mapTile) const; - }; } From 246e9a33926320d7ba6cccda120961321fe858b8 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Fri, 30 Oct 2020 11:56:25 +0100 Subject: [PATCH 05/11] Fix elevation compute. Dont use readBitmapColor with floats as sometimes the average can give wrong rounded value and thus wrong elevation. This fixes -5000 elevations --- all/native/layers/HillshadeRasterTileLayer.cpp | 10 +++++----- all/native/rastertiles/ElevationDecoder.cpp | 7 ------- all/native/rastertiles/ElevationDecoder.h | 3 +-- all/native/rastertiles/MapBoxElevationDataDecoder.cpp | 4 ++-- all/native/rastertiles/MapBoxElevationDataDecoder.h | 4 ++-- .../rastertiles/TerrariumElevationDataDecoder.cpp | 4 ++-- all/native/rastertiles/TerrariumElevationDataDecoder.h | 4 ++-- 7 files changed, 14 insertions(+), 22 deletions(-) diff --git a/all/native/layers/HillshadeRasterTileLayer.cpp b/all/native/layers/HillshadeRasterTileLayer.cpp index d420ef8c4..6aae08fd4 100644 --- a/all/native/layers/HillshadeRasterTileLayer.cpp +++ b/all/native/layers/HillshadeRasterTileLayer.cpp @@ -67,12 +67,12 @@ namespace { return std::array { { static_cast(result[0]), static_cast(result[1]), static_cast(result[2]), static_cast(result[3]) } }; } - double readPixelAltitude(const std::shared_ptr& tileBitmap, const carto::MapBounds& tileBounds, const carto::MapPos& pos, const std::array& components) { + double readPixelAltitude(const std::shared_ptr& tileBitmap, const carto::MapBounds& tileBounds, const carto::MapPos& pos, const std::array& components) { int tileSize = tileBitmap->getWidth(); float pixelX = (pos.getX() - tileBounds.getMin().getX()) / (tileBounds.getMax().getX() - tileBounds.getMin().getX()) * tileSize; float pixelY = tileSize - (pos.getY() - tileBounds.getMin().getY()) / (tileBounds.getMax().getY() - tileBounds.getMin().getY()) * tileSize; - std::array interpolatedComponents = readTileBitmapColor(tileBitmap, pixelX - 0.5f, pixelY - 0.5f); - int altitude = (double)(components[0] * (float)interpolatedComponents[0] + components[1] * (float)interpolatedComponents[1] + components[2] * (float)interpolatedComponents[2] + components[3] * (float)interpolatedComponents[3]/255.0f); + std::array interpolatedComponents = readTileBitmapColor(tileBitmap, std::round(pixelX), std::round(pixelY)); + double altitude = (components[0] * interpolatedComponents[0] + components[1] * interpolatedComponents[1] + components[2] * interpolatedComponents[2] + components[3] * interpolatedComponents[3]/255.0f); return altitude; } } @@ -282,7 +282,7 @@ namespace carto Log::Error("ElevationDecoder::getElevation: Null tile bitmap"); return -1000000; } - std::array components = _elevationDecoder->getColorComponentCoefficients(); + std::array components = _elevationDecoder->getColorComponentCoefficients(); return readPixelAltitude(tileBitmap, TileUtils::CalculateMapTileBounds(mapTile, projection), dataSourcePos, components); } std::vector HillshadeRasterTileLayer::getElevations(const std::vector poses) const @@ -291,7 +291,7 @@ namespace carto std::map>> indexedTiles; std::vector results; std::shared_ptr projection = dataSource->getProjection(); - std::array components = _elevationDecoder->getColorComponentCoefficients(); + std::array components = _elevationDecoder->getColorComponentCoefficients(); for (auto it = poses.begin(); it != poses.end(); it++) { // TODO: how to check if pos is in Wgs84? MapPos dataSourcePos = projection->fromWgs84(*it); diff --git a/all/native/rastertiles/ElevationDecoder.cpp b/all/native/rastertiles/ElevationDecoder.cpp index c4b6ab0af..43784a798 100644 --- a/all/native/rastertiles/ElevationDecoder.cpp +++ b/all/native/rastertiles/ElevationDecoder.cpp @@ -13,11 +13,4 @@ namespace carto ElevationDecoder::ElevationDecoder() { } - - double ElevationDecoder::decodeHeight(const Color &encodedHeight) const - { - // the 4th component is used to "translate" the result - const std::array components = getColorComponentCoefficients(); - return (double)(components[0] * encodedHeight.getR() + components[1] * encodedHeight.getG() + components[2] * encodedHeight.getB() + components[3] * encodedHeight.getA()); - } } // namespace carto diff --git a/all/native/rastertiles/ElevationDecoder.h b/all/native/rastertiles/ElevationDecoder.h index b0ed766ee..891d37ef6 100644 --- a/all/native/rastertiles/ElevationDecoder.h +++ b/all/native/rastertiles/ElevationDecoder.h @@ -31,9 +31,8 @@ namespace carto { ElevationDecoder(); virtual ~ElevationDecoder(); - virtual double decodeHeight(const Color& encodedHeight) const; virtual std::array getVectorTileScales() const = 0; - virtual std::array getColorComponentCoefficients() const = 0; + virtual std::array getColorComponentCoefficients() const = 0; }; diff --git a/all/native/rastertiles/MapBoxElevationDataDecoder.cpp b/all/native/rastertiles/MapBoxElevationDataDecoder.cpp index 14efbeaea..69a8097b9 100644 --- a/all/native/rastertiles/MapBoxElevationDataDecoder.cpp +++ b/all/native/rastertiles/MapBoxElevationDataDecoder.cpp @@ -12,7 +12,7 @@ namespace carto { } - std::array MapBoxElevationDataDecoder::getColorComponentCoefficients() const + std::array MapBoxElevationDataDecoder::getColorComponentCoefficients() const { return COMPONENTS; } @@ -22,6 +22,6 @@ namespace carto return SCALES; } - const std::array MapBoxElevationDataDecoder::COMPONENTS = std::array{256 * 256 * 0.1f, 256 * 0.1f, 0.1f, -10000.0f}; + const std::array MapBoxElevationDataDecoder::COMPONENTS = std::array{256 * 256 * 0.1f, 256 * 0.1f, 0.1f, -10000.0f}; const std::array MapBoxElevationDataDecoder::SCALES = std::array{256 * 256, 256.0f, 1.0f, 0.0f}; } // namespace carto diff --git a/all/native/rastertiles/MapBoxElevationDataDecoder.h b/all/native/rastertiles/MapBoxElevationDataDecoder.h index 7a6198a3f..234570638 100644 --- a/all/native/rastertiles/MapBoxElevationDataDecoder.h +++ b/all/native/rastertiles/MapBoxElevationDataDecoder.h @@ -28,10 +28,10 @@ namespace carto { virtual ~MapBoxElevationDataDecoder(); virtual std::array getVectorTileScales() const; - virtual std::array getColorComponentCoefficients() const; + virtual std::array getColorComponentCoefficients() const; private : - static const std::array COMPONENTS; + static const std::array COMPONENTS; static const std::array SCALES; }; diff --git a/all/native/rastertiles/TerrariumElevationDataDecoder.cpp b/all/native/rastertiles/TerrariumElevationDataDecoder.cpp index 7f31cdf93..ec9c9a381 100644 --- a/all/native/rastertiles/TerrariumElevationDataDecoder.cpp +++ b/all/native/rastertiles/TerrariumElevationDataDecoder.cpp @@ -12,7 +12,7 @@ namespace carto { } - std::array TerrariumElevationDataDecoder::getColorComponentCoefficients() const + std::array TerrariumElevationDataDecoder::getColorComponentCoefficients() const { return COMPONENTS; } @@ -22,6 +22,6 @@ namespace carto return SCALES; } - const std::array TerrariumElevationDataDecoder::COMPONENTS = std::array{256.0f, 1.0f, 1.0f / 256, -32768.0f}; + const std::array TerrariumElevationDataDecoder::COMPONENTS = std::array{256.0f, 1.0f, 1.0f / 256, -32768.0f}; const std::array TerrariumElevationDataDecoder::SCALES = std::array{256.0f, 1.0f, 1.0f / 256, -32768.0f}; } // namespace carto diff --git a/all/native/rastertiles/TerrariumElevationDataDecoder.h b/all/native/rastertiles/TerrariumElevationDataDecoder.h index cc93d02d2..b1d9c234a 100644 --- a/all/native/rastertiles/TerrariumElevationDataDecoder.h +++ b/all/native/rastertiles/TerrariumElevationDataDecoder.h @@ -28,10 +28,10 @@ namespace carto { virtual ~TerrariumElevationDataDecoder(); virtual std::array getVectorTileScales() const; - virtual std::array getColorComponentCoefficients() const; + virtual std::array getColorComponentCoefficients() const; private : - static const std::array COMPONENTS; + static const std::array COMPONENTS; static const std::array SCALES; }; From 6a61e9769f21d720eb6714de2c8b2a09d2e917f6 Mon Sep 17 00:00:00 2001 From: mtehver Date: Tue, 30 Mar 2021 10:27:18 +0300 Subject: [PATCH 06/11] iOS framework packaging changes. Fixed several issues with header files, added support for xcframeworks. --- scripts/build-ios.py | 165 +++++++++++++++++++++++++++---------------- 1 file changed, 103 insertions(+), 62 deletions(-) diff --git a/scripts/build-ios.py b/scripts/build-ios.py index f716da8fd..b0d713506 100644 --- a/scripts/build-ios.py +++ b/scripts/build-ios.py @@ -2,40 +2,48 @@ import sys import re import shutil +import itertools import argparse import string from build.sdk_build_utils import * IOS_ARCHS = ['i386', 'x86_64', 'armv7', 'arm64'] -def updateUmbrellaHeader(filename, args): +def updateUmbrellaHeader(filename, defines): with open(filename, 'r') as f: lines = f.readlines() for i in range(0, len(lines)): match = re.search('^\s*#import\s+"(.*)".*', lines[i].rstrip('\n')) if match: - lines[i] = '#import \n' % match.group(1) + headerFilename = match.group(1).split('/')[-1] + if not headerFilename.startswith('NT'): + headerFilename = 'NT%s' % headerFilename + lines[i] = '#import \n' % headerFilename for i in range(0, len(lines)): if re.search('^\s*#define\s+.*$', lines[i].rstrip('\n')): break - lines = lines[:i+1] + ['\n'] + ['#define %s\n' % define for define in args.defines.split(';') if define] + lines[i+1:] + lines = lines[:i+1] + ['\n'] + ['#define %s\n' % define for define in defines.split(';') if define] + lines[i+1:] with open(filename, 'w') as f: f.writelines(lines) -def updatePrivateHeader(filename, args): +def updatePublicHeader(filename): with open(filename, 'r') as f: lines = f.readlines() + externCMode = False for i in range(0, len(lines)): - match = re.search('^\s*#include\s+"(.*)".*', lines[i].rstrip('\n')) - if match: - lines[i] = '#include \n' % match.group(1) + if lines[i].find('extern "C"') != -1: + externCMode = True match = re.search('^\s*#import\s+"(.*)".*', lines[i].rstrip('\n')) if match: - lines[i] = '#import \n' % match.group(1) + headerFilename = match.group(1) + if externCMode: + lines[i] = '#ifdef __cplusplus\n}\n#endif\n#import "%s"\n#ifdef __cplusplus\nextern "C" {\n#endif\n' % headerFilename + else: + lines[i] = '#import "%s"\n' % headerFilename with open(filename, 'w') as f: f.writelines(lines) -def buildModuleMap(filename, publicHeaders, privateHeaders): +def buildModuleMap(filename, publicHeaders): with open(filename, 'w') as f: f.write('framework module CartoMobileSDK {\n') f.write(' umbrella header "CartoMobileSDK.h"\n') @@ -43,18 +51,50 @@ def buildModuleMap(filename, publicHeaders, privateHeaders): f.write(' header "%s"\n' % header) f.write(' export *\n') f.write(' module * { export * }\n') - f.write(' explicit module Private {\n') - f.write(' requires cplusplus\n') - for header in privateHeaders: - f.write(' header "%s"\n' % header) - f.write(' }\n') f.write('}\n') -def buildIOSLib(args, arch): +def copyHeaders(args, baseDir, outputDir): + proxyHeaderDir = '%s/generated/ios-objc/proxies' % baseDir + destDir = '%s/Headers' % outputDir + publicHeaders = [] + makedirs(destDir) + + currentDir = os.getcwd() + os.chdir(proxyHeaderDir) + for dirpath, dirnames, filenames in os.walk('.'): + for filename in filenames: + if filename.endswith('.h'): + publicHeaders.append(filename) + if not copyfile(os.path.join(dirpath, filename), '%s/%s' % (destDir, filename)): + os.chdir(currentDir) + return False + updatePublicHeader('%s/%s' % (destDir, filename)) + os.chdir(currentDir) + + extraHeaders = ['%s/ios/objc/utils/ExceptionWrapper.h', '%s/ios/objc/ui/MapView.h'] + if args.metalangle: + for extraHeader in ['MGLKit.h', 'MGLKitPlatform.h', 'MGLContext.h', 'MGLKView.h', 'MGLLayer.h', 'MGLKViewController.h']: + extraHeaders += ['%s/libs-external/angle-metal/include/' + extraHeader] + for extraHeader in extraHeaders: + dirpath, filename = (extraHeader % baseDir).rsplit('/', 1) + destFilename = filename if filename.startswith('MGL') else 'NT%s' % filename + publicHeaders.append(destFilename) + if not copyfile(os.path.join(dirpath, filename), '%s/%s' % (destDir, destFilename)): + return False + + if not copyfile('%s/ios/objc/CartoMobileSDK.h' % baseDir, '%s/CartoMobileSDK.h' % destDir): + return False + updateUmbrellaHeader('%s/CartoMobileSDK.h' % destDir, args.defines) + + makedirs('%s/Modules' % outputDir) + buildModuleMap('%s/Modules/module.modulemap' % outputDir, publicHeaders) + return True + +def buildIOSLib(args, arch, outputDir=None): platform = 'OS' if arch.startswith('arm') else 'SIMULATOR' version = getVersion(args.buildnumber) if args.configuration == 'Release' else 'Devel' baseDir = getBaseDir() - buildDir = getBuildDir('ios', '%s-%s' % (platform, arch)) + buildDir = outputDir or getBuildDir('ios', '%s-%s' % (platform, arch)) defines = ["-D%s" % define for define in args.defines.split(';') if define] options = ["-D%s" % option for option in args.cmakeoptions.split(';') if option] @@ -81,17 +121,16 @@ def buildIOSLib(args, arch): '--config', args.configuration ]) -def buildIOSFramework(args, archs): - shutil.rmtree(getDistDir('ios'), True) - +def buildIOSFramework(args, archs, outputDir=None): platformArchs = [('OS' if arch.startswith('arm') else 'SIMULATOR', arch) for arch in archs] baseDir = getBaseDir() - distDir = getDistDir('ios') + distDir = outputDir or getDistDir('ios') if args.sharedlib: - outputDir = '%s/CartoMobileSDK.framework' % distDir + frameworkDir = '%s/CartoMobileSDK.framework' % distDir else: - outputDir = '%s/CartoMobileSDK.framework/Versions/A' % distDir - makedirs(outputDir) + frameworkDir = '%s/CartoMobileSDK.framework/Versions/A' % distDir + shutil.rmtree(distDir, True) + makedirs(frameworkDir) libFilePaths = [] for platform, arch in platformArchs: @@ -107,21 +146,21 @@ def buildIOSFramework(args, archs): libFilePaths.append(libFilePath) if not execute('lipo', baseDir, - '-output', '%s/CartoMobileSDK' % outputDir, + '-output', '%s/CartoMobileSDK' % frameworkDir, '-create', *libFilePaths ): return False if args.sharedlib: - if not execute('install_name_tool', outputDir, + if not execute('install_name_tool', frameworkDir, '-id', '@rpath/CartoMobileSDK.framework/CartoMobileSDK', 'CartoMobileSDK' ): return False - if not copyfile('%s/scripts/ios/Info.plist' % baseDir, '%s/Info.plist' % outputDir): + if not copyfile('%s/scripts/ios/Info.plist' % baseDir, '%s/Info.plist' % frameworkDir): return False - makedirs('%s/Headers' % outputDir) + makedirs('%s/Headers' % frameworkDir) if not args.sharedlib: if not makesymlink('%s/CartoMobileSDK.framework/Versions' % distDir, 'A', 'Current'): return False @@ -129,43 +168,40 @@ def buildIOSFramework(args, archs): return False if not makesymlink('%s/CartoMobileSDK.framework' % distDir, 'Versions/A/Headers', 'Headers'): return False - if not makesymlink('%s/CartoMobileSDK.framework' % distDir, 'Versions/A/PrivateHeaders', 'PrivateHeaders'): - return False if not makesymlink('%s/CartoMobileSDK.framework' % distDir, 'Versions/A/CartoMobileSDK', 'CartoMobileSDK'): return False + if not copyHeaders(args, baseDir, frameworkDir): + return False - publicHeaders = [] - privateHeaders = [] - headerDirTemplates = ['%s/all/native', '%s/ios/native', '%s/ios/objc', '%s/generated/ios-objc/proxies', '%s/libs-external/cglib'] - if args.metalangle: - headerDirTemplates.append('%s/libs-external/angle-metal/include') - for headerDirTemplate in headerDirTemplates: - headerDir = headerDirTemplate % baseDir - if not os.path.exists(headerDir): - continue - currentDir = os.getcwd() - os.chdir(headerDir) - for dirpath, dirnames, filenames in os.walk('.'): - for filename in filenames: - if filename.endswith('.h'): - destDir = '%s/Headers/%s' % (outputDir, dirpath) - if headerDirTemplate.find('objc') == -1: - destDir = '%s/PrivateHeaders/%s' % (outputDir, dirpath) - privateHeaders.append(os.path.normpath(os.path.join(dirpath, filename))) - elif filename != 'CartoMobileSDK.h': - publicHeaders.append(os.path.normpath(os.path.join(dirpath, filename))) - if not (makedirs(destDir) and copyfile(os.path.join(dirpath, filename), '%s/%s' % (destDir, filename))): - os.chdir(currentDir) - return False - if filename == 'CartoMobileSDK.h': - updateUmbrellaHeader('%s/%s' % (destDir, filename), args) - else: - updatePrivateHeader('%s/%s' % (destDir, filename), args) - os.chdir(currentDir) - makedirs('%s/Modules' % outputDir) - buildModuleMap('%s/Modules/module.modulemap' % outputDir, publicHeaders, privateHeaders) + if outputDir is None: + print("Output available in:\n%s" % distDir) + return True + +def buildIOSXCFramework(args, archs, outputDir=None): + platformArchs = [('OS' if arch.startswith('arm') else 'SIMULATOR', arch) for arch in archs] + groupedPlatformArchs = {} + for platform, arch in platformArchs: + groupedPlatformArchs[platform] = groupedPlatformArchs.get(platform, []) + [arch] + baseDir = getBaseDir() + distDir = outputDir or getDistDir('ios') + shutil.rmtree(distDir, True) + makedirs(distDir) - print("Output available in:\n%s" % distDir) + frameworkBuildDirs = [] + for platform, archs in groupedPlatformArchs.items(): + frameworkBuildDir = getBuildDir('ios-framework', '%s-%s' % (platform, '-'.join(archs))) + if not buildIOSFramework(args, archs, frameworkBuildDir): + return False + frameworkBuildDirs.append(frameworkBuildDir) + + if not execute('xcodebuild', baseDir, + '-create-xcframework', '-output', '%s/CartoMobileSDK.xcframework' % distDir, + *list(itertools.chain(*[['-framework', '%s/CartoMobileSDK.framework' % frameworkBuildDir] for frameworkBuildDir in frameworkBuildDirs])) + ): + return False + + if outputDir is None: + print("Output available in:\n%s" % distDir) return True def buildIOSCocoapod(args, buildpackage): @@ -200,6 +236,7 @@ def buildIOSCocoapod(args, buildpackage): parser.add_argument('--configuration', dest='configuration', default='Release', choices=['Release', 'RelWithDebInfo', 'Debug'], help='Configuration') parser.add_argument('--build-number', dest='buildnumber', default='', help='Build sequence number, goes to version str') parser.add_argument('--build-version', dest='buildversion', default='%s-devel' % SDK_VERSION, help='Build version, goes to distributions') +parser.add_argument('--build-xcframework', dest='buildxcframework', default=False, action='store_true', help='Build XCFramework') parser.add_argument('--build-cocoapod', dest='buildcocoapod', default=False, action='store_true', help='Build CocoaPod') parser.add_argument('--build-cocoapod-package', dest='buildcocoapodpackage', default=False, action='store_true', help='Build CocoaPod') parser.add_argument('--metalangle', dest='metalangle', default=False, action='store_true', help='Use MetalANGLE instead of Apple GL') @@ -222,8 +259,12 @@ def buildIOSCocoapod(args, buildpackage): if not buildIOSLib(args, arch): sys.exit(-1) -if not buildIOSFramework(args, args.iosarch): - sys.exit(-1) +if args.buildxcframework: + if not buildIOSXCFramework(args, args.iosarch): + sys.exit(-1) +else: + if not buildIOSFramework(args, args.iosarch): + sys.exit(-1) if args.buildcocoapod or args.buildcocoapodpackage: if not buildIOSCocoapod(args, args.buildcocoapodpackage): From 011f6d525ce0b1910e016395d4994e67aec604b0 Mon Sep 17 00:00:00 2001 From: mtehver Date: Mon, 19 Apr 2021 10:26:41 +0300 Subject: [PATCH 07/11] Fixed handling of 'CANCEL' touch actions in Android. This caused mishandling of following touch events. --- android/csharp/UI/MapView.cs | 2 ++ android/java/com/carto/ui/MapView.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/android/csharp/UI/MapView.cs b/android/csharp/UI/MapView.cs index 383eecba8..0a0592e10 100644 --- a/android/csharp/UI/MapView.cs +++ b/android/csharp/UI/MapView.cs @@ -197,6 +197,8 @@ public override bool OnTouchEvent(MotionEvent motionEvent) { _baseMapView.OnInputEvent(NativeActionCancel, NativeNoCoordinate, NativeNoCoordinate, NativeNoCoordinate, NativeNoCoordinate); + _pointer1Id = InvalidPointerId; + _pointer2Id = InvalidPointerId; break; case MotionEventActions.Up: case MotionEventActions.PointerUp: diff --git a/android/java/com/carto/ui/MapView.java b/android/java/com/carto/ui/MapView.java index 20225737a..c7233fdf2 100644 --- a/android/java/com/carto/ui/MapView.java +++ b/android/java/com/carto/ui/MapView.java @@ -252,6 +252,8 @@ public synchronized boolean onTouchEvent(MotionEvent event) { baseMapView.onInputEvent(NATIVE_ACTION_CANCEL, NATIVE_NO_COORDINATE, NATIVE_NO_COORDINATE, NATIVE_NO_COORDINATE, NATIVE_NO_COORDINATE); + pointer1Index = INVALID_POINTER_ID; + pointer2Index = INVALID_POINTER_ID; break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: From cda3ed460ef98c45c397308f81827021723eceee Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Sat, 24 Apr 2021 11:09:38 +0200 Subject: [PATCH 08/11] fix: hillshade getElevation(s) handle isReplaceWithParent --- .../layers/HillshadeRasterTileLayer.cpp | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/all/native/layers/HillshadeRasterTileLayer.cpp b/all/native/layers/HillshadeRasterTileLayer.cpp index 6aae08fd4..e12fedd35 100644 --- a/all/native/layers/HillshadeRasterTileLayer.cpp +++ b/all/native/layers/HillshadeRasterTileLayer.cpp @@ -257,7 +257,7 @@ namespace carto std::shared_ptr binaryData = tileData->getData(); if (!binaryData) { - Log::Error("HillshadeRasterTileLayer::getMapTileBitmap: Null tile binary data"); + Log::Error("HillshadeRasterTileLayer::getTileDataBitmap: Null tile binary data"); return NULL; } int size = binaryData->size(); @@ -298,21 +298,28 @@ namespace carto // The tile is flipped so to get the bitmap we need to flip it MapTile mapTile = TileUtils::CalculateMapTile(dataSourcePos, dataSource->getMaxZoom(), projection); MapTile flippedMapTile = mapTile.getFlipped(); - long long tileId = mapTile.getTileId(); - std::map>>::iterator iter(indexedTiles.find(tileId)); - if (iter == indexedTiles.end()) { - std::shared_ptr tileBitmap = getMapTileBitmap(flippedMapTile); - MapBounds tileBounds = TileUtils::CalculateMapTileBounds(mapTile, projection); - std::pair> pair = std::make_pair(tileBounds, tileBitmap); - indexedTiles.insert(std::pair>>(tileId, pair)); - double altitude = readPixelAltitude(tileBitmap, tileBounds, dataSourcePos, components); - results.push_back(altitude); - } else { - std::pair> pair = iter->second; - const std::shared_ptr& tileBitmap = pair.second; - const MapBounds& tileBounds = pair.first; - double altitude = readPixelAltitude(tileBitmap, tileBounds, dataSourcePos, components); - results.push_back(altitude); + std::shared_ptr tileData = _dataSource->loadTile(flippedMapTile); + while(tileData && tileData->isReplaceWithParent()) { + mapTile = mapTile.getParent(); + flippedMapTile = mapTile.getFlipped(); + } + if (tileData) { + long long tileId = mapTile.getTileId(); + std::map>>::iterator iter(indexedTiles.find(tileId)); + if (iter == indexedTiles.end()) { + std::shared_ptr tileBitmap = getTileDataBitmap(tileData); + MapBounds tileBounds = TileUtils::CalculateMapTileBounds(mapTile, projection); + std::pair> pair = std::make_pair(tileBounds, tileBitmap); + indexedTiles.insert(std::pair>>(tileId, pair)); + double altitude = readPixelAltitude(tileBitmap, tileBounds, dataSourcePos, components); + results.push_back(altitude); + } else { + std::pair> pair = iter->second; + const std::shared_ptr& tileBitmap = pair.second; + const MapBounds& tileBounds = pair.first; + double altitude = readPixelAltitude(tileBitmap, tileBounds, dataSourcePos, components); + results.push_back(altitude); + } } } return results; From abce8bd4ce1fe0969cf7c9ce6f54aeda3e25515b Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Fri, 23 Apr 2021 10:47:10 +0200 Subject: [PATCH 09/11] fix: request parent tile if isReplacedByParent --- .../layers/HillshadeRasterTileLayer.cpp | 29 +++++++++++++------ all/native/layers/HillshadeRasterTileLayer.h | 1 + 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/all/native/layers/HillshadeRasterTileLayer.cpp b/all/native/layers/HillshadeRasterTileLayer.cpp index e12fedd35..f5fb3eb70 100644 --- a/all/native/layers/HillshadeRasterTileLayer.cpp +++ b/all/native/layers/HillshadeRasterTileLayer.cpp @@ -247,14 +247,7 @@ namespace carto return std::make_shared(vtTileId, tileSize, tileBackground, std::vector>{tileLayer}); } - - std::shared_ptr HillshadeRasterTileLayer::getMapTileBitmap(const MapTile& mapTile) const { - std::shared_ptr tileData = _dataSource->loadTile(mapTile); - if (!tileData) { - Log::Error("HillshadeRasterTileLayer::getMapTileBitmap: Null tile data"); - return NULL; - } - + std::shared_ptr HillshadeRasterTileLayer::getTileDataBitmap(std::shared_ptr tileData) const { std::shared_ptr binaryData = tileData->getData(); if (!binaryData) { Log::Error("HillshadeRasterTileLayer::getTileDataBitmap: Null tile binary data"); @@ -265,6 +258,15 @@ namespace carto return tileBitmap; } + std::shared_ptr HillshadeRasterTileLayer::getMapTileBitmap(const MapTile& mapTile) const { + std::shared_ptr tileData = _dataSource->loadTile(mapTile); + if (!tileData) { + Log::Error("HillshadeRasterTileLayer::getMapTileBitmap: Null tile data"); + return NULL; + } + return getTileDataBitmap(tileData); + } + double HillshadeRasterTileLayer::getElevation(const MapPos &pos) const { std::shared_ptr dataSource = getDataSource(); @@ -277,7 +279,16 @@ namespace carto MapTile mapTile = TileUtils::CalculateMapTile(dataSourcePos, dataSource->getMaxZoom(), projection); MapTile flippedMapTile = mapTile.getFlipped(); - std::shared_ptr tileBitmap = getMapTileBitmap(flippedMapTile); + std::shared_ptr tileData = _dataSource->loadTile(flippedMapTile); + while(tileData && tileData->isReplaceWithParent()) { + mapTile = mapTile.getParent(); + flippedMapTile = mapTile.getFlipped(); + } + if (!tileData) { + Log::Error("ElevationDecoder::getElevation: no tile found to get elevation"); + return -1000000; + } + std::shared_ptr tileBitmap = getTileDataBitmap(tileData); if (!tileBitmap) { Log::Error("ElevationDecoder::getElevation: Null tile bitmap"); return -1000000; diff --git a/all/native/layers/HillshadeRasterTileLayer.h b/all/native/layers/HillshadeRasterTileLayer.h index 25236dd36..29d2ba6b8 100644 --- a/all/native/layers/HillshadeRasterTileLayer.h +++ b/all/native/layers/HillshadeRasterTileLayer.h @@ -100,6 +100,7 @@ namespace carto { virtual std::shared_ptr createVectorTile(const MapTile& tile, const std::shared_ptr& bitmap) const; + std::shared_ptr getTileDataBitmap(std::shared_ptr tileData) const; std::shared_ptr getMapTileBitmap(const MapTile& mapTile) const; const DirectorPtr _elevationDecoder; From 37587dc13c157e439331a1adb628f1a8a8218320 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Sat, 24 Apr 2021 11:09:38 +0200 Subject: [PATCH 10/11] fix: hillshade getElevation(s) handle isReplaceWithParent --- all/native/layers/HillshadeRasterTileLayer.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/all/native/layers/HillshadeRasterTileLayer.cpp b/all/native/layers/HillshadeRasterTileLayer.cpp index f5fb3eb70..62e3f5bd3 100644 --- a/all/native/layers/HillshadeRasterTileLayer.cpp +++ b/all/native/layers/HillshadeRasterTileLayer.cpp @@ -258,15 +258,6 @@ namespace carto return tileBitmap; } - std::shared_ptr HillshadeRasterTileLayer::getMapTileBitmap(const MapTile& mapTile) const { - std::shared_ptr tileData = _dataSource->loadTile(mapTile); - if (!tileData) { - Log::Error("HillshadeRasterTileLayer::getMapTileBitmap: Null tile data"); - return NULL; - } - return getTileDataBitmap(tileData); - } - double HillshadeRasterTileLayer::getElevation(const MapPos &pos) const { std::shared_ptr dataSource = getDataSource(); From 7a964276cb80de8202e8a4b087740b1ecdbf518e Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Sat, 24 Apr 2021 17:00:00 +0200 Subject: [PATCH 11/11] fix: correctly query points elevation --- .../layers/HillshadeRasterTileLayer.cpp | 66 +++++++++++++------ 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/all/native/layers/HillshadeRasterTileLayer.cpp b/all/native/layers/HillshadeRasterTileLayer.cpp index 62e3f5bd3..e4d003c0b 100644 --- a/all/native/layers/HillshadeRasterTileLayer.cpp +++ b/all/native/layers/HillshadeRasterTileLayer.cpp @@ -274,6 +274,7 @@ namespace carto while(tileData && tileData->isReplaceWithParent()) { mapTile = mapTile.getParent(); flippedMapTile = mapTile.getFlipped(); + tileData = _dataSource->loadTile(flippedMapTile); } if (!tileData) { Log::Error("ElevationDecoder::getElevation: no tile found to get elevation"); @@ -297,32 +298,55 @@ namespace carto for (auto it = poses.begin(); it != poses.end(); it++) { // TODO: how to check if pos is in Wgs84? MapPos dataSourcePos = projection->fromWgs84(*it); - // The tile is flipped so to get the bitmap we need to flip it MapTile mapTile = TileUtils::CalculateMapTile(dataSourcePos, dataSource->getMaxZoom(), projection); - MapTile flippedMapTile = mapTile.getFlipped(); - std::shared_ptr tileData = _dataSource->loadTile(flippedMapTile); - while(tileData && tileData->isReplaceWithParent()) { - mapTile = mapTile.getParent(); - flippedMapTile = mapTile.getFlipped(); + + long long tileId = mapTile.getTileId(); + std::map>>::iterator iter(indexedTiles.find(tileId)); + std::shared_ptr tileData; + if (iter == indexedTiles.end()) { + // no cached bitmap found lets get it from TileData + // The tile is flipped so to get the bitmap we need to flip it + MapTile flippedMapTile = mapTile.getFlipped(); + tileData = _dataSource->loadTile(flippedMapTile); + // get the parent tile if necessary + while(tileData && tileData->isReplaceWithParent()) { + mapTile = mapTile.getParent(); + tileId = mapTile.getTileId(); + iter = (indexedTiles.find(tileId)); + // if the parent tile is cached let's stop + if (iter != indexedTiles.end()) { + break; + } + flippedMapTile = mapTile.getFlipped(); + tileData = _dataSource->loadTile(flippedMapTile); + } + } + + if (iter != indexedTiles.end()) { + // we found a cached bitmap + std::pair> pair = iter->second; + const std::shared_ptr& tileBitmap = pair.second; + const MapBounds& tileBounds = pair.first; + double altitude = readPixelAltitude(tileBitmap, tileBounds, dataSourcePos, components); + results.push_back(altitude); + continue; } if (tileData) { + // read from the tile data + // then put the bitmap in the cache for next points long long tileId = mapTile.getTileId(); - std::map>>::iterator iter(indexedTiles.find(tileId)); - if (iter == indexedTiles.end()) { - std::shared_ptr tileBitmap = getTileDataBitmap(tileData); - MapBounds tileBounds = TileUtils::CalculateMapTileBounds(mapTile, projection); - std::pair> pair = std::make_pair(tileBounds, tileBitmap); - indexedTiles.insert(std::pair>>(tileId, pair)); - double altitude = readPixelAltitude(tileBitmap, tileBounds, dataSourcePos, components); - results.push_back(altitude); - } else { - std::pair> pair = iter->second; - const std::shared_ptr& tileBitmap = pair.second; - const MapBounds& tileBounds = pair.first; - double altitude = readPixelAltitude(tileBitmap, tileBounds, dataSourcePos, components); - results.push_back(altitude); - } + std::shared_ptr tileBitmap = getTileDataBitmap(tileData); + MapBounds tileBounds = TileUtils::CalculateMapTileBounds(mapTile, projection); + std::pair> pair = std::make_pair(tileBounds, tileBitmap); + indexedTiles.insert(std::pair>>(tileId, pair)); + double altitude = readPixelAltitude(tileBitmap, tileBounds, dataSourcePos, components); + results.push_back(altitude); + } else { + // in case we did not find an elevation still return something + // so that the user can now for which point each elevation was + results.push_back(-1000000); } + } return results; }