summaryrefslogtreecommitdiff
path: root/src/mbgl/geometry
diff options
context:
space:
mode:
authorChris Loer <chris.loer@gmail.com>2018-04-18 16:33:37 -0700
committerChris Loer <chris.loer@mapbox.com>2018-04-25 14:39:03 -0700
commita62745edf9ee2da1f6ebda07acfd8260f3696e50 (patch)
tree3a756eecca1f9bbd03d588f3926425df43333dc7 /src/mbgl/geometry
parenteb39c80604935deb666907f90ddc31f50865f828 (diff)
downloadqtlocation-mapboxgl-a62745edf9ee2da1f6ebda07acfd8260f3696e50.tar.gz
Port global symbol query from GL JS:
- Symbol querying is now global instead of per-tile - Symbols that bleed over tile boundaries no longer missed in queries - Symbol results now sorted based on rendering order (ie overlapping symbols change their sort order when a bearing change causes their render order to change) - Placement::retainedQueryData now responsible for maintaining symbol querying data for buckets that may no longer be in the TilePyramid.
Diffstat (limited to 'src/mbgl/geometry')
-rw-r--r--src/mbgl/geometry/feature_index.cpp58
-rw-r--r--src/mbgl/geometry/feature_index.hpp32
2 files changed, 58 insertions, 32 deletions
diff --git a/src/mbgl/geometry/feature_index.cpp b/src/mbgl/geometry/feature_index.cpp
index c67786274a..8ea6259129 100644
--- a/src/mbgl/geometry/feature_index.cpp
+++ b/src/mbgl/geometry/feature_index.cpp
@@ -33,14 +33,6 @@ void FeatureIndex::insert(const GeometryCollection& geometries,
}
}
-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,
@@ -49,9 +41,7 @@ void FeatureIndex::query(
const double scale,
const RenderedQueryOptions& queryOptions,
const UnwrappedTileID& tileID,
- const std::string& sourceID,
const std::vector<const RenderLayer*>& layers,
- const CollisionIndex& collisionIndex,
const float additionalQueryRadius) const {
if (!tileData) {
@@ -68,7 +58,9 @@ void FeatureIndex::query(
convertPoint<float>(box.max + additionalRadius) });
- 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) {
@@ -76,23 +68,55 @@ void FeatureIndex::query(
if (indexedFeature.sortIndex == previousSortIndex) continue;
previousSortIndex = indexedFeature.sortIndex;
- addFeature(result, indexedFeature, queryGeometry, queryOptions, tileID.canonical, layers, bearing, pixelsToTileUnits);
+ addFeature(result, indexedFeature, queryOptions, tileID.canonical, layers, queryGeometry, bearing, pixelsToTileUnits);
}
+}
+
+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, tileID.canonical, layers, bearing, pixelsToTileUnits);
+ for (const auto& symbolFeature : sortedFeatures) {
+ addFeature(result, symbolFeature, queryOptions, tileID.canonical, layers, GeometryCoordinates(), 0, 0);
}
+ return result;
}
void FeatureIndex::addFeature(
std::unordered_map<std::string, std::vector<Feature>>& result,
const IndexedSubfeature& indexedFeature,
- const GeometryCoordinates& queryGeometry,
const RenderedQueryOptions& options,
const CanonicalTileID& tileID,
const std::vector<const RenderLayer*>& layers,
+ const GeometryCoordinates& queryGeometry,
const float bearing,
const float pixelsToTileUnits) const {
diff --git a/src/mbgl/geometry/feature_index.hpp b/src/mbgl/geometry/feature_index.hpp
index 9e0c172342..5a15a379c4 100644
--- a/src/mbgl/geometry/feature_index.hpp
+++ b/src/mbgl/geometry/feature_index.hpp
@@ -25,27 +25,24 @@ public:
, sourceLayerName(std::move(sourceLayerName_))
, bucketName(std::move(bucketName_))
, sortIndex(sortIndex_)
- , tileID(0, 0, 0)
+ , bucketInstanceId(0)
{}
- IndexedSubfeature(std::size_t index_, std::string sourceLayerName_, std::string bucketName_, size_t sortIndex_,
- std::string sourceID_, CanonicalTileID tileID_)
- : index(index_)
- , sourceLayerName(std::move(sourceLayerName_))
- , bucketName(std::move(bucketName_))
- , sortIndex(std::move(sortIndex_))
- , sourceID(std::move(sourceID_))
- , tileID(std::move(tileID_))
- {}
+ IndexedSubfeature(const IndexedSubfeature& other, uint32_t bucketInstanceId_)
+ : index(other.index)
+ , sourceLayerName(other.sourceLayerName)
+ , bucketName(other.bucketName)
+ , sortIndex(other.sortIndex)
+ , bucketInstanceId(bucketInstanceId_)
+ {}
size_t index;
std::string sourceLayerName;
std::string bucketName;
size_t sortIndex;
// Only used for symbol features
- std::string sourceID;
- CanonicalTileID tileID;
+ uint32_t bucketInstanceId;
};
class FeatureIndex {
@@ -64,9 +61,7 @@ public:
const double scale,
const RenderedQueryOptions& options,
const UnwrappedTileID&,
- const std::string&,
const std::vector<const RenderLayer*>&,
- const CollisionIndex&,
const float additionalQueryRadius) const;
static optional<GeometryCoordinates> translateQueryGeometry(
@@ -77,15 +72,22 @@ public:
const float pixelsToTileUnits);
void setBucketLayerIDs(const std::string& bucketName, const std::vector<std::string>& layerIDs);
+
+ std::unordered_map<std::string, std::vector<Feature>> lookupSymbolFeatures(
+ const std::vector<IndexedSubfeature>& symbolFeatures,
+ const RenderedQueryOptions& options,
+ const std::vector<const RenderLayer*>& layers,
+ const OverscaledTileID& tileID,
+ const std::shared_ptr<std::vector<size_t>>& featureSortOrder) const;
private:
void addFeature(
std::unordered_map<std::string, std::vector<Feature>>& result,
const IndexedSubfeature&,
- const GeometryCoordinates& queryGeometry,
const RenderedQueryOptions& options,
const CanonicalTileID&,
const std::vector<const RenderLayer*>&,
+ const GeometryCoordinates& queryGeometry,
const float bearing,
const float pixelsToTileUnits) const;