diff options
-rw-r--r-- | include/mbgl/map/map.hpp | 3 | ||||
-rw-r--r-- | platform/node/CHANGELOG.md | 1 | ||||
-rw-r--r-- | platform/node/src/node_map.cpp | 18 | ||||
-rw-r--r-- | platform/node/src/node_map.hpp | 1 | ||||
-rw-r--r-- | platform/node/test/ignores.json | 2 | ||||
-rw-r--r-- | platform/node/test/suite_implementation.js | 8 | ||||
-rw-r--r-- | src/mbgl/geometry/feature_index.hpp | 5 | ||||
-rw-r--r-- | src/mbgl/map/map.cpp | 17 | ||||
-rw-r--r-- | src/mbgl/renderer/renderer_impl.cpp | 4 | ||||
-rw-r--r-- | src/mbgl/renderer/update_parameters.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/text/collision_index.cpp | 34 | ||||
-rw-r--r-- | src/mbgl/text/collision_index.hpp | 8 | ||||
-rw-r--r-- | src/mbgl/text/placement.cpp | 39 | ||||
-rw-r--r-- | src/mbgl/text/placement.hpp | 24 | ||||
-rw-r--r-- | src/mbgl/tile/geometry_tile.hpp | 4 | ||||
-rw-r--r-- | src/mbgl/util/grid_index.cpp | 24 | ||||
-rw-r--r-- | src/mbgl/util/grid_index.hpp | 5 |
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; |