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

Commit

Permalink
[core] account for property functions in query rendered features
Browse files Browse the repository at this point in the history
  • Loading branch information
ivovandongen committed Apr 20, 2017
1 parent d752235 commit 7ddca3b
Show file tree
Hide file tree
Showing 21 changed files with 195 additions and 80 deletions.
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

0 comments on commit 7ddca3b

Please sign in to comment.