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

Account for property functions in query rendered features #8665

Merged
merged 3 commits into from
Apr 20, 2017
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
2 changes: 1 addition & 1 deletion mapbox-gl-js
Submodule mapbox-gl-js updated 66 files
+58 −0 CHANGELOG.md
+1 −0 _config.mb-pages.yml
+3 −2 dist/mapbox-gl.css
+3 −0 docs/_data/plugins.yml
+11 −9 docs/_layouts/default.html
+1 −0 docs/_layouts/pages.html
+43 −45 docs/_posts/examples/3400-01-02-cluster.html
+2 −2 docs/_posts/examples/3400-01-12-mapbox-gl-geocoder.html
+2 −2 docs/_posts/examples/3400-01-16-point-from-geocoder-result.html
+2 −2 docs/_posts/examples/3400-01-25-mapbox-gl-draw.html
+4 −4 docs/_theme/index.hbs
+1 −1 docs/_theme/note.hbs
+1 −1 docs/_theme/section.hbs
+2 −2 docs/_theme/section_list.hbs
+15 −1 docs/style-spec/_generate/index.html
+1 −1 package.json
+1 −1 src/geo/transform.js
+1 −1 src/shaders/fill_outline.fragment.glsl
+1 −1 src/shaders/fill_outline_pattern.fragment.glsl
+3 −0 src/source/geojson_worker_source.js
+9 −2 src/source/geojson_wrapper.js
+1 −1 src/source/load_tilejson.js
+17 −2 src/source/raster_tile_source.js
+4 −0 src/source/source_cache.js
+39 −0 src/source/tile_bounds.js
+15 −1 src/source/vector_tile_source.js
+8 −2 src/style-spec/CHANGELOG.md
+0 −0 src/style-spec/bin/gl-style-composite
+9 −0 src/style-spec/composite.js
+22 −39 src/style-spec/function/index.js
+1 −1 src/style-spec/migrate/v7.js
+1 −1 src/style-spec/migrate/v8.js
+1 −1 src/style-spec/package.json
+6 −2 src/style-spec/reference/v8.json
+0 −0 src/style-spec/util/interpolate.js
+5 −2 src/style/style.js
+1 −1 src/style/style_transition.js
+1 −1 src/symbol/get_anchors.js
+96 −99 src/ui/camera.js
+7 −0 src/ui/handler/box_zoom.js
+7 −6 src/ui/map.js
+2 −1 src/util/util.js
+10 −2 test/integration/lib/harness.js
+1 −4 test/integration/query-tests/circle-radius/property-function/style.json
+1 −4 test/integration/query-tests/circle-radius/zoom-and-property-function/style.json
+1 −4 test/integration/query-tests/line-gap-width/property-function/style.json
+6 −6 test/integration/query-tests/line-offset/property-function/expected.json
+5 −8 test/integration/query-tests/line-offset/property-function/style.json
+14 −0 test/integration/query-tests/regressions/mapbox-gl-js#4494/expected.json
+42 −0 test/integration/query-tests/regressions/mapbox-gl-js#4494/style.json
+ test/integration/render-tests/fill-outline-color/fill/expected.png
+56 −0 test/integration/render-tests/fill-outline-color/fill/style.json
+1 −1 test/integration/render-tests/regressions/mapbox-gl-js#4235/style.json
+ test/integration/render-tests/regressions/mapbox-gl-js#4564/expected.png
+43 −0 test/integration/render-tests/regressions/mapbox-gl-js#4564/style.json
+ test/integration/render-tests/regressions/mapbox-gl-js#4573/expected.png
+34 −0 test/integration/render-tests/regressions/mapbox-gl-js#4573/style.json
+ test/integration/render-tests/regressions/mapbox-gl-js#4605/expected.png
+53 −0 test/integration/render-tests/regressions/mapbox-gl-js#4605/style.json
+3 −3 test/integration/render-tests/regressions/mapbox-gl-native#7792/style.json
+65 −0 test/unit/source/raster_tile_source.test.js
+24 −0 test/unit/source/source_cache.test.js
+35 −0 test/unit/source/vector_tile_source.test.js
+31 −0 test/unit/style-spec/composite.test.js
+1 −1 test/unit/style-spec/interpolate.test.js
+39 −1 test/unit/ui/camera.test.js
45 changes: 40 additions & 5 deletions src/mbgl/geometry/feature_index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <mbgl/map/query.hpp>
#include <mbgl/style/filter.hpp>
#include <mbgl/style/filter_evaluator.hpp>
#include <mbgl/tile/geometry_tile.hpp>

