Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

[core] Enable circle-sort-key property #15875

Merged
merged 5 commits into from
Apr 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@
- `getPlacedSymbolsData()`
if collecting of the placed symbols data is enabled, returns the reference to the `PlacedSymbolData` vector holding the collected data.

- [core] Enable circle-sort-key property [#15875](https://github.com/mapbox/mapbox-gl-native/pull/15875/)

Adds support for `circle-sort-key` property, consistent with `symbol-sort-key`.

Sorts drawing order by sort key both within-tile and cross-tile.

### 🐞 Bug fixes

- [core][tile mode] Reduce cut-off labels (part 2) ([#16369](https://github.com/mapbox/mapbox-gl-native/pull/16369))
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ add_library(
${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/line_layer_factory.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/raster_layer_factory.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/symbol_layer_factory.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/layout/circle_layout.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/layout/clip_lines.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/layout/clip_lines.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/layout/layout.hpp
Expand Down
4 changes: 3 additions & 1 deletion include/mbgl/layermanager/circle_layer_factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ class CircleLayerFactory : public LayerFactory {
protected:
const style::LayerTypeInfo* getTypeInfo() const noexcept final;
std::unique_ptr<style::Layer> createLayer(const std::string& id, const style::conversion::Convertible& value) noexcept final;
std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<Immutable<style::LayerProperties>>&) noexcept final;
std::unique_ptr<Layout> createLayout(const LayoutParameters& parameters,
std::unique_ptr<GeometryTileLayer> tileLayer,
const std::vector<Immutable<style::LayerProperties>>& group) noexcept final;
std::unique_ptr<RenderLayer> createRenderLayer(Immutable<style::Layer::Impl>) noexcept final;
};

Expand Down
6 changes: 6 additions & 0 deletions include/mbgl/style/layers/circle_layer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ class CircleLayer : public Layer {
CircleLayer(const std::string& layerID, const std::string& sourceID);
~CircleLayer() final;

// Layout properties

static PropertyValue<float> getDefaultCircleSortKey();
const PropertyValue<float>& getCircleSortKey() const;
void setCircleSortKey(const PropertyValue<float>&);

// Paint properties

static PropertyValue<float> getDefaultCircleBlur();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"network": [
[
"probeNetwork - default - end",
0,
0
],
[
"probeNetwork - default - start",
0,
0
]
],
"gfx": [
[
"probeGFX - default - end",
4,
9,
13,
1,
[
65552,
65552
],
[
94,
94
],
[
448,
448
]
]
]
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion metrics/ignores/platform-all.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@
"render-tests/background-color/transition": "https://github.com/mapbox/mapbox-gl-native/issues/10619",
"render-tests/canvas/default": "skip - js specific",
"render-tests/canvas/update": "skip - js specific",
"render-tests/circle-sort-key/literal": "https://github.com/mapbox/mapbox-gl-native/issues/15008",
"render-tests/collator/default": "Some test platforms don't resolve 'en' locale",
"render-tests/collator/resolved-locale": "Some test platforms don't resolve 'en' locale",
"render-tests/custom-layer-js/depth": "skip - js specific",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"network": [
[
"probeNetwork - default - end",
0,
0
],
[
"probeNetwork - default - start",
0,
0
]
],
"gfx": [
[
"probeGFX - default - end",
4,
9,
13,
1,
[
65552,
65552
],
[
94,
94
],
[
448,
448
]
]
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"network": [
[
"probeNetwork - default - end",
0,
0
],
[
"probeNetwork - default - start",
0,
0
]
],
"gfx": [
[
"probeGFX - default - end",
4,
9,
13,
1,
[
65552,
65552
],
[
94,
94
],
[
448,
448
]
]
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"network": [
[
"probeNetwork - default - end",
0,
0
],
[
"probeNetwork - default - start",
0,
0
]
],
"gfx": [
[
"probeGFX - default - end",
4,
9,
13,
1,
[
65552,
65552
],
[
94,
94
],
[
448,
448
]
]
]
}
3 changes: 0 additions & 3 deletions scripts/generate-style-code.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ const ejs = require('ejs');
const spec = require('./style-spec');
const colorParser = require('csscolorparser');

// FIXME: https://github.com/mapbox/mapbox-gl-native/issues/15008
delete spec.layout_circle["circle-sort-key"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also remove these lines from the Darwin version of this script:

// FIXME: https://github.com/mapbox/mapbox-gl-native/issues/15008
delete spec.layout_circle["circle-sort-key"]

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future, these properties should be deleted in scripts/style-spec.js instead of both scripts/generate-style-code.js and platform/darwin/scripts/generate-style-code.js. This is the reason for the layout of indirection in scripts/style-spec.js.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that most of platform/darwin/ has been deleted in favor of the sources in the mapbox/mapbox-gl-native-ios repository, mapbox/mapbox-gl-native-ios#272 will take care of deleting the remnants of this override.


require('./style-code');

function parseCSSColor(str) {
Expand Down
8 changes: 6 additions & 2 deletions src/mbgl/layermanager/circle_layer_factory.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <mbgl/layermanager/circle_layer_factory.hpp>

#include <mbgl/layout/circle_layout.hpp>
#include <mbgl/renderer/buckets/circle_bucket.hpp>
#include <mbgl/renderer/layers/render_circle_layer.hpp>
#include <mbgl/style/layers/circle_layer.hpp>
Expand All @@ -20,8 +21,11 @@ std::unique_ptr<style::Layer> CircleLayerFactory::createLayer(const std::string&
return std::unique_ptr<style::Layer>(new style::CircleLayer(id, *source));
}

std::unique_ptr<Bucket> CircleLayerFactory::createBucket(const BucketParameters& parameters, const std::vector<Immutable<style::LayerProperties>>& layers) noexcept {
return std::make_unique<CircleBucket>(parameters, layers);
std::unique_ptr<Layout> CircleLayerFactory::createLayout(
const LayoutParameters& parameters,
std::unique_ptr<GeometryTileLayer> layer,
const std::vector<Immutable<style::LayerProperties>>& group) noexcept {
return std::make_unique<CircleLayout>(parameters.bucketParameters, group, std::move(layer));
}

std::unique_ptr<RenderLayer> CircleLayerFactory::createRenderLayer(Immutable<style::Layer::Impl> impl) noexcept {
Expand Down
161 changes: 161 additions & 0 deletions src/mbgl/layout/circle_layout.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
#pragma once
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/layout/layout.hpp>
#include <mbgl/renderer/bucket_parameters.hpp>
#include <mbgl/renderer/buckets/circle_bucket.hpp>
#include <mbgl/renderer/render_layer.hpp>
#include <mbgl/style/layers/circle_layer_impl.hpp>

namespace mbgl {

class CircleLayout final : public Layout {
public:
CircleLayout(const BucketParameters& parameters,
const std::vector<Immutable<style::LayerProperties>>& group,
std::unique_ptr<GeometryTileLayer> sourceLayer_)
: sourceLayer(std::move(sourceLayer_)), zoom(parameters.tileID.overscaledZ), mode(parameters.mode) {
assert(!group.empty());
auto leaderLayerProperties = staticImmutableCast<style::CircleLayerProperties>(group.front());
const auto& unevaluatedLayout = leaderLayerProperties->layerImpl().layout;
const bool sortFeaturesByKey = !unevaluatedLayout.get<style::CircleSortKey>().isUndefined();
const auto& layout = unevaluatedLayout.evaluate(PropertyEvaluationParameters(zoom));
sourceLayerID = leaderLayerProperties->layerImpl().sourceLayer;
bucketLeaderID = leaderLayerProperties->layerImpl().id;

for (const auto& layerProperties : group) {
const std::string& layerId = layerProperties->baseImpl->id;
layerPropertiesMap.emplace(layerId, layerProperties);
}

const size_t featureCount = sourceLayer->featureCount();
for (size_t i = 0; i < featureCount; ++i) {
auto feature = sourceLayer->getFeature(i);
if (!leaderLayerProperties->layerImpl().filter(style::expression::EvaluationContext(zoom, feature.get())
.withCanonicalTileID(&parameters.tileID.canonical))) {
continue;
}

if (!sortFeaturesByKey) {
features.push_back({i, std::move(feature), style::CircleSortKey::defaultValue()});
continue;
}

const auto& sortKeyProperty = layout.template get<style::CircleSortKey>();
float sortKey = sortKeyProperty.evaluate(*feature, zoom, style::CircleSortKey::defaultValue());
CircleFeature circleFeature{i, std::move(feature), sortKey};
const auto sortPosition = std::lower_bound(features.cbegin(), features.cend(), circleFeature);
features.insert(sortPosition, std::move(circleFeature));
}
}

bool hasDependencies() const override { return false; }

void createBucket(const ImagePositions&,
std::unique_ptr<FeatureIndex>& featureIndex,
std::unordered_map<std::string, LayerRenderData>& renderData,
const bool,
const bool,
const CanonicalTileID& canonical) override {
auto bucket = std::make_shared<CircleBucket>(layerPropertiesMap, mode, zoom);

for (auto& circleFeature : features) {
const auto i = circleFeature.i;
const std::unique_ptr<GeometryTileFeature>& feature = circleFeature.feature;
const GeometryCollection& geometries = feature->getGeometries();

addCircle(*bucket, *feature, geometries, i, circleFeature.sortKey, canonical);

bucket->addFeature(*feature, geometries, {}, PatternLayerMap(), i, canonical);
featureIndex->insert(geometries, i, sourceLayerID, bucketLeaderID);
}

if (!bucket->hasData()) return;

for (const auto& pair : layerPropertiesMap) {
renderData.emplace(pair.first, LayerRenderData{bucket, pair.second});
}
}

private:
struct CircleFeature {
friend bool operator<(const CircleFeature& lhs, const CircleFeature& rhs) { return lhs.sortKey < rhs.sortKey; }

size_t i;
std::unique_ptr<GeometryTileFeature> feature;
float sortKey;
};

void addCircle(CircleBucket& bucket,
const GeometryTileFeature& feature,
const GeometryCollection& geometry,
std::size_t featureIndex,
float sortKey,
const CanonicalTileID& canonical) {
constexpr const uint16_t vertexLength = 4;

auto& segments = bucket.segments;
auto& vertices = bucket.vertices;
auto& triangles = bucket.triangles;

for (auto& circle : geometry) {
for (auto& point : circle) {
auto x = point.x;
auto y = point.y;

// Do not include points that are outside the tile boundaries.
// Include all points in Still mode. You need to include points from
// neighbouring tiles so that they are not clipped at tile boundaries.
if ((mode == MapMode::Continuous) && (x < 0 || x >= util::EXTENT || y < 0 || y >= util::EXTENT))
continue;

if (segments.empty() ||
segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) {
// Move to a new segments because the old one can't hold the geometry.
segments.emplace_back(vertices.elements(), triangles.elements(), 0ul, 0ul, sortKey);
}

// this geometry will be of the Point type, and we'll derive
// two triangles from it.
//
// ┌─────────┐
// │ 4 3 │
// │ │
// │ 1 2 │
// └─────────┘
//
vertices.emplace_back(CircleProgram::vertex(point, -1, -1)); // 1
vertices.emplace_back(CircleProgram::vertex(point, 1, -1)); // 2
vertices.emplace_back(CircleProgram::vertex(point, 1, 1)); // 3
vertices.emplace_back(CircleProgram::vertex(point, -1, 1)); // 4

auto& segment = segments.back();
assert(segment.vertexLength <= std::numeric_limits<uint16_t>::max());
uint16_t index = segment.vertexLength;

// 1, 2, 3
// 1, 4, 3
triangles.emplace_back(index, index + 1, index + 2);
triangles.emplace_back(index, index + 3, index + 2);

segment.vertexLength += vertexLength;
segment.indexLength += 6;
}
}

for (auto& pair : bucket.paintPropertyBinders) {
pair.second.populateVertexVectors(feature, vertices.elements(), featureIndex, {}, {}, canonical);
}
}

std::map<std::string, Immutable<style::LayerProperties>> layerPropertiesMap;
std::string bucketLeaderID;

const std::unique_ptr<GeometryTileLayer> sourceLayer;
std::list<CircleFeature> features;
pozdnyakov marked this conversation as resolved.
Show resolved Hide resolved

const float zoom;
const MapMode mode;
std::string sourceLayerID;
};

} // namespace mbgl
Loading