summaryrefslogtreecommitdiff
path: root/src/mbgl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl')
-rw-r--r--src/mbgl/layout/layout.hpp3
-rw-r--r--src/mbgl/layout/pattern_layout.hpp9
-rw-r--r--src/mbgl/layout/symbol_feature.hpp14
-rw-r--r--src/mbgl/layout/symbol_layout.cpp69
-rw-r--r--src/mbgl/layout/symbol_layout.hpp11
-rw-r--r--src/mbgl/renderer/bucket.hpp8
-rw-r--r--src/mbgl/renderer/buckets/circle_bucket.cpp10
-rw-r--r--src/mbgl/renderer/buckets/circle_bucket.hpp8
-rw-r--r--src/mbgl/renderer/buckets/fill_bucket.cpp14
-rw-r--r--src/mbgl/renderer/buckets/fill_bucket.hpp8
-rw-r--r--src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp14
-rw-r--r--src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp8
-rw-r--r--src/mbgl/renderer/buckets/heatmap_bucket.cpp10
-rw-r--r--src/mbgl/renderer/buckets/heatmap_bucket.hpp8
-rw-r--r--src/mbgl/renderer/buckets/line_bucket.cpp14
-rw-r--r--src/mbgl/renderer/buckets/line_bucket.hpp8
-rw-r--r--src/mbgl/renderer/paint_property_binder.hpp70
-rw-r--r--src/mbgl/style/expression/is_constant.cpp4
-rw-r--r--src/mbgl/style/expression/parsing_context.cpp2
-rw-r--r--src/mbgl/style/expression/within.cpp139
-rw-r--r--src/mbgl/style/properties.hpp5
-rw-r--r--src/mbgl/tile/geometry_tile_data.cpp2
-rw-r--r--src/mbgl/tile/geometry_tile_data.hpp2
-rw-r--r--src/mbgl/tile/geometry_tile_worker.cpp7
24 files changed, 367 insertions, 80 deletions
diff --git a/src/mbgl/layout/layout.hpp b/src/mbgl/layout/layout.hpp
index 4e7c0c7aca..ae0eb5d5f3 100644
--- a/src/mbgl/layout/layout.hpp
+++ b/src/mbgl/layout/layout.hpp
@@ -21,7 +21,8 @@ public:
std::unique_ptr<FeatureIndex>&,
std::unordered_map<std::string, LayerRenderData>&,
const bool,
- const bool) = 0;
+ const bool,
+ const CanonicalTileID&) = 0;
virtual void prepareSymbols(const GlyphMap&, const GlyphPositions&, const ImageMap&, const ImagePositions&){};
diff --git a/src/mbgl/layout/pattern_layout.hpp b/src/mbgl/layout/pattern_layout.hpp
index 44729dea83..c6815e4cad 100644
--- a/src/mbgl/layout/pattern_layout.hpp
+++ b/src/mbgl/layout/pattern_layout.hpp
@@ -152,7 +152,12 @@ public:
return hasPattern;
}
- void createBucket(const ImagePositions& patternPositions, std::unique_ptr<FeatureIndex>& featureIndex, std::unordered_map<std::string, LayerRenderData>& renderData, const bool, const bool) override {
+ void createBucket(const ImagePositions& patternPositions,
+ 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<BucketType>(layout, layerPropertiesMap, zoom, overscaling);
for (auto & patternFeature : features) {
const auto i = patternFeature.i;
@@ -160,7 +165,7 @@ public:
const PatternLayerMap& patterns = patternFeature.patterns;
const GeometryCollection& geometries = feature->getGeometries();
- bucket->addFeature(*feature, geometries, patternPositions, patterns, i);
+ bucket->addFeature(*feature, geometries, patternPositions, patterns, i, canonical);
featureIndex->insert(geometries, i, sourceLayerID, bucketLeaderID);
}
if (bucket->hasData()) {
diff --git a/src/mbgl/layout/symbol_feature.hpp b/src/mbgl/layout/symbol_feature.hpp
index d0aced1b19..f536642709 100644
--- a/src/mbgl/layout/symbol_feature.hpp
+++ b/src/mbgl/layout/symbol_feature.hpp
@@ -12,16 +12,16 @@ namespace mbgl {
class SymbolFeature : public GeometryTileFeature {
public:
- SymbolFeature(std::unique_ptr<GeometryTileFeature> feature_) :
- feature(std::move(feature_)),
- geometry(feature->getGeometries().clone()) // we need a mutable copy of the geometry for mergeLines()
+ SymbolFeature(std::unique_ptr<GeometryTileFeature> feature_)
+ : feature(std::move(feature_)),
+ geometry(feature->getGeometries().clone()) // we need a mutable copy of the geometry for mergeLines()
{}
-
+
FeatureType getType() const override { return feature->getType(); }
- optional<Value> getValue(const std::string& key) const override { return feature->getValue(key); };
- const PropertyMap& getProperties() const override { return feature->getProperties(); };
+ optional<Value> getValue(const std::string& key) const override { return feature->getValue(key); }
+ const PropertyMap& getProperties() const override { return feature->getProperties(); }
FeatureIdentifier getID() const override { return feature->getID(); };
- const GeometryCollection& getGeometries() const override { return geometry; };
+ const GeometryCollection& getGeometries() const override { return feature->getGeometries(); }
friend bool operator < (const SymbolFeature& lhs, const SymbolFeature& rhs) {
return lhs.sortKey < rhs.sortKey;
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp
index 61c3b4ad66..a4890c85d1 100644
--- a/src/mbgl/layout/symbol_layout.cpp
+++ b/src/mbgl/layout/symbol_layout.cpp
@@ -742,7 +742,12 @@ std::vector<float> SymbolLayout::calculateTileDistances(const GeometryCoordinate
return tileDistances;
}
-void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr<FeatureIndex>&, std::unordered_map<std::string, LayerRenderData>& renderData, const bool firstLoad, const bool showCollisionBoxes) {
+void SymbolLayout::createBucket(const ImagePositions&,
+ std::unique_ptr<FeatureIndex>&,
+ std::unordered_map<std::string, LayerRenderData>& renderData,
+ const bool firstLoad,
+ const bool showCollisionBoxes,
+ const CanonicalTileID& canonical) {
auto bucket = std::make_shared<SymbolBucket>(layout,
layerPaintProperties,
textSize,
@@ -796,8 +801,8 @@ void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr<FeatureIn
}
for (auto& pair : bucket->paintProperties) {
- pair.second.iconBinders.populateVertexVectors(feature, iconBuffer.vertices.elements(),
- symbolInstance.dataFeatureIndex, {}, {});
+ pair.second.iconBinders.populateVertexVectors(
+ feature, iconBuffer.vertices.elements(), symbolInstance.dataFeatureIndex, {}, {}, canonical);
}
}
@@ -805,26 +810,61 @@ void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr<FeatureIn
optional<std::size_t> lastAddedSection;
if (singleLine) {
optional<std::size_t> placedTextIndex;
- lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, placedTextIndex, symbolInstance.rightJustifiedGlyphQuads(), lastAddedSection);
+ lastAddedSection = addSymbolGlyphQuads(*bucket,
+ symbolInstance,
+ feature,
+ symbolInstance.writingModes,
+ placedTextIndex,
+ symbolInstance.rightJustifiedGlyphQuads(),
+ canonical,
+ lastAddedSection);
symbolInstance.placedRightTextIndex = placedTextIndex;
symbolInstance.placedCenterTextIndex = placedTextIndex;
symbolInstance.placedLeftTextIndex = placedTextIndex;
} else {
if (symbolInstance.rightJustifiedGlyphQuadsSize) {
- lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedRightTextIndex, symbolInstance.rightJustifiedGlyphQuads(), lastAddedSection);
+ lastAddedSection = addSymbolGlyphQuads(*bucket,
+ symbolInstance,
+ feature,
+ symbolInstance.writingModes,
+ symbolInstance.placedRightTextIndex,
+ symbolInstance.rightJustifiedGlyphQuads(),
+ canonical,
+ lastAddedSection);
}
if (symbolInstance.centerJustifiedGlyphQuadsSize) {
- lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedCenterTextIndex, symbolInstance.centerJustifiedGlyphQuads(), lastAddedSection);
+ lastAddedSection = addSymbolGlyphQuads(*bucket,
+ symbolInstance,
+ feature,
+ symbolInstance.writingModes,
+ symbolInstance.placedCenterTextIndex,
+ symbolInstance.centerJustifiedGlyphQuads(),
+ canonical,
+ lastAddedSection);
}
if (symbolInstance.leftJustifiedGlyphQuadsSize) {
- lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedLeftTextIndex, symbolInstance.leftJustifiedGlyphQuads(), lastAddedSection);
+ lastAddedSection = addSymbolGlyphQuads(*bucket,
+ symbolInstance,
+ feature,
+ symbolInstance.writingModes,
+ symbolInstance.placedLeftTextIndex,
+ symbolInstance.leftJustifiedGlyphQuads(),
+ canonical,
+ lastAddedSection);
}
}
if (symbolInstance.writingModes & WritingModeType::Vertical && symbolInstance.verticalGlyphQuadsSize) {
- lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, WritingModeType::Vertical, symbolInstance.placedVerticalTextIndex, symbolInstance.verticalGlyphQuads(), lastAddedSection);
+ lastAddedSection = addSymbolGlyphQuads(*bucket,
+ symbolInstance,
+ feature,
+ WritingModeType::Vertical,
+ symbolInstance.placedVerticalTextIndex,
+ symbolInstance.verticalGlyphQuads(),
+ canonical,
+ lastAddedSection);
}
assert(lastAddedSection); // True, as hasText == true;
- updatePaintPropertiesForSection(*bucket, feature, *lastAddedSection);
+ updatePaintPropertiesForSection(*bucket, feature, *lastAddedSection, canonical);
}
symbolInstance.releaseSharedData();
@@ -841,16 +881,16 @@ void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr<FeatureIn
renderData.emplace(pair.first, LayerRenderData{bucket, pair.second});
}
}
-
}
void SymbolLayout::updatePaintPropertiesForSection(SymbolBucket& bucket,
const SymbolFeature& feature,
- std::size_t sectionIndex) {
+ std::size_t sectionIndex,
+ const CanonicalTileID& canonical) {
const auto& formattedSection = sectionOptionsToValue((*feature.formattedText).sectionAt(sectionIndex));
for (auto& pair : bucket.paintProperties) {
- pair.second.textBinders.populateVertexVectors(feature, bucket.text.vertices.elements(), feature.index, {}, {},
- formattedSection);
+ pair.second.textBinders.populateVertexVectors(
+ feature, bucket.text.vertices.elements(), feature.index, {}, {}, canonical, formattedSection);
}
}
@@ -860,6 +900,7 @@ std::size_t SymbolLayout::addSymbolGlyphQuads(SymbolBucket& bucket,
WritingModeType writingMode,
optional<size_t>& placedIndex,
const SymbolQuads& glyphQuads,
+ const CanonicalTileID& canonical,
optional<std::size_t> lastAddedSection) {
const Range<float> sizeData = bucket.textSizeBinder->getVertexSizeData(feature);
const bool hasFormatSectionOverrides = bucket.hasFormatSectionOverrides();
@@ -881,7 +922,7 @@ std::size_t SymbolLayout::addSymbolGlyphQuads(SymbolBucket& bucket,
for (const auto& symbolQuad : glyphQuads) {
if (hasFormatSectionOverrides) {
if (lastAddedSection && *lastAddedSection != symbolQuad.sectionIndex) {
- updatePaintPropertiesForSection(bucket, feature, *lastAddedSection);
+ updatePaintPropertiesForSection(bucket, feature, *lastAddedSection, canonical);
}
lastAddedSection = symbolQuad.sectionIndex;
}
diff --git a/src/mbgl/layout/symbol_layout.hpp b/src/mbgl/layout/symbol_layout.hpp
index 52c912c8ae..740a69df9e 100644
--- a/src/mbgl/layout/symbol_layout.hpp
+++ b/src/mbgl/layout/symbol_layout.hpp
@@ -36,7 +36,12 @@ public:
const ImageMap&,
const ImagePositions&) override;
- void createBucket(const ImagePositions&, std::unique_ptr<FeatureIndex>&, std::unordered_map<std::string, LayerRenderData>&, const bool firstLoad, const bool showCollisionBoxes) override;
+ void createBucket(const ImagePositions&,
+ std::unique_ptr<FeatureIndex>&,
+ std::unordered_map<std::string, LayerRenderData>&,
+ const bool firstLoad,
+ const bool showCollisionBoxes,
+ const CanonicalTileID& canonical) override;
bool hasSymbolInstances() const override;
bool hasDependencies() const override;
@@ -97,11 +102,13 @@ private:
WritingModeType,
optional<size_t>& placedIndex,
const SymbolQuads&,
+ const CanonicalTileID& canonical,
optional<std::size_t> lastAddedSection = nullopt);
void updatePaintPropertiesForSection(SymbolBucket&,
const SymbolFeature&,
- std::size_t sectionIndex);
+ std::size_t sectionIndex,
+ const CanonicalTileID& canonical);
// Stores the layer so that we can hold on to GeometryTileFeature instances in SymbolFeature,
// which may reference data from this object.
diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp
index fc34f55e75..4e28107f07 100644
--- a/src/mbgl/renderer/bucket.hpp
+++ b/src/mbgl/renderer/bucket.hpp
@@ -32,8 +32,12 @@ public:
// Feature geometries are also used to populate the feature index.
// Obtaining these is a costly operation, so we do it only once, and
// pass-by-const-ref the geometries as a second parameter.
- virtual void addFeature(const GeometryTileFeature&, const GeometryCollection&, const ImagePositions&,
- const PatternLayerMap&, std::size_t){};
+ virtual void addFeature(const GeometryTileFeature&,
+ const GeometryCollection&,
+ const ImagePositions&,
+ const PatternLayerMap&,
+ std::size_t,
+ const CanonicalTileID&){};
virtual void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) {}
diff --git a/src/mbgl/renderer/buckets/circle_bucket.cpp b/src/mbgl/renderer/buckets/circle_bucket.cpp
index 560a74781a..744b559c42 100644
--- a/src/mbgl/renderer/buckets/circle_bucket.cpp
+++ b/src/mbgl/renderer/buckets/circle_bucket.cpp
@@ -41,8 +41,12 @@ bool CircleBucket::hasData() const {
return !segments.empty();
}
-void CircleBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry,
- const ImagePositions&, const PatternLayerMap&, std::size_t featureIndex) {
+void CircleBucket::addFeature(const GeometryTileFeature& feature,
+ const GeometryCollection& geometry,
+ const ImagePositions&,
+ const PatternLayerMap&,
+ std::size_t featureIndex,
+ const CanonicalTileID& canonical) {
constexpr const uint16_t vertexLength = 4;
for (auto& circle : geometry) {
@@ -90,7 +94,7 @@ void CircleBucket::addFeature(const GeometryTileFeature& feature, const Geometry
}
for (auto& pair : paintPropertyBinders) {
- pair.second.populateVertexVectors(feature, vertices.elements(), featureIndex, {}, {});
+ pair.second.populateVertexVectors(feature, vertices.elements(), featureIndex, {}, {}, canonical);
}
}
diff --git a/src/mbgl/renderer/buckets/circle_bucket.hpp b/src/mbgl/renderer/buckets/circle_bucket.hpp
index e514f8a5f2..17ddd9dc10 100644
--- a/src/mbgl/renderer/buckets/circle_bucket.hpp
+++ b/src/mbgl/renderer/buckets/circle_bucket.hpp
@@ -18,8 +18,12 @@ public:
CircleBucket(const BucketParameters&, const std::vector<Immutable<style::LayerProperties>>&);
~CircleBucket() override;
- void addFeature(const GeometryTileFeature&, const GeometryCollection&, const ImagePositions&,
- const PatternLayerMap&, std::size_t) override;
+ void addFeature(const GeometryTileFeature&,
+ const GeometryCollection&,
+ const ImagePositions&,
+ const PatternLayerMap&,
+ std::size_t,
+ const CanonicalTileID&) override;
bool hasData() const override;
diff --git a/src/mbgl/renderer/buckets/fill_bucket.cpp b/src/mbgl/renderer/buckets/fill_bucket.cpp
index 6660934f8d..73c2530241 100644
--- a/src/mbgl/renderer/buckets/fill_bucket.cpp
+++ b/src/mbgl/renderer/buckets/fill_bucket.cpp
@@ -44,9 +44,12 @@ FillBucket::FillBucket(const FillBucket::PossiblyEvaluatedLayoutProperties,
FillBucket::~FillBucket() = default;
-void FillBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry,
- const ImagePositions& patternPositions, const PatternLayerMap& patternDependencies,
- std::size_t index) {
+void FillBucket::addFeature(const GeometryTileFeature& feature,
+ const GeometryCollection& geometry,
+ const ImagePositions& patternPositions,
+ const PatternLayerMap& patternDependencies,
+ std::size_t index,
+ const CanonicalTileID& canonical) {
for (auto& polygon : classifyRings(geometry)) {
// Optimize polygons with many interior rings for earcut tesselation.
limitHoles(polygon, 500);
@@ -113,9 +116,10 @@ void FillBucket::addFeature(const GeometryTileFeature& feature, const GeometryCo
for (auto& pair : paintPropertyBinders) {
const auto it = patternDependencies.find(pair.first);
if (it != patternDependencies.end()){
- pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, it->second);
+ pair.second.populateVertexVectors(
+ feature, vertices.elements(), index, patternPositions, it->second, canonical);
} else {
- pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, {});
+ pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, {}, canonical);
}
}
}
diff --git a/src/mbgl/renderer/buckets/fill_bucket.hpp b/src/mbgl/renderer/buckets/fill_bucket.hpp
index 7a3f681121..4de97141a7 100644
--- a/src/mbgl/renderer/buckets/fill_bucket.hpp
+++ b/src/mbgl/renderer/buckets/fill_bucket.hpp
@@ -25,8 +25,12 @@ public:
const float zoom,
const uint32_t overscaling);
- void addFeature(const GeometryTileFeature&, const GeometryCollection&, const mbgl::ImagePositions&,
- const PatternLayerMap&, std::size_t) override;
+ void addFeature(const GeometryTileFeature&,
+ const GeometryCollection&,
+ const mbgl::ImagePositions&,
+ const PatternLayerMap&,
+ std::size_t,
+ const CanonicalTileID&) override;
bool hasData() const override;
diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp
index 698895fdcf..39c9f9af1e 100644
--- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp
+++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp
@@ -50,9 +50,12 @@ FillExtrusionBucket::FillExtrusionBucket(const FillExtrusionBucket::PossiblyEval
FillExtrusionBucket::~FillExtrusionBucket() = default;
-void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry,
- const ImagePositions& patternPositions, const PatternLayerMap& patternDependencies,
- std::size_t index) {
+void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature,
+ const GeometryCollection& geometry,
+ const ImagePositions& patternPositions,
+ const PatternLayerMap& patternDependencies,
+ std::size_t index,
+ const CanonicalTileID& canonical) {
for (auto& polygon : classifyRings(geometry)) {
// Optimize polygons with many interior rings for earcut tesselation.
limitHoles(polygon, 500);
@@ -157,9 +160,10 @@ void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature, const G
for (auto& pair : paintPropertyBinders) {
const auto it = patternDependencies.find(pair.first);
if (it != patternDependencies.end()){
- pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, it->second);
+ pair.second.populateVertexVectors(
+ feature, vertices.elements(), index, patternPositions, it->second, canonical);
} else {
- pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, {});
+ pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, {}, canonical);
}
}
}
diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp
index 8535f99b70..833eee7a73 100644
--- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp
+++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp
@@ -24,8 +24,12 @@ public:
const float,
const uint32_t);
- void addFeature(const GeometryTileFeature&, const GeometryCollection&, const mbgl::ImagePositions&,
- const PatternLayerMap&, std::size_t) override;
+ void addFeature(const GeometryTileFeature&,
+ const GeometryCollection&,
+ const mbgl::ImagePositions&,
+ const PatternLayerMap&,
+ std::size_t,
+ const CanonicalTileID&) override;
bool hasData() const override;
diff --git a/src/mbgl/renderer/buckets/heatmap_bucket.cpp b/src/mbgl/renderer/buckets/heatmap_bucket.cpp
index 78c4fb7507..31c4bc0e9c 100644
--- a/src/mbgl/renderer/buckets/heatmap_bucket.cpp
+++ b/src/mbgl/renderer/buckets/heatmap_bucket.cpp
@@ -39,8 +39,12 @@ bool HeatmapBucket::hasData() const {
return !segments.empty();
}
-void HeatmapBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry,
- const ImagePositions&, const PatternLayerMap&, std::size_t featureIndex) {
+void HeatmapBucket::addFeature(const GeometryTileFeature& feature,
+ const GeometryCollection& geometry,
+ const ImagePositions&,
+ const PatternLayerMap&,
+ std::size_t featureIndex,
+ const CanonicalTileID& canonical) {
constexpr const uint16_t vertexLength = 4;
for (auto& points : geometry) {
@@ -87,7 +91,7 @@ void HeatmapBucket::addFeature(const GeometryTileFeature& feature, const Geometr
}
for (auto& pair : paintPropertyBinders) {
- pair.second.populateVertexVectors(feature, vertices.elements(), featureIndex, {}, {});
+ pair.second.populateVertexVectors(feature, vertices.elements(), featureIndex, {}, {}, canonical);
}
}
diff --git a/src/mbgl/renderer/buckets/heatmap_bucket.hpp b/src/mbgl/renderer/buckets/heatmap_bucket.hpp
index 04d4170b50..0aaff7f298 100644
--- a/src/mbgl/renderer/buckets/heatmap_bucket.hpp
+++ b/src/mbgl/renderer/buckets/heatmap_bucket.hpp
@@ -18,8 +18,12 @@ public:
HeatmapBucket(const BucketParameters&, const std::vector<Immutable<style::LayerProperties>>&);
~HeatmapBucket() override;
- void addFeature(const GeometryTileFeature&, const GeometryCollection&, const ImagePositions&,
- const PatternLayerMap&, std::size_t) override;
+ void addFeature(const GeometryTileFeature&,
+ const GeometryCollection&,
+ const ImagePositions&,
+ const PatternLayerMap&,
+ std::size_t,
+ const CanonicalTileID&) override;
bool hasData() const override;
void upload(gfx::UploadPass&) override;
diff --git a/src/mbgl/renderer/buckets/line_bucket.cpp b/src/mbgl/renderer/buckets/line_bucket.cpp
index c32515e016..fdb110bc9d 100644
--- a/src/mbgl/renderer/buckets/line_bucket.cpp
+++ b/src/mbgl/renderer/buckets/line_bucket.cpp
@@ -27,9 +27,12 @@ LineBucket::LineBucket(const LineBucket::PossiblyEvaluatedLayoutProperties layou
LineBucket::~LineBucket() = default;
-void LineBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometryCollection,
- const ImagePositions& patternPositions, const PatternLayerMap& patternDependencies,
- std::size_t index) {
+void LineBucket::addFeature(const GeometryTileFeature& feature,
+ const GeometryCollection& geometryCollection,
+ const ImagePositions& patternPositions,
+ const PatternLayerMap& patternDependencies,
+ std::size_t index,
+ const CanonicalTileID& canonical) {
for (auto& line : geometryCollection) {
addGeometry(line, feature);
}
@@ -37,9 +40,10 @@ void LineBucket::addFeature(const GeometryTileFeature& feature, const GeometryCo
for (auto& pair : paintPropertyBinders) {
const auto it = patternDependencies.find(pair.first);
if (it != patternDependencies.end()){
- pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, it->second);
+ pair.second.populateVertexVectors(
+ feature, vertices.elements(), index, patternPositions, it->second, canonical);
} else {
- pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, {});
+ pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, {}, canonical);
}
}
}
diff --git a/src/mbgl/renderer/buckets/line_bucket.hpp b/src/mbgl/renderer/buckets/line_bucket.hpp
index a3237c9df9..a3821d108b 100644
--- a/src/mbgl/renderer/buckets/line_bucket.hpp
+++ b/src/mbgl/renderer/buckets/line_bucket.hpp
@@ -25,8 +25,12 @@ public:
const uint32_t overscaling);
~LineBucket() override;
- void addFeature(const GeometryTileFeature&, const GeometryCollection&, const mbgl::ImagePositions& patternPositions,
- const PatternLayerMap&, std::size_t) override;
+ void addFeature(const GeometryTileFeature&,
+ const GeometryCollection&,
+ const mbgl::ImagePositions& patternPositions,
+ const PatternLayerMap&,
+ std::size_t,
+ const CanonicalTileID&) override;
bool hasData() const override;
diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp
index db9f61411a..3a9dceacc0 100644
--- a/src/mbgl/renderer/paint_property_binder.hpp
+++ b/src/mbgl/renderer/paint_property_binder.hpp
@@ -105,8 +105,12 @@ public:
virtual ~PaintPropertyBinder() = default;
- virtual void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, std::size_t index,
- const ImagePositions&, const optional<PatternDependency>&,
+ virtual void populateVertexVector(const GeometryTileFeature& feature,
+ std::size_t length,
+ std::size_t index,
+ const ImagePositions&,
+ const optional<PatternDependency>&,
+ const CanonicalTileID& canonical,
const style::expression::Value&) = 0;
virtual void updateVertexVectors(const FeatureStates&, const GeometryTileLayer&, const ImagePositions&) {}
@@ -131,8 +135,13 @@ public:
: constant(std::move(constant_)) {
}
- void populateVertexVector(const GeometryTileFeature&, std::size_t, std::size_t, const ImagePositions&,
- const optional<PatternDependency>&, const style::expression::Value&) override {}
+ void populateVertexVector(const GeometryTileFeature&,
+ std::size_t,
+ std::size_t,
+ const ImagePositions&,
+ const optional<PatternDependency>&,
+ const CanonicalTileID&,
+ const style::expression::Value&) override {}
void updateVertexVector(std::size_t, std::size_t, const GeometryTileFeature&, const FeatureState&) override {}
void upload(gfx::UploadPass&) override {}
void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, const CrossfadeParameters&) override {};
@@ -160,8 +169,13 @@ public:
: constant(std::move(constant_)), constantPatternPositions({}) {
}
- void populateVertexVector(const GeometryTileFeature&, std::size_t, std::size_t, const ImagePositions&,
- const optional<PatternDependency>&, const style::expression::Value&) override {}
+ void populateVertexVector(const GeometryTileFeature&,
+ std::size_t,
+ std::size_t,
+ const ImagePositions&,
+ const optional<PatternDependency>&,
+ const CanonicalTileID&,
+ const style::expression::Value&) override {}
void updateVertexVector(std::size_t, std::size_t, const GeometryTileFeature&, const FeatureState&) override {}
void upload(gfx::UploadPass&) override {}
@@ -204,11 +218,17 @@ public:
defaultValue(std::move(defaultValue_)) {
}
void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, const CrossfadeParameters&) override {};
- void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, std::size_t index,
- const ImagePositions&, const optional<PatternDependency>&,
+ void populateVertexVector(const GeometryTileFeature& feature,
+ std::size_t length,
+ std::size_t index,
+ const ImagePositions&,
+ const optional<PatternDependency>&,
+ const CanonicalTileID& canonical,
const style::expression::Value& formattedSection) override {
using style::expression::EvaluationContext;
- auto evaluated = expression.evaluate(EvaluationContext(&feature).withFormattedSection(&formattedSection), defaultValue);
+ auto evaluated = expression.evaluate(
+ EvaluationContext(&feature).withFormattedSection(&formattedSection).withCanonicalTileID(canonical),
+ defaultValue);
this->statistics.add(evaluated);
auto value = attributeValue(evaluated);
auto elements = vertexVector.elements();
@@ -299,13 +319,23 @@ public:
zoomRange({zoom, zoom + 1}) {
}
void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, const CrossfadeParameters&) override {};
- void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, std::size_t index,
- const ImagePositions&, const optional<PatternDependency>&,
+ void populateVertexVector(const GeometryTileFeature& feature,
+ std::size_t length,
+ std::size_t index,
+ const ImagePositions&,
+ const optional<PatternDependency>&,
+ const CanonicalTileID& canonical,
const style::expression::Value& formattedSection) override {
using style::expression::EvaluationContext;
Range<T> range = {
- expression.evaluate(EvaluationContext(zoomRange.min, &feature).withFormattedSection(&formattedSection), defaultValue),
- expression.evaluate(EvaluationContext(zoomRange.max, &feature).withFormattedSection(&formattedSection), defaultValue),
+ expression.evaluate(EvaluationContext(zoomRange.min, &feature)
+ .withFormattedSection(&formattedSection)
+ .withCanonicalTileID(canonical),
+ defaultValue),
+ expression.evaluate(EvaluationContext(zoomRange.max, &feature)
+ .withFormattedSection(&formattedSection)
+ .withCanonicalTileID(canonical),
+ defaultValue),
};
this->statistics.add(range.min);
this->statistics.add(range.max);
@@ -416,9 +446,12 @@ public:
crossfade = crossfade_;
};
- void populateVertexVector(const GeometryTileFeature&, std::size_t length, std::size_t /* index */,
+ void populateVertexVector(const GeometryTileFeature&,
+ std::size_t length,
+ std::size_t /* index */,
const ImagePositions& patternPositions,
const optional<PatternDependency>& patternDependencies,
+ const CanonicalTileID&,
const style::expression::Value&) override {
if (!patternDependencies || patternDependencies->mid.empty()) {
// Unlike other propperties with expressions that evaluate to null, the default value for `*-pattern` properties is an empty
@@ -589,12 +622,15 @@ public:
PaintPropertyBinders(PaintPropertyBinders&&) = default;
PaintPropertyBinders(const PaintPropertyBinders&) = delete;
- void populateVertexVectors(const GeometryTileFeature& feature, std::size_t length, std::size_t index,
+ void populateVertexVectors(const GeometryTileFeature& feature,
+ std::size_t length,
+ std::size_t index,
const ImagePositions& patternPositions,
const optional<PatternDependency>& patternDependencies,
+ const CanonicalTileID& canonical,
const style::expression::Value& formattedSection = {}) {
- util::ignore({(binders.template get<Ps>()->populateVertexVector(feature, length, index, patternPositions,
- patternDependencies, formattedSection),
+ util::ignore({(binders.template get<Ps>()->populateVertexVector(
+ feature, length, index, patternPositions, patternDependencies, canonical, formattedSection),
0)...});
}
diff --git a/src/mbgl/style/expression/is_constant.cpp b/src/mbgl/style/expression/is_constant.cpp
index eb823bc77c..e6bd05418f 100644
--- a/src/mbgl/style/expression/is_constant.cpp
+++ b/src/mbgl/style/expression/is_constant.cpp
@@ -29,6 +29,10 @@ bool isFeatureConstant(const Expression& expression) {
return false;
}
+ if (expression.getKind() == Kind::Within) {
+ return false;
+ }
+
if (expression.getKind() == Kind::CollatorExpression) {
// Although the results of a Collator expression with fixed arguments
// generally shouldn't change between executions, we can't serialize them
diff --git a/src/mbgl/style/expression/parsing_context.cpp b/src/mbgl/style/expression/parsing_context.cpp
index ae991b2e88..d42c46bb09 100644
--- a/src/mbgl/style/expression/parsing_context.cpp
+++ b/src/mbgl/style/expression/parsing_context.cpp
@@ -22,6 +22,7 @@
#include <mbgl/style/expression/match.hpp>
#include <mbgl/style/expression/number_format.hpp>
#include <mbgl/style/expression/step.hpp>
+#include <mbgl/style/expression/within.hpp>
#include <mbgl/style/expression/find_zoom_curve.hpp>
#include <mbgl/style/expression/dsl.hpp>
@@ -134,6 +135,7 @@ MAPBOX_ETERNAL_CONSTEXPR const auto expressionRegistry =
{"to-number", Coercion::parse},
{"to-string", Coercion::parse},
{"var", Var::parse},
+ {"within", Within::parse},
});
bool isExpression(const std::string& name) {
diff --git a/src/mbgl/style/expression/within.cpp b/src/mbgl/style/expression/within.cpp
new file mode 100644
index 0000000000..1b1b8b11b9
--- /dev/null
+++ b/src/mbgl/style/expression/within.cpp
@@ -0,0 +1,139 @@
+#include <mapbox/geojson.hpp>
+#include <mapbox/geometry.hpp>
+#include <mbgl/style/conversion_impl.hpp>
+#include <mbgl/style/expression/within.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
+#include <mbgl/util/string.hpp>
+
+namespace {
+
+double isLeft(mbgl::Point<double> P0, mbgl::Point<double> P1, mbgl::Point<double> P2) {
+ return ((P1.x - P0.x) * (P2.y - P0.y) - (P2.x - P0.x) * (P1.y - P0.y));
+}
+
+// winding number algorithm for checking if point inside a ploygon or not.
+// http://geomalgorithms.com/a03-_inclusion.html#wn_PnPoly()
+bool pointWithinPoly(mbgl::Point<double> point, const mapbox::geometry::polygon<double>& polys) {
+ // wn = the winding number (=0 only when point is outside)
+ int wn = 0;
+ for (auto poly : polys) {
+ auto size = poly.size();
+ auto i = size;
+ // loop through every edge of the polygon
+ for (i = 0; i < size - 1; ++i) {
+ if (poly[i].y <= point.y) {
+ if (poly[i + 1].y > point.y) { // upward horizontal crossing from point to edge E(poly[i], poly[i+1])
+ if (isLeft(poly[i], poly[i + 1], point) > 0) {
+ ++wn;
+ }
+ }
+ } else {
+ if (poly[i + 1].y <= point.y) { // downward crossing
+ if (isLeft(poly[i], poly[i + 1], point) < 0) {
+ --wn;
+ }
+ }
+ }
+ }
+ if (wn != 0) {
+ return true;
+ }
+ }
+ return wn != 0;
+}
+
+bool pointsWithinPoly(const mbgl::GeometryTileFeature& feature,
+ const mbgl::CanonicalTileID& canonical,
+ const mbgl::GeoJSON& geoJson) {
+ bool result = false;
+ geoJson.match(
+ [&](const mapbox::geometry::geometry<double>& geometrySet) {
+ geometrySet.match(
+ [&](const mapbox::geometry::polygon<double>& polygons) {
+ convertGeometry(feature, canonical)
+ .match(
+ [&](const mapbox::geometry::point<double>& point) {
+ result = pointWithinPoly(point, polygons);
+ },
+ [&](const mapbox::geometry::multi_point<double>& points) {
+ for (const auto& p : points) {
+ result = pointWithinPoly(p, polygons);
+ if (!result) {
+ return;
+ }
+ }
+ },
+ [&](const auto&) { return; });
+ },
+ [&](const auto&) { return; });
+ },
+ [&](const auto&) { return; });
+
+ return result;
+}
+
+mbgl::optional<mbgl::GeoJSON> parseValue(const mbgl::style::conversion::Convertible& value_,
+ mbgl::style::expression::ParsingContext& ctx) {
+ if (isObject(value_)) {
+ const auto geometryType = objectMember(value_, "type");
+ if (geometryType) {
+ const auto type = toString(*geometryType);
+ if (type && *type == "Polygon") {
+ mbgl::style::conversion::Error error;
+ auto geojson = toGeoJSON(value_, error);
+ if (geojson && error.message.empty()) {
+ return geojson;
+ }
+ ctx.error(error.message);
+ }
+ }
+ }
+ ctx.error("'Within' expression requires valid geojson source that contains polygon geometry type.");
+ return mbgl::optional<mbgl::GeoJSON>();
+}
+
+} // namespace
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+using namespace mbgl::style::conversion;
+
+EvaluationResult Within::evaluate(const EvaluationContext& params) const {
+ if (!params.feature || !params.canonical) {
+ return false;
+ }
+ auto geometryType = params.feature->getType();
+ // Currently only support Point/Points in polygon
+ if (geometryType == FeatureType::Point) {
+ return pointsWithinPoly(*params.feature, *params.canonical, geoJSONSource);
+ }
+ return false;
+}
+
+ParseResult Within::parse(const Convertible& value, ParsingContext& ctx) {
+ if (isArray(value)) {
+ // object value, quoted with ["Within", value]
+ if (arrayLength(value) != 2) {
+ ctx.error("'Within' expression requires exactly one argument, but found " +
+ util::toString(arrayLength(value) - 1) + " instead.");
+ return ParseResult();
+ }
+
+ auto parsedValue = parseValue(arrayMember(value, 1), ctx);
+ if (!parsedValue) {
+ return ParseResult();
+ }
+ return ParseResult(std::make_unique<Within>(*parsedValue));
+ }
+ return ParseResult();
+}
+
+mbgl::Value Within::serialize() const {
+ return std::vector<mbgl::Value>{{getOperator()}, {mapbox::geojson::stringify(geoJSONSource)}};
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/properties.hpp b/src/mbgl/style/properties.hpp
index 9c8996fcbe..2fab53ad12 100644
--- a/src/mbgl/style/properties.hpp
+++ b/src/mbgl/style/properties.hpp
@@ -206,6 +206,11 @@ public:
}
template <class P>
+ auto evaluate(float z, const GeometryTileFeature& feature, const CanonicalTileID& canonical) const {
+ return evaluate(z, feature, canonical, this->template get<P>(), P::defaultValue());
+ }
+
+ template <class P>
auto evaluate(float z, const GeometryTileFeature& feature, const FeatureState& state) const {
return evaluate(z, feature, state, this->template get<P>(), P::defaultValue());
}
diff --git a/src/mbgl/tile/geometry_tile_data.cpp b/src/mbgl/tile/geometry_tile_data.cpp
index f723a94800..838f37f0da 100644
--- a/src/mbgl/tile/geometry_tile_data.cpp
+++ b/src/mbgl/tile/geometry_tile_data.cpp
@@ -99,7 +99,7 @@ void limitHoles(GeometryCollection& polygon, uint32_t maxHoles) {
}
}
-static Feature::geometry_type convertGeometry(const GeometryTileFeature& geometryTileFeature, const CanonicalTileID& tileID) {
+Feature::geometry_type convertGeometry(const GeometryTileFeature& geometryTileFeature, const CanonicalTileID& tileID) {
const double size = util::EXTENT * std::pow(2, tileID.z);
const double x0 = util::EXTENT * static_cast<double>(tileID.x);
const double y0 = util::EXTENT * static_cast<double>(tileID.y);
diff --git a/src/mbgl/tile/geometry_tile_data.hpp b/src/mbgl/tile/geometry_tile_data.hpp
index 49620982c1..a0a069f3d1 100644
--- a/src/mbgl/tile/geometry_tile_data.hpp
+++ b/src/mbgl/tile/geometry_tile_data.hpp
@@ -80,6 +80,8 @@ std::vector<GeometryCollection> classifyRings(const GeometryCollection&);
// Truncate polygon to the largest `maxHoles` inner rings by area.
void limitHoles(GeometryCollection&, uint32_t maxHoles);
+Feature::geometry_type convertGeometry(const GeometryTileFeature& geometryTileFeature, const CanonicalTileID& tileID);
+
// convert from GeometryTileFeature to Feature (eventually we should eliminate GeometryTileFeature)
Feature convertFeature(const GeometryTileFeature&, const CanonicalTileID&);
diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp
index c38464bb04..0729ed2aa5 100644
--- a/src/mbgl/tile/geometry_tile_worker.cpp
+++ b/src/mbgl/tile/geometry_tile_worker.cpp
@@ -391,7 +391,7 @@ void GeometryTileWorker::parse() {
if (layout->hasDependencies()) {
layouts.push_back(std::move(layout));
} else {
- layout->createBucket({}, featureIndex, renderData, firstLoad, showCollisionBoxes);
+ layout->createBucket({}, featureIndex, renderData, firstLoad, showCollisionBoxes, id.canonical);
}
} else {
const Filter& filter = leaderImpl.filter;
@@ -405,7 +405,7 @@ void GeometryTileWorker::parse() {
continue;
const GeometryCollection& geometries = feature->getGeometries();
- bucket->addFeature(*feature, geometries, {}, PatternLayerMap(), i);
+ bucket->addFeature(*feature, geometries, {}, PatternLayerMap(), i, id.canonical);
featureIndex->insert(geometries, i, sourceLayerID, leaderImpl.id);
}
@@ -467,7 +467,8 @@ void GeometryTileWorker::finalizeLayout() {
}
// layout adds the bucket to buckets
- layout->createBucket(iconAtlas.patternPositions, featureIndex, renderData, firstLoad, showCollisionBoxes);
+ layout->createBucket(
+ iconAtlas.patternPositions, featureIndex, renderData, firstLoad, showCollisionBoxes, id.canonical);
}
}