diff options
Diffstat (limited to 'src/mbgl/geometry/feature_index.cpp')
-rw-r--r-- | src/mbgl/geometry/feature_index.cpp | 109 |
1 files changed, 72 insertions, 37 deletions
diff --git a/src/mbgl/geometry/feature_index.cpp b/src/mbgl/geometry/feature_index.cpp index 3b5e12b54a..fdd9558d0b 100644 --- a/src/mbgl/geometry/feature_index.cpp +++ b/src/mbgl/geometry/feature_index.cpp @@ -17,54 +17,56 @@ namespace mbgl { -FeatureIndex::FeatureIndex() - : grid(util::EXTENT, util::EXTENT, util::EXTENT / 16) { // 16x16 grid -> 32px cell +FeatureIndex::FeatureIndex(std::unique_ptr<const GeometryTileData> tileData_) + : grid(util::EXTENT, util::EXTENT, util::EXTENT / 16) // 16x16 grid -> 32px cell + , tileData(std::move(tileData_)) { } void FeatureIndex::insert(const GeometryCollection& geometries, std::size_t index, const std::string& sourceLayerName, - const std::string& bucketName) { + const std::string& bucketLeaderID) { for (const auto& ring : geometries) { auto envelope = mapbox::geometry::envelope(ring); - grid.insert(IndexedSubfeature(index, sourceLayerName, bucketName, sortIndex++), - {convertPoint<float>(envelope.min), convertPoint<float>(envelope.max)}); + if (envelope.min.x < util::EXTENT && + envelope.min.y < util::EXTENT && + envelope.max.x >= 0 && + envelope.max.y >= 0) { + grid.insert(IndexedSubfeature(index, sourceLayerName, bucketLeaderID, sortIndex++), + {convertPoint<float>(envelope.min), convertPoint<float>(envelope.max)}); + } } } -static bool topDown(const IndexedSubfeature& a, const IndexedSubfeature& b) { - return a.sortIndex > b.sortIndex; -} - -static bool topDownSymbols(const IndexedSubfeature& a, const IndexedSubfeature& b) { - return a.sortIndex < b.sortIndex; -} - void FeatureIndex::query( std::unordered_map<std::string, std::vector<Feature>>& result, const GeometryCoordinates& queryGeometry, - const float bearing, + const TransformState& transformState, + const mat4& posMatrix, const double tileSize, const double scale, const RenderedQueryOptions& queryOptions, - const GeometryTileData& geometryTileData, const UnwrappedTileID& tileID, - const std::string& sourceID, const std::vector<const RenderLayer*>& layers, - const CollisionIndex& collisionIndex, - const float additionalQueryRadius) const { + const float additionalQueryPadding) const { + + if (!tileData) { + return; + } // Determine query radius const float pixelsToTileUnits = util::EXTENT / tileSize / scale; - const int16_t additionalRadius = std::min<int16_t>(util::EXTENT, additionalQueryRadius * pixelsToTileUnits); + const int16_t additionalPadding = std::min<int16_t>(util::EXTENT, additionalQueryPadding * pixelsToTileUnits); // Query the grid index mapbox::geometry::box<int16_t> box = mapbox::geometry::envelope(queryGeometry); - std::vector<IndexedSubfeature> features = grid.query({ convertPoint<float>(box.min - additionalRadius), - convertPoint<float>(box.max + additionalRadius) }); + std::vector<IndexedSubfeature> features = grid.query({ convertPoint<float>(box.min - additionalPadding), + convertPoint<float>(box.max + additionalPadding) }); - std::sort(features.begin(), features.end(), topDown); + std::sort(features.begin(), features.end(), [](const IndexedSubfeature& a, const IndexedSubfeature& b) { + return a.sortIndex > b.sortIndex; + }); size_t previousSortIndex = std::numeric_limits<size_t>::max(); for (const auto& indexedFeature : features) { @@ -72,26 +74,59 @@ void FeatureIndex::query( if (indexedFeature.sortIndex == previousSortIndex) continue; previousSortIndex = indexedFeature.sortIndex; - addFeature(result, indexedFeature, queryGeometry, queryOptions, geometryTileData, tileID.canonical, layers, bearing, pixelsToTileUnits); + addFeature(result, indexedFeature, queryOptions, tileID.canonical, layers, queryGeometry, transformState, pixelsToTileUnits, posMatrix); + } +} + +std::unordered_map<std::string, std::vector<Feature>> FeatureIndex::lookupSymbolFeatures(const std::vector<IndexedSubfeature>& symbolFeatures, + const RenderedQueryOptions& queryOptions, + const std::vector<const RenderLayer*>& layers, + const OverscaledTileID& tileID, + const std::shared_ptr<std::vector<size_t>>& featureSortOrder) const { + std::unordered_map<std::string, std::vector<Feature>> result; + if (!tileData) { + return result; } + std::vector<IndexedSubfeature> sortedFeatures(symbolFeatures.begin(), symbolFeatures.end()); + + std::sort(sortedFeatures.begin(), sortedFeatures.end(), [featureSortOrder](const IndexedSubfeature& a, const IndexedSubfeature& b) { + // Same idea as the non-symbol sort order, but symbol features may have changed their sort order + // since their corresponding IndexedSubfeature was added to the CollisionIndex + // The 'featureSortOrder' is relatively inefficient for querying but cheap to build on every bucket sort + if (featureSortOrder) { + // queryRenderedSymbols documentation says we'll return features in + // "top-to-bottom" rendering order (aka last-to-first). + // Actually there can be multiple symbol instances per feature, so + // we sort each feature based on the first matching symbol instance. + auto sortedA = std::find(featureSortOrder->begin(), featureSortOrder->end(), a.index); + auto sortedB = std::find(featureSortOrder->begin(), featureSortOrder->end(), b.index); + assert(sortedA != featureSortOrder->end()); + assert(sortedB != featureSortOrder->end()); + return sortedA > sortedB; + } else { + // Bucket hasn't been re-sorted based on angle, so use same "reverse of appearance in source data" + // logic as non-symboles + return a.sortIndex > b.sortIndex; + } + }); - std::vector<IndexedSubfeature> symbolFeatures = collisionIndex.queryRenderedSymbols(queryGeometry, tileID, sourceID); - std::sort(symbolFeatures.begin(), symbolFeatures.end(), topDownSymbols); - for (const auto& symbolFeature : symbolFeatures) { - addFeature(result, symbolFeature, queryGeometry, queryOptions, geometryTileData, tileID.canonical, layers, bearing, pixelsToTileUnits); + for (const auto& symbolFeature : sortedFeatures) { + mat4 unusedMatrix; + addFeature(result, symbolFeature, queryOptions, tileID.canonical, layers, GeometryCoordinates(), {}, 0, unusedMatrix); } + return result; } void FeatureIndex::addFeature( std::unordered_map<std::string, std::vector<Feature>>& result, const IndexedSubfeature& indexedFeature, - const GeometryCoordinates& queryGeometry, const RenderedQueryOptions& options, - const GeometryTileData& geometryTileData, const CanonicalTileID& tileID, const std::vector<const RenderLayer*>& layers, - const float bearing, - const float pixelsToTileUnits) const { + const GeometryCoordinates& queryGeometry, + const TransformState& transformState, + const float pixelsToTileUnits, + const mat4& posMatrix) const { auto getRenderLayer = [&] (const std::string& layerID) -> const RenderLayer* { for (const auto& layer : layers) { @@ -106,14 +141,14 @@ void FeatureIndex::addFeature( std::unique_ptr<GeometryTileLayer> sourceLayer; std::unique_ptr<GeometryTileFeature> geometryTileFeature; - for (const std::string& layerID : bucketLayerIDs.at(indexedFeature.bucketName)) { + for (const std::string& layerID : bucketLayerIDs.at(indexedFeature.bucketLeaderID)) { const RenderLayer* renderLayer = getRenderLayer(layerID); if (!renderLayer) { continue; } if (!geometryTileFeature) { - sourceLayer = geometryTileData.getLayer(indexedFeature.sourceLayerName); + sourceLayer = tileData->getLayer(indexedFeature.sourceLayerName); assert(sourceLayer); geometryTileFeature = sourceLayer->getFeature(indexedFeature.index); @@ -121,11 +156,11 @@ void FeatureIndex::addFeature( } if (!renderLayer->is<RenderSymbolLayer>() && - !renderLayer->queryIntersectsFeature(queryGeometry, *geometryTileFeature, tileID.z, bearing, pixelsToTileUnits)) { + !renderLayer->queryIntersectsFeature(queryGeometry, *geometryTileFeature, tileID.z, transformState, pixelsToTileUnits, posMatrix)) { continue; } - if (options.filter && !(*options.filter)(*geometryTileFeature)) { + if (options.filter && !(*options.filter)(style::expression::EvaluationContext { static_cast<float>(tileID.z), geometryTileFeature.get() })) { continue; } @@ -155,8 +190,8 @@ optional<GeometryCoordinates> FeatureIndex::translateQueryGeometry( return translated; } -void FeatureIndex::setBucketLayerIDs(const std::string& bucketName, const std::vector<std::string>& layerIDs) { - bucketLayerIDs[bucketName] = layerIDs; +void FeatureIndex::setBucketLayerIDs(const std::string& bucketLeaderID, const std::vector<std::string>& layerIDs) { + bucketLayerIDs[bucketLeaderID] = layerIDs; } } // namespace mbgl |