[core] fix collisionBox alignment when Icon/text translation is enabled (#15467)

* add initial fix

* fix bug for collision circle

* refind code structure

* fix indentation

* update test

* refind code structure

* Add changelog

* Add comment for boolean
This commit is contained in:
zmiao
2019-08-30 08:24:03 +03:00
committed by GitHub
parent 29b11a5037
commit 6ef2710e5c
10 changed files with 205 additions and 143 deletions

View File

@@ -10,6 +10,9 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to
### Performance improvements
- Mark used offline region resources in batches. [#15521](https://github.com/mapbox/mapbox-gl-native/pull/15521)
### Bug fixes
- Fixed a rendering issue of `collisionBox` when `text-translate` or `icon-translate` is enabled. [#15467](https://github.com/mapbox/mapbox-gl-native/pull/15467)
## 8.3.0 - August 28, 2019
[Changes](https://github.com/mapbox/mapbox-gl-native/compare/android-v8.3.0-beta.1...android-v8.3.0) since [Mapbox Maps SDK for Android v8.3.0-beta.1](https://github.com/mapbox/mapbox-gl-native/releases/tag/android-v8.3.0-beta.1):

View File

@@ -6,6 +6,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
* Fixed an issue that caused the tilt gesture to trigger too easily and conflict with pinch or pan gestures. ([#15349](https://github.com/mapbox/mapbox-gl-native/pull/15349))
* Fixed a bug with annotation view positions after camera transitions. ([#15122](https://github.com/mapbox/mapbox-gl-native/pull/15122/))
* Fixed a rendering issue of `collisionBox` when `text-translate` or `icon-translate` is enabled. ([#15467](https://github.com/mapbox/mapbox-gl-native/pull/15467))
### Performance improvements

View File

@@ -14,6 +14,7 @@
* Fixed rendering and collision detection issues with using `text-variable-anchor` and `icon-text-fit` properties on the same layer. ([#15367](https://github.com/mapbox/mapbox-gl-native/pull/15367))
* Fixed symbol overlap when zooming out quickly. ([15416](https://github.com/mapbox/mapbox-gl-native/pull/15416))
* Fixed a rendering issue that non-SDF icon would be treated as SDF icon if they are in the same layer. ([#15456](https://github.com/mapbox/mapbox-gl-native/pull/15456))
* Fixed a rendering issue of `collisionBox` when `text-translate` or `icon-translate` is enabled. ([#15467](https://github.com/mapbox/mapbox-gl-native/pull/15467))
### Styles and rendering

View File

@@ -2,6 +2,7 @@
* Introduce `text-writing-mode` layout property for symbol layer ([#14932](https://github.com/mapbox/mapbox-gl-native/pull/14932)). The `text-writing-mode` layout property allows control over symbol's preferred writing mode. The new property value is an array, whose values are enumeration values from a ( `horizontal` | `vertical` ) set.
* Fixed rendering and collision detection issues with using `text-variable-anchor` and `icon-text-fit` properties on the same layer ([#15367](https://github.com/mapbox/mapbox-gl-native/pull/15367)).
* Fixed a rendering issue that non-SDF icon would be treated as SDF icon if they are in the same layer. ([#15456](https://github.com/mapbox/mapbox-gl-native/pull/15456))
* Fixed a rendering issue of `collisionBox` when `text-translate` or `icon-translate` is enabled. ([#15467](https://github.com/mapbox/mapbox-gl-native/pull/15467))
# 4.2.0
- Add an option to set whether or not an image should be treated as a SDF ([#15054](https://github.com/mapbox/mapbox-gl-native/issues/15054))

View File

@@ -812,12 +812,15 @@ void SymbolLayout::addToDebugBuffers(SymbolBucket& bucket) {
return;
}
for (const SymbolInstance &symbolInstance : symbolInstances) {
auto populateCollisionBox = [&](const auto& feature) {
SymbolBucket::CollisionBuffer& collisionBuffer = feature.alongLine ?
static_cast<SymbolBucket::CollisionBuffer&>(bucket.getOrCreateCollisionCircleBuffer()) :
static_cast<SymbolBucket::CollisionBuffer&>(bucket.getOrCreateCollisionBox());
for (const CollisionBox &box : feature.boxes) {
for (const SymbolInstance& symbolInstance : symbolInstances) {
auto populateCollisionBox = [&](const auto& feature, bool isText) {
SymbolBucket::CollisionBuffer& collisionBuffer =
feature.alongLine ? (isText ? static_cast<SymbolBucket::CollisionBuffer&>(bucket.getOrCreateTextCollisionCircleBuffer())
: static_cast<SymbolBucket::CollisionBuffer&>(bucket.getOrCreateIconCollisionCircleBuffer()))
: (isText ? static_cast<SymbolBucket::CollisionBuffer&>(bucket.getOrCreateTextCollisionBox())
: static_cast<SymbolBucket::CollisionBuffer&>(bucket.getOrCreateIconCollisionBox()));
for (const CollisionBox& box : feature.boxes) {
auto& anchor = box.anchor;
Point<float> tl{box.x1, box.y1};
@@ -829,8 +832,11 @@ void SymbolLayout::addToDebugBuffers(SymbolBucket& bucket) {
const std::size_t indexLength = feature.alongLine ? 6 : 8;
if (collisionBuffer.segments.empty() || collisionBuffer.segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) {
collisionBuffer.segments.emplace_back(collisionBuffer.vertices.elements(),
feature.alongLine ? bucket.collisionCircle->triangles.elements() : bucket.collisionBox->lines.elements());
collisionBuffer.segments.emplace_back(
collisionBuffer.vertices.elements(),
feature.alongLine
? (isText ? bucket.textCollisionCircle->triangles.elements() : bucket.iconCollisionCircle->triangles.elements())
: (isText ? bucket.textCollisionBox->lines.elements() : bucket.iconCollisionBox->lines.elements()));
}
auto& segment = collisionBuffer.segments.back();
@@ -850,27 +856,29 @@ void SymbolLayout::addToDebugBuffers(SymbolBucket& bucket) {
collisionBuffer.dynamicVertices.emplace_back(dynamicVertex);
if (feature.alongLine) {
bucket.collisionCircle->triangles.emplace_back(index, index + 1, index + 2);
bucket.collisionCircle->triangles.emplace_back(index, index + 2, index + 3);
auto& collisionCircle = (isText ? bucket.textCollisionCircle : bucket.iconCollisionCircle);
collisionCircle->triangles.emplace_back(index, index + 1, index + 2);
collisionCircle->triangles.emplace_back(index, index + 2, index + 3);
} else {
bucket.collisionBox->lines.emplace_back(index + 0, index + 1);
bucket.collisionBox->lines.emplace_back(index + 1, index + 2);
bucket.collisionBox->lines.emplace_back(index + 2, index + 3);
bucket.collisionBox->lines.emplace_back(index + 3, index + 0);
auto& collisionBox = (isText ? bucket.textCollisionBox : bucket.iconCollisionBox);
collisionBox->lines.emplace_back(index + 0, index + 1);
collisionBox->lines.emplace_back(index + 1, index + 2);
collisionBox->lines.emplace_back(index + 2, index + 3);
collisionBox->lines.emplace_back(index + 3, index + 0);
}
segment.vertexLength += vertexLength;
segment.indexLength += indexLength;
}
};
populateCollisionBox(symbolInstance.textCollisionFeature);
populateCollisionBox(symbolInstance.textCollisionFeature, true /*isText*/);
if (symbolInstance.verticalTextCollisionFeature) {
populateCollisionBox(*symbolInstance.verticalTextCollisionFeature);
populateCollisionBox(*symbolInstance.verticalTextCollisionFeature, true /*isText*/);
}
if (symbolInstance.verticalIconCollisionFeature) {
populateCollisionBox(*symbolInstance.verticalIconCollisionFeature);
populateCollisionBox(*symbolInstance.verticalIconCollisionFeature, false /*isText*/);
}
populateCollisionBox(symbolInstance.iconCollisionFeature);
populateCollisionBox(symbolInstance.iconCollisionFeature, false /*isText*/);
}
}

View File

@@ -113,37 +113,50 @@ void SymbolBucket::upload(gfx::UploadPass& uploadPass) {
if (hasIconData()) {
updateIconBuffer(icon);
}
if (hasSdfIconData()) {
updateIconBuffer(sdfIcon);
}
if (hasCollisionBoxData()) {
const auto updateCollisionBox = [&](CollisionBoxBuffer& collisionBox) {
if (!staticUploaded) {
collisionBox->indexBuffer = uploadPass.createIndexBuffer(std::move(collisionBox->lines));
collisionBox->vertexBuffer = uploadPass.createVertexBuffer(std::move(collisionBox->vertices));
collisionBox.indexBuffer = uploadPass.createIndexBuffer(std::move(collisionBox.lines));
collisionBox.vertexBuffer = uploadPass.createVertexBuffer(std::move(collisionBox.vertices));
}
if (!placementChangesUploaded) {
if (!collisionBox->dynamicVertexBuffer) {
collisionBox->dynamicVertexBuffer = uploadPass.createVertexBuffer(std::move(collisionBox->dynamicVertices), gfx::BufferUsageType::StreamDraw);
if (!collisionBox.dynamicVertexBuffer) {
collisionBox.dynamicVertexBuffer = uploadPass.createVertexBuffer(std::move(collisionBox.dynamicVertices), gfx::BufferUsageType::StreamDraw);
} else {
uploadPass.updateVertexBuffer(*collisionBox->dynamicVertexBuffer, std::move(collisionBox->dynamicVertices));
uploadPass.updateVertexBuffer(*collisionBox.dynamicVertexBuffer, std::move(collisionBox.dynamicVertices));
}
}
};
if (hasIconCollisionBoxData()) {
updateCollisionBox(*iconCollisionBox);
}
if (hasCollisionCircleData()) {
if (hasTextCollisionBoxData()) {
updateCollisionBox(*textCollisionBox);
}
const auto updateCollisionCircle = [&](CollisionCircleBuffer& collisionCircle) {
if (!staticUploaded) {
collisionCircle->indexBuffer = uploadPass.createIndexBuffer(std::move(collisionCircle->triangles));
collisionCircle->vertexBuffer = uploadPass.createVertexBuffer(std::move(collisionCircle->vertices));
collisionCircle.indexBuffer = uploadPass.createIndexBuffer(std::move(collisionCircle.triangles));
collisionCircle.vertexBuffer = uploadPass.createVertexBuffer(std::move(collisionCircle.vertices));
}
if (!placementChangesUploaded) {
if (!collisionCircle->dynamicVertexBuffer) {
collisionCircle->dynamicVertexBuffer = uploadPass.createVertexBuffer(std::move(collisionCircle->dynamicVertices), gfx::BufferUsageType::StreamDraw);
if (!collisionCircle.dynamicVertexBuffer) {
collisionCircle.dynamicVertexBuffer = uploadPass.createVertexBuffer(std::move(collisionCircle.dynamicVertices), gfx::BufferUsageType::StreamDraw);
} else {
uploadPass.updateVertexBuffer(*collisionCircle->dynamicVertexBuffer, std::move(collisionCircle->dynamicVertices));
uploadPass.updateVertexBuffer(*collisionCircle.dynamicVertexBuffer, std::move(collisionCircle.dynamicVertices));
}
}
};
if (hasIconCollisionCircleData()) {
updateCollisionCircle(*iconCollisionCircle);
}
if (hasTextCollisionCircleData()) {
updateCollisionCircle(*textCollisionCircle);
}
uploaded = true;
@@ -154,7 +167,8 @@ void SymbolBucket::upload(gfx::UploadPass& uploadPass) {
}
bool SymbolBucket::hasData() const {
return hasTextData() || hasIconData() || hasSdfIconData() || hasCollisionBoxData();
return hasTextData() || hasIconData() || hasSdfIconData() || hasIconCollisionBoxData() ||
hasTextCollisionBoxData() || hasIconCollisionCircleData() || hasTextCollisionCircleData();
}
bool SymbolBucket::hasTextData() const {
@@ -169,12 +183,20 @@ bool SymbolBucket::hasSdfIconData() const {
return !sdfIcon.segments.empty();
}
bool SymbolBucket::hasCollisionBoxData() const {
return collisionBox && !collisionBox->segments.empty();
bool SymbolBucket::hasIconCollisionBoxData() const {
return iconCollisionBox && !iconCollisionBox->segments.empty();
}
bool SymbolBucket::hasCollisionCircleData() const {
return collisionCircle && !collisionCircle->segments.empty();
bool SymbolBucket::hasIconCollisionCircleData() const {
return iconCollisionCircle && !iconCollisionCircle->segments.empty();
}
bool SymbolBucket::hasTextCollisionBoxData() const {
return textCollisionBox && !textCollisionBox->segments.empty();
}
bool SymbolBucket::hasTextCollisionCircleData() const {
return textCollisionCircle && !textCollisionCircle->segments.empty();
}
void addPlacedSymbol(gfx::IndexVector<gfx::Triangles>& triangles, const PlacedSymbol& placedSymbol) {

View File

@@ -72,8 +72,10 @@ public:
bool hasTextData() const;
bool hasIconData() const;
bool hasSdfIconData() const;
bool hasCollisionBoxData() const;
bool hasCollisionCircleData() const;
bool hasIconCollisionBoxData() const;
bool hasIconCollisionCircleData() const;
bool hasTextCollisionBoxData() const;
bool hasTextCollisionCircleData() const;
bool hasFormatSectionOverrides() const;
@@ -138,22 +140,34 @@ public:
gfx::IndexVector<gfx::Lines> lines;
optional<gfx::IndexBuffer> indexBuffer;
};
std::unique_ptr<CollisionBoxBuffer> collisionBox;
std::unique_ptr<CollisionBoxBuffer> iconCollisionBox;
std::unique_ptr<CollisionBoxBuffer> textCollisionBox;
CollisionBoxBuffer& getOrCreateCollisionBox() {
if (!collisionBox) collisionBox = std::make_unique<CollisionBoxBuffer>();
return *collisionBox;
CollisionBoxBuffer& getOrCreateIconCollisionBox() {
if (!iconCollisionBox) iconCollisionBox = std::make_unique<CollisionBoxBuffer>();
return *iconCollisionBox;
}
CollisionBoxBuffer& getOrCreateTextCollisionBox() {
if (!textCollisionBox) textCollisionBox = std::make_unique<CollisionBoxBuffer>();
return *textCollisionBox;
}
struct CollisionCircleBuffer : public CollisionBuffer {
gfx::IndexVector<gfx::Triangles> triangles;
optional<gfx::IndexBuffer> indexBuffer;
};
std::unique_ptr<CollisionCircleBuffer> collisionCircle;
std::unique_ptr<CollisionCircleBuffer> iconCollisionCircle;
std::unique_ptr<CollisionCircleBuffer> textCollisionCircle;
CollisionCircleBuffer& getOrCreateCollisionCircleBuffer() {
if (!collisionCircle) collisionCircle = std::make_unique<CollisionCircleBuffer>();
return *collisionCircle;
CollisionCircleBuffer& getOrCreateIconCollisionCircleBuffer() {
if (!iconCollisionCircle) iconCollisionCircle = std::make_unique<CollisionCircleBuffer>();
return *iconCollisionCircle;
}
CollisionCircleBuffer& getOrCreateTextCollisionCircleBuffer() {
if (!textCollisionCircle) textCollisionCircle = std::make_unique<CollisionCircleBuffer>();
return *textCollisionCircle;
}
const float tilePixelRatio;

View File

@@ -392,10 +392,11 @@ void RenderSymbolLayer::render(PaintParameters& parameters) {
}
}
if (bucket.hasCollisionBoxData()) {
static const style::Properties<>::PossiblyEvaluated properties {};
static const CollisionBoxProgram::Binders paintAttributeData(properties, 0);
const auto drawCollisonData = [&](const bool isText, const bool hasCollisionBox, const bool hasCollisionCircle) {
if (!hasCollisionBox && !hasCollisionCircle) return;
static const style::Properties<>::PossiblyEvaluated properties{};
static const CollisionBoxProgram::Binders paintAttributeData(properties, 0);
auto pixelRatio = tile.id.pixelsToTileUnits(1, parameters.state.getZoom());
const float scale = std::pow(2, parameters.state.getZoom() - tile.getOverscaledTileID().overscaledZ);
std::array<float,2> extrudeScale =
@@ -403,68 +404,69 @@ void RenderSymbolLayer::render(PaintParameters& parameters) {
parameters.pixelsToGLUnits[0] / (pixelRatio * scale),
parameters.pixelsToGLUnits[1] / (pixelRatio * scale)
}};
parameters.programs.getSymbolLayerPrograms().collisionBox.draw(
parameters.context,
*parameters.renderPass,
gfx::Lines { 1.0f },
gfx::DepthMode::disabled(),
gfx::StencilMode::disabled(),
parameters.colorModeForRenderPass(),
gfx::CullFaceMode::disabled(),
CollisionBoxProgram::LayoutUniformValues {
uniforms::matrix::Value( tile.matrix ),
uniforms::extrude_scale::Value( extrudeScale ),
uniforms::camera_to_center_distance::Value( parameters.state.getCameraToCenterDistance() )
},
*bucket.collisionBox->vertexBuffer,
*bucket.collisionBox->dynamicVertexBuffer,
*bucket.collisionBox->indexBuffer,
bucket.collisionBox->segments,
paintAttributeData,
properties,
CollisionBoxProgram::TextureBindings{},
parameters.state.getZoom(),
getID()
);
}
const auto& evaluated = getEvaluated<SymbolLayerProperties>(renderData->layerProperties);
const auto& layout = *bucket.layout;
const auto values = isText ? textPropertyValues(evaluated, layout): iconPropertyValues(evaluated, layout);
const bool needTranslate = values.translate[0] != 0 || values.translate[1] != 0;
if (bucket.hasCollisionCircleData()) {
static const style::Properties<>::PossiblyEvaluated properties {};
static const CollisionBoxProgram::Binders paintAttributeData(properties, 0);
auto pixelRatio = tile.id.pixelsToTileUnits(1, parameters.state.getZoom());
const float scale = std::pow(2, parameters.state.getZoom() - tile.getOverscaledTileID().overscaledZ);
std::array<float,2> extrudeScale =
{{
parameters.pixelsToGLUnits[0] / (pixelRatio * scale),
parameters.pixelsToGLUnits[1] / (pixelRatio * scale)
}};
parameters.programs.getSymbolLayerPrograms().collisionCircle.draw(
parameters.context,
*parameters.renderPass,
gfx::Triangles(),
gfx::DepthMode::disabled(),
gfx::StencilMode::disabled(),
parameters.colorModeForRenderPass(),
gfx::CullFaceMode::disabled(),
CollisionCircleProgram::LayoutUniformValues {
uniforms::matrix::Value( tile.matrix ),
uniforms::extrude_scale::Value( extrudeScale ),
uniforms::overscale_factor::Value( float(tile.getOverscaledTileID().overscaleFactor()) ),
uniforms::camera_to_center_distance::Value( parameters.state.getCameraToCenterDistance() )
},
*bucket.collisionCircle->vertexBuffer,
*bucket.collisionCircle->dynamicVertexBuffer,
*bucket.collisionCircle->indexBuffer,
bucket.collisionCircle->segments,
paintAttributeData,
properties,
CollisionCircleProgram::TextureBindings{},
parameters.state.getZoom(),
getID()
);
}
if (hasCollisionBox) {
const auto& collisionBox = isText ? bucket.textCollisionBox : bucket.iconCollisionBox;
parameters.programs.getSymbolLayerPrograms().collisionBox.draw(
parameters.context,
*parameters.renderPass,
gfx::Lines{ 1.0f },
gfx::DepthMode::disabled(),
gfx::StencilMode::disabled(),
parameters.colorModeForRenderPass(),
gfx::CullFaceMode::disabled(),
CollisionBoxProgram::LayoutUniformValues {
uniforms::matrix::Value((needTranslate
? tile.translatedMatrix(values.translate, values.translateAnchor, parameters.state)
: tile.matrix)),
uniforms::extrude_scale::Value(extrudeScale),
uniforms::camera_to_center_distance::Value(parameters.state.getCameraToCenterDistance())
},
*collisionBox->vertexBuffer,
*collisionBox->dynamicVertexBuffer,
*collisionBox->indexBuffer,
collisionBox->segments,
paintAttributeData,
properties,
CollisionBoxProgram::TextureBindings{},
parameters.state.getZoom(),
getID());
}
if (hasCollisionCircle) {
const auto& collisionCircle = isText ? bucket.textCollisionCircle : bucket.iconCollisionCircle;
parameters.programs.getSymbolLayerPrograms().collisionCircle.draw(
parameters.context,
*parameters.renderPass,
gfx::Triangles(),
gfx::DepthMode::disabled(),
gfx::StencilMode::disabled(),
parameters.colorModeForRenderPass(),
gfx::CullFaceMode::disabled(),
CollisionCircleProgram::LayoutUniformValues {
uniforms::matrix::Value((needTranslate
? tile.translatedMatrix(values.translate, values.translateAnchor, parameters.state)
: tile.matrix)),
uniforms::extrude_scale::Value(extrudeScale),
uniforms::overscale_factor::Value(float(tile.getOverscaledTileID().overscaleFactor())),
uniforms::camera_to_center_distance::Value(parameters.state.getCameraToCenterDistance())
},
*collisionCircle->vertexBuffer,
*collisionCircle->dynamicVertexBuffer,
*collisionCircle->indexBuffer,
collisionCircle->segments,
paintAttributeData,
properties,
CollisionCircleProgram::TextureBindings{},
parameters.state.getZoom(),
getID());
}
};
drawCollisonData(false /*isText*/, bucket.hasIconCollisionBoxData(), bucket.hasIconCollisionCircleData());
drawCollisonData(true /*isText*/, bucket.hasTextCollisionBoxData(), bucket.hasTextCollisionCircleData());
}
if (sortFeaturesByKey) {

View File

@@ -159,7 +159,6 @@ void Placement::placeBucket(
const bool rotateWithMap = layout.get<style::TextRotationAlignment>() == style::AlignmentType::Map;
const bool pitchWithMap = layout.get<style::TextPitchAlignment>() == style::AlignmentType::Map;
const bool hasIconTextFit = layout.get<style::IconTextFit>() != style::IconTextFitType::None;
const bool hasCollisionCircleData = bucket.hasCollisionCircleData();
const bool zOrderByViewportY = layout.get<style::SymbolZOrder>() == style::SymbolZOrderType::ViewportY;
std::vector<ProjectedCollisionBox> textBoxes;
@@ -418,13 +417,14 @@ void Placement::placeBucket(
}
}
if (hasCollisionCircleData) {
if (symbolInstance.iconCollisionFeature.alongLine && !iconBoxes.empty()) {
collisionCircles[&symbolInstance.iconCollisionFeature] = iconBoxes;
}
if (symbolInstance.textCollisionFeature.alongLine && !textBoxes.empty()) {
collisionCircles[&symbolInstance.textCollisionFeature] = textBoxes;
}
const bool hasIconCollisionCircleData = bucket.hasIconCollisionCircleData();
const bool hasTextCollisionCircleData = bucket.hasTextCollisionCircleData();
if (hasIconCollisionCircleData && symbolInstance.iconCollisionFeature.alongLine && !iconBoxes.empty()) {
collisionCircles[&symbolInstance.iconCollisionFeature] = iconBoxes;
}
if (hasTextCollisionCircleData && symbolInstance.textCollisionFeature.alongLine && !textBoxes.empty()) {
collisionCircles[&symbolInstance.textCollisionFeature] = textBoxes;
}
assert(symbolInstance.crossTileID != 0);
@@ -696,8 +696,10 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState
if (bucket.hasTextData()) bucket.text.opacityVertices.clear();
if (bucket.hasIconData()) bucket.icon.opacityVertices.clear();
if (bucket.hasSdfIconData()) bucket.sdfIcon.opacityVertices.clear();
if (bucket.hasCollisionBoxData()) bucket.collisionBox->dynamicVertices.clear();
if (bucket.hasCollisionCircleData()) bucket.collisionCircle->dynamicVertices.clear();
if (bucket.hasIconCollisionBoxData()) bucket.iconCollisionBox->dynamicVertices.clear();
if (bucket.hasIconCollisionCircleData()) bucket.iconCollisionCircle->dynamicVertices.clear();
if (bucket.hasTextCollisionBoxData()) bucket.textCollisionBox->dynamicVertices.clear();
if (bucket.hasTextCollisionCircleData()) bucket.textCollisionCircle->dynamicVertices.clear();
JointOpacityState duplicateOpacityState(false, false, true);
@@ -788,15 +790,15 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState
}
}
auto updateCollisionBox = [&](const auto& feature, const bool placed, const Point<float>& shift) {
auto updateIconCollisionBox = [&](const auto& feature, const bool placed, const Point<float>& shift) {
if (feature.alongLine) {
return;
}
const auto& dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, false, shift);
bucket.collisionBox->dynamicVertices.extend(feature.boxes.size() * 4, dynamicVertex);
bucket.iconCollisionBox->dynamicVertices.extend(feature.boxes.size() * 4, dynamicVertex);
};
auto updateCollisionTextBox = [this, &bucket, &symbolInstance, &state, variablePlacement, rotateWithMap, pitchWithMap](const auto& feature, const bool placed) {
auto updateTextCollisionBox = [this, &bucket, &symbolInstance, &state, variablePlacement, rotateWithMap, pitchWithMap](const auto& feature, const bool placed) {
Point<float> shift{0.0f, 0.0f};
if (feature.alongLine) {
return shift;
@@ -826,11 +828,11 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState
}
}
const auto& dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, !used, shift);
bucket.collisionBox->dynamicVertices.extend(feature.boxes.size() * 4, dynamicVertex);
bucket.textCollisionBox->dynamicVertices.extend(feature.boxes.size() * 4, dynamicVertex);
return shift;
};
auto updateCollisionCircles = [&](const auto& feature, const bool placed) {
auto updateCollisionCircles = [&](const auto& feature, const bool placed, bool isText) {
if (!feature.alongLine) {
return;
}
@@ -838,31 +840,36 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState
if (circles != collisionCircles.end()) {
for (const auto& circle : circles->second) {
const auto& dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, !circle.isCircle(), {});
bucket.collisionCircle->dynamicVertices.extend(4, dynamicVertex);
isText ? bucket.textCollisionCircle->dynamicVertices.extend(4, dynamicVertex):
bucket.iconCollisionCircle->dynamicVertices.extend(4, dynamicVertex);
}
} else {
// This feature was not placed, because it was not loaded or from a fading tile. Apply default values.
static const auto dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, false /*not used*/, {});
bucket.collisionCircle->dynamicVertices.extend(4 * feature.boxes.size(), dynamicVertex);
isText ? bucket.textCollisionCircle->dynamicVertices.extend(4 * feature.boxes.size(), dynamicVertex):
bucket.iconCollisionCircle->dynamicVertices.extend(4 * feature.boxes.size(), dynamicVertex);
}
};
if (bucket.hasCollisionBoxData()) {
const auto& textShift = updateCollisionTextBox(symbolInstance.textCollisionFeature, opacityState.text.placed);
if (bucket.allowVerticalPlacement) {
Point<float> verticalTextShift{0.0f, 0.0f};
if (symbolInstance.verticalTextCollisionFeature) {
verticalTextShift = updateCollisionTextBox(*symbolInstance.verticalTextCollisionFeature, opacityState.text.placed);
}
if (symbolInstance.verticalIconCollisionFeature) {
updateCollisionBox(*symbolInstance.verticalIconCollisionFeature, opacityState.text.placed, hasIconTextFit ? verticalTextShift : Point<float>{0.0f, 0.0f});
}
Point<float> textShift{0.0f, 0.0f};
Point<float> verticalTextShift{0.0f, 0.0f};
if (bucket.hasTextCollisionBoxData()) {
textShift = updateTextCollisionBox(symbolInstance.textCollisionFeature, opacityState.text.placed);
if (bucket.allowVerticalPlacement && symbolInstance.verticalTextCollisionFeature) {
verticalTextShift = updateTextCollisionBox(*symbolInstance.verticalTextCollisionFeature, opacityState.text.placed);
}
updateCollisionBox(symbolInstance.iconCollisionFeature, opacityState.icon.placed, hasIconTextFit ? textShift : Point<float>{0.0f, 0.0f});
}
if (bucket.hasCollisionCircleData()) {
updateCollisionCircles(symbolInstance.textCollisionFeature, opacityState.text.placed);
updateCollisionCircles(symbolInstance.iconCollisionFeature, opacityState.icon.placed);
if (bucket.hasIconCollisionBoxData()) {
updateIconCollisionBox(symbolInstance.iconCollisionFeature, opacityState.icon.placed, hasIconTextFit ? textShift : Point<float>{0.0f, 0.0f});
if (bucket.allowVerticalPlacement && symbolInstance.verticalIconCollisionFeature) {
updateIconCollisionBox(*symbolInstance.verticalIconCollisionFeature, opacityState.text.placed, hasIconTextFit ? verticalTextShift : Point<float>{0.0f, 0.0f});
}
}
if (bucket.hasIconCollisionCircleData()) {
updateCollisionCircles(symbolInstance.iconCollisionFeature, opacityState.icon.placed, false);
}
if (bucket.hasTextCollisionCircleData()) {
updateCollisionCircles(symbolInstance.textCollisionFeature, opacityState.text.placed, true);
}
}

View File

@@ -125,7 +125,10 @@ TEST(Buckets, SymbolBucket) {
ASSERT_FALSE(bucket.hasIconData());
ASSERT_FALSE(bucket.hasSdfIconData());
ASSERT_FALSE(bucket.hasTextData());
ASSERT_FALSE(bucket.hasCollisionBoxData());
ASSERT_FALSE(bucket.hasIconCollisionBoxData());
ASSERT_FALSE(bucket.hasTextCollisionBoxData());
ASSERT_FALSE(bucket.hasIconCollisionCircleData());
ASSERT_FALSE(bucket.hasTextCollisionCircleData());
ASSERT_FALSE(bucket.hasData());
ASSERT_FALSE(bucket.needsUpload());