std::unordered_map<uint32_t, std::vector<IndexedSubfeature>> CollisionIndex::queryRenderedSymbols(const ScreenLineString& queryGeometry) const { std::unordered_map<uint32_t, std::vector<IndexedSubfeature>> result; if (queryGeometry.empty() || (collisionGrid.empty() && ignoredGrid.empty())) { return result; } LineString<float> gridQuery; for (const auto& point : queryGeometry) { gridQuery.emplace_back(point.x + viewportPadding, point.y + viewportPadding); } auto envelope = mapbox::geometry::envelope(gridQuery); using QueryResult = std::pair<IndexedSubfeature, GridIndex<IndexedSubfeature>::BBox>; std::vector<QueryResult> features = collisionGrid.queryWithBoxes(envelope); std::vector<QueryResult> ignoredFeatures = ignoredGrid.queryWithBoxes(envelope); features.insert(features.end(), ignoredFeatures.begin(), ignoredFeatures.end()); std::unordered_map<uint32_t, std::unordered_set<size_t>> seenBuckets; for (auto& queryResult : features) { auto& feature = queryResult.first; auto& bbox = queryResult.second; // Skip already seen features. auto& seenFeatures = seenBuckets[feature.bucketInstanceId]; if (seenFeatures.find(feature.index) != seenFeatures.end()) continue; if (!polygonIntersectsBox(gridQuery, bbox)) { continue; } seenFeatures.insert(feature.index); result[feature.bucketInstanceId].push_back(feature); } return result; }