summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Loer <chris.loer@gmail.com>2018-09-06 14:58:37 -0700
committerChris Loer <chris.loer@mapbox.com>2018-09-12 14:10:46 -0700
commitd735d89835fb3076e09594fce2a141fe1495e33f (patch)
tree36fb80484b3952fb730fd34a77439d303d002cdc
parent079ba0209ed383c15123902f0810e658c2b0abf4 (diff)
downloadqtlocation-mapboxgl-d735d89835fb3076e09594fce2a141fe1495e33f.tar.gz
[core] Port "collision group" plumbing to gl-native.
[node] Hook up map-wide "crossSourceCollisions" option, defaulting to true. [test] Pass "crossSourceCollisions" test option through test harness; enable cross-source-collisions tests on native.
-rw-r--r--include/mbgl/map/map.hpp3
-rw-r--r--platform/node/CHANGELOG.md1
-rw-r--r--platform/node/src/node_map.cpp18
-rw-r--r--platform/node/src/node_map.hpp1
-rw-r--r--platform/node/test/ignores.json2
-rw-r--r--platform/node/test/suite_implementation.js8
-rw-r--r--src/mbgl/geometry/feature_index.hpp5
-rw-r--r--src/mbgl/map/map.cpp17
-rw-r--r--src/mbgl/renderer/renderer_impl.cpp4
-rw-r--r--src/mbgl/renderer/update_parameters.hpp2
-rw-r--r--src/mbgl/text/collision_index.cpp34
-rw-r--r--src/mbgl/text/collision_index.hpp8
-rw-r--r--src/mbgl/text/placement.cpp39
-rw-r--r--src/mbgl/text/placement.hpp24
-rw-r--r--src/mbgl/tile/geometry_tile.hpp4
-rw-r--r--src/mbgl/util/grid_index.cpp24
-rw-r--r--src/mbgl/util/grid_index.hpp5
17 files changed, 149 insertions, 50 deletions
diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp
index 3aee932070..ca6c62d280 100644
--- a/include/mbgl/map/map.hpp
+++ b/include/mbgl/map/map.hpp
@@ -37,7 +37,8 @@ public:
Scheduler&,
MapMode mapMode = MapMode::Continuous,
ConstrainMode constrainMode = ConstrainMode::HeightOnly,
- ViewportMode viewportMode = ViewportMode::Default);
+ ViewportMode viewportMode = ViewportMode::Default,
+ bool crossSourceCollisions = true);
~Map();
// Register a callback that will get called (on the render thread) when all resources have
diff --git a/platform/node/CHANGELOG.md b/platform/node/CHANGELOG.md
index 5b44d5be1f..fc8d2afe7b 100644
--- a/platform/node/CHANGELOG.md
+++ b/platform/node/CHANGELOG.md
@@ -6,6 +6,7 @@
- Remove unnecessary memory use when collision debug mode is not enabled ([#12294](https://github.com/mapbox/mapbox-gl-native/issues/12294))
- Added support for rendering `symbol-placement: line-center` ([#12337](https://github.com/mapbox/mapbox-gl-native/pull/12337))
- Add support for feature expressions in `line-pattern`, `fill-pattern`, and `fill-extrusion-pattern` properties. [#12284](https://github.com/mapbox/mapbox-gl-native/pull/12284)
+- Add `crossSourceCollisions` map option, with default of `true`. When set to `false`, cross-source collision detection is disabled. ([#12820] (https://github.com/mapbox/mapbox-gl-native/issues/12820))
# 3.5.8 - October 19, 2017
- Fixes an issue that causes memory leaks when not deleting the frontend object
diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp
index 7dbccfcf41..e32c576e14 100644
--- a/platform/node/src/node_map.cpp
+++ b/platform/node/src/node_map.cpp
@@ -621,7 +621,10 @@ void NodeMap::cancel() {
frontend = std::make_unique<mbgl::HeadlessFrontend>(mbgl::Size{ 256, 256 }, pixelRatio, *this, threadpool);
map = std::make_unique<mbgl::Map>(*frontend, mapObserver, frontend->getSize(), pixelRatio,
- *this, threadpool, mode);
+ *this, threadpool, mode,
+ mbgl::ConstrainMode::HeightOnly,
+ mbgl::ViewportMode::Default,
+ crossSourceCollisions);
// FIXME: Reload the style after recreating the map. We need to find
// a better way of canceling an ongoing rendering on the core level
@@ -1212,6 +1215,14 @@ NodeMap::NodeMap(v8::Local<v8::Object> options)
return mbgl::MapMode::Static;
}
}())
+ , crossSourceCollisions([&] {
+ Nan::HandleScope scope;
+ return Nan::Has(options, Nan::New("crossSourceCollisions").ToLocalChecked()).FromJust()
+ ? Nan::Get(options, Nan::New("crossSourceCollisions").ToLocalChecked())
+ .ToLocalChecked()
+ ->BooleanValue()
+ : true;
+ }())
, mapObserver(NodeMapObserver())
, frontend(std::make_unique<mbgl::HeadlessFrontend>(mbgl::Size { 256, 256 }, pixelRatio, *this, threadpool))
, map(std::make_unique<mbgl::Map>(*frontend,
@@ -1220,7 +1231,10 @@ NodeMap::NodeMap(v8::Local<v8::Object> options)
pixelRatio,
*this,
threadpool,
- mode)),
+ mode,
+ mbgl::ConstrainMode::HeightOnly,
+ mbgl::ViewportMode::Default,
+ crossSourceCollisions)),
async(new uv_async_t) {
async->data = this;
diff --git a/platform/node/src/node_map.hpp b/platform/node/src/node_map.hpp
index 52fc1ef659..b83a238681 100644
--- a/platform/node/src/node_map.hpp
+++ b/platform/node/src/node_map.hpp
@@ -82,6 +82,7 @@ public:
const float pixelRatio;
mbgl::MapMode mode;
+ bool crossSourceCollisions;
NodeThreadPool threadpool;
NodeMapObserver mapObserver;
std::unique_ptr<mbgl::HeadlessFrontend> frontend;
diff --git a/platform/node/test/ignores.json b/platform/node/test/ignores.json
index d2ec3644d9..67f0ff9a72 100644
--- a/platform/node/test/ignores.json
+++ b/platform/node/test/ignores.json
@@ -95,7 +95,6 @@
"render-tests/geojson/inline-linestring-fill": "current behavior is arbitrary",
"render-tests/geojson/inline-polygon-symbol": "behavior needs reconciliation with gl-js",
"render-tests/icon-rotate/with-offset": "https://github.com/mapbox/mapbox-gl-native/issues/11872",
- "render-tests/icon-no-cross-source-collision/default": "skip - gl-js only",
"render-tests/mixed-zoom/z10-z11": "https://github.com/mapbox/mapbox-gl-native/issues/10397",
"render-tests/raster-masking/overlapping-zoom": "https://github.com/mapbox/mapbox-gl-native/issues/10195",
"render-tests/real-world/bangkok": "https://github.com/mapbox/mapbox-gl-native/issues/10412",
@@ -122,7 +121,6 @@
"render-tests/text-field/formatted-arabic": "skip - https://github.com/mapbox/mapbox-gl-native/pull/12624",
"render-tests/text-field/formatted-line": "skip - https://github.com/mapbox/mapbox-gl-native/pull/12624",
"render-tests/text-field/formatted": "skip - https://github.com/mapbox/mapbox-gl-native/pull/12624",
- "render-tests/text-no-cross-source-collision/default": "skip - gl-js only",
"render-tests/text-pitch-alignment/auto-text-rotation-alignment-map": "https://github.com/mapbox/mapbox-gl-native/issues/9732",
"render-tests/text-pitch-alignment/map-text-rotation-alignment-map": "https://github.com/mapbox/mapbox-gl-native/issues/9732",
"render-tests/text-pitch-alignment/viewport-text-rotation-alignment-map": "https://github.com/mapbox/mapbox-gl-native/issues/9732",
diff --git a/platform/node/test/suite_implementation.js b/platform/node/test/suite_implementation.js
index 704cab8940..f868af8ece 100644
--- a/platform/node/test/suite_implementation.js
+++ b/platform/node/test/suite_implementation.js
@@ -16,7 +16,7 @@ export default function (style, options, callback) {
let map;
if (options.recycleMap) {
- const key = options.pixelRatio + '/' + tileMode;
+ const key = options.pixelRatio + '/' + tileMode + '/' + options.crossSourceCollisions;
if (maps.has(key)) {
map = maps.get(key);
map.request = mapRequest;
@@ -24,7 +24,8 @@ export default function (style, options, callback) {
maps.set(key, new mbgl.Map({
ratio: options.pixelRatio,
request: mapRequest,
- mode: options.mapMode
+ mode: options.mapMode,
+ crossSourceCollisions: typeof options.crossSourceCollisions === "undefined" ? true : options.crossSourceCollisions
}));
map = maps.get(key);
}
@@ -32,7 +33,8 @@ export default function (style, options, callback) {
map = new mbgl.Map({
ratio: options.pixelRatio,
request: mapRequest,
- mode: options.mapMode
+ mode: options.mapMode,
+ crossSourceCollisions: typeof options.crossSourceCollisions === "undefined" ? true : options.crossSourceCollisions
});
}
diff --git a/src/mbgl/geometry/feature_index.hpp b/src/mbgl/geometry/feature_index.hpp
index 739c1f282f..cd041a7fdb 100644
--- a/src/mbgl/geometry/feature_index.hpp
+++ b/src/mbgl/geometry/feature_index.hpp
@@ -28,15 +28,17 @@ public:
, bucketLeaderID(std::move(bucketName_))
, sortIndex(sortIndex_)
, bucketInstanceId(0)
+ , collisionGroupId(0)
{}
- IndexedSubfeature(const IndexedSubfeature& other, uint32_t bucketInstanceId_)
+ IndexedSubfeature(const IndexedSubfeature& other, uint32_t bucketInstanceId_, uint16_t collisionGroupId_)
: index(other.index)
, sourceLayerName(other.sourceLayerName)
, bucketLeaderID(other.bucketLeaderID)
, sortIndex(other.sortIndex)
, bucketInstanceId(bucketInstanceId_)
+ , collisionGroupId(collisionGroupId_)
{}
size_t index;
std::string sourceLayerName;
@@ -45,6 +47,7 @@ public:
// Only used for symbol features
uint32_t bucketInstanceId;
+ uint16_t collisionGroupId;
};
class FeatureIndex {
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp
index ddac5c5c8f..9d886cb74c 100644
--- a/src/mbgl/map/map.cpp
+++ b/src/mbgl/map/map.cpp
@@ -44,7 +44,8 @@ public:
Scheduler&,
MapMode,
ConstrainMode,
- ViewportMode);
+ ViewportMode,
+ bool);
~Impl();
@@ -73,6 +74,7 @@ public:
const MapMode mode;
const float pixelRatio;
+ const bool crossSourceCollisions;
MapDebugOptions debugOptions { MapDebugOptions::NoDebug };
@@ -96,7 +98,8 @@ Map::Map(RendererFrontend& rendererFrontend,
Scheduler& scheduler,
MapMode mapMode,
ConstrainMode constrainMode,
- ViewportMode viewportMode)
+ ViewportMode viewportMode,
+ bool crossSourceCollisions)
: impl(std::make_unique<Impl>(*this,
rendererFrontend,
mapObserver,
@@ -105,7 +108,8 @@ Map::Map(RendererFrontend& rendererFrontend,
scheduler,
mapMode,
constrainMode,
- viewportMode)) {
+ viewportMode,
+ crossSourceCollisions)) {
impl->transform.resize(size);
}
@@ -117,7 +121,8 @@ Map::Impl::Impl(Map& map_,
Scheduler& scheduler_,
MapMode mode_,
ConstrainMode constrainMode_,
- ViewportMode viewportMode_)
+ ViewportMode viewportMode_,
+ bool crossSourceCollisions_)
: map(map_),
observer(mapObserver),
rendererFrontend(frontend),
@@ -128,6 +133,7 @@ Map::Impl::Impl(Map& map_,
viewportMode_),
mode(mode_),
pixelRatio(pixelRatio_),
+ crossSourceCollisions(crossSourceCollisions_),
style(std::make_unique<Style>(scheduler, fileSource, pixelRatio)),
annotationManager(*style) {
@@ -783,7 +789,8 @@ void Map::Impl::onUpdate() {
style->impl->getLayerImpls(),
annotationManager,
prefetchZoomDelta,
- bool(stillImageRequest)
+ bool(stillImageRequest),
+ crossSourceCollisions
};
rendererFrontend.update(std::make_shared<UpdateParameters>(std::move(params)));
diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp
index 92d04063ca..6f7814190d 100644
--- a/src/mbgl/renderer/renderer_impl.cpp
+++ b/src/mbgl/renderer/renderer_impl.cpp
@@ -61,7 +61,7 @@ Renderer::Impl::Impl(RendererBackend& backend_,
, sourceImpls(makeMutable<std::vector<Immutable<style::Source::Impl>>>())
, layerImpls(makeMutable<std::vector<Immutable<style::Layer::Impl>>>())
, renderLight(makeMutable<Light::Impl>())
- , placement(std::make_unique<Placement>(TransformState{}, MapMode::Static)) {
+ , placement(std::make_unique<Placement>(TransformState{}, MapMode::Static, true)) {
glyphManager->setObserver(this);
}
@@ -398,7 +398,7 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
if (!placement->stillRecent(parameters.timePoint)) {
placementChanged = true;
- auto newPlacement = std::make_unique<Placement>(parameters.state, parameters.mapMode);
+ auto newPlacement = std::make_unique<Placement>(parameters.state, parameters.mapMode, updateParameters.crossSourceCollisions);
std::set<std::string> usedSymbolLayers;
for (auto it = order.rbegin(); it != order.rend(); ++it) {
if (it->layer.is<RenderSymbolLayer>()) {
diff --git a/src/mbgl/renderer/update_parameters.hpp b/src/mbgl/renderer/update_parameters.hpp
index b54abc050d..a668c64f48 100644
--- a/src/mbgl/renderer/update_parameters.hpp
+++ b/src/mbgl/renderer/update_parameters.hpp
@@ -38,6 +38,8 @@ public:
// For still image requests, render requested
const bool stillImageRequest;
+
+ const bool crossSourceCollisions;
};
} // namespace mbgl
diff --git a/src/mbgl/text/collision_index.cpp b/src/mbgl/text/collision_index.cpp
index dae789a196..90acb2b441 100644
--- a/src/mbgl/text/collision_index.cpp
+++ b/src/mbgl/text/collision_index.cpp
@@ -89,7 +89,8 @@ std::pair<bool,bool> CollisionIndex::placeFeature(CollisionFeature& feature,
const bool allowOverlap,
const bool pitchWithMap,
const bool collisionDebug,
- const optional<CollisionTileBoundaries>& avoidEdges) {
+ const optional<CollisionTileBoundaries>& avoidEdges,
+ const optional<std::function<bool(const IndexedSubfeature&)>> collisionGroupPredicate) {
if (!feature.alongLine) {
CollisionBox& box = feature.boxes.front();
const auto projectedPoint = projectAndGetPerspectiveRatio(posMatrix, box.anchor);
@@ -102,13 +103,13 @@ std::pair<bool,bool> CollisionIndex::placeFeature(CollisionFeature& feature,
if ((avoidEdges && !isInsideTile(box, *avoidEdges)) ||
!isInsideGrid(box) ||
- (!allowOverlap && collisionGrid.hitTest({{ box.px1, box.py1 }, { box.px2, box.py2 }}))) {
+ (!allowOverlap && collisionGrid.hitTest({{ box.px1, box.py1 }, { box.px2, box.py2 }}, collisionGroupPredicate))) {
return { false, false };
}
return {true, isOffscreen(box)};
} else {
- return placeLineFeature(feature, posMatrix, labelPlaneMatrix, textPixelRatio, symbol, scale, fontSize, allowOverlap, pitchWithMap, collisionDebug, avoidEdges);
+ return placeLineFeature(feature, posMatrix, labelPlaneMatrix, textPixelRatio, symbol, scale, fontSize, allowOverlap, pitchWithMap, collisionDebug, avoidEdges, collisionGroupPredicate);
}
}
@@ -122,7 +123,8 @@ std::pair<bool,bool> CollisionIndex::placeLineFeature(CollisionFeature& feature,
const bool allowOverlap,
const bool pitchWithMap,
const bool collisionDebug,
- const optional<CollisionTileBoundaries>& avoidEdges) {
+ const optional<CollisionTileBoundaries>& avoidEdges,
+ const optional<std::function<bool(const IndexedSubfeature&)>> collisionGroupPredicate) {
const auto tileUnitAnchorPoint = symbol.anchorPoint;
const auto projectedAnchor = projectAnchor(posMatrix, tileUnitAnchorPoint);
@@ -222,7 +224,7 @@ std::pair<bool,bool> CollisionIndex::placeLineFeature(CollisionFeature& feature,
inGrid |= isInsideGrid(circle);
if ((avoidEdges && !isInsideTile(circle, *avoidEdges)) ||
- (!allowOverlap && collisionGrid.hitTest({{circle.px, circle.py}, circle.radius}))) {
+ (!allowOverlap && collisionGrid.hitTest({{circle.px, circle.py}, circle.radius}, collisionGroupPredicate))) {
if (!collisionDebug) {
return {false, false};
} else {
@@ -237,7 +239,7 @@ std::pair<bool,bool> CollisionIndex::placeLineFeature(CollisionFeature& feature,
}
-void CollisionIndex::insertFeature(CollisionFeature& feature, bool ignorePlacement, uint32_t bucketInstanceId) {
+void CollisionIndex::insertFeature(CollisionFeature& feature, bool ignorePlacement, uint32_t bucketInstanceId, uint16_t collisionGroupId) {
if (feature.alongLine) {
for (auto& circle : feature.boxes) {
if (!circle.used) {
@@ -245,18 +247,30 @@ void CollisionIndex::insertFeature(CollisionFeature& feature, bool ignorePlaceme
}
if (ignorePlacement) {
- ignoredGrid.insert(IndexedSubfeature(feature.indexedFeature, bucketInstanceId), {{ circle.px, circle.py }, circle.radius});
+ ignoredGrid.insert(
+ IndexedSubfeature(feature.indexedFeature, bucketInstanceId, collisionGroupId),
+ {{ circle.px, circle.py }, circle.radius}
+ );
} else {
- collisionGrid.insert(IndexedSubfeature(feature.indexedFeature, bucketInstanceId), {{ circle.px, circle.py }, circle.radius});
+ collisionGrid.insert(
+ IndexedSubfeature(feature.indexedFeature, bucketInstanceId, collisionGroupId),
+ {{ circle.px, circle.py }, circle.radius}
+ );
}
}
} else {
assert(feature.boxes.size() == 1);
auto& box = feature.boxes[0];
if (ignorePlacement) {
- ignoredGrid.insert(IndexedSubfeature(feature.indexedFeature, bucketInstanceId), {{ box.px1, box.py1 }, { box.px2, box.py2 }});
+ ignoredGrid.insert(
+ IndexedSubfeature(feature.indexedFeature, bucketInstanceId, collisionGroupId),
+ {{ box.px1, box.py1 }, { box.px2, box.py2 }}
+ );
} else {
- collisionGrid.insert(IndexedSubfeature(feature.indexedFeature, bucketInstanceId), {{ box.px1, box.py1 }, { box.px2, box.py2 }});
+ collisionGrid.insert(
+ IndexedSubfeature(feature.indexedFeature, bucketInstanceId, collisionGroupId),
+ {{ box.px1, box.py1 }, { box.px2, box.py2 }}
+ );
}
}
}
diff --git a/src/mbgl/text/collision_index.hpp b/src/mbgl/text/collision_index.hpp
index 78782fe61c..dac0aa0bf7 100644
--- a/src/mbgl/text/collision_index.hpp
+++ b/src/mbgl/text/collision_index.hpp
@@ -32,9 +32,10 @@ public:
const bool allowOverlap,
const bool pitchWithMap,
const bool collisionDebug,
- const optional<CollisionTileBoundaries>& avoidEdges);
+ const optional<CollisionTileBoundaries>& avoidEdges,
+ const optional<std::function<bool(const IndexedSubfeature&)>> collisionGroupPredicate);
- void insertFeature(CollisionFeature& feature, bool ignorePlacement, uint32_t bucketInstanceId);
+ void insertFeature(CollisionFeature& feature, bool ignorePlacement, uint32_t bucketInstanceId, uint16_t collisionGroupId);
std::unordered_map<uint32_t, std::vector<IndexedSubfeature>> queryRenderedSymbols(const ScreenLineString&) const;
@@ -55,7 +56,8 @@ private:
const bool allowOverlap,
const bool pitchWithMap,
const bool collisionDebug,
- const optional<CollisionTileBoundaries>& avoidEdges);
+ const optional<CollisionTileBoundaries>& avoidEdges,
+ const optional<std::function<bool(const IndexedSubfeature&)>> collisionGroupPredicate);
float approximateTileDistance(const TileDistance& tileDistance, const float lastSegmentAngle, const float pixelsToTileUnits, const float cameraToAnchorDistance, const bool pitchWithMap);
diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp
index 48c58a962e..5c6cdcde6c 100644
--- a/src/mbgl/text/placement.cpp
+++ b/src/mbgl/text/placement.cpp
@@ -33,11 +33,33 @@ JointOpacityState::JointOpacityState(const JointOpacityState& prevOpacityState,
bool JointOpacityState::isHidden() const {
return icon.isHidden() && text.isHidden();
}
+
+const CollisionGroups::CollisionGroup& CollisionGroups::get(const std::string& sourceID) {
+ // The predicate/groupID mechanism allows for arbitrary grouping,
+ // but the current interface defines one source == one group when
+ // crossSourceCollisions == true.
+ if (!crossSourceCollisions) {
+ if (collisionGroups.find(sourceID) == collisionGroups.end()) {
+ uint16_t nextGroupID = ++maxGroupID;
+ collisionGroups.emplace(sourceID, CollisionGroup(
+ nextGroupID,
+ optional<Predicate>([nextGroupID](const IndexedSubfeature& feature) -> bool {
+ return feature.collisionGroupId == nextGroupID;
+ })
+ ));
+ }
+ return collisionGroups[sourceID];
+ } else {
+ static CollisionGroup nullGroup{0, nullopt};
+ return nullGroup;
+ }
+}
-Placement::Placement(const TransformState& state_, MapMode mapMode_)
+Placement::Placement(const TransformState& state_, MapMode mapMode_, const bool crossSourceCollisions)
: collisionIndex(state_)
, state(state_)
, mapMode(mapMode_)
+ , collisionGroups(crossSourceCollisions)
{}
void Placement::placeLayer(RenderSymbolLayer& symbolLayer, const mat4& projMatrix, bool showCollisionBoxes) {
@@ -92,7 +114,9 @@ void Placement::placeLayer(RenderSymbolLayer& symbolLayer, const mat4& projMatri
std::forward_as_tuple(symbolBucket.bucketInstanceId),
std::forward_as_tuple(symbolBucket.bucketInstanceId, geometryTile.getFeatureIndex(), geometryTile.id));
- placeLayerBucket(symbolBucket, posMatrix, textLabelPlaneMatrix, iconLabelPlaneMatrix, scale, textPixelRatio, showCollisionBoxes, seenCrossTileIDs, renderTile.tile.holdForFade());
+ const auto collisionGroup = collisionGroups.get(geometryTile.sourceID);
+
+ placeLayerBucket(symbolBucket, posMatrix, textLabelPlaneMatrix, iconLabelPlaneMatrix, scale, textPixelRatio, showCollisionBoxes, seenCrossTileIDs, renderTile.tile.holdForFade(), collisionGroup);
}
}
@@ -105,7 +129,8 @@ void Placement::placeLayerBucket(
const float textPixelRatio,
const bool showCollisionBoxes,
std::unordered_set<uint32_t>& seenCrossTileIDs,
- const bool holdingForFade) {
+ const bool holdingForFade,
+ const CollisionGroups::CollisionGroup& collisionGroup) {
auto partiallyEvaluatedTextSize = bucket.textSizeBinder->evaluateForZoom(state.getZoom());
auto partiallyEvaluatedIconSize = bucket.iconSizeBinder->evaluateForZoom(state.getZoom());
@@ -159,7 +184,7 @@ void Placement::placeLayerBucket(
placedSymbol, scale, fontSize,
bucket.layout.get<style::TextAllowOverlap>(),
bucket.layout.get<style::TextPitchAlignment>() == style::AlignmentType::Map,
- showCollisionBoxes, avoidEdges);
+ showCollisionBoxes, avoidEdges, collisionGroup.second);
placeText = placed.first;
offscreen &= placed.second;
}
@@ -173,7 +198,7 @@ void Placement::placeLayerBucket(
placedSymbol, scale, fontSize,
bucket.layout.get<style::IconAllowOverlap>(),
bucket.layout.get<style::IconPitchAlignment>() == style::AlignmentType::Map,
- showCollisionBoxes, avoidEdges);
+ showCollisionBoxes, avoidEdges, collisionGroup.second);
placeIcon = placed.first;
offscreen &= placed.second;
}
@@ -191,11 +216,11 @@ void Placement::placeLayerBucket(
}
if (placeText) {
- collisionIndex.insertFeature(symbolInstance.textCollisionFeature, bucket.layout.get<style::TextIgnorePlacement>(), bucket.bucketInstanceId);
+ collisionIndex.insertFeature(symbolInstance.textCollisionFeature, bucket.layout.get<style::TextIgnorePlacement>(), bucket.bucketInstanceId, collisionGroup.first);
}
if (placeIcon) {
- collisionIndex.insertFeature(symbolInstance.iconCollisionFeature, bucket.layout.get<style::IconIgnorePlacement>(), bucket.bucketInstanceId);
+ collisionIndex.insertFeature(symbolInstance.iconCollisionFeature, bucket.layout.get<style::IconIgnorePlacement>(), bucket.bucketInstanceId, collisionGroup.first);
}
assert(symbolInstance.crossTileID != 0);
diff --git a/src/mbgl/text/placement.hpp b/src/mbgl/text/placement.hpp
index 24de4c054a..8527d6df57 100644
--- a/src/mbgl/text/placement.hpp
+++ b/src/mbgl/text/placement.hpp
@@ -59,9 +59,27 @@ struct RetainedQueryData {
, tileID(std::move(tileID_)) {}
};
+class CollisionGroups {
+public:
+ using Predicate = std::function<bool(const IndexedSubfeature&)>;
+ using CollisionGroup = std::pair<uint16_t, optional<Predicate>>;
+
+ CollisionGroups(const bool crossSourceCollisions_)
+ : maxGroupID(0)
+ , crossSourceCollisions(crossSourceCollisions_)
+ {}
+
+ const CollisionGroup& get(const std::string& sourceID);
+
+private:
+ std::map<std::string, CollisionGroup> collisionGroups;
+ uint16_t maxGroupID;
+ bool crossSourceCollisions;
+};
+
class Placement {
public:
- Placement(const TransformState&, MapMode mapMode);
+ Placement(const TransformState&, MapMode mapMode, const bool crossSourceCollisions);
void placeLayer(RenderSymbolLayer&, const mat4&, bool showCollisionBoxes);
void commit(const Placement& prevPlacement, TimePoint);
void updateLayerOpacities(RenderSymbolLayer&);
@@ -86,7 +104,8 @@ private:
const float pixelRatio,
const bool showCollisionBoxes,
std::unordered_set<uint32_t>& seenCrossTileIDs,
- const bool holdingForFade);
+ const bool holdingForFade,
+ const CollisionGroups::CollisionGroup& collisionGroup);
void updateBucketOpacities(SymbolBucket&, std::set<uint32_t>&);
@@ -103,6 +122,7 @@ private:
bool stale = false;
std::unordered_map<uint32_t, RetainedQueryData> retainedQueryData;
+ CollisionGroups collisionGroups;
};
} // namespace mbgl
diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp
index 3d0ca03a82..c5c7cb6623 100644
--- a/src/mbgl/tile/geometry_tile.hpp
+++ b/src/mbgl/tile/geometry_tile.hpp
@@ -91,6 +91,8 @@ public:
const optional<ImagePosition> getPattern(const std::string& pattern);
const std::shared_ptr<FeatureIndex> getFeatureIndex() const { return latestFeatureIndex; }
+ const std::string sourceID;
+
protected:
const GeometryTileData* getData() {
return latestFeatureIndex ? latestFeatureIndex->getData() : nullptr;
@@ -99,8 +101,6 @@ protected:
private:
void markObsolete();
- const std::string sourceID;
-
// Used to signal the worker that it should abandon parsing this tile as soon as possible.
std::atomic<bool> obsolete { false };
diff --git a/src/mbgl/util/grid_index.cpp b/src/mbgl/util/grid_index.cpp
index afd469501d..f6b59b1bac 100644
--- a/src/mbgl/util/grid_index.cpp
+++ b/src/mbgl/util/grid_index.cpp
@@ -82,21 +82,29 @@ std::vector<std::pair<T, typename GridIndex<T>::BBox>> GridIndex<T>::queryWithBo
}
template <class T>
-bool GridIndex<T>::hitTest(const BBox& queryBBox) const {
+bool GridIndex<T>::hitTest(const BBox& queryBBox, optional<std::function<bool(const T&)>> predicate) const {
bool hit = false;
- query(queryBBox, [&](const T&, const BBox&) -> bool {
- hit = true;
- return true;
+ query(queryBBox, [&](const T& t, const BBox&) -> bool {
+ if (!predicate || (*predicate)(t)) {
+ hit = true;
+ return true;
+ } else {
+ return false;
+ }
});
return hit;
}
template <class T>
-bool GridIndex<T>::hitTest(const BCircle& queryBCircle) const {
+bool GridIndex<T>::hitTest(const BCircle& queryBCircle, optional<std::function<bool(const T&)>> predicate) const {
bool hit = false;
- query(queryBCircle, [&](const T&, const BBox&) -> bool {
- hit = true;
- return true;
+ query(queryBCircle, [&](const T& t, const BBox&) -> bool {
+ if (!predicate || (*predicate)(t)) {
+ hit = true;
+ return true;
+ } else {
+ return false;
+ }
});
return hit;
}
diff --git a/src/mbgl/util/grid_index.hpp b/src/mbgl/util/grid_index.hpp
index 6ef2966bee..4c2d7dccc8 100644
--- a/src/mbgl/util/grid_index.hpp
+++ b/src/mbgl/util/grid_index.hpp
@@ -2,6 +2,7 @@
#include <mapbox/geometry/point.hpp>
#include <mapbox/geometry/box.hpp>
+#include <mbgl/util/optional.hpp>
#include <cstdint>
#include <cstddef>
@@ -67,8 +68,8 @@ public:
std::vector<T> query(const BBox&) const;
std::vector<std::pair<T,BBox>> queryWithBoxes(const BBox&) const;
- bool hitTest(const BBox&) const;
- bool hitTest(const BCircle&) const;
+ bool hitTest(const BBox&, optional<std::function<bool(const T&)>> predicate = nullopt) const;
+ bool hitTest(const BCircle&, optional<std::function<bool(const T&)>> predicate = nullopt) const;
bool empty() const;