diff options
author | Gali Nelle <galinelle.mapbox@gmail.com> | 2020-04-15 18:15:29 +0300 |
---|---|---|
committer | galinelle <paolo.angelelli@mapbox.com> | 2020-04-17 22:26:32 +0300 |
commit | fea8a83e7f72ba59e41e713b3a37f6b946565d74 (patch) | |
tree | a1ca136e4d33d63f9ffb07cf6aa107c331ace992 /src/mbgl | |
parent | c4b061bd959a0efa5d0202d16d39e92e4f416abb (diff) | |
download | qtlocation-mapboxgl-fea8a83e7f72ba59e41e713b3a37f6b946565d74.tar.gz |
Introduce a mean to add render features in layers with no sources
This change also uses the support in the LocationIndicator layer, to
return a point feature when queried in correspondence of the location
indicator.
Diffstat (limited to 'src/mbgl')
-rw-r--r-- | src/mbgl/geometry/feature_index.cpp | 47 | ||||
-rw-r--r-- | src/mbgl/geometry/feature_index.hpp | 21 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_location_indicator_layer.cpp | 40 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_location_indicator_layer.hpp | 1 | ||||
-rw-r--r-- | src/mbgl/renderer/render_layer.hpp | 3 | ||||
-rw-r--r-- | src/mbgl/renderer/render_orchestrator.cpp | 21 |
6 files changed, 122 insertions, 11 deletions
diff --git a/src/mbgl/geometry/feature_index.cpp b/src/mbgl/geometry/feature_index.cpp index 623b661695..85a116bc2f 100644 --- a/src/mbgl/geometry/feature_index.cpp +++ b/src/mbgl/geometry/feature_index.cpp @@ -8,13 +8,29 @@ #include <mbgl/text/collision_index.hpp> #include <mbgl/tile/tile_id.hpp> #include <mbgl/util/constants.hpp> +#include <mbgl/util/geometry_within.hpp> #include <mbgl/util/math.hpp> +#include <mbgl/util/projection.hpp> #include <mapbox/geometry/envelope.hpp> #include <cassert> #include <string> +namespace { +mbgl::LatLng screenCoordinateToLatLng(mbgl::ScreenCoordinate point, + const mbgl::TransformState& state, + mbgl::LatLng::WrapMode wrapMode = mbgl::LatLng::Wrapped) { + point.y = state.getSize().height - point.y; + return state.screenCoordinateToLatLng(point, wrapMode); +} +mbgl::Point<double> project(const mbgl::LatLng& coordinate, const mbgl::TransformState& state) { + mbgl::LatLng unwrappedLatLng = coordinate.wrapped(); + unwrappedLatLng.unwrapForShortestPath(state.getLatLng(mbgl::LatLng::Wrapped)); + return mbgl::Projection::project(unwrappedLatLng, state.getScale()); +} +} // namespace + namespace mbgl { FeatureIndex::FeatureIndex(std::unique_ptr<const GeometryTileData> tileData_) @@ -194,4 +210,35 @@ void FeatureIndex::setBucketLayerIDs(const std::string& bucketLeaderID, const st bucketLayerIDs[bucketLeaderID] = layerIDs; } +DynamicFeatureIndex::~DynamicFeatureIndex() = default; + +void DynamicFeatureIndex::query(std::unordered_map<std::string, std::vector<Feature>>& result, + const mbgl::ScreenLineString& queryGeometry, + const TransformState& state) const { + if (features.empty()) return; + mbgl::WithinBBox queryBox = DefaultBBox; + for (const auto& p : queryGeometry) { + const LatLng c = screenCoordinateToLatLng(p, state); + const Point<double> pm = project(c, state); + const Point<int64_t> coord = {int64_t(pm.x), int64_t(pm.y)}; + mbgl::updateBBox(queryBox, coord); + } + for (const auto& f : features) { + // hit testing + mbgl::WithinBBox featureBox = DefaultBBox; + for (const auto& p : f.envelope->front()) mbgl::updateBBox(featureBox, p); + + const bool hit = mbgl::boxWithinBox(featureBox, queryBox) || mbgl::boxWithinBox(queryBox, featureBox); + if (hit) { + assert(f.feature); + result[f.feature->sourceLayer].push_back(*f.feature); + } + } +} + +void DynamicFeatureIndex::insert(std::shared_ptr<Feature> feature, + std::shared_ptr<mapbox::geometry::polygon<int64_t>> envelope) { + features.push_back({std::move(feature), std::move(envelope)}); +} + } // namespace mbgl diff --git a/src/mbgl/geometry/feature_index.hpp b/src/mbgl/geometry/feature_index.hpp index 24f36d98a0..dc6aa55f5e 100644 --- a/src/mbgl/geometry/feature_index.hpp +++ b/src/mbgl/geometry/feature_index.hpp @@ -3,8 +3,9 @@ #include <mbgl/style/types.hpp> #include <mbgl/tile/geometry_tile_data.hpp> #include <mbgl/tile/tile_id.hpp> -#include <mbgl/util/grid_index.hpp> #include <mbgl/util/feature.hpp> +#include <mbgl/util/geo.hpp> +#include <mbgl/util/grid_index.hpp> #include <mbgl/util/mat4.hpp> #include <vector> @@ -53,6 +54,24 @@ public: using FeatureSortOrder = std::shared_ptr<const std::vector<size_t>>; +class DynamicFeatureIndex { +public: + ~DynamicFeatureIndex(); + void query(std::unordered_map<std::string, std::vector<Feature>>& result, + const mbgl::ScreenLineString& queryGeometry, + const TransformState& state) const; + + void insert(std::shared_ptr<Feature> feature, std::shared_ptr<mapbox::geometry::polygon<int64_t>> envelope); + +protected: + struct FeatureRecord { + std::shared_ptr<Feature> feature; + std::shared_ptr<mapbox::geometry::polygon<int64_t>> envelope; + }; + + std::vector<FeatureRecord> features; +}; + class FeatureIndex { public: FeatureIndex(std::unique_ptr<const GeometryTileData> tileData_); diff --git a/src/mbgl/renderer/layers/render_location_indicator_layer.cpp b/src/mbgl/renderer/layers/render_location_indicator_layer.cpp index 933f674b89..c3872e92d0 100644 --- a/src/mbgl/renderer/layers/render_location_indicator_layer.cpp +++ b/src/mbgl/renderer/layers/render_location_indicator_layer.cpp @@ -1,5 +1,6 @@ #include <array> #include <mapbox/cheap_ruler.hpp> +#include <mbgl/geometry/feature_index.hpp> #include <mbgl/gfx/backend_scope.hpp> #include <mbgl/gfx/renderer_backend.hpp> #include <mbgl/gl/context.hpp> @@ -266,6 +267,7 @@ public: ~Texture() { release(); } void release() { MBGL_CHECK_ERROR(glDeleteTextures(1, &texId)); + texId = 0; image = nullptr; } /* @@ -338,7 +340,12 @@ public: float pixelRatio = 1.0f; }; - RenderLocationIndicatorImpl() : ruler(0, mapbox::cheap_ruler::CheapRuler::Meters) {} + RenderLocationIndicatorImpl(std::string sourceLayer) + : ruler(0, mapbox::cheap_ruler::CheapRuler::Meters), + feature(std::make_shared<mbgl::Feature>()), + featureEnvelope(std::make_shared<mapbox::geometry::polygon<int64_t>>()) { + feature->sourceLayer = std::move(sourceLayer); + } static bool hasAnisotropicFiltering() { const auto* extensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); @@ -404,7 +411,6 @@ public: projectionCircle = params.projectionMatrix; const Point<double> positionMercator = project(params.puckPosition, *params.state); - mat4 translation; matrix::identity(translation); matrix::translate(translation, translation, positionMercator.x, positionMercator.y, 0.0); matrix::multiply(projectionCircle, projectionCircle, translation); @@ -422,6 +428,25 @@ public: } } oldParams = params; + dirtyFeature = true; + } + + void updateFeature() { + if (!dirtyFeature) return; + dirtyFeature = false; + featureEnvelope->clear(); + if (!texPuck || !texPuck->isValid()) return; + + feature->geometry = + mapbox::geometry::point<double>{oldParams.puckPosition.latitude(), oldParams.puckPosition.longitude()}; + mapbox::geometry::linear_ring<int64_t> border; + for (const auto& v : puckGeometry) { + vec4 p{v.x, v.y, 0, 1}; + matrix::transformMat4(p, p, translation); + border.push_back(Point<int64_t>{int64_t(p[0]), int64_t(p[1])}); + } + border.push_back(border.front()); + featureEnvelope->push_back(border); } protected: @@ -682,6 +707,7 @@ protected: std::array<vec2, 4> puckGeometry; std::array<vec2, 4> hatGeometry; std::array<vec2, 4> texCoords; + mbgl::mat4 translation; mbgl::mat4 projectionCircle; mbgl::mat4 projectionPuck; @@ -690,9 +716,12 @@ protected: bool bearingChanged = false; mbgl::LocationIndicatorRenderParameters oldParams; bool initialized = false; + bool dirtyFeature = true; public: mbgl::LocationIndicatorRenderParameters parameters; + std::shared_ptr<mbgl::Feature> feature; + std::shared_ptr<mapbox::geometry::polygon<int64_t>> featureEnvelope; static bool anisotropicFilteringAvailable; }; @@ -709,7 +738,7 @@ inline const LocationIndicatorLayer::Impl& impl(const Immutable<style::Layer::Im RenderLocationIndicatorLayer::RenderLocationIndicatorLayer(Immutable<style::LocationIndicatorLayer::Impl> _impl) : RenderLayer(makeMutable<LocationIndicatorLayerProperties>(std::move(_impl))), - renderImpl(std::make_unique<RenderLocationIndicatorImpl>()), + renderImpl(std::make_unique<RenderLocationIndicatorImpl>(impl(baseImpl).id)), unevaluated(impl(baseImpl).paint.untransitioned()) { assert(gfx::BackendScope::exists()); } @@ -804,4 +833,9 @@ void RenderLocationIndicatorLayer::render(PaintParameters& paintParameters) { glContext.setDirtyState(); } +void RenderLocationIndicatorLayer::populateDynamicRenderFeatureIndex(DynamicFeatureIndex& index) const { + renderImpl->updateFeature(); + if (!renderImpl->featureEnvelope->empty()) index.insert(renderImpl->feature, renderImpl->featureEnvelope); +} + } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_location_indicator_layer.hpp b/src/mbgl/renderer/layers/render_location_indicator_layer.hpp index 0adb328df9..78d1203731 100644 --- a/src/mbgl/renderer/layers/render_location_indicator_layer.hpp +++ b/src/mbgl/renderer/layers/render_location_indicator_layer.hpp @@ -21,6 +21,7 @@ private: void prepare(const LayerPrepareParameters &) override; void render(PaintParameters &) override; + void populateDynamicRenderFeatureIndex(DynamicFeatureIndex &) const override; bool contextDestroyed = false; std::unique_ptr<RenderLocationIndicatorImpl> renderImpl; diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp index f7232a5aa0..553730de24 100644 --- a/src/mbgl/renderer/render_layer.hpp +++ b/src/mbgl/renderer/render_layer.hpp @@ -21,6 +21,7 @@ class TransformState; class PatternAtlas; class LineAtlas; class SymbolBucket; +class DynamicFeatureIndex; class LayerRenderData { public: @@ -106,6 +107,8 @@ public: return false; }; + virtual void populateDynamicRenderFeatureIndex(DynamicFeatureIndex&) const {} + virtual void prepare(const LayerPrepareParameters&); const LayerPlacementData& getPlacementData() const { return placementData; } diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index 77e23d3ab6..d7f13695de 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -52,7 +52,7 @@ private: bool hasRenderPass(RenderPass pass) const override { return layer.get().hasRenderPass(pass); } void upload(gfx::UploadPass& pass) const override { layer.get().upload(pass); } void render(PaintParameters& parameters) const override { layer.get().render(parameters); } - const std::string& getName() const override { return layer.get().getID(); } + const std::string& getName() const override { return layer.get().getID(); } }; class RenderTreeImpl final : public RenderTree { @@ -327,7 +327,7 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree( } } continue; - } + } // Handle layers without source. if (layerIsVisible && zoomFitsLayer && sourceImpl.get() == sourceImpls->at(0).get()) { @@ -335,7 +335,8 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree( const auto& solidBackground = layer.getSolidBackground(); if (solidBackground) { renderTreeParameters->backgroundColor = *solidBackground; - continue; // This layer is shown with background color, and it shall not be added to render items. + continue; // This layer is shown with background color, and it shall not be added to render + // items. } } renderItemsEmplaceHint = layerRenderItems.emplace_hint(renderItemsEmplaceHint, layer, nullptr, index); @@ -474,7 +475,7 @@ std::vector<Feature> RenderOrchestrator::queryRenderedFeatures(const ScreenLineS return queryRenderedFeatures(geometry, options, layers); } - + void RenderOrchestrator::queryRenderedSymbols(std::unordered_map<std::string, std::vector<Feature>>& resultsByLayer, const ScreenLineString& geometry, const std::unordered_map<std::string, const RenderLayer*>& layers, @@ -506,7 +507,7 @@ void RenderOrchestrator::queryRenderedSymbols(std::unordered_map<std::string, st std::tie(a.tileID.canonical.z, a.tileID.canonical.y, a.tileID.wrap, a.tileID.canonical.x) < std::tie(b.tileID.canonical.z, b.tileID.canonical.y, b.tileID.wrap, b.tileID.canonical.x); }); - + for (auto wrappedQueryData : bucketQueryData) { auto& queryData = wrappedQueryData.get(); auto bucketSymbols = queryData.featureIndex->lookupSymbolFeatures(renderedSymbols[queryData.bucketInstanceId], @@ -514,7 +515,7 @@ void RenderOrchestrator::queryRenderedSymbols(std::unordered_map<std::string, st crossTileSymbolIndexLayers, queryData.tileID, queryData.featureSortOrder); - + for (auto layer : bucketSymbols) { auto& resultFeatures = resultsByLayer[layer.first]; std::move(layer.second.begin(), layer.second.end(), std::inserter(resultFeatures, resultFeatures.end())); @@ -543,9 +544,15 @@ std::vector<Feature> RenderOrchestrator::queryRenderedFeatures(const ScreenLineS std::move(sourceResults.begin(), sourceResults.end(), std::inserter(resultsByLayer, resultsByLayer.begin())); } } - + queryRenderedSymbols(resultsByLayer, geometry, filteredLayers, options); + mbgl::DynamicFeatureIndex dynamicIndex; + for (const auto& pair : filteredLayers) { + const RenderLayer* layer = pair.second; + layer->populateDynamicRenderFeatureIndex(dynamicIndex); + } + dynamicIndex.query(resultsByLayer, geometry, transformState); std::vector<Feature> result; if (resultsByLayer.empty()) { |