[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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -82,6 +82,7 @@ public:
|
||||
|
||||
const float pixelRatio;
|
||||
mbgl::MapMode mode;
|
||||
bool crossSourceCollisions;
|
||||
NodeThreadPool threadpool;
|
||||
NodeMapObserver mapObserver;
|
||||
std::unique_ptr<mbgl::HeadlessFrontend> frontend;
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)));
|
||||
|
||||
@@ -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>()) {
|
||||
|
||||
@@ -38,6 +38,8 @@ public:
|
||||
|
||||
// For still image requests, render requested
|
||||
const bool stillImageRequest;
|
||||
|
||||
const bool crossSourceCollisions;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -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 }}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 };
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user