diff --git a/jvm/src/test/resources/golden/OffscreenMapRendererTest_testTiler_tile_7_66_44.png b/jvm/src/test/resources/golden/OffscreenMapRendererTest_testTiler_tile_7_66_44.png index 16b93c1cb..7da730f3a 100644 Binary files a/jvm/src/test/resources/golden/OffscreenMapRendererTest_testTiler_tile_7_66_44.png and b/jvm/src/test/resources/golden/OffscreenMapRendererTest_testTiler_tile_7_66_44.png differ diff --git a/jvm/src/test/resources/golden/OffscreenMapRendererTest_testTiler_tile_7_66_45.png b/jvm/src/test/resources/golden/OffscreenMapRendererTest_testTiler_tile_7_66_45.png index b1e9beee3..d51d68188 100644 Binary files a/jvm/src/test/resources/golden/OffscreenMapRendererTest_testTiler_tile_7_66_45.png and b/jvm/src/test/resources/golden/OffscreenMapRendererTest_testTiler_tile_7_66_45.png differ diff --git a/jvm/src/test/resources/golden/OffscreenMapRendererTest_testTiler_tile_7_67_44.png b/jvm/src/test/resources/golden/OffscreenMapRendererTest_testTiler_tile_7_67_44.png index 934f19b19..ba9c1e2ab 100644 Binary files a/jvm/src/test/resources/golden/OffscreenMapRendererTest_testTiler_tile_7_67_44.png and b/jvm/src/test/resources/golden/OffscreenMapRendererTest_testTiler_tile_7_67_44.png differ diff --git a/jvm/src/test/resources/golden/OffscreenMapRendererTest_testTiler_tile_7_67_45.png b/jvm/src/test/resources/golden/OffscreenMapRendererTest_testTiler_tile_7_67_45.png index ba404c1f9..e7ab16b8a 100644 Binary files a/jvm/src/test/resources/golden/OffscreenMapRendererTest_testTiler_tile_7_67_45.png and b/jvm/src/test/resources/golden/OffscreenMapRendererTest_testTiler_tile_7_67_45.png differ diff --git a/shared/public/RasterVectorLayerDescription.h b/shared/public/RasterVectorLayerDescription.h index 73f694ac2..f0bee23b8 100644 --- a/shared/public/RasterVectorLayerDescription.h +++ b/shared/public/RasterVectorLayerDescription.h @@ -11,7 +11,7 @@ #pragma once #include "VectorLayerDescription.h" -#include "Color.h" +#include "VectorMapSourceDescription.h" #include "RasterShaderStyle.h" #include "FeatureValueEvaluator.h" @@ -44,7 +44,7 @@ class RasterVectorStyle { UsedKeysCollection getUsedKeys() const { UsedKeysCollection usedKeys; - std::shared_ptr values[] = { + std::shared_ptr values[] = { rasterOpacityEvaluator.getValue(), rasterBrightnessMinEvaluator.getValue(), rasterBrightnessMaxEvaluator.getValue(), @@ -68,7 +68,7 @@ class RasterVectorStyle { static const BlendMode defaultValue = BlendMode::NORMAL; return blendModeEvaluator.getResult(context, defaultValue).value; } - + RasterShaderStyle getRasterStyle(const EvaluationContext &context) { return { (float) getRasterOpacity(context), @@ -85,17 +85,17 @@ class RasterVectorStyle { double defaultValue = 1.0; return rasterOpacityEvaluator.getResult(context, defaultValue).value; } - + double getRasterBrightnessMin(const EvaluationContext &context) { double defaultValue = 0.0; return rasterBrightnessMinEvaluator.getResult(context, defaultValue).value; } - + double getRasterBrightnessMax(const EvaluationContext &context) { double defaultValue = 1.0; return rasterBrightnessMaxEvaluator.getResult(context, defaultValue).value; } - + double getRasterContrast(const EvaluationContext &context) { double defaultValue = 0.0; return rasterContrastEvaluator.getResult(context, defaultValue).value; @@ -127,68 +127,60 @@ class RasterVectorStyle { FeatureValueEvaluator blendModeEvaluator; }; +struct RasterVectorMapSourceDescription : public VectorMapSourceDescription { + bool maskTiles; + + RasterVectorMapSourceDescription(std::string identifier, + std::string url, + int minZoom, + int maxZoom, + std::optional<::RectCoord> bounds, + std::optional zoomLevelScaleFactor, + std::optional adaptScaleToScreen, + std::optional numDrawPreviousLayers, + std::optional underzoom, + std::optional overzoom, + std::optional> levels, + std::optional coordinateReferenceSystem, + bool maskTiles) + : VectorMapSourceDescription(identifier, url, minZoom, maxZoom, bounds, zoomLevelScaleFactor, adaptScaleToScreen, numDrawPreviousLayers, underzoom, overzoom, levels, coordinateReferenceSystem) + , maskTiles(maskTiles) {} + + virtual Tiled2dMapZoomInfo getZoomInfo(bool is3d) const { + auto zoomInfo = VectorMapSourceDescription::getZoomInfo(is3d); + zoomInfo.maskTile = maskTiles; + return zoomInfo; + } +}; + class RasterVectorLayerDescription: public VectorLayerDescription { public: VectorLayerType getType() override { return VectorLayerType::raster; }; - std::string url; + std::shared_ptr source; RasterVectorStyle style; - bool adaptScaleToScreen; - int32_t numDrawPreviousLayers; - bool maskTiles; - double zoomLevelScaleFactor; - bool overzoom; - bool underzoom; - std::optional<::RectCoord> bounds; - std::optional coordinateReferenceSystem; - std::optional> levels; RasterVectorLayerDescription(std::string identifier, - std::string source, + std::shared_ptr source, int minZoom, int maxZoom, - int sourceMinZoom, - int sourceMaxZoom, - std::string url, std::shared_ptr filter, - RasterVectorStyle style, - bool adaptScaleToScreen, - int32_t numDrawPreviousLayers, - bool maskTiles, - double zoomLevelScaleFactor, std::optional renderPassIndex, std::shared_ptr interactable, - bool underzoom, - bool overzoom, - std::optional<::RectCoord> bounds, - std::optional coordinateReferenceSystem, - std::optional> levels) : - VectorLayerDescription(identifier, source, "", minZoom, maxZoom, sourceMinZoom, sourceMaxZoom, filter, renderPassIndex, interactable, false, false), - style(style), url(url), underzoom(underzoom), overzoom(overzoom), adaptScaleToScreen(adaptScaleToScreen), numDrawPreviousLayers(numDrawPreviousLayers), - maskTiles(maskTiles), zoomLevelScaleFactor(zoomLevelScaleFactor), bounds(bounds), coordinateReferenceSystem(coordinateReferenceSystem), levels(levels) {}; - + RasterVectorStyle style) + : VectorLayerDescription(identifier, source->identifier, "", minZoom, maxZoom, source->minZoom, source->maxZoom, filter, renderPassIndex, interactable, false, false) + , source(source) + , style(style) {} std::unique_ptr clone() override { return std::make_unique(identifier, source, minZoom, maxZoom, - sourceMinZoom, - sourceMaxZoom, - url, filter, - style, - adaptScaleToScreen, - numDrawPreviousLayers, - maskTiles, - zoomLevelScaleFactor, renderPassIndex, interactable ? interactable->clone() : nullptr, - underzoom, - overzoom, - bounds, - coordinateReferenceSystem, - levels); + style); } virtual UsedKeysCollection getUsedKeys() const override { diff --git a/shared/public/Tiled2dMapVectorLayerConfig.h b/shared/public/Tiled2dMapVectorLayerConfig.h index 019b5b43d..c407154bd 100644 --- a/shared/public/Tiled2dMapVectorLayerConfig.h +++ b/shared/public/Tiled2dMapVectorLayerConfig.h @@ -9,145 +9,63 @@ */ #pragma once +#include "RectCoord.h" #include "Tiled2dMapLayerConfig.h" -#include "Tiled2dMapZoomInfo.h" -#include "Tiled2dMapZoomLevelInfo.h" -#include "VectorMapSourceDescription.h" -#include "VectorLayerDescription.h" -#include "CoordinateSystemIdentifiers.h" #include "Tiled2dMapVectorSettings.h" -#include "Logger.h" +#include "Tiled2dMapZoomInfo.h" +#include +#include +#include +/** +* Abstract base class for different layer configurations. +*/ class Tiled2dMapVectorLayerConfig : public Tiled2dMapLayerConfig { public: - Tiled2dMapVectorLayerConfig(const std::shared_ptr &sourceDescription, - const Tiled2dMapZoomInfo &zoomInfo) - : sourceDescription(sourceDescription), zoomInfo(zoomInfo) {} - - Tiled2dMapVectorLayerConfig(const std::shared_ptr &sourceDescription, - const bool is3d) - : sourceDescription(sourceDescription), - zoomInfo(Tiled2dMapZoomInfo( - sourceDescription->zoomLevelScaleFactor ? *sourceDescription->zoomLevelScaleFactor : (is3d ? 0.75 : 1.0), - sourceDescription->numDrawPreviousLayers ? *sourceDescription->numDrawPreviousLayers : 0, - 0, - sourceDescription->adaptScaleToScreen ? *sourceDescription->adaptScaleToScreen : false, - true, - sourceDescription->underzoom ? *sourceDescription->underzoom : false, - sourceDescription->overzoom ? *sourceDescription->overzoom : true)) {} - - ~Tiled2dMapVectorLayerConfig() {} - - int32_t getCoordinateSystemIdentifier() override { - return epsg3857Id; - } - - std::string getTileUrl(int32_t x, int32_t y, int32_t t, int32_t zoom) override { - std::string url = sourceDescription->vectorUrl; - size_t epsg3857Index = url.find("{bbox-epsg-3857}", 0); - if (epsg3857Index != std::string::npos) { - const auto zoomLevelInfos = getDefaultEpsg3857ZoomLevels(zoom, zoom, std::nullopt); - const Tiled2dMapZoomLevelInfo &zoomLevelInfo = zoomLevelInfos.at(0); - RectCoord layerBounds = zoomLevelInfo.bounds; - const double tileWidth = zoomLevelInfo.tileWidthLayerSystemUnits; + virtual double getZoomIdentifier(double zoom) = 0; + virtual double getZoomFactorAtIdentifier(double zoomIdentifier) = 0; - const bool leftToRight = layerBounds.topLeft.x < layerBounds.bottomRight.x; - const bool topToBottom = layerBounds.topLeft.y < layerBounds.bottomRight.y; - const double tileWidthAdj = leftToRight ? tileWidth : -tileWidth; - const double tileHeightAdj = topToBottom ? tileWidth : -tileWidth; - - const double boundsLeft = layerBounds.topLeft.x; - const double boundsTop = layerBounds.topLeft.y; - - const Coord topLeft = Coord(epsg3857Id, x * tileWidthAdj + boundsLeft, y * tileHeightAdj + boundsTop, 0); - const Coord bottomRight = Coord(epsg3857Id, topLeft.x + tileWidthAdj, topLeft.y + tileHeightAdj, 0); - - std::string boxString = std::to_string(topLeft.x) + "," + std::to_string(bottomRight.y) + "," + std::to_string(bottomRight.x) + "," + std::to_string(topLeft.y); - url = url.replace(epsg3857Index, 16, boxString); - return url; +public: + Tiled2dMapVectorLayerConfig( + std::string layerName, + std::string urlFormat, + const std::optional &bounds, + const Tiled2dMapZoomInfo &zoomInfo, + const std::vector &levels + ); - } - size_t zoomIndex = url.find("{z}", 0); - if (zoomIndex == std::string::npos) throw std::invalid_argument("Layer url \'" + url + "\' has no valid format!"); - url = url.replace(zoomIndex, 3, std::to_string(zoom)); - size_t xIndex = url.find("{x}", 0); - if (xIndex == std::string::npos) throw std::invalid_argument("Layer url \'" + url + "\' has no valid format!"); - url = url.replace(xIndex, 3, std::to_string(x)); - size_t yIndex = url.find("{y}", 0); - if (yIndex == std::string::npos) throw std::invalid_argument("Layer url \'" + url + "\' has no valid format!"); - return url.replace(yIndex, 3, std::to_string(y)); - } + virtual ~Tiled2dMapVectorLayerConfig() = default; - std::vector getZoomLevelInfos() override { - return getDefaultEpsg3857ZoomLevels(sourceDescription->minZoom, sourceDescription->maxZoom, sourceDescription->levels); +public: + virtual std::string getLayerName() override { + return layerName; } - std::vector getVirtualZoomLevelInfos() override { - return getDefaultEpsg3857ZoomLevels(0, sourceDescription->minZoom - 1, sourceDescription->levels); - }; + virtual std::string getTileUrl(int32_t x, int32_t y, int32_t t, int32_t zoom) override; - Tiled2dMapZoomInfo getZoomInfo() override { + virtual Tiled2dMapZoomInfo getZoomInfo() override { return zoomInfo; } - std::string getLayerName() override { - return sourceDescription->identifier; + std::optional<::RectCoord> getBounds() override { + return bounds; } - std::optional getVectorSettings() override { + virtual std::optional getVectorSettings() override { return std::nullopt; } - virtual double getZoomIdentifier(double zoom) { - return std::max(0.0, std::round(log(baseValueZoom * zoomInfo.zoomLevelScaleFactor / zoom) / log(2) * 100) / 100); - } - - virtual double getZoomFactorAtIdentifier(double zoomIdentifier) { - double factor = pow(2, zoomIdentifier); - return baseValueZoom * zoomInfo.zoomLevelScaleFactor / factor; - } - - std::optional<::RectCoord> getBounds() override { - if (sourceDescription) { - return sourceDescription->bounds; - } - else { - return std::nullopt; - } - } - - static std::vector getDefaultEpsg3857ZoomLevels(int minZoom, int maxZoom, const std::optional> &levels) { - std::vector infos; - if (levels.has_value()) { - for (const auto &level : levels.value()) { - double factor = pow(2, level); - double zoom = baseValueZoom / factor; - double width = baseValueWidth / factor; - infos.push_back(Tiled2dMapZoomLevelInfo(zoom, width, factor, factor, 1, level, epsg3857Bounds)); - } - } else { - for (int i = minZoom; i <= maxZoom; i++) { - double factor = pow(2, i); - double zoom = baseValueZoom / factor; - double width = baseValueWidth / factor; - infos.push_back(Tiled2dMapZoomLevelInfo(zoom, width, factor, factor, 1, i, epsg3857Bounds)); - } - } - return infos; - } +public: + // Helper to initialize `zoomInfo` + static Tiled2dMapZoomInfo defaultMapZoomInfo(); + // Helper to initalize `levels` from min/max zoom levels value + static std::vector generateLevelsFromMinMax(int minZoomLevel, int maxZoomLevel); protected: - std::shared_ptr sourceDescription; + std::string layerName; + std::string urlFormat; Tiled2dMapZoomInfo zoomInfo; - - static constexpr double baseValueZoom = 500000000.0; - static constexpr double baseValueWidth = 40075016.0; - static const inline int32_t epsg3857Id = CoordinateSystemIdentifiers::EPSG3857(); - static const inline RectCoord epsg3857Bounds = RectCoord( - Coord(epsg3857Id, -20037508.34, 20037508.34, 0.0), - Coord(epsg3857Id, 20037508.34, -20037508.34, 0.0) - ); - - + std::optional bounds; + std::vector levels; // zoom level indices (kept sorted ascending) }; diff --git a/shared/public/VectorLayerDescription.h b/shared/public/VectorLayerDescription.h index 684bd9213..543b9fa71 100644 --- a/shared/public/VectorLayerDescription.h +++ b/shared/public/VectorLayerDescription.h @@ -11,7 +11,8 @@ #pragma once #include "Value.h" -#include +#include +#include enum VectorLayerType { background, raster, line, polygon, symbol, custom diff --git a/shared/public/VectorMapSourceDescription.h b/shared/public/VectorMapSourceDescription.h index 20081a43e..3aaf59e05 100644 --- a/shared/public/VectorMapSourceDescription.h +++ b/shared/public/VectorMapSourceDescription.h @@ -10,10 +10,11 @@ #pragma once -#include "VectorLayerDescription.h" -#include "Color.h" #include "GeoJsonTypes.h" #include "RectCoord.h" +#include "Tiled2dMapVectorLayerConfig.h" +#include "Tiled2dMapZoomInfo.h" +#include "VectorLayerDescription.h" class VectorMapSourceDescription { public: @@ -28,6 +29,7 @@ class VectorMapSourceDescription { std::optional underzoom; std::optional overzoom; std::optional> levels; + std::optional coordinateReferenceSystem; VectorMapSourceDescription(std::string identifier, std::string vectorUrl, @@ -39,10 +41,31 @@ class VectorMapSourceDescription { std::optional numDrawPreviousLayers, std::optional underzoom, std::optional overzoom, - std::optional> levels) : + std::optional> levels, + std::optional coordinateReferenceSystem) : identifier(identifier), vectorUrl(vectorUrl), minZoom(minZoom), maxZoom(maxZoom), bounds(bounds), adaptScaleToScreen(adaptScaleToScreen), numDrawPreviousLayers(numDrawPreviousLayers), - zoomLevelScaleFactor(zoomLevelScaleFactor), underzoom(underzoom), overzoom(overzoom), levels(levels) {} + zoomLevelScaleFactor(zoomLevelScaleFactor), underzoom(underzoom), overzoom(overzoom), levels(levels), + coordinateReferenceSystem(coordinateReferenceSystem) {} + + virtual Tiled2dMapZoomInfo getZoomInfo(bool is3d) const { + return Tiled2dMapZoomInfo( + zoomLevelScaleFactor ? *zoomLevelScaleFactor : (is3d ? 0.75 : 1.0), + numDrawPreviousLayers ? *numDrawPreviousLayers : 0, + 0, + adaptScaleToScreen ? *adaptScaleToScreen : false, + true, + underzoom ? *underzoom : false, + overzoom ? *overzoom : true); + }; + + std::vector getZoomLevels() { + if(levels) { + return *levels; + } else { + return Tiled2dMapVectorLayerConfig::generateLevelsFromMinMax(minZoom, maxZoom); + } + } }; struct SpriteSourceDescription { diff --git a/shared/src/map/coordinates/CoordinateSystemFactory.cpp b/shared/src/map/coordinates/CoordinateSystemFactory.cpp index 40f26e92a..51a965698 100644 --- a/shared/src/map/coordinates/CoordinateSystemFactory.cpp +++ b/shared/src/map/coordinates/CoordinateSystemFactory.cpp @@ -17,8 +17,8 @@ ::MapCoordinateSystem CoordinateSystemFactory::getEpsg2056System() { return MapCoordinateSystem(CoordinateSystemIdentifiers::EPSG2056(), - RectCoord(Coord(CoordinateSystemIdentifiers::EPSG2056(), 2485000.0, 1300000.0, 0), - Coord(CoordinateSystemIdentifiers::EPSG2056(), 2840000.0, 1070000.0, 0)), + RectCoord(Coord(CoordinateSystemIdentifiers::EPSG2056(), 2420000.0, 1350000.0, 0), + Coord(CoordinateSystemIdentifiers::EPSG2056(), 2900000.0, 1030000.0, 0)), 1.0); } diff --git a/shared/src/map/layers/tiled/DefaultTiled2dMapLayerConfigs.cpp b/shared/src/map/layers/tiled/DefaultTiled2dMapLayerConfigs.cpp index 3a2df1559..7bbda7f3b 100644 --- a/shared/src/map/layers/tiled/DefaultTiled2dMapLayerConfigs.cpp +++ b/shared/src/map/layers/tiled/DefaultTiled2dMapLayerConfigs.cpp @@ -5,24 +5,21 @@ // Created by Nicolas Märki on 13.02.2024. // -#ifndef DefaultTiled2dMapLayerConfigs_h -#define DefaultTiled2dMapLayerConfigs_h - #include "DefaultTiled2dMapLayerConfigs.h" -#include "WebMercatorTiled2dMapLayerConfig.h" +#include "Epsg3857Tiled2dMapLayerConfig.h" #include "Epsg4326Tiled2dMapLayerConfig.h" std::shared_ptr DefaultTiled2dMapLayerConfigs::webMercator(const std::string & layerName, const std::string & urlFormat) { - return std::make_shared(layerName, urlFormat); + return std::make_shared(layerName, urlFormat); } std::shared_ptr DefaultTiled2dMapLayerConfigs::webMercatorCustom(const std::string &layerName, const std::string &urlFormat, const std::optional & zoomInfo, int32_t minZoomLevel, int32_t maxZoomLevel) { - if (zoomInfo.has_value()) { - return std::make_shared(layerName, urlFormat, zoomInfo.value(), minZoomLevel, maxZoomLevel); - } - return std::make_shared(layerName, urlFormat, minZoomLevel, maxZoomLevel); + return std::make_shared( + layerName, urlFormat, std::nullopt, + zoomInfo.value_or(Tiled2dMapVectorLayerConfig::defaultMapZoomInfo()), + Tiled2dMapVectorLayerConfig::generateLevelsFromMinMax(minZoomLevel, maxZoomLevel)); } std::shared_ptr @@ -33,7 +30,7 @@ DefaultTiled2dMapLayerConfigs::epsg4326(const std::string &layerName, const std: std::shared_ptr DefaultTiled2dMapLayerConfigs::epsg4326Custom(const std::string &layerName, const std::string &urlFormat, const Tiled2dMapZoomInfo &zoomInfo, int32_t minZoomLevel, int32_t maxZoomLevel) { - return std::make_shared(layerName, urlFormat, zoomInfo, minZoomLevel, maxZoomLevel); + return std::make_shared( + layerName, urlFormat, std::nullopt, zoomInfo, + Tiled2dMapVectorLayerConfig::generateLevelsFromMinMax(minZoomLevel, maxZoomLevel)); } - -#endif /* DefaultTiled2dMapLayerConfigs_h */ diff --git a/shared/src/map/layers/tiled/Epsg2056Tiled2dMapLayerConfig.cpp b/shared/src/map/layers/tiled/Epsg2056Tiled2dMapLayerConfig.cpp new file mode 100644 index 000000000..d858c15ba --- /dev/null +++ b/shared/src/map/layers/tiled/Epsg2056Tiled2dMapLayerConfig.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2026 Ubique Innovation AG + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +#include "RectCoord.h" +#include "CoordinateSystemIdentifiers.h" +#include "Epsg2056Tiled2dMapLayerConfig.h" + +Epsg2056Tiled2dMapLayerConfig::Epsg2056Tiled2dMapLayerConfig( + std::string layerName, + std::string urlFormat) + : IrregularTiled2dMapLayerConfig( + layerName, urlFormat, std::nullopt, + defaultMapZoomInfo(), + generateLevelsFromMinMax(0, 28), + swisstopoZoomLevelInfos()) +{} + +Epsg2056Tiled2dMapLayerConfig::Epsg2056Tiled2dMapLayerConfig( + std::string layerName, + std::string urlFormat, + const std::optional &bounds, + const Tiled2dMapZoomInfo &zoomInfo, + const std::vector &levels) + : IrregularTiled2dMapLayerConfig( + layerName, urlFormat, bounds, zoomInfo, levels, swisstopoZoomLevelInfos()) +{} + +static Tiled2dMapZoomLevelInfo makeZoomLevelInfo( + const Coord &topLeft, double zoom, float tileWidthLayerSystemUnits, + int32_t numTilesX, int32_t numTilesY, int32_t numTilesT, int32_t zoomLevelIdentifier) +{ + const auto bounds = RectCoord( + topLeft, + Coord(topLeft.systemIdentifier, + topLeft.x + tileWidthLayerSystemUnits * numTilesX, + topLeft.y - tileWidthLayerSystemUnits * numTilesY, 0)); + + return Tiled2dMapZoomLevelInfo(zoom, tileWidthLayerSystemUnits, numTilesX, + numTilesY, numTilesT, zoomLevelIdentifier, + bounds); +} + +std::vector Epsg2056Tiled2dMapLayerConfig::swisstopoZoomLevelInfos() { + const Coord topLeft{CoordinateSystemIdentifiers::EPSG2056(), 2420000.0, 1350000.0, 0.f}; + return { + makeZoomLevelInfo(topLeft, 14285714.2857, 1024000, 1, 1, 1, 0), + makeZoomLevelInfo(topLeft, 13392857.1429, 960000, 1, 1, 1, 1), + makeZoomLevelInfo(topLeft, 12500000.0, 896000, 1, 1, 1, 2), + makeZoomLevelInfo(topLeft, 11607142.8571, 832000, 1, 1, 1, 3), + makeZoomLevelInfo(topLeft, 10714285.7143, 768000, 1, 1, 1, 4), + makeZoomLevelInfo(topLeft, 9821428.57143, 704000, 1, 1, 1, 5), + makeZoomLevelInfo(topLeft, 8928571.42857, 640000, 1, 1, 1, 6), + makeZoomLevelInfo(topLeft, 8035714.28571, 576000, 1, 1, 1, 7), + makeZoomLevelInfo(topLeft, 7142857.14286, 512000, 1, 1, 1, 8), + makeZoomLevelInfo(topLeft, 6250000.0, 448000, 2, 1, 1, 9), + makeZoomLevelInfo(topLeft, 5357142.85714, 384000, 2, 1, 1, 10), + makeZoomLevelInfo(topLeft, 4464285.71429, 320000, 2, 1, 1, 11), + makeZoomLevelInfo(topLeft, 3571428.57143, 256000, 2, 2, 1, 12), + makeZoomLevelInfo(topLeft, 2678571.42857, 192000, 3, 2, 1, 13), + makeZoomLevelInfo(topLeft, 2321428.57143, 166400, 3, 2, 1, 14), + makeZoomLevelInfo(topLeft, 1785714.28571, 128000, 4, 3, 1, 15), + makeZoomLevelInfo(topLeft, 892857.142857, 64000, 8, 5, 1, 16), + makeZoomLevelInfo(topLeft, 357142.857143, 25600, 19, 13, 1, 17), + makeZoomLevelInfo(topLeft, 178571.428571, 12800, 38, 25, 1, 18), + makeZoomLevelInfo(topLeft, 71428.5714286, 5120, 94, 63, 1, 19), + makeZoomLevelInfo(topLeft, 35714.2857143, 2560, 188, 125, 1, 20), + makeZoomLevelInfo(topLeft, 17857.1428571, 1280, 375, 250, 1, 21), + makeZoomLevelInfo(topLeft, 8928.57142857, 640, 750, 500, 1, 22), + makeZoomLevelInfo(topLeft, 7142.85714286, 512, 938, 625, 1, 23), + makeZoomLevelInfo(topLeft, 5357.14285714, 384, 1250, 834, 1, 24), + makeZoomLevelInfo(topLeft, 3571.42857143, 256, 1875, 1250, 1, 25), + makeZoomLevelInfo(topLeft, 1785.71428571, 128, 3750, 2500, 1, 26), + makeZoomLevelInfo(topLeft, 892.857142857, 64, 7500, 5000, 1, 27), + makeZoomLevelInfo(topLeft, 357.142857143, 25.6, 18750, 12500, 1, 28) + }; +} diff --git a/shared/src/map/layers/tiled/Epsg2056Tiled2dMapLayerConfig.h b/shared/src/map/layers/tiled/Epsg2056Tiled2dMapLayerConfig.h new file mode 100644 index 000000000..15b8a7f47 --- /dev/null +++ b/shared/src/map/layers/tiled/Epsg2056Tiled2dMapLayerConfig.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2026 Ubique Innovation AG + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +#pragma once + +#include "IrregularTiled2dMapLayerConfig.h" +#include "Tiled2dMapZoomInfo.h" + +class Epsg2056Tiled2dMapLayerConfig : public IrregularTiled2dMapLayerConfig { +public: + Epsg2056Tiled2dMapLayerConfig( + std::string layerName, + std::string urlFormat + ); + + Epsg2056Tiled2dMapLayerConfig( + std::string layerName, + std::string urlFormat, + const std::optional &bounds, + const Tiled2dMapZoomInfo &zoomInfo, + const std::vector &levels + ); + + static std::vector swisstopoZoomLevelInfos(); +}; diff --git a/shared/src/map/layers/tiled/Epsg21781Tiled2dMapLayerConfig.cpp b/shared/src/map/layers/tiled/Epsg21781Tiled2dMapLayerConfig.cpp new file mode 100644 index 000000000..1f28264bd --- /dev/null +++ b/shared/src/map/layers/tiled/Epsg21781Tiled2dMapLayerConfig.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2026 Ubique Innovation AG + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +#include "Epsg21781Tiled2dMapLayerConfig.h" +#include "CoordinateSystemIdentifiers.h" +#include "Epsg2056Tiled2dMapLayerConfig.h" +#include "RectCoord.h" + +Epsg21781Tiled2dMapLayerConfig::Epsg21781Tiled2dMapLayerConfig( + std::string layerName, + std::string urlFormat) + : IrregularTiled2dMapLayerConfig( + layerName, urlFormat, std::nullopt, + defaultMapZoomInfo(), + generateLevelsFromMinMax(0, 28), + swisstopoZoomLevelInfos()) +{} + +Epsg21781Tiled2dMapLayerConfig::Epsg21781Tiled2dMapLayerConfig( + std::string layerName, + std::string urlFormat, + const std::optional &bounds, + const Tiled2dMapZoomInfo &zoomInfo, + const std::vector &levels) + : IrregularTiled2dMapLayerConfig( + layerName, urlFormat, bounds, zoomInfo, levels, swisstopoZoomLevelInfos()) +{} + +static Tiled2dMapZoomLevelInfo makeZoomLevelInfo( + const Coord &topLeft, double zoom, float tileWidthLayerSystemUnits, + int32_t numTilesX, int32_t numTilesY, int32_t numTilesT, int32_t zoomLevelIdentifier) +{ + const auto bounds = RectCoord( + topLeft, + Coord(topLeft.systemIdentifier, + topLeft.x + tileWidthLayerSystemUnits * numTilesX, + topLeft.y - tileWidthLayerSystemUnits * numTilesY, 0)); + + return Tiled2dMapZoomLevelInfo(zoom, tileWidthLayerSystemUnits, numTilesX, + numTilesY, numTilesT, zoomLevelIdentifier, + bounds); +} + +std::vector Epsg21781Tiled2dMapLayerConfig::swisstopoZoomLevelInfos() { + // same zoom level pyramid as for 2056, just different coordinate origin. + const Coord topLeft{CoordinateSystemIdentifiers::EPSG21781(), 420000.0, 350000.0, 0.}; + + std::vector result; + const auto epsg2056ZoomLevelInfos = Epsg2056Tiled2dMapLayerConfig::swisstopoZoomLevelInfos(); + for(const auto &other : epsg2056ZoomLevelInfos) { + result.push_back(makeZoomLevelInfo( + topLeft, other.zoom, other.tileWidthLayerSystemUnits, + other.numTilesX, other.numTilesY, other.numTilesT, + other.zoomLevelIdentifier)); + } + return result; +} diff --git a/shared/src/map/layers/tiled/Epsg21781Tiled2dMapLayerConfig.h b/shared/src/map/layers/tiled/Epsg21781Tiled2dMapLayerConfig.h new file mode 100644 index 000000000..3c80627e0 --- /dev/null +++ b/shared/src/map/layers/tiled/Epsg21781Tiled2dMapLayerConfig.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2026 Ubique Innovation AG + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +#pragma once + +#include "IrregularTiled2dMapLayerConfig.h" +#include "Tiled2dMapZoomInfo.h" + +class Epsg21781Tiled2dMapLayerConfig : public IrregularTiled2dMapLayerConfig { +public: + Epsg21781Tiled2dMapLayerConfig( + std::string layerName, + std::string urlFormat + ); + + Epsg21781Tiled2dMapLayerConfig( + std::string layerName, + std::string urlFormat, + const std::optional &bounds, + const Tiled2dMapZoomInfo &zoomInfo, + const std::vector &levels + ); + + static std::vector swisstopoZoomLevelInfos(); +}; diff --git a/shared/src/map/layers/tiled/Epsg3857Tiled2dMapLayerConfig.cpp b/shared/src/map/layers/tiled/Epsg3857Tiled2dMapLayerConfig.cpp new file mode 100644 index 000000000..4656a4470 --- /dev/null +++ b/shared/src/map/layers/tiled/Epsg3857Tiled2dMapLayerConfig.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2026 Ubique Innovation AG + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +#include "Epsg3857Tiled2dMapLayerConfig.h" +#include "CoordinateSystemFactory.h" + +const double Epsg3857Tiled2dMapLayerConfig::BASE_ZOOM = 559082264.029; + +Epsg3857Tiled2dMapLayerConfig::Epsg3857Tiled2dMapLayerConfig( + std::string layerName, + std::string urlFormat) + : RegularTiled2dMapLayerConfig( + layerName, urlFormat, std::nullopt, + defaultMapZoomInfo(), + generateLevelsFromMinMax(0, 20), + CoordinateSystemFactory::getEpsg3857System(), + BASE_ZOOM) +{} + +Epsg3857Tiled2dMapLayerConfig::Epsg3857Tiled2dMapLayerConfig( + std::string layerName, + std::string urlFormat, + const std::optional &bounds, + const Tiled2dMapZoomInfo &zoomInfo, + const std::vector &levels) + : RegularTiled2dMapLayerConfig( + layerName, urlFormat, bounds, zoomInfo, levels, + CoordinateSystemFactory::getEpsg3857System(), BASE_ZOOM) +{} + +std::string Epsg3857Tiled2dMapLayerConfig::getTileUrl(int32_t x, int32_t y, int32_t t, int32_t zoom) { + std::string url = urlFormat; + size_t epsg3857Index = url.find("{bbox-epsg-3857}", 0); + if (epsg3857Index != std::string::npos) { + const auto &zoomLevelInfo = getRegularZoomLevelInfo(zoom); + RectCoord levelBounds = zoomLevelInfo.bounds; + const double tileWidth = zoomLevelInfo.tileWidthLayerSystemUnits; + + const bool leftToRight = levelBounds.topLeft.x < levelBounds.bottomRight.x; + const bool topToBottom = levelBounds.topLeft.y < levelBounds.bottomRight.y; + const double tileWidthAdj = leftToRight ? tileWidth : -tileWidth; + const double tileHeightAdj = topToBottom ? tileWidth : -tileWidth; + + const double boundsLeft = levelBounds.topLeft.x; + const double boundsTop = levelBounds.topLeft.y; + + const Coord topLeft = Coord(coordinateSystem.identifier, x * tileWidthAdj + boundsLeft, y * tileHeightAdj + boundsTop, 0); + const Coord bottomRight = Coord(coordinateSystem.identifier, topLeft.x + tileWidthAdj, topLeft.y + tileHeightAdj, 0); + + std::string boxString = std::to_string(topLeft.x) + "," + std::to_string(bottomRight.y) + "," + std::to_string(bottomRight.x) + "," + std::to_string(topLeft.y); + url = url.replace(epsg3857Index, 16, boxString); + return url; + } + return RegularTiled2dMapLayerConfig::getTileUrl(x, y, t, zoom); +} diff --git a/shared/src/map/layers/tiled/Epsg3857Tiled2dMapLayerConfig.h b/shared/src/map/layers/tiled/Epsg3857Tiled2dMapLayerConfig.h new file mode 100644 index 000000000..68b7dd7ff --- /dev/null +++ b/shared/src/map/layers/tiled/Epsg3857Tiled2dMapLayerConfig.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2026 Ubique Innovation AG + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +#pragma once + +#include "RegularTiled2dMapLayerConfig.h" +#include "Tiled2dMapZoomInfo.h" + +class Epsg3857Tiled2dMapLayerConfig : public RegularTiled2dMapLayerConfig { +public: + Epsg3857Tiled2dMapLayerConfig( + std::string layerName, + std::string urlFormat + ); + + Epsg3857Tiled2dMapLayerConfig( + std::string layerName, + std::string urlFormat, + const std::optional &bounds, + const Tiled2dMapZoomInfo &zoomInfo, + const std::vector &levels + ); + + virtual std::string getTileUrl(int32_t x, int32_t y, int32_t t, int32_t zoom) override; + +private: + const static double BASE_ZOOM; +}; diff --git a/shared/src/map/layers/tiled/Epsg4326Tiled2dMapLayerConfig.cpp b/shared/src/map/layers/tiled/Epsg4326Tiled2dMapLayerConfig.cpp index 20781a0e6..125a3604e 100644 --- a/shared/src/map/layers/tiled/Epsg4326Tiled2dMapLayerConfig.cpp +++ b/shared/src/map/layers/tiled/Epsg4326Tiled2dMapLayerConfig.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Ubique Innovation AG + * Copyright (c) 2026 Ubique Innovation AG * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -9,77 +9,28 @@ */ #include "Epsg4326Tiled2dMapLayerConfig.h" -#include "Tiled2dMapVectorSettings.h" -#include "CoordinateSystemIdentifiers.h" -#include -#include +#include "CoordinateSystemFactory.h" -const RectCoord Epsg4326Tiled2dMapLayerConfig::EPSG_4326_BOUNDS = RectCoord(Coord(CoordinateSystemIdentifiers::EPSG4326(), -180.0, 90.0, 0.0), - Coord(CoordinateSystemIdentifiers::EPSG4326(), 180.0, -90.0, 0.0)); const double Epsg4326Tiled2dMapLayerConfig::BASE_ZOOM = 500000000.0; -const double Epsg4326Tiled2dMapLayerConfig::BASE_WIDTH = 360.0; -Epsg4326Tiled2dMapLayerConfig::Epsg4326Tiled2dMapLayerConfig(std::string layerName, std::string urlFormat) - : layerName(layerName), urlFormat(urlFormat) - {} - -Epsg4326Tiled2dMapLayerConfig::Epsg4326Tiled2dMapLayerConfig(std::string layerName, std::string urlFormat, - const Tiled2dMapZoomInfo &zoomInfo, int32_t minZoomLevel, - int32_t maxZoomLevel) - : layerName(layerName), urlFormat(urlFormat), zoomInfo(zoomInfo), minZoomLevel(minZoomLevel), maxZoomLevel(maxZoomLevel) {} - -int32_t Epsg4326Tiled2dMapLayerConfig::getCoordinateSystemIdentifier() { return CoordinateSystemIdentifiers::EPSG4326(); } - -std::string Epsg4326Tiled2dMapLayerConfig::getTileUrl(int32_t x, int32_t y, int32_t t, int32_t zoom) { - std::string url = urlFormat; - size_t zoomIndex = url.find("{z}", 0); - if (zoomIndex == std::string::npos) - throw std::invalid_argument("Layer url \'" + url + "\' has no valid format!"); - url = url.replace(zoomIndex, 3, std::to_string(zoom)); - size_t xIndex = url.find("{x}", 0); - if (xIndex == std::string::npos) - throw std::invalid_argument("Layer url \'" + url + "\' has no valid format!"); - url = url.replace(xIndex, 3, std::to_string(x)); - size_t yIndex = url.find("{y}", 0); - if (yIndex == std::string::npos) - throw std::invalid_argument("Layer url \'" + url + "\' has no valid format!"); - return url.replace(yIndex, 3, std::to_string(y)); -} - -std::string Epsg4326Tiled2dMapLayerConfig::getLayerName() { return layerName; } - -std::vector Epsg4326Tiled2dMapLayerConfig::getZoomLevelInfos() { - std::vector levels; - levels.reserve(maxZoomLevel - minZoomLevel + 1); - for (int32_t i = minZoomLevel; i <= maxZoomLevel; ++i) { - levels.emplace_back(getZoomLevelInfo(i)); - } - return levels; -} - -std::vector Epsg4326Tiled2dMapLayerConfig::getVirtualZoomLevelInfos() { - std::vector levels; - levels.reserve(minZoomLevel); - for (int32_t i = 0; i < minZoomLevel; ++i) { - levels.emplace_back(getZoomLevelInfo(i)); - } - return levels; -} - -Tiled2dMapZoomInfo Epsg4326Tiled2dMapLayerConfig::getZoomInfo() { - return zoomInfo; -} - -std::optional Epsg4326Tiled2dMapLayerConfig::getVectorSettings() { - return std::nullopt; -} - -std::optional<::RectCoord> Epsg4326Tiled2dMapLayerConfig::getBounds() { - return EPSG_4326_BOUNDS; -} - -Tiled2dMapZoomLevelInfo Epsg4326Tiled2dMapLayerConfig::getZoomLevelInfo(int32_t zoomLevel) { - double tileCount = std::pow(2.0,zoomLevel); - double zoom = BASE_ZOOM / tileCount; - return {zoom, (float) (BASE_WIDTH / tileCount), (int32_t) tileCount, (int32_t) tileCount, 1, zoomLevel, EPSG_4326_BOUNDS}; -} +Epsg4326Tiled2dMapLayerConfig::Epsg4326Tiled2dMapLayerConfig( + std::string layerName, + std::string urlFormat) + : RegularTiled2dMapLayerConfig( + layerName, urlFormat, std::nullopt, + defaultMapZoomInfo(), + generateLevelsFromMinMax(0, 20), + CoordinateSystemFactory::getEpsg4326System(), + BASE_ZOOM) +{} + +Epsg4326Tiled2dMapLayerConfig::Epsg4326Tiled2dMapLayerConfig( + std::string layerName, + std::string urlFormat, + const std::optional &bounds, + const Tiled2dMapZoomInfo &zoomInfo, + const std::vector &levels) + : RegularTiled2dMapLayerConfig( + layerName, urlFormat, bounds, zoomInfo, levels, + CoordinateSystemFactory::getEpsg4326System(), BASE_ZOOM) +{} diff --git a/shared/src/map/layers/tiled/Epsg4326Tiled2dMapLayerConfig.h b/shared/src/map/layers/tiled/Epsg4326Tiled2dMapLayerConfig.h index c9b2ed3d0..99e2e25b7 100644 --- a/shared/src/map/layers/tiled/Epsg4326Tiled2dMapLayerConfig.h +++ b/shared/src/map/layers/tiled/Epsg4326Tiled2dMapLayerConfig.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Ubique Innovation AG + * Copyright (c) 2026 Ubique Innovation AG * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -10,44 +10,23 @@ #pragma once -#include "Tiled2dMapLayerConfig.h" +#include "RegularTiled2dMapLayerConfig.h" #include "Tiled2dMapZoomInfo.h" -#include "Tiled2dMapZoomLevelInfo.h" -#include "WmtsLayerDescription.h" - -class Epsg4326Tiled2dMapLayerConfig : public Tiled2dMapLayerConfig { - public: - Epsg4326Tiled2dMapLayerConfig(std::string layerName, std::string urlFormat); - - Epsg4326Tiled2dMapLayerConfig(std::string layerName, std::string urlFormat, const Tiled2dMapZoomInfo &zoomInfo, int32_t minZoomLevel, int32_t maxZoomLevel); - - virtual int32_t getCoordinateSystemIdentifier() override; - - virtual std::string getTileUrl(int32_t x, int32_t y, int32_t t, int32_t zoom) override; - - virtual std::string getLayerName() override; - - virtual std::vector getZoomLevelInfos() override; - - virtual std::vector getVirtualZoomLevelInfos() override; - - virtual Tiled2dMapZoomInfo getZoomInfo() override; - - virtual std::optional getVectorSettings() override; - - std::optional<::RectCoord> getBounds() override; +class Epsg4326Tiled2dMapLayerConfig : public RegularTiled2dMapLayerConfig { +public: + Epsg4326Tiled2dMapLayerConfig( + std::string layerName, + std::string urlFormat + ); + + Epsg4326Tiled2dMapLayerConfig( + std::string layerName, + std::string urlFormat, + const std::optional &bounds, + const Tiled2dMapZoomInfo &zoomInfo, + const std::vector &levels + ); private: - Tiled2dMapZoomLevelInfo getZoomLevelInfo(int32_t zoomLevel); - - const static RectCoord EPSG_4326_BOUNDS; const static double BASE_ZOOM; - const static double BASE_WIDTH; - - std::string layerName; - std::string urlFormat; - - int32_t minZoomLevel = 0; - int32_t maxZoomLevel = 20; - Tiled2dMapZoomInfo zoomInfo = Tiled2dMapZoomInfo(1.0, 0, 0, true, false, true, true); }; diff --git a/shared/src/map/layers/tiled/IrregularTiled2dMapLayerConfig.cpp b/shared/src/map/layers/tiled/IrregularTiled2dMapLayerConfig.cpp new file mode 100644 index 000000000..bab210de1 --- /dev/null +++ b/shared/src/map/layers/tiled/IrregularTiled2dMapLayerConfig.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2026 Ubique Innovation AG + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +#include "IrregularTiled2dMapLayerConfig.h" + +std::vector IrregularTiled2dMapLayerConfig::getZoomLevelInfos() { + std::vector result; + result.reserve(levels.size()); + for(int level : levels) { + result.push_back(zoomLevelInfos[level]); + } + return result; +} + +std::vector IrregularTiled2dMapLayerConfig::getVirtualZoomLevelInfos() { + const int minZoomLevel = levels.front(); + std::vector result(zoomLevelInfos.begin(), zoomLevelInfos.begin() + minZoomLevel); + return result; + }; + +double IrregularTiled2dMapLayerConfig::getZoomIdentifier(double zoom) { + const int minZoomLevel = levels.front(); + const int maxZoomLevel = levels.back(); + + Tiled2dMapZoomLevelInfo prevZoom = zoomLevelInfos.back(); + + for (auto it = zoomLevelInfos.rbegin() + maxZoomLevel; it != zoomLevelInfos.rend() + minZoomLevel; ++it) { + if ((*it).zoom <= zoom) { + prevZoom = *it; + } else { + // Linear Interpolation + auto y0 = prevZoom.zoomLevelIdentifier; + auto x0 = prevZoom.zoom; + auto y1 = (*it).zoomLevelIdentifier; + auto x1 = (*it).zoom; + + return y0 + (zoom - x0) * (y1 - y0) / (x1 - x0); + } + } + + return prevZoom.zoomLevelIdentifier; +} + +double IrregularTiled2dMapLayerConfig::getZoomFactorAtIdentifier(double zoomIdentifier) { + const int minZoomLevel = levels.front(); + const int maxZoomLevel = levels.back(); + + Tiled2dMapZoomLevelInfo prevZoom = zoomLevelInfos.back(); + + for (auto it = zoomLevelInfos.begin() + minZoomLevel; it != zoomLevelInfos.end() + maxZoomLevel; ++it) { + if ((*it).zoomLevelIdentifier <= zoomIdentifier) { + prevZoom = *it; + } else { + // Linear Interpolation + auto y0 = prevZoom.zoom; + auto x0 = prevZoom.zoomLevelIdentifier; + auto y1 = (*it).zoom; + auto x1 = (*it).zoomLevelIdentifier; + + return y0 + (zoomIdentifier - x0) * (y1 - y0) / (x1 - x0); + } + } + + return prevZoom.zoom; +} diff --git a/shared/src/map/layers/tiled/IrregularTiled2dMapLayerConfig.h b/shared/src/map/layers/tiled/IrregularTiled2dMapLayerConfig.h new file mode 100644 index 000000000..2b3cc706f --- /dev/null +++ b/shared/src/map/layers/tiled/IrregularTiled2dMapLayerConfig.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2026 Ubique Innovation AG + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ +#pragma once + +#include "Tiled2dMapVectorLayerConfig.h" +#include "Tiled2dMapZoomLevelInfo.h" + +/** Base class for Tiled2dMapVectorLayerConfig implementations for _irregular_ + * tile pyramids, i.e. for tile systems that do not follow a simple power-of-2 + * relation between zoom levels, but are defined with a table of fixed zoom + * levels. + */ +class IrregularTiled2dMapLayerConfig : public Tiled2dMapVectorLayerConfig { +public: + IrregularTiled2dMapLayerConfig( + std::string layerName, + std::string urlFormat, + const std::optional &bounds, + const Tiled2dMapZoomInfo &zoomInfo, + const std::vector &levels, + const std::vector &zoomLevelInfos + ) + : Tiled2dMapVectorLayerConfig(layerName, urlFormat, bounds, zoomInfo, levels) + , zoomLevelInfos(zoomLevelInfos) + {} + + virtual int32_t getCoordinateSystemIdentifier() override { + return zoomLevelInfos.front().bounds.topLeft.systemIdentifier; + } + + virtual std::vector getZoomLevelInfos() override; + virtual std::vector getVirtualZoomLevelInfos() override; + + virtual double getZoomIdentifier(double zoom) override; + virtual double getZoomFactorAtIdentifier(double zoomIdentifier) override; + +protected: + std::vector zoomLevelInfos; +}; diff --git a/shared/src/map/layers/tiled/RegularTiled2dMapLayerConfig.cpp b/shared/src/map/layers/tiled/RegularTiled2dMapLayerConfig.cpp new file mode 100644 index 000000000..a3d17563d --- /dev/null +++ b/shared/src/map/layers/tiled/RegularTiled2dMapLayerConfig.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2026 Ubique Innovation AG + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +#include "RegularTiled2dMapLayerConfig.h" +#include + +std::vector RegularTiled2dMapLayerConfig::getZoomLevelInfos() { + std::vector result; + result.reserve(levels.size()); + for(int level : levels) { + result.push_back(getRegularZoomLevelInfo(level)); + } + return result; +} + +std::vector RegularTiled2dMapLayerConfig::getVirtualZoomLevelInfos() { + int minZoomLevel = levels.front(); + std::vector result; + result.reserve(minZoomLevel); + for(int level = 0; level < minZoomLevel; level++) { + result.push_back(getRegularZoomLevelInfo(level)); + } + return result; +}; + +double RegularTiled2dMapLayerConfig::getZoomIdentifier(double zoom) { + return std::max(0.0, std::round(log(baseZoom * zoomInfo.zoomLevelScaleFactor / zoom) / log(2) * 100) / 100); +} + +double RegularTiled2dMapLayerConfig::getZoomFactorAtIdentifier(double zoomIdentifier) { + double factor = pow(2, zoomIdentifier); + return baseZoom * zoomInfo.zoomLevelScaleFactor / factor; +} + +Tiled2dMapZoomLevelInfo RegularTiled2dMapLayerConfig::getRegularZoomLevelInfo(int zoomLevel) { + const double baseValueWidth = (coordinateSystem.bounds.bottomRight.x - coordinateSystem.bounds.topLeft.x); + double factor = pow(2, zoomLevel); + double zoom = baseZoom / factor; + double width = baseValueWidth / factor; + return Tiled2dMapZoomLevelInfo(zoom, width, factor, factor, 1, zoomLevel, coordinateSystem.bounds); +} diff --git a/shared/src/map/layers/tiled/RegularTiled2dMapLayerConfig.h b/shared/src/map/layers/tiled/RegularTiled2dMapLayerConfig.h new file mode 100644 index 000000000..857f1ba68 --- /dev/null +++ b/shared/src/map/layers/tiled/RegularTiled2dMapLayerConfig.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2026 Ubique Innovation AG + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ +#pragma once + +#include "Tiled2dMapVectorLayerConfig.h" +#include "Tiled2dMapZoomLevelInfo.h" +#include "MapCoordinateSystem.h" + +/** Base class for Tiled2dMapVectorLayerConfig implementations for _regular_ + * tile pyramids, i.e. for tile systems with a simple power-of-2 relation + * between zoom levels. + */ +class RegularTiled2dMapLayerConfig : public Tiled2dMapVectorLayerConfig { +public: + RegularTiled2dMapLayerConfig( + std::string layerName, + std::string urlFormat, + const std::optional &bounds, + const Tiled2dMapZoomInfo &zoomInfo, + const std::vector &levels, + const MapCoordinateSystem &coordinateSystem, + double baseZoom) + : Tiled2dMapVectorLayerConfig(layerName, urlFormat, bounds, zoomInfo, levels) + , coordinateSystem(coordinateSystem) + , baseZoom(baseZoom) + {} + + virtual int32_t getCoordinateSystemIdentifier() override { + return coordinateSystem.identifier; + } + + virtual std::vector getZoomLevelInfos() override; + + virtual std::vector getVirtualZoomLevelInfos() override; + + virtual double getZoomIdentifier(double zoom) override; + + virtual double getZoomFactorAtIdentifier(double zoomIdentifier) override; + +protected: + Tiled2dMapZoomLevelInfo getRegularZoomLevelInfo(int zoomLevel); + +protected: + double baseZoom; + MapCoordinateSystem coordinateSystem; +}; diff --git a/shared/src/map/layers/tiled/Tiled2dMapVectorLayerConfig.cpp b/shared/src/map/layers/tiled/Tiled2dMapVectorLayerConfig.cpp new file mode 100644 index 000000000..8b42f0ac1 --- /dev/null +++ b/shared/src/map/layers/tiled/Tiled2dMapVectorLayerConfig.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2026 Ubique Innovation AG + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +#include "Tiled2dMapVectorLayerConfig.h" +#include +#include +#include + +Tiled2dMapVectorLayerConfig::Tiled2dMapVectorLayerConfig( + std::string layerName, + std::string urlFormat, + const std::optional &bounds, + const Tiled2dMapZoomInfo &zoomInfo, + const std::vector &levels_ +) + : layerName(layerName) + , urlFormat(urlFormat) + , bounds(bounds) + , zoomInfo(zoomInfo) + , levels(levels_) +{ + std::sort(levels.begin(), levels.end()); +} + +std::string Tiled2dMapVectorLayerConfig::getTileUrl(int32_t x, int32_t y, int32_t t, int32_t zoom) { + std::string url = urlFormat; + size_t zoomIndex = url.find("{z}", 0); + if (zoomIndex == std::string::npos) throw std::invalid_argument("Layer url \'" + url + "\' has no valid format!"); + url = url.replace(zoomIndex, 3, std::to_string(zoom)); + size_t xIndex = url.find("{x}", 0); + if (xIndex == std::string::npos) throw std::invalid_argument("Layer url \'" + url + "\' has no valid format!"); + url = url.replace(xIndex, 3, std::to_string(x)); + size_t yIndex = url.find("{y}", 0); + if (yIndex == std::string::npos) throw std::invalid_argument("Layer url \'" + url + "\' has no valid format!"); + return url.replace(yIndex, 3, std::to_string(y)); +} + +Tiled2dMapZoomInfo Tiled2dMapVectorLayerConfig::defaultMapZoomInfo() { + return Tiled2dMapZoomInfo(1.0, 0, 0, true, false, true, true); +} + +std::vector Tiled2dMapVectorLayerConfig::generateLevelsFromMinMax(int minZoomLevel, int maxZoomLevel) { + std::vector levels(maxZoomLevel - minZoomLevel + 1); + std::iota(levels.begin(), levels.end(), minZoomLevel); + return levels; +} diff --git a/shared/src/map/layers/tiled/WebMercatorTiled2dMapLayerConfig.cpp b/shared/src/map/layers/tiled/WebMercatorTiled2dMapLayerConfig.cpp deleted file mode 100644 index a9bb90b34..000000000 --- a/shared/src/map/layers/tiled/WebMercatorTiled2dMapLayerConfig.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2021 Ubique Innovation AG - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - * - * SPDX-License-Identifier: MPL-2.0 - */ - -#include "WebMercatorTiled2dMapLayerConfig.h" -#include "Tiled2dMapVectorSettings.h" -#include "CoordinateSystemIdentifiers.h" -#include -#include - - -const RectCoord WebMercatorTiled2dMapLayerConfig::WEB_MERCATOR_BOUNDS = RectCoord(Coord(CoordinateSystemIdentifiers::EPSG3857(), -20037508.34, 20037508.34, 0.0), - Coord(CoordinateSystemIdentifiers::EPSG3857(), 20037508.34, -20037508.34, 0.0)); -const double WebMercatorTiled2dMapLayerConfig::BASE_ZOOM = 559082264.029; -const double WebMercatorTiled2dMapLayerConfig::BASE_WIDTH = 40075016; - -WebMercatorTiled2dMapLayerConfig::WebMercatorTiled2dMapLayerConfig(std::string layerName, std::string urlFormat, int32_t minZoomLevel, - int32_t maxZoomLevel) - : layerName(layerName), urlFormat(urlFormat), minZoomLevel(minZoomLevel), maxZoomLevel(maxZoomLevel) - {} - -WebMercatorTiled2dMapLayerConfig::WebMercatorTiled2dMapLayerConfig(std::string layerName, std::string urlFormat, - const Tiled2dMapZoomInfo &zoomInfo, int32_t minZoomLevel, - int32_t maxZoomLevel) - : layerName(layerName), urlFormat(urlFormat), zoomInfo(zoomInfo), minZoomLevel(minZoomLevel), maxZoomLevel(maxZoomLevel) {} - -int32_t WebMercatorTiled2dMapLayerConfig::getCoordinateSystemIdentifier() { return CoordinateSystemIdentifiers::EPSG3857(); } - -std::string WebMercatorTiled2dMapLayerConfig::getTileUrl(int32_t x, int32_t y, int32_t t, int32_t zoom) { - std::string url = urlFormat; - size_t zoomIndex = url.find("{z}", 0); - if (zoomIndex == std::string::npos) - throw std::invalid_argument("Layer url \'" + url + "\' has no valid format!"); - url = url.replace(zoomIndex, 3, std::to_string(zoom)); - size_t xIndex = url.find("{x}", 0); - if (xIndex == std::string::npos) - throw std::invalid_argument("Layer url \'" + url + "\' has no valid format!"); - url = url.replace(xIndex, 3, std::to_string(x)); - size_t yIndex = url.find("{y}", 0); - if (yIndex == std::string::npos) - throw std::invalid_argument("Layer url \'" + url + "\' has no valid format!"); - return url.replace(yIndex, 3, std::to_string(y)); -} - -std::string WebMercatorTiled2dMapLayerConfig::getLayerName() { return layerName; } - -std::vector WebMercatorTiled2dMapLayerConfig::getZoomLevelInfos() { - std::vector levels; - levels.reserve(maxZoomLevel - minZoomLevel + 1); - for (int32_t i = minZoomLevel; i <= maxZoomLevel; ++i) { - levels.emplace_back(getZoomLevelInfo(i)); - } - return levels; -} - -std::vector WebMercatorTiled2dMapLayerConfig::getVirtualZoomLevelInfos() { - std::vector levels; - levels.reserve(minZoomLevel); - for (int32_t i = 0; i < minZoomLevel; ++i) { - levels.emplace_back(getZoomLevelInfo(i)); - } - return levels; -}; - -Tiled2dMapZoomInfo WebMercatorTiled2dMapLayerConfig::getZoomInfo() { - return zoomInfo; -} - -std::optional WebMercatorTiled2dMapLayerConfig::getVectorSettings() { - return std::nullopt; -} - -std::optional<::RectCoord> WebMercatorTiled2dMapLayerConfig::getBounds() { - return WEB_MERCATOR_BOUNDS; -} - -Tiled2dMapZoomLevelInfo WebMercatorTiled2dMapLayerConfig::getZoomLevelInfo(int32_t zoomLevel) { - double tileCount = std::pow(2.0,zoomLevel); - double zoom = BASE_ZOOM / tileCount; - return {zoom, (float) (BASE_WIDTH / tileCount), (int32_t) tileCount, (int32_t) tileCount, 1, zoomLevel, WEB_MERCATOR_BOUNDS}; -} diff --git a/shared/src/map/layers/tiled/WebMercatorTiled2dMapLayerConfig.h b/shared/src/map/layers/tiled/WebMercatorTiled2dMapLayerConfig.h deleted file mode 100644 index b7e0dc02d..000000000 --- a/shared/src/map/layers/tiled/WebMercatorTiled2dMapLayerConfig.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2021 Ubique Innovation AG - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - * - * SPDX-License-Identifier: MPL-2.0 - */ - -#pragma once - -#include "Tiled2dMapLayerConfig.h" -#include "Tiled2dMapZoomInfo.h" -#include "Tiled2dMapZoomLevelInfo.h" -#include "WmtsLayerDescription.h" - -class WebMercatorTiled2dMapLayerConfig : public Tiled2dMapLayerConfig { - public: - WebMercatorTiled2dMapLayerConfig(std::string layerName, std::string urlFormat, int32_t minZoomLevel = 0, int32_t maxZoomLevel = 20); - - WebMercatorTiled2dMapLayerConfig(std::string layerName, std::string urlFormat, const Tiled2dMapZoomInfo &zoomInfo, int32_t minZoomLevel, int32_t maxZoomLevel); - - virtual int32_t getCoordinateSystemIdentifier() override; - - virtual std::string getTileUrl(int32_t x, int32_t y, int32_t t, int32_t zoom) override; - - virtual std::string getLayerName() override; - - virtual std::vector getZoomLevelInfos() override; - - virtual std::vector getVirtualZoomLevelInfos() override; - - virtual Tiled2dMapZoomInfo getZoomInfo() override; - - virtual std::optional getVectorSettings() override; - - std::optional<::RectCoord> getBounds() override; - -private: - Tiled2dMapZoomLevelInfo getZoomLevelInfo(int32_t zoomLevel); - - const static RectCoord WEB_MERCATOR_BOUNDS; - const static double BASE_ZOOM; - const static double BASE_WIDTH; - - std::string layerName; - std::string urlFormat; - - int32_t minZoomLevel = 0; - int32_t maxZoomLevel = 20; - Tiled2dMapZoomInfo zoomInfo = Tiled2dMapZoomInfo(1.0, 0, 0, true, false, true, true); -}; diff --git a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorGeoJSONLayerConfig.h b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorGeoJSONLayerConfig.h deleted file mode 100644 index 322f49ef3..000000000 --- a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorGeoJSONLayerConfig.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2021 Ubique Innovation AG - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - * - * SPDX-License-Identifier: MPL-2.0 - */ - -#pragma once -#include "Tiled2dMapVectorLayerConfig.h" - -class Tiled2dMapVectorGeoJSONLayerConfig : public Tiled2dMapVectorLayerConfig { -public: - Tiled2dMapVectorGeoJSONLayerConfig(const std::string &sourceName, const std::weak_ptr geoJSON, const Tiled2dMapZoomInfo &zoomInfo = Tiled2dMapZoomInfo(1.0, 0, 0, false, true, false, true)) - : Tiled2dMapVectorLayerConfig(nullptr, zoomInfo), geoJSON(geoJSON), sourceName(sourceName) {} - - ~Tiled2dMapVectorGeoJSONLayerConfig() {} - - std::string getTileUrl(int32_t x, int32_t y, int32_t t, int32_t zoom) override { - static std::string empty = ""; - return empty; - } - - std::vector getZoomLevelInfos() override { - int maxZoom = 0; - int minZoom = 0; - if (auto geoJSON = this->geoJSON.lock()){ - minZoom = geoJSON->getMinZoom(); - maxZoom = geoJSON->getMaxZoom(); - } - return getDefaultEpsg3857ZoomLevels(minZoom, maxZoom, std::nullopt); - } - - std::vector getVirtualZoomLevelInfos() override { - return {}; - } - - std::string getLayerName() override { - return sourceName; - } - -protected: - std::weak_ptr geoJSON; - const std::string sourceName; -}; diff --git a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp index 96baf38a9..2fa393676 100644 --- a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp +++ b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp @@ -19,7 +19,6 @@ #include "BackgroundVectorLayerDescription.h" #include "VectorTileGeometryHandler.h" #include "Tiled2dMapVectorBackgroundSubLayer.h" -#include "Tiled2dMapVectorRasterSubLayerConfig.h" #include "Polygon2dInterface.h" #include "MapCameraInterface.h" #include "QuadMaskObject.h" @@ -45,10 +44,14 @@ #include "Tiled2dMapVectorReadyManager.h" #include "Tiled2dVectorGeoJsonSource.h" #include "Tiled2dMapVectorStyleParser.h" -#include "Tiled2dMapVectorGeoJSONLayerConfig.h" #include "GeoJsonVTFactory.h" #include "VectorLayerFeatureCoordInfo.h" +#include "Epsg2056Tiled2dMapLayerConfig.h" +#include "Epsg21781Tiled2dMapLayerConfig.h" +#include "Epsg3857Tiled2dMapLayerConfig.h" +#include "Epsg4326Tiled2dMapLayerConfig.h" + Tiled2dMapVectorLayer::Tiled2dMapVectorLayer(const std::string &layerName, const std::optional &remoteStyleJsonUrl, const std::vector> &loaders, @@ -237,14 +240,26 @@ Tiled2dMapVectorLayer::getLayerConfig(const std::shared_ptr(source, *customZoomInfo) - : std::make_shared(source, mapInterface->is3d()); + const std::optional crs = source->coordinateReferenceSystem; + const auto &zoomInfo = customZoomInfo.has_value() ? *customZoomInfo : source->getZoomInfo(mapInterface->is3d()); + if(!crs.has_value() || *crs == CoordinateSystemIdentifiers::EPSG3857()) { + return std::make_shared(source->identifier, source->vectorUrl, source->bounds, zoomInfo, source->getZoomLevels()); + } else if(*crs == CoordinateSystemIdentifiers::EPSG4326()){ + return std::make_shared(source->identifier, source->vectorUrl, source->bounds, zoomInfo, source->getZoomLevels()); + } else if(*crs == CoordinateSystemIdentifiers::EPSG2056()){ + return std::static_pointer_cast(std::make_shared(source->identifier, source->vectorUrl, source->bounds, zoomInfo, source->getZoomLevels())); + } else if(*crs == CoordinateSystemIdentifiers::EPSG21781()){ + return std::make_shared(source->identifier, source->vectorUrl, source->bounds, zoomInfo, source->getZoomLevels()); + } + // layer will be ignored + return nullptr; } std::shared_ptr Tiled2dMapVectorLayer::getGeoJSONLayerConfig(const std::string &sourceName, const std::shared_ptr &source) { - return customZoomInfo.has_value() ? std::make_shared(sourceName, source, *customZoomInfo) - : std::make_shared(sourceName, source); + const auto levels = Tiled2dMapVectorLayerConfig::generateLevelsFromMinMax(source->getMinZoom(), source->getMaxZoom()); + auto zoomInfo = customZoomInfo.has_value() ? *customZoomInfo : Tiled2dMapZoomInfo(1.0, 0, 0, false, true, false, true); + return std::make_shared(sourceName, "", std::nullopt, zoomInfo, levels); } void Tiled2dMapVectorLayer::setMapDescription(const std::shared_ptr &mapDescription) { @@ -296,7 +311,6 @@ void Tiled2dMapVectorLayer::initializeVectorLayer() { if (!mapInterface) { return; } - bool is3d = mapInterface->is3d(); std::shared_ptr selfMailbox = mailbox; if (!mailbox) { @@ -332,10 +346,7 @@ void Tiled2dMapVectorLayer::initializeVectorLayer() { break; } case raster: { - auto rasterSubLayerConfig = customZoomInfo.has_value() ? std::make_shared( - std::static_pointer_cast(layerDesc), is3d,*customZoomInfo) - : std::make_shared( - std::static_pointer_cast(layerDesc), is3d); + auto rasterSubLayerConfig = getLayerConfig(std::dynamic_pointer_cast(layerDesc)->source); auto sourceMailbox = std::make_shared(mapInterface->getScheduler()); auto sourceActor = Actor(sourceMailbox, diff --git a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayerParserHelper.cpp b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayerParserHelper.cpp index ae0d45e59..6da9439cf 100644 --- a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayerParserHelper.cpp +++ b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayerParserHelper.cpp @@ -73,7 +73,7 @@ Tiled2dMapVectorLayerParserResult Tiled2dMapVectorLayerParserHelper::parseStyleJ std::vector> layers; - std::map> rasterLayerMap; + std::map> rasterSourceMap; std::map> geojsonSources; @@ -92,8 +92,8 @@ Tiled2dMapVectorLayerParserResult Tiled2dMapVectorLayerParserHelper::parseStyleJ bool maskTiles = true; double zoomLevelScaleFactor = 1.0; - bool overzoom = val.contains("overzoom") ? tileJsons["overzoom"].get() : true; - bool underzoom = val.contains("underzoom") ? tileJsons["underzoom"].get() : false; + bool overzoom = val.contains("overzoom") ? val["overzoom"].get() : true; + bool underzoom = val.contains("underzoom") ? val["underzoom"].get() : false; std::optional> levels; int minZoom = std::numeric_limits::max(); @@ -111,9 +111,14 @@ Tiled2dMapVectorLayerParserResult Tiled2dMapVectorLayerParserHelper::parseStyleJ minZoom = val.value("minzoom", 0); maxZoom = val.value("maxzoom", 22); } + std::optional coordinateReferenceSystem; + if(val.contains("crs") && val["crs"].is_string()) { + coordinateReferenceSystem = CoordinateSystemIdentifiers::fromCrsIdentifier(val["crs"].get()); + } else if(val["metadata"].is_object() && val["metadata"].contains("crs") && val["metadata"]["crs"].is_string()) { + coordinateReferenceSystem = CoordinateSystemIdentifiers::fromCrsIdentifier(val["metadata"]["crs"].get()); + } std::optional<::RectCoord> bounds; - std::optional coordinateReferenceSystem; if (val["tiles"].is_array()) { auto str = val.dump(); @@ -135,9 +140,6 @@ Tiled2dMapVectorLayerParserResult Tiled2dMapVectorLayerParserHelper::parseStyleJ } } - if(val["metadata"].is_object() && val["metadata"].contains("crs") && val["metadata"]["crs"].is_string()) { - coordinateReferenceSystem = val["metadata"]["crs"].get(); - } } else if (val["url"].is_string()) { auto result = LoaderHelper::loadData(replaceUrlParams(val["url"].get(), sourceUrlParams), std::nullopt, loaders); @@ -166,36 +168,26 @@ Tiled2dMapVectorLayerParserResult Tiled2dMapVectorLayerParserHelper::parseStyleJ } } - if(json["metadata"].is_object() && json["metadata"].contains("crs") && json["metadata"]["crs"].is_string()) { - coordinateReferenceSystem = json["metadata"]["crs"].get(); - } minZoom = json.value("minzoom", 0); maxZoom = json.value("maxzoom", 22); } - - RasterVectorStyle style = RasterVectorStyle(nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); - rasterLayerMap[key] = std::make_shared(layerName, - key, - 0, - 24, - minZoom, - maxZoom, - url, - nullptr, - style, - adaptScaleToScreen, - numDrawPreviousLayers, - maskTiles, - zoomLevelScaleFactor, - std::nullopt, - nullptr, - underzoom, - overzoom, - bounds, - coordinateReferenceSystem, - levels); + rasterSourceMap[key] = std::make_shared( + key, + url, + minZoom, + maxZoom, + bounds, + zoomLevelScaleFactor, + adaptScaleToScreen, + numDrawPreviousLayers, + underzoom, + overzoom, + levels, + coordinateReferenceSystem, + maskTiles + ); } else if (type == "vector" && val["url"].is_string()) { auto result = LoaderHelper::loadData(replaceUrlParams(val["url"].get(), sourceUrlParams), std::nullopt, loaders); @@ -275,6 +267,10 @@ Tiled2dMapVectorLayerParserResult Tiled2dMapVectorLayerParserHelper::parseStyleJ minZoom = tileJson.value("minzoom", 0); maxZoom = tileJson.value("maxzoom", 22); } + std::optional coordinateReferenceSystem; + if(tileJson.contains("crs") && tileJson["crs"].is_string()) { + coordinateReferenceSystem = CoordinateSystemIdentifiers::fromCrsIdentifier(tileJson["crs"].get()); + } sourceDescriptions.push_back( std::make_shared(identifier, @@ -287,7 +283,9 @@ Tiled2dMapVectorLayerParserResult Tiled2dMapVectorLayerParserHelper::parseStyleJ numDrawPreviousLayers, underzoom, overzoom, - levels)); + levels, + coordinateReferenceSystem + )); } @@ -361,8 +359,8 @@ Tiled2dMapVectorLayerParserResult Tiled2dMapVectorLayerParserHelper::parseStyleJ interactable); layers.push_back(layerDesc); - } else if (val["type"] == "raster" && rasterLayerMap.count(val["source"]) != 0) { - auto layer = rasterLayerMap[val["source"]]; + } else if (val["type"] == "raster" && rasterSourceMap.count(val["source"]) != 0) { + const auto &source = rasterSourceMap[val["source"]]; RasterVectorStyle style = RasterVectorStyle(parser.parseValue(val["paint"]["raster-opacity"]), parser.parseValue(val["paint"]["raster-brightness-min"]), parser.parseValue(val["paint"]["raster-brightness-max"]), @@ -373,30 +371,21 @@ Tiled2dMapVectorLayerParserResult Tiled2dMapVectorLayerParserHelper::parseStyleJ blendMode); std::shared_ptr filter = parser.parseValue(val["filter"]); - bool underzoom = layer->underzoom && !val.contains("minzoom"); - bool overzoom = layer->overzoom && !val.contains("maxzoom"); - - auto newLayer = std::make_shared(val["id"], - val["source"], - val.value("minzoom", layer->minZoom), - val.value("maxzoom", layer->maxZoom), - layer->sourceMinZoom, - layer->sourceMaxZoom, - layer->url, - filter, - style, - layer->adaptScaleToScreen, - layer->numDrawPreviousLayers, - layer->maskTiles, - layer->zoomLevelScaleFactor, - layer->renderPassIndex, - interactable, - underzoom, - overzoom, - layer->bounds, - layer->coordinateReferenceSystem, - layer->levels); - layers.push_back(newLayer); + // TODO + [[maybe_unused]] + bool underzoom = source->underzoom && !val.contains("minzoom"); + [[maybe_unused]] + bool overzoom = source->overzoom && !val.contains("maxzoom"); + + auto layer = std::make_shared(val["id"], + source, + val.value("minzoom", source->minZoom), + val.value("maxzoom", source->maxZoom), + filter, + renderPassIndex, + interactable, + style); + layers.push_back(layer); } else if (val["type"] == "line") { std::shared_ptr filter = parser.parseValue(val["filter"]); diff --git a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorRasterSubLayerConfig.h b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorRasterSubLayerConfig.h deleted file mode 100644 index 0dca53544..000000000 --- a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorRasterSubLayerConfig.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2021 Ubique Innovation AG - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - * - * SPDX-License-Identifier: MPL-2.0 - */ -#pragma once - -#include "VectorLayerDescription.h" -#include "RasterVectorLayerDescription.h" -#include "Tiled2dMapVectorLayerConfig.h" -#include "Tiled2dMapZoomInfo.h" -#include "CoordinateSystemIdentifiers.h" -#include "Tiled2dMapZoomLevelInfo.h" -#include "Logger.h" -#include "Tiled2dMapVectorSettings.h" -#include "Epsg4326Tiled2dMapLayerConfig.h" - -class Tiled2dMapVectorRasterSubLayerConfig : public Tiled2dMapVectorLayerConfig { -public: - Tiled2dMapVectorRasterSubLayerConfig(const std::shared_ptr &layerDescription, - const bool is3d, - const std::optional &customZoomInfo = std::nullopt) - : Tiled2dMapVectorLayerConfig( - std::make_shared(layerDescription->source, layerDescription->url, layerDescription->sourceMinZoom, - layerDescription->sourceMaxZoom, layerDescription->bounds, - layerDescription->zoomLevelScaleFactor, - layerDescription->adaptScaleToScreen, - layerDescription->numDrawPreviousLayers, - layerDescription->underzoom, - layerDescription->overzoom, - layerDescription->levels), is3d), - description(layerDescription) { - if (customZoomInfo.has_value()) { - zoomInfo = Tiled2dMapZoomInfo(customZoomInfo->zoomLevelScaleFactor * description->zoomLevelScaleFactor, - std::max(customZoomInfo->numDrawPreviousLayers, description->numDrawPreviousLayers), - 0, - customZoomInfo->adaptScaleToScreen || description->adaptScaleToScreen, - customZoomInfo->maskTile || description->maskTiles, - customZoomInfo->underzoom && description->underzoom, - customZoomInfo->overzoom && description->overzoom); - } else { - zoomInfo = Tiled2dMapZoomInfo(description->zoomLevelScaleFactor, description->numDrawPreviousLayers, 0, - description->adaptScaleToScreen, description->maskTiles, description->underzoom, - description->overzoom); - } - - if (description->coordinateReferenceSystem == "EPSG:4326") { - customConfig = std::make_shared(layerDescription->source, - layerDescription->url, - zoomInfo, - layerDescription->sourceMinZoom, - layerDescription->sourceMaxZoom); - } - } - - int32_t getCoordinateSystemIdentifier() override { - if (customConfig) { - return customConfig->getCoordinateSystemIdentifier(); - } - return Tiled2dMapVectorLayerConfig::getCoordinateSystemIdentifier(); - } - - std::string getTileUrl(int32_t x, int32_t y, int32_t t, int32_t zoom) override { - if (customConfig) { - return customConfig->getTileUrl(x,y,t,zoom); - } - return Tiled2dMapVectorLayerConfig::getTileUrl(x,y,t,zoom); - } - - std::string getLayerName() override { - if (customConfig) { - return customConfig->getLayerName(); - } - return Tiled2dMapVectorLayerConfig::getLayerName(); - } - - std::vector getZoomLevelInfos() override { - if (customConfig) { - return customConfig->getZoomLevelInfos(); - } - return Tiled2dMapVectorLayerConfig::getZoomLevelInfos(); - } - - std::vector getVirtualZoomLevelInfos() override { - if (customConfig) { - return customConfig->getVirtualZoomLevelInfos(); - } - return Tiled2dMapVectorLayerConfig::getVirtualZoomLevelInfos(); - } - - Tiled2dMapZoomInfo getZoomInfo() override { - if (customConfig) { - return customConfig->getZoomInfo(); - } - return Tiled2dMapVectorLayerConfig::getZoomInfo(); - } - - std::optional getVectorSettings() override { - if (customConfig) { - return customConfig->getVectorSettings(); - } - return Tiled2dMapVectorLayerConfig::getVectorSettings(); - } - - std::optional<::RectCoord> getBounds() override { - if (customConfig) { - return customConfig->getBounds(); - } - return Tiled2dMapVectorLayerConfig::getBounds(); - } - - -private: - std::shared_ptr description; - - std::shared_ptr customConfig; -}; diff --git a/shared/src/map/layers/tiled/wmts/WmtsTiled2dMapLayerConfig.cpp b/shared/src/map/layers/tiled/wmts/WmtsTiled2dMapLayerConfig.cpp index 4f91171f6..58c750737 100644 --- a/shared/src/map/layers/tiled/wmts/WmtsTiled2dMapLayerConfig.cpp +++ b/shared/src/map/layers/tiled/wmts/WmtsTiled2dMapLayerConfig.cpp @@ -11,7 +11,6 @@ #include "WmtsTiled2dMapLayerConfig.h" #include "Tiled2dMapVectorSettings.h" -#include "Logger.h" #include WmtsTiled2dMapLayerConfig::WmtsTiled2dMapLayerConfig(const WmtsLayerDescription &description, diff --git a/shared/test/TestTileSource.cpp b/shared/test/TestTileSource.cpp index dc87cf455..0e28fe3e1 100644 --- a/shared/test/TestTileSource.cpp +++ b/shared/test/TestTileSource.cpp @@ -1,9 +1,9 @@ #include "CoordinateSystemFactory.h" #include "DataLoaderResult.h" +#include "Epsg3857Tiled2dMapLayerConfig.h" #include "LoaderInterface.h" #include "TextureLoaderResult.h" #include "Tiled2dMapSource.h" -#include "WebMercatorTiled2dMapLayerConfig.h" #include "helper/TestScheduler.h" #include "Tiled2dMapSourceImpl.h" @@ -219,9 +219,18 @@ class BlockingTestLoader : public LoaderInterface { std::list blockedLoads; }; +static std::shared_ptr createTestLayerConfig() { + auto zoomInfo = Tiled2dMapVectorLayerConfig::defaultMapZoomInfo(); + zoomInfo.adaptScaleToScreen = false; // Important, otherwise the onVisibleBoundsChanged does not pick up the (in the tests) expected zoom level. + return std::make_shared("mock", "test-data://tile/{z}/{x}/{y}", + std::nullopt, + zoomInfo, + Tiled2dMapVectorLayerConfig::generateLevelsFromMinMax(0, 20) + ); +} + TEST_CASE("VectorTileSource") { - auto layerConfig = std::make_shared( - "mock", "{z}/{x}/{y}", Tiled2dMapZoomInfo(1.0, 0, 0, false, true, false, true), 0, 20); + auto layerConfig = createTestLayerConfig(); auto scheduler = std::make_shared(); std::shared_ptr source = std::make_shared( layerConfig, scheduler, std::vector>{std::make_shared()}); @@ -273,11 +282,10 @@ static std::unordered_map generateDummyData(const std: */ TEST_CASE("Tiled2dMapSource slow fallback does not block local loads") { - auto layerConfig = std::make_shared( - "mock", "test-data://tile/{z}/{x}/{y}", Tiled2dMapZoomInfo(1.0, 0, 0, false, true, false, true), 0, 20); + auto layerConfig = createTestLayerConfig(); // Load the entire world. - auto rect = *layerConfig->getBounds(); + auto rect = CoordinateSystemFactory::getEpsg3857System().bounds; auto zoomLevelInfos = layerConfig->getZoomLevelInfos(); // Try with different zoom levels; that's 1, 16, 256 or 1024 tiles const int z = GENERATE(0, 2, 4, 5); @@ -320,6 +328,7 @@ TEST_CASE("Tiled2dMapSource slow fallback does not block local loads") { // Complete all "local" loads scheduler->drain(); + CAPTURE(z); REQUIRE(source->numLoadingOrQueued() == expectedTiles.size()); while (localLoader->unblockAll()) { scheduler->drain(); @@ -347,11 +356,10 @@ TEST_CASE("Tiled2dMapSource slow fallback does not block local loads") { TEST_CASE("Tiled2dMapSource error load retry") { - auto layerConfig = std::make_shared( - "mock", "test-data://tile/{z}/{x}/{y}", Tiled2dMapZoomInfo(1.0, 0, 0, false, true, false, true), 0, 20); + auto layerConfig = createTestLayerConfig(); // Load the entire world at zoom level 3 - auto rect = *layerConfig->getBounds(); + auto rect = CoordinateSystemFactory::getEpsg3857System().bounds; auto zoomLevelInfos = layerConfig->getZoomLevelInfos(); const int z = 3; std::vector expectedTiles = {{rect, 0, 0, 0, 0, int(zoomLevelInfos[0].zoom)}};