From b92094c762fc9d0cd4f3e34d668dbfcaad792146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=C3=A4rki?= Date: Fri, 16 Feb 2024 17:10:30 +0100 Subject: [PATCH 01/23] Bugfixes --- ios/maps/MCMapView.swift | 14 +++++++++----- shared/public/GeoJsonTypes.h | 1 + shared/public/Tiled2dMapSourceImpl.h | 14 +++++++++++++- .../layers/tiled/vector/geojson/GeoJsonParser.h | 5 ++--- .../vector/geojson/Tiled2dVectorGeoJsonSource.h | 9 +++++++++ .../tiled/vector/geojson/geojsonvt/geojsonvt.hpp | 5 ++++- .../symbol/Tiled2dMapVectorSymbolLabelObject.cpp | 4 ++++ 7 files changed, 42 insertions(+), 10 deletions(-) diff --git a/ios/maps/MCMapView.swift b/ios/maps/MCMapView.swift index ca27929a1..2f3c542cb 100644 --- a/ios/maps/MCMapView.swift +++ b/ios/maps/MCMapView.swift @@ -190,15 +190,18 @@ extension MCMapView: MTKViewDelegate { } } - public func renderToImage(size: CGSize, timeout: Float, bounds: MCRectCoord, callback: @escaping (UIImage?, MCLayerReadyState) -> Void) { + public func renderToImage(size: CGSize, timeout: Float, bounds: MCRectCoord, callbackQueue: DispatchQueue = .main, callback: @escaping (UIImage?, MCLayerReadyState) -> Void) { renderToImageQueue.async { - self.frame = CGRect(origin: .zero, size: .init(width: size.width / UIScreen.main.scale, height: size.height / UIScreen.main.scale)) - self.setNeedsLayout() - self.layoutIfNeeded() + DispatchQueue.main.sync { + self.frame = CGRect(origin: .zero, size: .init(width: size.width / UIScreen.main.scale, height: size.height / UIScreen.main.scale)) + self.setNeedsLayout() + self.layoutIfNeeded() + } let mapReadyCallbacks = MCMapViewMapReadyCallbacks() mapReadyCallbacks.delegate = self mapReadyCallbacks.callback = callback + mapReadyCallbacks.callbackQueue = callbackQueue self.mapInterface.drawReadyFrame(bounds, timeout: timeout, callbacks: mapReadyCallbacks) } @@ -319,13 +322,14 @@ public extension MCMapView { private class MCMapViewMapReadyCallbacks: MCMapReadyCallbackInterface { public weak var delegate: MCMapView? public var callback: ((UIImage?, MCLayerReadyState) -> Void)? + public var callbackQueue: DispatchQueue? func stateDidUpdate(_ state: MCLayerReadyState) { guard let delegate = self.delegate else { return } delegate.draw(in: delegate) - DispatchQueue.main.async { + callbackQueue?.async { switch state { case .NOT_READY: break diff --git a/shared/public/GeoJsonTypes.h b/shared/public/GeoJsonTypes.h index 2fa8050dc..aebf4f4f4 100644 --- a/shared/public/GeoJsonTypes.h +++ b/shared/public/GeoJsonTypes.h @@ -67,6 +67,7 @@ class GeoJSONTileInterface { class GeoJSONTileDelegate { public: virtual void didLoad(uint8_t maxZoom) = 0; + virtual void failedToLoad() = 0; }; class GeoJson { diff --git a/shared/public/Tiled2dMapSourceImpl.h b/shared/public/Tiled2dMapSourceImpl.h index 37c2972bd..281bcf97d 100644 --- a/shared/public/Tiled2dMapSourceImpl.h +++ b/shared/public/Tiled2dMapSourceImpl.h @@ -396,9 +396,17 @@ void Tiled2dMapSource::performLoadingTask(Tiled2dMapTileInfo tile, size auto weakActor = WeakActor(mailbox, std::static_pointer_cast(shared_from_this())); currentlyLoading.insert({tile, loaderIndex}); + std::string layerName = layerConfig->getLayerName(); + if (layerName == "uzh_test_building_lines") { + LogDebug << "performLoadingTask " << layerName<< ": " << tile.zoomIdentifier << "/" << tile.x << "/" <<= tile.y; + } readyTiles.erase(tile); - loadDataAsync(tile, loaderIndex).then([weakActor, loaderIndex, tile, weakSelfPtr](::djinni::Future result) { + loadDataAsync(tile, loaderIndex).then([weakActor, loaderIndex, tile, weakSelfPtr, layerName](::djinni::Future result) { + + if (layerName == "uzh_test_building_lines") { + LogDebug << "loaded " << layerName << ": " << tile.zoomIdentifier << "/" << tile.x << "/" <<= tile.y; + } auto strongSelf = weakSelfPtr.lock(); if (strongSelf) { @@ -430,6 +438,10 @@ void Tiled2dMapSource::performLoadingTask(Tiled2dMapTileInfo tile, size template void Tiled2dMapSource::didLoad(Tiled2dMapTileInfo tile, size_t loaderIndex, const R &result) { currentlyLoading.erase(tile); + std::string layerName = layerConfig->getLayerName(); + if (layerName == "uzh_test_building_lines") { + LogDebug << "didLoad " << layerConfig->getLayerName() << ": " << tile.zoomIdentifier << "/" << tile.x << "/" <<= tile.y; + } const bool isVisible = currentVisibleTiles.count(tile); if (!isVisible) { diff --git a/shared/src/map/layers/tiled/vector/geojson/GeoJsonParser.h b/shared/src/map/layers/tiled/vector/geojson/GeoJsonParser.h index 51c0b8def..fc7ff87ef 100644 --- a/shared/src/map/layers/tiled/vector/geojson/GeoJsonParser.h +++ b/shared/src/map/layers/tiled/vector/geojson/GeoJsonParser.h @@ -35,11 +35,10 @@ class GeoJsonParser { public: static std::shared_ptr getGeoJson(const nlohmann::json &geojson) { // preconditions - if (!geojson["type"].is_string() || + if (!geojson.contains("type") || (!geojson["type"].is_string() || geojson["type"] != "FeatureCollection" || - !geojson["features"].is_array()) { + !geojson["features"].is_array())) { LogError <<= "Geojson is not valid"; - assert(false); return nullptr; } diff --git a/shared/src/map/layers/tiled/vector/geojson/Tiled2dVectorGeoJsonSource.h b/shared/src/map/layers/tiled/vector/geojson/Tiled2dVectorGeoJsonSource.h index f8526cd2b..50e8952a3 100644 --- a/shared/src/map/layers/tiled/vector/geojson/Tiled2dVectorGeoJsonSource.h +++ b/shared/src/map/layers/tiled/vector/geojson/Tiled2dVectorGeoJsonSource.h @@ -70,7 +70,14 @@ class Tiled2dVectorGeoJsonSource : public Tiled2dMapVectorSource, public GeoJSON } } + void failedToLoad() override { + loadFailed = true; + } + virtual ::LayerReadyState isReadyToRenderOffscreen() override { + if (loadFailed) { + return LayerReadyState::ERROR; + } if (geoJson->isLoaded()) { return Tiled2dMapVectorSource::isReadyToRenderOffscreen(); } @@ -105,4 +112,6 @@ class Tiled2dVectorGeoJsonSource : public Tiled2dMapVectorSource, public GeoJSON private: const std::shared_ptr geoJson; const std::weak_ptr<::MapCamera2dInterface> camera; + + bool loadFailed = false; }; diff --git a/shared/src/map/layers/tiled/vector/geojson/geojsonvt/geojsonvt.hpp b/shared/src/map/layers/tiled/vector/geojson/geojsonvt/geojsonvt.hpp index 86d7feca2..64880df69 100644 --- a/shared/src/map/layers/tiled/vector/geojson/geojsonvt/geojsonvt.hpp +++ b/shared/src/map/layers/tiled/vector/geojson/geojsonvt/geojsonvt.hpp @@ -106,6 +106,9 @@ class GeoJSONVT: public GeoJSONVTInterface, public std::enable_shared_from_this< if (fromLocal) { self->load(false); } + else { + self->delegate.message(&GeoJSONTileDelegate::failedToLoad); + } } else { auto string = std::string((char*)result.data->buf(), result.data->len()); nlohmann::json json; @@ -275,7 +278,7 @@ class GeoJSONVT: public GeoJSONVTInterface, public std::enable_shared_from_this< auto& tile = it->second; if (geometries.empty()) { - tiles.erase(it); + // We need to keep empty tiles, otherwise getTile will throw an error return; } diff --git a/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSymbolLabelObject.cpp b/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSymbolLabelObject.cpp index 84ec97092..ae9ff9455 100644 --- a/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSymbolLabelObject.cpp +++ b/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSymbolLabelObject.cpp @@ -333,6 +333,7 @@ void Tiled2dMapVectorSymbolLabelObject::updatePropertiesPoint(std::vector for(const auto &i : splittedTextInfo) { if(i.glyphIndex >= 0) { + assert(i.glyphIndex < fontResult->fontData->glyphs.size()); auto &d = fontResult->fontData->glyphs[i.glyphIndex]; auto scale = fontSize * i.scale; @@ -381,6 +382,9 @@ void Tiled2dMapVectorSymbolLabelObject::updatePropertiesPoint(std::vector baseLineStartIndex = numberOfCharacters; } + else { + assert(false); + } } // Use the median base line of the last line for size calculations From 0e4645a293f157b359f235b6be47630345357e92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=C3=A4rki?= Date: Sun, 18 Feb 2024 16:36:54 +0100 Subject: [PATCH 02/23] remove debug log --- shared/public/Tiled2dMapVectorStyleParser.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/shared/public/Tiled2dMapVectorStyleParser.h b/shared/public/Tiled2dMapVectorStyleParser.h index 012285edf..44355a65a 100644 --- a/shared/public/Tiled2dMapVectorStyleParser.h +++ b/shared/public/Tiled2dMapVectorStyleParser.h @@ -377,9 +377,6 @@ class Tiled2dMapVectorStyleParser { }; ValueVariant getVariant(const nlohmann::json &json) { - if (json == "–") { - LogDebug <<= "break"; - } if (json.is_number_float()) { return json.get(); } else if (json.is_number_integer()) { From f268254f0c90cc4a3017f25b1129ad4026766f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=C3=A4rki?= Date: Sun, 18 Feb 2024 16:37:01 +0100 Subject: [PATCH 03/23] fix djinni version --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 81dae954e..dfd9b3c20 100644 --- a/Package.swift +++ b/Package.swift @@ -23,7 +23,7 @@ let package = Package( ), ], dependencies: [ - .package(url: "https://github.com/UbiqueInnovation/djinni.git", branch: "master"), + .package(url: "https://github.com/UbiqueInnovation/djinni.git", .upToNextMajor(from: "1.0.6")), ], targets: [ .target( From 9ea6b76fb18f12d349d7ce862c92eaae317e950d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=C3=A4rki?= Date: Fri, 23 Feb 2024 15:53:11 +0100 Subject: [PATCH 04/23] Set vertex data for both shaders --- ios/graphics/Model/Polygon/PolygonPatternGroup2d.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/ios/graphics/Model/Polygon/PolygonPatternGroup2d.swift b/ios/graphics/Model/Polygon/PolygonPatternGroup2d.swift index 9dc7b5a64..0aabfbece 100644 --- a/ios/graphics/Model/Polygon/PolygonPatternGroup2d.swift +++ b/ios/graphics/Model/Polygon/PolygonPatternGroup2d.swift @@ -109,6 +109,7 @@ final class PolygonPatternGroup2d: BaseGraphicsObject { } else { var scaleFactors = customScreenPixelFactor.x != 0 ? customScreenPixelFactor : SIMD2([pixelFactor, pixelFactor]) encoder.setVertexBytes(&scaleFactors, length: MemoryLayout>.stride, index: 2) + encoder.setVertexBytes(&posOffset, length: MemoryLayout>.stride, index: 3) } // texture From 78e480cf4cf2d3a4d1d7359f21200522d14959da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=C3=A4rki?= Date: Fri, 23 Feb 2024 15:54:43 +0100 Subject: [PATCH 05/23] ensure map draw callbacks are scheduled in order --- ios/maps/MCMapView.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ios/maps/MCMapView.swift b/ios/maps/MCMapView.swift index 2f3c542cb..8559b65ff 100644 --- a/ios/maps/MCMapView.swift +++ b/ios/maps/MCMapView.swift @@ -323,10 +323,13 @@ private class MCMapViewMapReadyCallbacks: MCMapReadyCallbackInterface { public weak var delegate: MCMapView? public var callback: ((UIImage?, MCLayerReadyState) -> Void)? public var callbackQueue: DispatchQueue? + public let semaphore = DispatchSemaphore(value: 1) func stateDidUpdate(_ state: MCLayerReadyState) { guard let delegate = self.delegate else { return } + semaphore.wait() + delegate.draw(in: delegate) callbackQueue?.async { @@ -340,6 +343,7 @@ private class MCMapViewMapReadyCallbacks: MCMapReadyCallbackInterface { @unknown default: break } + self.semaphore.signal() } } } From 5fbd287396379ced354c90eb4c6d5177c6f8b6a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=C3=A4rki?= Date: Fri, 23 Feb 2024 15:57:12 +0100 Subject: [PATCH 06/23] fix loading state from geojson that never resolves --- .../map/layers/tiled/vector/geojson/geojsonvt/geojsonvt.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/src/map/layers/tiled/vector/geojson/geojsonvt/geojsonvt.hpp b/shared/src/map/layers/tiled/vector/geojson/geojsonvt/geojsonvt.hpp index 64880df69..a655c402a 100644 --- a/shared/src/map/layers/tiled/vector/geojson/geojsonvt/geojsonvt.hpp +++ b/shared/src/map/layers/tiled/vector/geojson/geojsonvt/geojsonvt.hpp @@ -327,8 +327,8 @@ class GeoJSONVT: public GeoJSONVTInterface, public std::enable_shared_from_this< tile.source_features.clear(); if (z < options.minZoom) { - // if z smaller than min zoom, no need to keep tile - tiles.erase(it); + // if z smaller than min zoom, no need to keep tile, but we keep it + // otherwise some loading states are never resolved } } From 76e98bf5d8de437aa013e035f5c379005886840a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=C3=A4rki?= Date: Fri, 23 Feb 2024 15:59:53 +0100 Subject: [PATCH 07/23] =?UTF-8?q?add=20assertions=20to=20label=20computati?= =?UTF-8?q?on,=20don=E2=80=99t=20share=20lineEndIndices?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../symbol/Tiled2dMapVectorSymbolLabelObject.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSymbolLabelObject.cpp b/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSymbolLabelObject.cpp index ae9ff9455..eff46dd29 100644 --- a/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSymbolLabelObject.cpp +++ b/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSymbolLabelObject.cpp @@ -305,7 +305,7 @@ void Tiled2dMapVectorSymbolLabelObject::updatePropertiesPoint(std::vector centerPositions.push_back(zero); } - static std::vector lineEndIndices; + std::vector lineEndIndices; lineEndIndices.clear(); auto pen = zero; @@ -376,6 +376,7 @@ void Tiled2dMapVectorSymbolLabelObject::updatePropertiesPoint(std::vector } else if(i.glyphIndex == -1) { if (numberOfCharacters > 0) { lineEndIndices.push_back(numberOfCharacters - 1); + assert((countOffset + numberOfCharacters-1)*2 < scales.size()); } pen.x = 0.0; pen.y += fontSize * lineHeight; @@ -402,6 +403,7 @@ void Tiled2dMapVectorSymbolLabelObject::updatePropertiesPoint(std::vector if (numberOfCharacters > 0) { lineEndIndices.push_back(numberOfCharacters - 1); + assert((countOffset + numberOfCharacters-1)*2 < scales.size()); } const Vec2D size((boxMax.x - boxMin.x), (medianLastBaseLine - boxMin.y)); @@ -415,10 +417,18 @@ void Tiled2dMapVectorSymbolLabelObject::updatePropertiesPoint(std::vector case TextJustify::RIGHT: case TextJustify::CENTER: { size_t lineStart = 0; + size_t centerPositionsSize = centerPositions.size(); for (auto const lineEndIndex: lineEndIndices) { + if (lineStart >= centerPositionsSize || lineEndIndex >= centerPositionsSize) { + continue; + } auto factor = textJustify == TextJustify::CENTER ? 2.0 : 1.0; - double startFirst = centerPositions[lineStart].x - scales[2 * (countOffset + lineStart)] * 0.5; - double endLast = centerPositions[lineEndIndex].x + scales[2 * (countOffset + lineEndIndex)] * 0.5; + const auto idx = 2 * (countOffset + lineEndIndex); + assert(idx >= 0 && idx < scales.size()); + assert(lineStart < centerPositions.size()); + assert(lineEndIndex < centerPositions.size()); + double startFirst = centerPositions[lineStart].x - scales[idx] * 0.5; + double endLast = centerPositions[lineEndIndex].x + scales[idx] * 0.5; double lineWidth = endLast - startFirst; double delta = (size.x - lineWidth) / factor; From 23b9f69375d9fe1c82656d0a2ee6c8a2c87632b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=C3=A4rki?= Date: Fri, 23 Feb 2024 16:00:43 +0100 Subject: [PATCH 08/23] sync source reload to avoid geojson crashes --- .../tiled/vector/Tiled2dMapVectorLayer.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp index 068e3b6f9..c6138085a 100644 --- a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp +++ b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp @@ -482,15 +482,16 @@ void Tiled2dMapVectorLayer::initializeVectorLayer() { } void Tiled2dMapVectorLayer::reloadDataSource(const std::string &sourceName) { - if (const auto &geoSource = mapDescription->geoJsonSources[sourceName]) { - geoSource->reload(loaders); - auto promise = std::make_shared<::djinni::Promise>>(); - geoSource->waitIfNotLoaded(promise); - promise->getFuture().wait(); - } + auto &source = vectorTileSources[sourceName]; + const auto &geoSource = mapDescription->geoJsonSources[sourceName]; + if (source && geoSource) { + source.syncAccess([&,geoSource](const auto &source) { + + geoSource->reload(loaders); + auto promise = std::make_shared<::djinni::Promise>>(); + geoSource->waitIfNotLoaded(promise); + promise->getFuture().wait(); - if (auto &source = vectorTileSources[sourceName]) { - source.syncAccess([](const auto &source) { source->reloadTiles(); }); } From 57ed69fa2562af60d8a5043d671e25e1250db2ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=C3=A4rki?= Date: Sat, 24 Feb 2024 20:30:46 +0100 Subject: [PATCH 09/23] fix loading crashes --- shared/public/Tiled2dMapRasterSource.h | 4 ++-- shared/public/Tiled2dMapSource.h | 2 +- shared/public/Tiled2dMapVectorSource.h | 2 +- .../map/layers/tiled/raster/Tiled2dMapRasterSource.cpp | 4 ++-- .../map/layers/tiled/vector/Tiled2dMapVectorSource.cpp | 9 ++++++++- .../tiled/vector/geojson/Tiled2dVectorGeoJsonSource.h | 2 +- 6 files changed, 15 insertions(+), 8 deletions(-) diff --git a/shared/public/Tiled2dMapRasterSource.h b/shared/public/Tiled2dMapRasterSource.h index ea0676e37..f1030fa8c 100644 --- a/shared/public/Tiled2dMapRasterSource.h +++ b/shared/public/Tiled2dMapRasterSource.h @@ -40,8 +40,8 @@ class Tiled2dMapRasterSource virtual bool hasExpensivePostLoadingTask() override; - virtual std::shared_ptr<::TextureHolderInterface> postLoadingTask(const std::shared_ptr &loadedData, - const Tiled2dMapTileInfo &tile) override; + virtual std::shared_ptr<::TextureHolderInterface> postLoadingTask(std::shared_ptr loadedData, + Tiled2dMapTileInfo tile) override; private: diff --git a/shared/public/Tiled2dMapSource.h b/shared/public/Tiled2dMapSource.h index b5ef4f085..6b37b8614 100644 --- a/shared/public/Tiled2dMapSource.h +++ b/shared/public/Tiled2dMapSource.h @@ -125,7 +125,7 @@ class Tiled2dMapSource : protected: virtual bool hasExpensivePostLoadingTask() = 0; - virtual R postLoadingTask(const L &loadedData, const Tiled2dMapTileInfo &tile) = 0; + virtual R postLoadingTask(L loadedData, Tiled2dMapTileInfo tile) = 0; MapConfig mapConfig; std::shared_ptr layerConfig; diff --git a/shared/public/Tiled2dMapVectorSource.h b/shared/public/Tiled2dMapVectorSource.h index 3dccd3eea..0493f08dc 100644 --- a/shared/public/Tiled2dMapVectorSource.h +++ b/shared/public/Tiled2dMapVectorSource.h @@ -52,7 +52,7 @@ class Tiled2dMapVectorSource : public Tiled2dMapSource &loadedData, const Tiled2dMapTileInfo &tile) override; + virtual Tiled2dMapVectorTileInfo::FeatureMap postLoadingTask(std::shared_ptr loadedData, Tiled2dMapTileInfo tile) override; const std::vector> loaders; const std::unordered_set layersToDecode; diff --git a/shared/src/map/layers/tiled/raster/Tiled2dMapRasterSource.cpp b/shared/src/map/layers/tiled/raster/Tiled2dMapRasterSource.cpp index 066e83861..a96fae1d6 100644 --- a/shared/src/map/layers/tiled/raster/Tiled2dMapRasterSource.cpp +++ b/shared/src/map/layers/tiled/raster/Tiled2dMapRasterSource.cpp @@ -45,8 +45,8 @@ bool Tiled2dMapRasterSource::hasExpensivePostLoadingTask() { return false; } -std::shared_ptr<::TextureHolderInterface> Tiled2dMapRasterSource::postLoadingTask(const std::shared_ptr &loadedData, - const Tiled2dMapTileInfo &tile) { +std::shared_ptr<::TextureHolderInterface> Tiled2dMapRasterSource::postLoadingTask(std::shared_ptr loadedData, + Tiled2dMapTileInfo tile) { return loadedData->data; } diff --git a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorSource.cpp b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorSource.cpp index 9ab3972c0..50a9c200d 100644 --- a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorSource.cpp +++ b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorSource.cpp @@ -45,8 +45,15 @@ bool Tiled2dMapVectorSource::hasExpensivePostLoadingTask() { return true; } -Tiled2dMapVectorTileInfo::FeatureMap Tiled2dMapVectorSource::postLoadingTask(const std::shared_ptr &loadedData, const Tiled2dMapTileInfo &tile) { +Tiled2dMapVectorTileInfo::FeatureMap Tiled2dMapVectorSource::postLoadingTask(std::shared_ptr loadedData, Tiled2dMapTileInfo tile) { auto layerFeatureMap = std::make_shared>>>(); + + if (!loadedData->data.has_value()) { + LogError <<= "postLoadingTask, but data has no value for " + layerConfig->getLayerName() + ": " + std::to_string(tile.zoomIdentifier) + "/" + + std::to_string(tile.x) + "/" + std::to_string(tile.y); + return layerFeatureMap; + } + try { vtzero::vector_tile tileData((char*)loadedData->data->buf(), loadedData->data->len()); diff --git a/shared/src/map/layers/tiled/vector/geojson/Tiled2dVectorGeoJsonSource.h b/shared/src/map/layers/tiled/vector/geojson/Tiled2dVectorGeoJsonSource.h index 50e8952a3..431ac0489 100644 --- a/shared/src/map/layers/tiled/vector/geojson/Tiled2dVectorGeoJsonSource.h +++ b/shared/src/map/layers/tiled/vector/geojson/Tiled2dVectorGeoJsonSource.h @@ -96,7 +96,7 @@ class Tiled2dVectorGeoJsonSource : public Tiled2dMapVectorSource, public GeoJSON virtual bool hasExpensivePostLoadingTask() override { return false; }; - virtual Tiled2dMapVectorTileInfo::FeatureMap postLoadingTask(const std::shared_ptr &loadedData, const Tiled2dMapTileInfo &tile) override { + virtual Tiled2dMapVectorTileInfo::FeatureMap postLoadingTask(std::shared_ptr loadedData, Tiled2dMapTileInfo tile) override { const auto &geoJsonTile = geoJson->getTile(tile.zoomIdentifier, tile.x, tile.y); Tiled2dMapVectorTileInfo::FeatureMap featureMap = std::make_shared>>>(); std::shared_ptr> features = std::make_shared>(); From b202f2059f715c8ccb8132024993a948a007e4b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=C3=A4rki?= Date: Mon, 26 Feb 2024 12:08:02 +0100 Subject: [PATCH 10/23] semi-fix missing layer configs --- .../src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp index c6138085a..21f9fe6cc 100644 --- a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp +++ b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp @@ -340,6 +340,12 @@ void Tiled2dMapVectorLayer::initializeVectorLayer() { auto layerConfig = layerConfigs[source]; + + if (!layerConfig) { + LogError << "Missing layer config for " << source <<= ", layer will be ignored."; + continue; + } + auto sourceMailbox = std::make_shared(mapInterface->getScheduler()); Actor vectorSource; From fc8bdb9ca377b245fb761b5ff148bf7e81f07cd7 Mon Sep 17 00:00:00 2001 From: Mike Wong Date: Thu, 29 Feb 2024 16:56:38 +0100 Subject: [PATCH 11/23] Add missing destroy call in OffscreenMapRenderer (analogue to MapView) --- .../io/openmobilemaps/mapscore/map/util/OffscreenMapRenderer.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/main/java/io/openmobilemaps/mapscore/map/util/OffscreenMapRenderer.kt b/android/src/main/java/io/openmobilemaps/mapscore/map/util/OffscreenMapRenderer.kt index bd581f4ab..3e66caa2b 100644 --- a/android/src/main/java/io/openmobilemaps/mapscore/map/util/OffscreenMapRenderer.kt +++ b/android/src/main/java/io/openmobilemaps/mapscore/map/util/OffscreenMapRenderer.kt @@ -2,7 +2,6 @@ package io.openmobilemaps.mapscore.map.util import android.opengl.GLSurfaceView import io.openmobilemaps.mapscore.graphics.GLThread -import io.openmobilemaps.mapscore.map.scheduling.AndroidScheduler import io.openmobilemaps.mapscore.map.scheduling.AndroidSchedulerCallback import io.openmobilemaps.mapscore.shared.graphics.common.Color import io.openmobilemaps.mapscore.shared.graphics.common.Vec2I @@ -56,6 +55,7 @@ open class OffscreenMapRenderer(val sizePx: Vec2I, val density: Float = 72f) : G protected open fun onGlThreadFinishing() { glThread.renderer = null + mapInterface?.destroy() mapInterface = null } From 5d3496cb7adc9aa9e24973f5ad1c425758a68203 Mon Sep 17 00:00:00 2001 From: Christoph Maurhofer Date: Tue, 5 Mar 2024 15:17:49 +0100 Subject: [PATCH 12/23] Allow for underzoom to render whole bounds area when camera is restricted --- shared/src/map/camera/MapCamera2d.cpp | 96 +++++++++++++++++++-------- 1 file changed, 67 insertions(+), 29 deletions(-) diff --git a/shared/src/map/camera/MapCamera2d.cpp b/shared/src/map/camera/MapCamera2d.cpp index 6b1d29061..d208f9118 100644 --- a/shared/src/map/camera/MapCamera2d.cpp +++ b/shared/src/map/camera/MapCamera2d.cpp @@ -216,7 +216,10 @@ void MapCamera2d::setZoom(double zoom, bool animated) { zoomAnimation->start(); mapInterface->invalidate(); } else { - this->zoom = targetZoom; + const auto [adjPosition, adjZoom] = + getBoundsCorrectedCoords(adjustCoordForPadding(centerPosition, targetZoom), targetZoom); + centerPosition = adjPosition; + zoom = adjZoom; notifyListeners(ListenerType::BOUNDS); mapInterface->invalidate(); } @@ -251,8 +254,10 @@ void MapCamera2d::setRotation(float angle, bool animated) { Coord realCenter = getCenterPosition(); Vec2D rotatedDiff = Vec2DHelper::rotate(Vec2D(centerScreen.x - realCenter.x, centerScreen.y - realCenter.y), Vec2D(0.0, 0.0), angleDiff); - centerPosition.x = realCenter.x + rotatedDiff.x; - centerPosition.y = realCenter.y + rotatedDiff.y; + const auto [adjPosition, adjZoom] = + getBoundsCorrectedCoords(adjustCoordForPadding(Coord(mapCoordinateSystem.identifier, realCenter.x + rotatedDiff.x, realCenter.y + rotatedDiff.y, centerPosition.z), zoom), zoom); + centerPosition = adjPosition; + zoom = adjZoom; this->angle = newAngle; notifyListeners(ListenerType::ROTATION | ListenerType::BOUNDS); @@ -666,9 +671,9 @@ bool MapCamera2d::onTwoFingerMove(const std::vector<::Vec2F> &posScreenOld, cons double scaleFactor = Vec2FHelper::distance(posScreenNew[0], posScreenNew[1]) / Vec2FHelper::distance(posScreenOld[0], posScreenOld[1]); - zoom /= scaleFactor; + double newZoom = zoom / scaleFactor; - zoom = std::clamp(zoom, zoomMax, zoomMin); + newZoom = std::clamp(newZoom, zoomMax, zoomMin); if (zoom > startZoom * ROTATION_LOCKING_FACTOR || zoom < startZoom / ROTATION_LOCKING_FACTOR) { rotationPossible = false; @@ -691,8 +696,10 @@ bool MapCamera2d::onTwoFingerMove(const std::vector<::Vec2F> &posScreenOld, cons double diffCenterX = -leftDiff * zoom * screenPixelAsRealMeterFactor; double diffCenterY = topDiff * zoom * screenPixelAsRealMeterFactor; - centerPosition.x += diffCenterX; - centerPosition.y += diffCenterY; + Coord newPos = Coord(centerPosition.systemIdentifier, + centerPosition.x + diffCenterX, + centerPosition.y + diffCenterY, + centerPosition.z); if (config.rotationEnabled) { float olda = atan2(posScreenOld[0].x - posScreenOld[1].x, posScreenOld[0].y - posScreenOld[1].y); @@ -707,8 +714,8 @@ bool MapCamera2d::onTwoFingerMove(const std::vector<::Vec2F> &posScreenOld, cons (centerScreen.x - midpoint.x) * sin(newa - olda) + midpoint.y - centerScreen.y; double rotDiffX = (cosAngle * centerXDiff - sinAngle * centerYDiff); double rotDiffY = (cosAngle * centerYDiff + sinAngle * centerXDiff); - centerPosition.x += rotDiffX * zoom * screenPixelAsRealMeterFactor; - centerPosition.y += rotDiffY * zoom * screenPixelAsRealMeterFactor; + newPos.x += rotDiffX * zoom * screenPixelAsRealMeterFactor; + newPos.y += rotDiffY * zoom * screenPixelAsRealMeterFactor; listenerType |= ListenerType::ROTATION; } else { @@ -720,9 +727,9 @@ bool MapCamera2d::onTwoFingerMove(const std::vector<::Vec2F> &posScreenOld, cons } } - auto mapConfig = mapInterface->getMapConfig(); - - clampCenterToPaddingCorrectedBounds(); + const auto [adjPosition, adjZoom] = getBoundsCorrectedCoords(newPos, newZoom); + centerPosition = adjPosition; + zoom = adjZoom; notifyListeners(listenerType); mapInterface->invalidate(); @@ -872,28 +879,59 @@ std::tuple MapCamera2d::getBoundsCorrectedCoords(const Coord &pos double sinAngle = sin(angle * M_PI / 180.0); double cosAngle = cos(angle * M_PI / 180.0); - double deltaX = std::abs(halfWidth * cosAngle) + std::abs(halfHeight * sinAngle); - double deltaY = std::abs(halfWidth * sinAngle) + std::abs(halfHeight * cosAngle); - - double diffLeft = deltaX - (position.x - paddingCorrectedBounds.topLeft.x); - double diffRight = deltaX - (paddingCorrectedBounds.bottomRight.x - position.x); - double targetScaleDiffFactorX = std::min((paddingCorrectedBounds.bottomRight.x - paddingCorrectedBounds.topLeft.x) / (2.0 * deltaX), 1.0); - - double diffTop = deltaY - (paddingCorrectedBounds.topLeft.y - position.y); - double diffBottom = deltaY - (position.y - paddingCorrectedBounds.bottomRight.y); - double targetScaleDiffFactorY = std::min((paddingCorrectedBounds.topLeft.y - paddingCorrectedBounds.bottomRight.y) / (2.0 * deltaY), 1.0); + double negSinAngle = sin(-angle * M_PI / 180.0); + double negCosAngle = cos(-angle * M_PI / 180.0); + + double boundsHalfWidth = std::abs(paddingCorrectedBounds.bottomRight.x - paddingCorrectedBounds.topLeft.x) * 0.5; + double boundsHalfHeight = std::abs(paddingCorrectedBounds.topLeft.y - paddingCorrectedBounds.bottomRight.y) * 0.5; + double boundsDeltaXVp = std::abs(boundsHalfWidth * negCosAngle) + std::abs(boundsHalfHeight * negSinAngle); + double boundsDeltaYVp = std::abs(boundsHalfWidth * negSinAngle) + std::abs(boundsHalfHeight * negCosAngle); + + double targetScaleDiffFactorX = boundsDeltaXVp / halfWidth; + double targetScaleDiffFactorY = boundsDeltaYVp / halfHeight; + double targetScaleDiffFactor = std::min(std::max(targetScaleDiffFactorX, targetScaleDiffFactorY), 1.0); + + double centerBBoxX = (paddingCorrectedBounds.topLeft.x + (paddingCorrectedBounds.bottomRight.x - paddingCorrectedBounds.topLeft.x) * 0.5); + double centerBBoxY = (paddingCorrectedBounds.topLeft.y + (paddingCorrectedBounds.bottomRight.y - paddingCorrectedBounds.topLeft.y) * 0.5); + double centerDiffsX = centerBBoxX - position.x; + double centerDiffsY = centerBBoxY - position.y; + double dotHor = centerDiffsX * cosAngle + centerDiffsY * sinAngle; + double centerDiffHorX = dotHor * cosAngle; + double centerDiffHorY = dotHor * sinAngle; + double dotVert = centerDiffsX * -sinAngle + centerDiffsY * cosAngle; + double centerDiffVertX = -(dotVert * sinAngle); + double centerDiffVertY = dotVert * cosAngle; + + double positionVpX = negCosAngle * position.x - negSinAngle * position.y; + double positionVpY = negSinAngle * position.x + negCosAngle * position.y; + double centerBBoxVpX = negCosAngle * centerBBoxX - negSinAngle * centerBBoxY; + double centerBBoxVpY = negSinAngle * centerBBoxX + negCosAngle * centerBBoxY; + double diffLeftVp = (centerBBoxVpX - boundsDeltaXVp) - (positionVpX - halfWidth); + double diffRightVp = (positionVpX + halfWidth) - (centerBBoxVpX + boundsDeltaXVp); + double diffTopVp = (positionVpY + halfHeight) - (centerBBoxVpY + boundsDeltaYVp); + double diffBottomVp = (centerBBoxVpY - boundsDeltaYVp) - (positionVpY - halfHeight); + double shiftRightVp = std::max(0.0, diffLeftVp) - std::max(0.0, diffRightVp); + double shiftTopVp = std::max(0.0, diffBottomVp) - std::max(0.0, diffTopVp); + + double shiftRightX = cosAngle * shiftRightVp; + double shiftRightY = sinAngle * shiftRightVp; + double shiftTopX = -(sinAngle * shiftTopVp); + double shiftTopY = cosAngle * shiftTopVp; - double targetScaleDiffFactor = std::min(targetScaleDiffFactorX, targetScaleDiffFactorY); Coord newPosition = position; - if (targetScaleDiffFactorX < 1.0) { - newPosition.x = paddingCorrectedBounds.topLeft.x + (paddingCorrectedBounds.bottomRight.x - paddingCorrectedBounds.topLeft.x) / 2.0; + if (targetScaleDiffFactorX <= 1.0) { + newPosition.x += centerDiffHorX; + newPosition.y += centerDiffHorY; } else { - newPosition.x += (std::max(0.0, diffLeft) - std::max(0.0, diffRight)) * targetScaleDiffFactor; + newPosition.x += shiftRightX * targetScaleDiffFactor; + newPosition.y += shiftRightY * targetScaleDiffFactor; } - if (targetScaleDiffFactorY < 1.0) { - newPosition.y = paddingCorrectedBounds.bottomRight.y + (paddingCorrectedBounds.topLeft.y - paddingCorrectedBounds.bottomRight.y) / 2.0; + if (targetScaleDiffFactorY <= 1.0) { + newPosition.x += centerDiffVertX; + newPosition.y += centerDiffVertY; } else { - newPosition.y += (std::max(0.0, diffBottom) - std::max(0.0, diffTop)) * targetScaleDiffFactor; + newPosition.x += shiftTopX * targetScaleDiffFactor; + newPosition.y += shiftTopY * targetScaleDiffFactor; } double newZoom = zoom * targetScaleDiffFactor; From dc7db2a3c6fb4336ac0fd77c72887c8a970c26bb Mon Sep 17 00:00:00 2001 From: Stefan Mitterrutzner Date: Tue, 5 Mar 2024 16:27:14 +0100 Subject: [PATCH 13/23] fixes pattern scaling --- ios/graphics/Shader/Metal/PolygonGroupShader.metal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/graphics/Shader/Metal/PolygonGroupShader.metal b/ios/graphics/Shader/Metal/PolygonGroupShader.metal index cabf600f7..c1e039baa 100644 --- a/ios/graphics/Shader/Metal/PolygonGroupShader.metal +++ b/ios/graphics/Shader/Metal/PolygonGroupShader.metal @@ -150,7 +150,7 @@ polygonPatternGroupFadeInFragmentShader(PolygonPatternGroupVertexOut in [[stage_ const float scalingFactorFactor = (scalingFactor.x / screenPixelAsRealMeterFactor) - 1.0; const float2 spacing = pixelSize * scalingFactorFactor; const float2 totalSize = pixelSize + spacing; - const float2 adjustedPixelPosition = in.pixelPosition + totalSize * 0.5; // in other project pixelSize + const float2 adjustedPixelPosition = in.pixelPosition + pixelSize * 0.5; // in other project pixelSize float2 uvTot = fmod(adjustedPixelPosition, totalSize); const int yIndex = int(adjustedPixelPosition.y / totalSize.y) % 2; From 60c358369bba1922242090455f658cc226388f68 Mon Sep 17 00:00:00 2001 From: Stefan Mitterrutzner Date: Wed, 28 Feb 2024 14:07:15 +0100 Subject: [PATCH 14/23] fixes bug in vector render pass grouping --- shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp index 21f9fe6cc..e7c0d60ab 100644 --- a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp +++ b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp @@ -639,10 +639,11 @@ void Tiled2dMapVectorLayer::pregenerateRenderPasses() { if (description->renderObjects.empty()) { continue; } - if (description->maskingObject != lastMask && !renderObjects.empty()) { - newPasses.emplace_back(std::make_shared(RenderPassConfig(description->renderPassIndex, false), renderObjects, lastMask)); + if ((description->renderPassIndex != lastRenderPassIndex || description->maskingObject != lastMask) && !renderObjects.empty()) { + newPasses.emplace_back(std::make_shared(RenderPassConfig(lastRenderPassIndex, false), renderObjects, lastMask)); renderObjects.clear(); lastMask = nullptr; + lastRenderPassIndex = 0; } if (description->isModifyingMask || description->selfMasked) { From 509934fd6a9a0b321cd4f7911156fa08353efcf5 Mon Sep 17 00:00:00 2001 From: Stefan Mitterrutzner Date: Wed, 6 Mar 2024 14:42:19 +0100 Subject: [PATCH 15/23] only restrict bounds if viewport is set --- shared/src/map/camera/MapCamera2d.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/shared/src/map/camera/MapCamera2d.cpp b/shared/src/map/camera/MapCamera2d.cpp index d208f9118..a2ce198e8 100644 --- a/shared/src/map/camera/MapCamera2d.cpp +++ b/shared/src/map/camera/MapCamera2d.cpp @@ -858,19 +858,27 @@ bool MapCamera2d::isInBounds(const Coord &coords) { std::tuple MapCamera2d::getBoundsCorrectedCoords(const Coord &position, double zoom) { auto const &paddingCorrectedBounds = getPaddingCorrectedBounds(); + auto const clampedPosition = [&paddingCorrectedBounds](const Coord& position) -> Coord { + return Coord(position.systemIdentifier, + std::clamp(position.x, + std::min(paddingCorrectedBounds.topLeft.x, paddingCorrectedBounds.bottomRight.x), + std::max(paddingCorrectedBounds.topLeft.x, paddingCorrectedBounds.bottomRight.x)), + std::clamp(position.y, + std::min(paddingCorrectedBounds.topLeft.y, paddingCorrectedBounds.bottomRight.y), + std::max(paddingCorrectedBounds.topLeft.y, paddingCorrectedBounds.bottomRight.y)), + position.z); + }; + if (!config.boundsRestrictWholeVisibleRect) { - Coord newPosition = Coord(position.systemIdentifier, - std::clamp(position.x, - std::min(paddingCorrectedBounds.topLeft.x, paddingCorrectedBounds.bottomRight.x), - std::max(paddingCorrectedBounds.topLeft.x, paddingCorrectedBounds.bottomRight.x)), - std::clamp(position.y, - std::min(paddingCorrectedBounds.topLeft.y, paddingCorrectedBounds.bottomRight.y), - std::max(paddingCorrectedBounds.topLeft.y, paddingCorrectedBounds.bottomRight.y)), - position.z); - return {newPosition, zoom}; + return {clampedPosition(position), zoom}; } else { Vec2I sizeViewport = mapInterface->getRenderingContext()->getViewportSize(); + // fallback if the viewport size is not set yet + if (sizeViewport.x == 0 && sizeViewport.y == 0) { + return {clampedPosition(position), zoom}; + } + double zoomFactor = screenPixelAsRealMeterFactor * zoom; double halfWidth = sizeViewport.x * 0.5 * zoomFactor; From b7e2c8165022cef911df2c10386442af11c36238 Mon Sep 17 00:00:00 2001 From: Stefan Mitterrutzner Date: Thu, 7 Mar 2024 07:59:30 +0100 Subject: [PATCH 16/23] remove debug logs --- shared/public/Tiled2dMapSourceImpl.h | 12 ------------ shared/public/VectorTilePolygonHandler.h | 5 ----- 2 files changed, 17 deletions(-) diff --git a/shared/public/Tiled2dMapSourceImpl.h b/shared/public/Tiled2dMapSourceImpl.h index 281bcf97d..9e7d3ae62 100644 --- a/shared/public/Tiled2dMapSourceImpl.h +++ b/shared/public/Tiled2dMapSourceImpl.h @@ -397,17 +397,9 @@ void Tiled2dMapSource::performLoadingTask(Tiled2dMapTileInfo tile, size currentlyLoading.insert({tile, loaderIndex}); std::string layerName = layerConfig->getLayerName(); - if (layerName == "uzh_test_building_lines") { - LogDebug << "performLoadingTask " << layerName<< ": " << tile.zoomIdentifier << "/" << tile.x << "/" <<= tile.y; - } readyTiles.erase(tile); loadDataAsync(tile, loaderIndex).then([weakActor, loaderIndex, tile, weakSelfPtr, layerName](::djinni::Future result) { - - if (layerName == "uzh_test_building_lines") { - LogDebug << "loaded " << layerName << ": " << tile.zoomIdentifier << "/" << tile.x << "/" <<= tile.y; - } - auto strongSelf = weakSelfPtr.lock(); if (strongSelf) { auto res = result.get(); @@ -439,10 +431,6 @@ template void Tiled2dMapSource::didLoad(Tiled2dMapTileInfo tile, size_t loaderIndex, const R &result) { currentlyLoading.erase(tile); std::string layerName = layerConfig->getLayerName(); - if (layerName == "uzh_test_building_lines") { - LogDebug << "didLoad " << layerConfig->getLayerName() << ": " << tile.zoomIdentifier << "/" << tile.x << "/" <<= tile.y; - } - const bool isVisible = currentVisibleTiles.count(tile); if (!isVisible) { errorTiles[loaderIndex].erase(tile); diff --git a/shared/public/VectorTilePolygonHandler.h b/shared/public/VectorTilePolygonHandler.h index 284938c0e..501c32ab1 100644 --- a/shared/public/VectorTilePolygonHandler.h +++ b/shared/public/VectorTilePolygonHandler.h @@ -23,9 +23,6 @@ class VectorTilePolygonHandler { void ring_begin(uint32_t count) { currentRing = std::vector<::Coord>(); currentRing.reserve(count); - /*LogDebug <<= " new Polygon with TopLeft: (" + tileCoords.topLeft.systemIdentifier + ": " + std::to_string(tileCoords.topLeft.x) + ", " + std::to_string(tileCoords.topLeft.y) + ")"; - LogDebug <<= " BottomRight: (" + tileCoords.bottomRight.systemIdentifier + ": " + std::to_string(tileCoords.bottomRight.x) + ", " + std::to_string(tileCoords.bottomRight.y) + ")"; - LogDebug <<= " and width/height: (" + std::to_string(tileWidth) + ", " + std::to_string(tileHeight) + ")";*/ } void ring_point(vtzero::point point) noexcept { @@ -33,8 +30,6 @@ class VectorTilePolygonHandler { double y = tileCoords.topLeft.y + tileHeight * (point.y / extent); Coord newCoord = Coord(tileCoords.topLeft.systemIdentifier, x, y, 0.0); currentRing.push_back(newCoord); - /*LogDebug <<= " -> new point: (" + std::to_string(point.x) + ", " + std::to_string(point.y) + ") in extent " + std::to_string(extent); - LogDebug <<= " -> coord (" + newCoord.systemIdentifier + ": " + std::to_string(newCoord.x) + ", " + std::to_string(newCoord.y) + ")";*/ } void ring_end(vtzero::ring_type ringType) noexcept { From ebbaaa324172f86667bf690ac75bd14d7a807907 Mon Sep 17 00:00:00 2001 From: Mike Wong Date: Wed, 6 Mar 2024 13:00:19 +0100 Subject: [PATCH 17/23] Fix bounding box parsing for WMTS layers --- .../layers/tiled/wmts/WmtsCapabilitiesResource.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/shared/src/map/layers/tiled/wmts/WmtsCapabilitiesResource.cpp b/shared/src/map/layers/tiled/wmts/WmtsCapabilitiesResource.cpp index 103bc0ba9..9c6328911 100644 --- a/shared/src/map/layers/tiled/wmts/WmtsCapabilitiesResource.cpp +++ b/shared/src/map/layers/tiled/wmts/WmtsCapabilitiesResource.cpp @@ -169,21 +169,23 @@ int32_t numZ) override { double c2 = 0; std::string lowerCorner = boundingBox.child_value("ows:LowerCorner"); if (lowerCorner.size() > 0) { - c1 = std::stod(lowerCorner.substr(0, lowerCorner.find(" "))); - c2 = std::stod(lowerCorner.substr(lowerCorner.find(" "))); + auto delimiterIndex = lowerCorner.find(" "); + c1 = std::stod(lowerCorner.substr(0, delimiterIndex)); + c2 = std::stod(lowerCorner.substr(delimiterIndex)); } double c3 = 0; double c4 = 0; std::string upperCorner = boundingBox.child_value("ows:UpperCorner"); if (upperCorner.size() > 0) { - c3 = std::stod(upperCorner.substr(0, lowerCorner.find(" "))); - c4 = std::stod(upperCorner.substr(lowerCorner.find(" "))); + auto delimiterIndex = upperCorner.find(" "); + c3 = std::stod(upperCorner.substr(0, delimiterIndex)); + c4 = std::stod(upperCorner.substr(delimiterIndex)); } std::optional bounds; if (c1 != 0 && c2 != 0 && c3 != 0 && c4 != 0) { - bounds = RectCoord(Coord(CoordinateSystemIdentifiers::EPSG4326(), c1, c2, 0), - Coord(CoordinateSystemIdentifiers::EPSG4326(), c3, c4, 0)); + bounds = RectCoord(Coord(CoordinateSystemIdentifiers::EPSG4326(), c1, c4, 0), + Coord(CoordinateSystemIdentifiers::EPSG4326(), c3, c2, 0)); } std::string tileMatrixSetLink = layer.child("TileMatrixSetLink").child_value("TileMatrixSet"); std::string resourceTemplate = layer.child("ResourceURL").attribute("template").as_string(); From 72b984d5d6abb3f076ab32b01466e3e4a0677aa5 Mon Sep 17 00:00:00 2001 From: Mike Wong Date: Wed, 6 Mar 2024 19:12:10 +0100 Subject: [PATCH 18/23] Update changelog --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62bfc2009..9fa6519ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Changelog for Open Mobile Maps -## Version 2.0.0 (16.02.2023) +## Version 2.0.1 (tbd) +- Fixed WGS84 bounding box parsing for WMTS layers + +## Version 2.0.0 (16.02.2024) - Major improvements in vector map performance, stability, and rendering, alongside expanded options for style specifications and GeoJSON support. - Enhanced stability and performance for raster, icon, polygon, and line layers. - Many additional improvements and bug fixes. From 912ef77dc82ee79e03438ba2bee8628b9d1a520e Mon Sep 17 00:00:00 2001 From: Christoph Maurhofer Date: Thu, 7 Mar 2024 08:22:02 +0100 Subject: [PATCH 19/23] Increase version numbers --- android/gradle.properties | 4 ++-- shared/src/MapsCoreSharedModule.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/android/gradle.properties b/android/gradle.properties index d2f43f957..0714414ea 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -31,8 +31,8 @@ SNAPSHOT_REPOSITORY_URL=https://oss.sonatype.org/content/repositories/snapshots/ GROUP=io.openmobilemaps POM_ARTIFACT_ID=mapscore -VERSION_NAME=2.0.0 -VERSION_CODE=2000000 +VERSION_NAME=2.0.1 +VERSION_CODE=2001000 POM_NAME=mapscore POM_PACKAGING=aar diff --git a/shared/src/MapsCoreSharedModule.cpp b/shared/src/MapsCoreSharedModule.cpp index de532cd72..c900b4b1f 100644 --- a/shared/src/MapsCoreSharedModule.cpp +++ b/shared/src/MapsCoreSharedModule.cpp @@ -10,4 +10,4 @@ #include "MapsCoreSharedModule.h" -std::string MapsCoreSharedModule::version() { return "2.0.0"; } +std::string MapsCoreSharedModule::version() { return "2.0.1"; } From 1f73ea1433df370eb2753c504caac9c32bdb2f71 Mon Sep 17 00:00:00 2001 From: Christoph Maurhofer Date: Thu, 7 Mar 2024 08:29:35 +0100 Subject: [PATCH 20/23] Update changelog --- CHANGELOG.md | 11 ++++++++++- android/gradle.properties | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fa6519ba..a18fadae7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,16 @@ # Changelog for Open Mobile Maps -## Version 2.0.1 (tbd) +## Version 2.0.1 (07.03.2024) - Fixed WGS84 bounding box parsing for WMTS layers +- Fix deadlock in renderToImage on iOS +- Fix crash for geojsons without type +- Fix renderToImage for vector layers +- Reference djinni by version on iOS +- Fix crash on certain polygon patters on iOS +- Fix constant loading for some geojsons +- Fix crash of symbol objects +- Fix crash from race condition in geojson reload +- Fix deallocation on OffscreenMapRenderer on Android ## Version 2.0.0 (16.02.2024) - Major improvements in vector map performance, stability, and rendering, alongside expanded options for style specifications and GeoJSON support. diff --git a/android/gradle.properties b/android/gradle.properties index 0714414ea..a1d13adfa 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -32,7 +32,7 @@ SNAPSHOT_REPOSITORY_URL=https://oss.sonatype.org/content/repositories/snapshots/ GROUP=io.openmobilemaps POM_ARTIFACT_ID=mapscore VERSION_NAME=2.0.1 -VERSION_CODE=2001000 +VERSION_CODE=2000100 POM_NAME=mapscore POM_PACKAGING=aar From 0e719b599830ecb233a30e639f60bc1c07574256 Mon Sep 17 00:00:00 2001 From: Stefan Mitterrutzner Date: Thu, 7 Mar 2024 08:35:16 +0100 Subject: [PATCH 21/23] extends debug labels --- .../tiled/vector/symbol/Tiled2dMapVectorSymbolGroup.cpp | 6 +++--- .../tiled/vector/tiles/line/Tiled2dMapVectorLineTile.cpp | 2 +- .../tiles/polygon/Tiled2dMapVectorPolygonPatternTile.cpp | 2 +- .../vector/tiles/polygon/Tiled2dMapVectorPolygonTile.cpp | 2 +- .../vector/tiles/raster/Tiled2dMapVectorRasterTile.cpp | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSymbolGroup.cpp b/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSymbolGroup.cpp index bf6633e20..5b403c836 100644 --- a/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSymbolGroup.cpp +++ b/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSymbolGroup.cpp @@ -357,7 +357,7 @@ void Tiled2dMapVectorSymbolGroup::initialize(std::weak_ptrstyle.getBlendMode(EvaluationContext(0.0, dpFactor, std::make_shared(), featureStateManager))); iconInstancedObject = strongMapInterface->getGraphicsObjectFactory()->createQuadInstanced(alphaInstancedShader); #if DEBUG - iconInstancedObject->asGraphicsObject()->setDebugLabel(layerDescription->identifier); + iconInstancedObject->asGraphicsObject()->setDebugLabel(layerDescription->identifier + "_" + tileInfo.tileInfo.to_string_short()); #endif iconInstancedObject->setInstanceCount(instanceCounts.icons); @@ -376,7 +376,7 @@ void Tiled2dMapVectorSymbolGroup::initialize(std::weak_ptrstyle.getBlendMode(EvaluationContext(0.0, dpFactor, std::make_shared(), featureStateManager))); stretchedInstancedObject = strongMapInterface->getGraphicsObjectFactory()->createQuadStretchedInstanced(shader); #if DEBUG - stretchedInstancedObject->asGraphicsObject()->setDebugLabel(layerDescription->identifier); + stretchedInstancedObject->asGraphicsObject()->setDebugLabel(layerDescription->identifier + "_" + tileInfo.tileInfo.to_string_short()); #endif stretchedInstancedObject->setInstanceCount(instanceCounts.stretchedIcons); @@ -395,7 +395,7 @@ void Tiled2dMapVectorSymbolGroup::initialize(std::weak_ptrstyle.getBlendMode(EvaluationContext(0.0, dpFactor, std::make_shared(), featureStateManager))); textInstancedObject = strongMapInterface->getGraphicsObjectFactory()->createTextInstanced(shader); #if DEBUG - textInstancedObject->asGraphicsObject()->setDebugLabel(layerDescription->identifier); + textInstancedObject->asGraphicsObject()->setDebugLabel(layerDescription->identifier + "_" + tileInfo.tileInfo.to_string_short()); #endif textInstancedObject->setInstanceCount(instanceCounts.textCharacters); diff --git a/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.cpp b/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.cpp index dbfbceada..0610d5d68 100644 --- a/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.cpp +++ b/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.cpp @@ -348,7 +348,7 @@ void Tiled2dMapVectorLineTile::addLines(const std::vectorcreateLineGroup(shader->asShaderProgramInterface()); #if DEBUG - lineGroupGraphicsObject->asGraphicsObject()->setDebugLabel(description->identifier); + lineGroupGraphicsObject->asGraphicsObject()->setDebugLabel(description->identifier + "_" + tileInfo.tileInfo.to_string_short()); #endif auto lineGroupObject = std::make_shared(coordinateConverterHelper, lineGroupGraphicsObject, diff --git a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.cpp b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.cpp index 923f083b3..2637736ae 100644 --- a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.cpp +++ b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.cpp @@ -295,7 +295,7 @@ void Tiled2dMapVectorPolygonPatternTile::addPolygons(const std::vectorcreatePolygonPatternGroup(shader->asShaderProgramInterface()); #if DEBUG - polygonObject->asGraphicsObject()->setDebugLabel(description->identifier); + polygonObject->asGraphicsObject()->setDebugLabel(description->identifier + "_" + tileInfo.tileInfo.to_string_short()); #endif auto layerObject = std::make_shared(converter, polygonObject, shader); diff --git a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.cpp b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.cpp index 9da3501f9..57ce00574 100644 --- a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.cpp +++ b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.cpp @@ -275,7 +275,7 @@ void Tiled2dMapVectorPolygonTile::addPolygons(const std::vectorcreatePolygonGroup(shader->asShaderProgramInterface()); #if DEBUG - polygonObject->asGraphicsObject()->setDebugLabel(description->identifier); + polygonObject->asGraphicsObject()->setDebugLabel(description->identifier + "_" + tileInfo.tileInfo.to_string_short()); #endif auto layerObject = std::make_shared(converter, polygonObject, shader); diff --git a/shared/src/map/layers/tiled/vector/tiles/raster/Tiled2dMapVectorRasterTile.cpp b/shared/src/map/layers/tiled/vector/tiles/raster/Tiled2dMapVectorRasterTile.cpp index 4d7a5ebc1..68b80cbb9 100644 --- a/shared/src/map/layers/tiled/vector/tiles/raster/Tiled2dMapVectorRasterTile.cpp +++ b/shared/src/map/layers/tiled/vector/tiles/raster/Tiled2dMapVectorRasterTile.cpp @@ -31,7 +31,7 @@ Tiled2dMapVectorRasterTile::Tiled2dMapVectorRasterTile(const std::weak_ptrasShaderProgramInterface()->setBlendMode(description->style.getBlendMode(EvaluationContext(0.0, dpFactor, std::make_shared(), featureStateManager))); auto quad = pMapInterface->getGraphicsObjectFactory()->createQuad(shader->asShaderProgramInterface()); #if DEBUG - quad->asGraphicsObject()->setDebugLabel(description->identifier); + quad->asGraphicsObject()->setDebugLabel(description->identifier + "_" + tileInfo.tileInfo.to_string_short()); #endif tileObject = std::make_shared(quad, shader, pMapInterface); tileObject->setRectCoord(tileInfo.tileInfo.bounds); From bf0da1aba35b40b1f94e8c5f1c75c274e868ce14 Mon Sep 17 00:00:00 2001 From: Stefan Mitterrutzner Date: Thu, 7 Mar 2024 08:35:36 +0100 Subject: [PATCH 22/23] initialize visibleTileHash with targetZoomLevelIdentifier --- shared/public/Tiled2dMapSourceImpl.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/shared/public/Tiled2dMapSourceImpl.h b/shared/public/Tiled2dMapSourceImpl.h index 9e7d3ae62..ab7c09e49 100644 --- a/shared/public/Tiled2dMapSourceImpl.h +++ b/shared/public/Tiled2dMapSourceImpl.h @@ -126,9 +126,7 @@ void Tiled2dMapSource::onVisibleBoundsChanged(const ::RectCoord &visibl const double visibleBottom = visibleBoundsLayer.bottomRight.y - signHeight * viewboundsPadding; visibleHeight = std::abs(visibleHeight) + 2 * viewboundsPadding; - - - size_t visibleTileHash = 0; + size_t visibleTileHash = targetZoomLevelIdentifier; for (int i = startZoomLayer; i <= endZoomLevel; i++) { const Tiled2dMapZoomLevelInfo &zoomLevelInfo = zoomLevelInfos.at(i); From 1bd3610fcbfd86fadb3bc6f4e8a17a04faf658a9 Mon Sep 17 00:00:00 2001 From: Christoph Maurhofer Date: Thu, 7 Mar 2024 09:01:15 +0100 Subject: [PATCH 23/23] Safety check in wmts bounds parsing --- .../layers/tiled/wmts/WmtsCapabilitiesResource.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/shared/src/map/layers/tiled/wmts/WmtsCapabilitiesResource.cpp b/shared/src/map/layers/tiled/wmts/WmtsCapabilitiesResource.cpp index 9c6328911..9ff081749 100644 --- a/shared/src/map/layers/tiled/wmts/WmtsCapabilitiesResource.cpp +++ b/shared/src/map/layers/tiled/wmts/WmtsCapabilitiesResource.cpp @@ -170,16 +170,20 @@ int32_t numZ) override { std::string lowerCorner = boundingBox.child_value("ows:LowerCorner"); if (lowerCorner.size() > 0) { auto delimiterIndex = lowerCorner.find(" "); - c1 = std::stod(lowerCorner.substr(0, delimiterIndex)); - c2 = std::stod(lowerCorner.substr(delimiterIndex)); + if (delimiterIndex != std::string::npos) { + c1 = std::stod(lowerCorner.substr(0, delimiterIndex)); + c2 = std::stod(lowerCorner.substr(delimiterIndex + 1)); + } } double c3 = 0; double c4 = 0; std::string upperCorner = boundingBox.child_value("ows:UpperCorner"); if (upperCorner.size() > 0) { auto delimiterIndex = upperCorner.find(" "); - c3 = std::stod(upperCorner.substr(0, delimiterIndex)); - c4 = std::stod(upperCorner.substr(delimiterIndex)); + if (delimiterIndex != std::string::npos) { + c3 = std::stod(upperCorner.substr(0, delimiterIndex)); + c4 = std::stod(upperCorner.substr(delimiterIndex + 1)); + } } std::optional bounds;