#include <mapbox/geometry/envelope.hpp>

Expand Down Expand Up @@ -53,6 +54,36 @@ static bool topDownSymbols(const IndexedSubfeature& a, const IndexedSubfeature&
return a.sortIndex < b.sortIndex;
}

static int16_t getAdditionalQueryRadius(const RenderedQueryOptions& queryOptions,
const style::Style& style,
const GeometryTile& tile,
const float pixelsToTileUnits) {

// Determine the additional radius needed factoring in property functions
float additionalRadius = 0;
auto getQueryRadius = [&](const style::Layer& layer) {
auto bucket = tile.getBucket(layer);
if (bucket) {
additionalRadius = std::max(additionalRadius, bucket->getQueryRadius(layer) * pixelsToTileUnits);
}
};

if (queryOptions.layerIDs) {
for (const auto& layerID : *queryOptions.layerIDs) {
style::Layer* layer = style.getLayer(layerID);
if (layer) {
getQueryRadius(*layer);
}
}
} else {
for (const style::Layer* layer : style.getLayers()) {
getQueryRadius(*layer);
}
}

return std::min<int16_t>(util::EXTENT, additionalRadius);
}

void FeatureIndex::query(
std::unordered_map<std::string, std::vector<Feature>>& result,
const GeometryCoordinates& queryGeometry,
Expand All @@ -63,14 +94,18 @@ void FeatureIndex::query(
const GeometryTileData& geometryTileData,
const CanonicalTileID& tileID,
const style::Style& style,
const CollisionTile* collisionTile) const {

mapbox::geometry::box<int16_t> box = mapbox::geometry::envelope(queryGeometry);
const CollisionTile* collisionTile,
const GeometryTile& tile) const {

// Determine query radius
const float pixelsToTileUnits = util::EXTENT / tileSize / scale;
const int16_t additionalRadius = std::min<int16_t>(util::EXTENT, std::ceil(style.getQueryRadius() * pixelsToTileUnits));
const int16_t additionalRadius = getAdditionalQueryRadius(queryOptions, style, tile, pixelsToTileUnits);

// Query the grid index
mapbox::geometry::box<int16_t> box = mapbox::geometry::envelope(queryGeometry);
std::vector<IndexedSubfeature> features = grid.query({ box.min - additionalRadius, box.max + additionalRadius });


std::sort(features.begin(), features.end(), topDown);
size_t previousSortIndex = std::numeric_limits<size_t>::max();
for (const auto& indexedFeature : features) {
Expand Down Expand Up @@ -124,7 +159,7 @@ void FeatureIndex::addFeature(
auto styleLayer = style.getLayer(layerID);
if (!styleLayer ||
(!styleLayer->is<style::SymbolLayer>() &&
!styleLayer->baseImpl->queryIntersectsGeometry(queryGeometry, geometryTileFeature->getGeometries(), bearing, pixelsToTileUnits))) {
!styleLayer->baseImpl->queryIntersectsFeature(queryGeometry, *geometryTileFeature, tileID.z, bearing, pixelsToTileUnits))) {
continue;
}

Expand Down
4 changes: 3 additions & 1 deletion src/mbgl/geometry/feature_index.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace mbgl {

class GeometryTile;
class RenderedQueryOptions;

namespace style {
Expand Down Expand Up @@ -45,7 +46,8 @@ class FeatureIndex {
const GeometryTileData&,
const CanonicalTileID&,
const style::Style&,
const CollisionTile*) const;
const CollisionTile*,
const GeometryTile& tile) const;

static optional<GeometryCoordinates> translateQueryGeometry(
const GeometryCoordinates& queryGeometry,
Expand Down
6 changes: 6 additions & 0 deletions src/mbgl/renderer/bucket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <mbgl/tile/geometry_tile_data.hpp>

#include <atomic>
#include <string>
#include <unordered_map>

namespace mbgl {

Expand Down Expand Up @@ -38,6 +40,10 @@ class Bucket : private util::noncopyable {

virtual bool hasData() const = 0;

virtual float getQueryRadius(const style::Layer&) const {
return 0;
};

bool needsUpload() const {
return !uploaded;
}
Expand Down
23 changes: 23 additions & 0 deletions src/mbgl/renderer/circle_bucket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <mbgl/style/layers/circle_layer.hpp>
#include <mbgl/style/layers/circle_layer_impl.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/math.hpp>

namespace mbgl {

Expand Down Expand Up @@ -97,4 +98,26 @@ void CircleBucket::addFeature(const GeometryTileFeature& feature,
}
}

template <class Property>
static float get(const CircleLayer& layer, const std::map<std::string, CircleProgram::PaintPropertyBinders>& paintPropertyBinders) {
auto it = paintPropertyBinders.find(layer.getID());
if (it == paintPropertyBinders.end() || !it->second.statistics<Property>().max()) {
return layer.impl->paint.evaluated.get<Property>().constantOr(Property::defaultValue());
} else {
return *it->second.statistics<Property>().max();
}
}

float CircleBucket::getQueryRadius(const style::Layer& layer) const {
if (!layer.is<CircleLayer>()) {
return 0;
}

auto circleLayer = layer.as<CircleLayer>();

float radius = get<CircleRadius>(*circleLayer, paintPropertyBinders);
auto translate = circleLayer->impl->paint.evaluated.get<CircleTranslate>();
return radius + util::length(translate[0], translate[1]);
}

} // namespace mbgl
2 changes: 2 additions & 0 deletions src/mbgl/renderer/circle_bucket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class CircleBucket : public Bucket {
void upload(gl::Context&) override;
void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) override;

float getQueryRadius(const style::Layer&) const override;

gl::VertexVector<CircleLayoutVertex> vertices;
gl::IndexVector<gl::Triangles> triangles;
gl::SegmentVector<CircleAttributes> segments;
Expand Down
11 changes: 11 additions & 0 deletions src/mbgl/renderer/fill_bucket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <mbgl/style/bucket_parameters.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
#include <mbgl/style/layers/fill_layer_impl.hpp>
#include <mbgl/util/math.hpp>

#include <mapbox/earcut.hpp>

Expand Down Expand Up @@ -131,4 +132,14 @@ bool FillBucket::hasData() const {
return !triangleSegments.empty() || !lineSegments.empty();
}

float FillBucket::getQueryRadius(const style::Layer& layer) const {
if (!layer.is<FillLayer>()) {
return 0;
}

const std::array<float, 2>& translate = layer.as<FillLayer>()->impl->paint.evaluated.get<FillTranslate>();
return util::length(translate[0], translate[1]);

}

} // namespace mbgl
2 changes: 2 additions & 0 deletions src/mbgl/renderer/fill_bucket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class FillBucket : public Bucket {
void upload(gl::Context&) override;
void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) override;

float getQueryRadius(const style::Layer&) const override;

gl::VertexVector<FillLayoutVertex> vertices;
gl::IndexVector<gl::Lines> lines;
gl::IndexVector<gl::Triangles> triangles;
Expand Down
35 changes: 35 additions & 0 deletions src/mbgl/renderer/line_bucket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,4 +460,39 @@ bool LineBucket::hasData() const {
return !segments.empty();
}

template <class Property>
static float get(const LineLayer& layer, const std::map<std::string, LineProgram::PaintPropertyBinders>& paintPropertyBinders) {
auto it = paintPropertyBinders.find(layer.getID());
if (it == paintPropertyBinders.end() || !it->second.statistics<Property>().max()) {
return layer.impl->paint.evaluated.get<Property>().constantOr(Property::defaultValue());
} else {
return *it->second.statistics<Property>().max();
}
}

float LineBucket::getLineWidth(const style::LineLayer& layer) const {
float lineWidth = layer.impl->paint.evaluated.get<LineWidth>();
float gapWidth = get<LineGapWidth>(layer, paintPropertyBinders);

if (gapWidth) {
return gapWidth + 2 * lineWidth;
} else {
return lineWidth;
}
}

float LineBucket::getQueryRadius(const style::Layer& layer) const {
if (!layer.is<LineLayer>()) {
return 0;
}

auto lineLayer = layer.as<LineLayer>();
auto paint = lineLayer->impl->paint;

const std::array<float, 2>& translate = paint.evaluated.get<LineTranslate>();
float offset = get<LineOffset>(*lineLayer, paintPropertyBinders);
return getLineWidth(*lineLayer) / 2.0 + std::abs(offset) + util::length(translate[0], translate[1]);
}


} // namespace mbgl
5 changes: 5 additions & 0 deletions src/mbgl/renderer/line_bucket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace mbgl {

namespace style {
class BucketParameters;
class LineLayer;
} // namespace style

class LineBucket : public Bucket {
Expand All @@ -29,6 +30,8 @@ class LineBucket : public Bucket {
void upload(gl::Context&) override;
void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) override;

float getQueryRadius(const style::Layer&) const override;

style::LineLayoutProperties::PossiblyEvaluated layout;

gl::VertexVector<LineLayoutVertex> vertices;
Expand Down Expand Up @@ -59,6 +62,8 @@ class LineBucket : public Bucket {
std::ptrdiff_t e3;

const uint32_t overscaling;

float getLineWidth(const style::LineLayer& layer) const;
};

} // namespace mbgl
6 changes: 3 additions & 3 deletions src/mbgl/style/layer_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ class Layer::Impl {
// Checks whether this layer can be rendered.
bool needsRendering(float zoom) const;

virtual float getQueryRadius() const { return 0; }
virtual bool queryIntersectsGeometry(
virtual bool queryIntersectsFeature(
const GeometryCoordinates&,
const GeometryCollection&,
const GeometryTileFeature&,
const float,
const float,
const float) const { return false; };

Expand Down
21 changes: 10 additions & 11 deletions src/mbgl/style/layers/circle_layer_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,24 @@ std::unique_ptr<Bucket> CircleLayer::Impl::createBucket(const BucketParameters&
return std::make_unique<CircleBucket>(parameters, layers);
}

float CircleLayer::Impl::getQueryRadius() const {
const std::array<float, 2>& translate = paint.evaluated.get<CircleTranslate>();
return paint.evaluated.get<CircleRadius>().constantOr(CircleRadius::defaultValue())
+ util::length(translate[0], translate[1]);
}

bool CircleLayer::Impl::queryIntersectsGeometry(
bool CircleLayer::Impl::queryIntersectsFeature(
const GeometryCoordinates& queryGeometry,
const GeometryCollection& geometry,
const GeometryTileFeature& feature,
const float zoom,
const float bearing,
const float pixelsToTileUnits) const {

// Translate query geometry
auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
queryGeometry, paint.evaluated.get<CircleTranslate>(), paint.evaluated.get<CircleTranslateAnchor>(), bearing, pixelsToTileUnits);

auto circleRadius = paint.evaluated.get<CircleRadius>().constantOr(CircleRadius::defaultValue()) * pixelsToTileUnits;
// Evaluate function
auto circleRadius = paint.evaluated.get<CircleRadius>()
.evaluate(feature, zoom, CircleRadius::defaultValue())
* pixelsToTileUnits;

return util::polygonIntersectsBufferedMultiPoint(
translatedQueryGeometry.value_or(queryGeometry), geometry, circleRadius);
// Test intersection
return util::polygonIntersectsBufferedMultiPoint(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries(), circleRadius);
}

} // namespace style
Expand Down
12 changes: 6 additions & 6 deletions src/mbgl/style/layers/circle_layer_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ class CircleLayer::Impl : public Layer::Impl {

std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const Layer*>&) const override;

float getQueryRadius() const override;
bool queryIntersectsGeometry(
const GeometryCoordinates& queryGeometry,
const GeometryCollection& geometry,
const float bearing,
const float pixelsToTileUnits) const override;
bool queryIntersectsFeature(
const GeometryCoordinates&,
const GeometryTileFeature&,
const float,
const float,
const float) const override;

CirclePaintProperties paint;
};
Expand Down
12 changes: 4 additions & 8 deletions src/mbgl/style/layers/fill_layer_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,17 @@ std::unique_ptr<Bucket> FillLayer::Impl::createBucket(const BucketParameters& pa
return std::make_unique<FillBucket>(parameters, layers);
}

float FillLayer::Impl::getQueryRadius() const {
const std::array<float, 2>& translate = paint.evaluated.get<FillTranslate>();
return util::length(translate[0], translate[1]);
}

bool FillLayer::Impl::queryIntersectsGeometry(
bool FillLayer::Impl::queryIntersectsFeature(
const GeometryCoordinates& queryGeometry,
const GeometryCollection& geometry,
const GeometryTileFeature& feature,
const float,
const float bearing,
const float pixelsToTileUnits) const {

auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
queryGeometry, paint.evaluated.get<FillTranslate>(), paint.evaluated.get<FillTranslateAnchor>(), bearing, pixelsToTileUnits);

return util::polygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), geometry);
return util::polygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries());
}

} // namespace style
Expand Down
12 changes: 6 additions & 6 deletions src/mbgl/style/layers/fill_layer_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ class FillLayer::Impl : public Layer::Impl {

std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const Layer*>&) const override;

float getQueryRadius() const override;
bool queryIntersectsGeometry(
const GeometryCoordinates& queryGeometry,
const GeometryCollection& geometry,
const float bearing,
const float pixelsToTileUnits) const override;
bool queryIntersectsFeature(
const GeometryCoordinates&,
const GeometryTileFeature&,
const float,
const float,
const float) const override;

FillPaintProperties paint;
};
Expand Down
Loading