diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java index 4ecd7c92468..b9f220af1a2 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java @@ -96,28 +96,30 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback { @UiThread public MapView(@NonNull Context context) { super(context); - initialise(context, MapboxMapOptions.createFromAttributes(context, null)); + initialize(context, MapboxMapOptions.createFromAttributes(context, null)); } @UiThread public MapView(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); - initialise(context, MapboxMapOptions.createFromAttributes(context, attrs)); + initialize(context, MapboxMapOptions.createFromAttributes(context, attrs)); } @UiThread public MapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - initialise(context, MapboxMapOptions.createFromAttributes(context, attrs)); + initialize(context, MapboxMapOptions.createFromAttributes(context, attrs)); } @UiThread public MapView(@NonNull Context context, @Nullable MapboxMapOptions options) { super(context); - initialise(context, options == null ? MapboxMapOptions.createFromAttributes(context, null) : options); + initialize(context, options == null ? MapboxMapOptions.createFromAttributes(context, null) : options); } - private void initialise(@NonNull final Context context, @NonNull final MapboxMapOptions options) { + @CallSuper + @UiThread + protected void initialize(@NonNull final Context context, @NonNull final MapboxMapOptions options) { if (isInEditMode()) { // in IDE layout editor, just return return; diff --git a/platform/android/gradle/dependencies.gradle b/platform/android/gradle/dependencies.gradle index 65bd778b696..c13e6742712 100644 --- a/platform/android/gradle/dependencies.gradle +++ b/platform/android/gradle/dependencies.gradle @@ -9,7 +9,7 @@ ext { versions = [ mapboxServices : '3.0.1', - mapboxTelemetry: '3.1.1', + mapboxTelemetry: '3.1.2', mapboxGestures : '0.2.0', supportLib : '25.4.0', espresso : '3.0.1', diff --git a/platform/node/test/ignores.json b/platform/node/test/ignores.json index b7ca72cee0f..7b8eaeb49f5 100644 --- a/platform/node/test/ignores.json +++ b/platform/node/test/ignores.json @@ -1,4 +1,22 @@ { + "expression-tests/collator/accent-equals-de": "https://github.com/mapbox/mapbox-gl-native/issues/11692", + "expression-tests/collator/accent-lt-en": "https://github.com/mapbox/mapbox-gl-native/issues/11692", + "expression-tests/collator/accent-not-equals-en": "https://github.com/mapbox/mapbox-gl-native/issues/11692", + "expression-tests/collator/base-default-locale": "https://github.com/mapbox/mapbox-gl-native/issues/11692", + "expression-tests/collator/base-equals-en": "https://github.com/mapbox/mapbox-gl-native/issues/11692", + "expression-tests/collator/base-gt-en": "https://github.com/mapbox/mapbox-gl-native/issues/11692", + "expression-tests/collator/case-lteq-en": "https://github.com/mapbox/mapbox-gl-native/issues/11692", + "expression-tests/collator/case-not-equals-en": "https://github.com/mapbox/mapbox-gl-native/issues/11692", + "expression-tests/collator/case-omitted-en": "https://github.com/mapbox/mapbox-gl-native/issues/11692", + "expression-tests/collator/comparison-number-error": "https://github.com/mapbox/mapbox-gl-native/issues/11692", + "expression-tests/collator/diacritic-omitted-en": "https://github.com/mapbox/mapbox-gl-native/issues/11692", + "expression-tests/collator/equals-non-string-error": "https://github.com/mapbox/mapbox-gl-native/issues/11692", + "expression-tests/collator/non-object-error": "https://github.com/mapbox/mapbox-gl-native/issues/11692", + "expression-tests/collator/variant-equals-en": "https://github.com/mapbox/mapbox-gl-native/issues/11692", + "expression-tests/collator/variant-gteq-en": "https://github.com/mapbox/mapbox-gl-native/issues/11692", + "expression-tests/is-supported-script/default": "https://github.com/mapbox/mapbox-gl-native/issues/11693", + "expression-tests/resolved-locale/basic": "https://github.com/mapbox/mapbox-gl-native/issues/11692", + "expression-tests/to-string/basic": "https://github.com/mapbox/mapbox-gl-native/issues/11719", "query-tests/circle-pitch-scale/viewport-inside-align-map": "https://github.com/mapbox/mapbox-gl-native/issues/10615", "query-tests/circle-pitch-scale/viewport-inside-align-viewport": "https://github.com/mapbox/mapbox-gl-native/issues/10615", "query-tests/edge-cases/box-cutting-antimeridian-z0": "https://github.com/mapbox/mapbox-gl-native/issues/11607", diff --git a/src/mbgl/annotation/render_annotation_source.cpp b/src/mbgl/annotation/render_annotation_source.cpp index 19d19d29011..7d776f21c45 100644 --- a/src/mbgl/annotation/render_annotation_source.cpp +++ b/src/mbgl/annotation/render_annotation_source.cpp @@ -64,8 +64,9 @@ std::unordered_map> RenderAnnotationSource::queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector& layers, - const RenderedQueryOptions& options) const { - return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options); + const RenderedQueryOptions& options, + const mat4& projMatrix) const { + return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, projMatrix); } std::vector RenderAnnotationSource::querySourceFeatures(const SourceQueryOptions&) const { diff --git a/src/mbgl/annotation/render_annotation_source.hpp b/src/mbgl/annotation/render_annotation_source.hpp index da5376ab2d6..da87d13814c 100644 --- a/src/mbgl/annotation/render_annotation_source.hpp +++ b/src/mbgl/annotation/render_annotation_source.hpp @@ -27,7 +27,8 @@ class RenderAnnotationSource : public RenderSource { queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector& layers, - const RenderedQueryOptions& options) const final; + const RenderedQueryOptions& options, + const mat4& projMatrix) const final; std::vector querySourceFeatures(const SourceQueryOptions&) const final; diff --git a/src/mbgl/geometry/feature_index.cpp b/src/mbgl/geometry/feature_index.cpp index 145c16bf09d..6bb4783da70 100644 --- a/src/mbgl/geometry/feature_index.cpp +++ b/src/mbgl/geometry/feature_index.cpp @@ -27,21 +27,27 @@ void FeatureIndex::insert(const GeometryCollection& geometries, const std::string& bucketName) { for (const auto& ring : geometries) { auto envelope = mapbox::geometry::envelope(ring); - grid.insert(IndexedSubfeature(index, sourceLayerName, bucketName, sortIndex++), - {convertPoint(envelope.min), convertPoint(envelope.max)}); + if (envelope.min.x < util::EXTENT && + envelope.min.y < util::EXTENT && + envelope.max.x >= 0 && + envelope.max.y >= 0) { + grid.insert(IndexedSubfeature(index, sourceLayerName, bucketName, sortIndex++), + {convertPoint(envelope.min), convertPoint(envelope.max)}); + } } } void FeatureIndex::query( std::unordered_map>& result, const GeometryCoordinates& queryGeometry, - const float bearing, + const TransformState& transformState, + const mat4& posMatrix, const double tileSize, const double scale, const RenderedQueryOptions& queryOptions, const UnwrappedTileID& tileID, const std::vector& layers, - const float additionalQueryRadius) const { + const float additionalQueryPadding) const { if (!tileData) { return; @@ -49,12 +55,12 @@ void FeatureIndex::query( // Determine query radius const float pixelsToTileUnits = util::EXTENT / tileSize / scale; - const int16_t additionalRadius = std::min(util::EXTENT, additionalQueryRadius * pixelsToTileUnits); + const int16_t additionalPadding = std::min(util::EXTENT, additionalQueryPadding * pixelsToTileUnits); // Query the grid index mapbox::geometry::box box = mapbox::geometry::envelope(queryGeometry); - std::vector features = grid.query({ convertPoint(box.min - additionalRadius), - convertPoint(box.max + additionalRadius) }); + std::vector features = grid.query({ convertPoint(box.min - additionalPadding), + convertPoint(box.max + additionalPadding) }); std::sort(features.begin(), features.end(), [](const IndexedSubfeature& a, const IndexedSubfeature& b) { @@ -67,7 +73,7 @@ void FeatureIndex::query( if (indexedFeature.sortIndex == previousSortIndex) continue; previousSortIndex = indexedFeature.sortIndex; - addFeature(result, indexedFeature, queryOptions, tileID.canonical, layers, queryGeometry, bearing, pixelsToTileUnits); + addFeature(result, indexedFeature, queryOptions, tileID.canonical, layers, queryGeometry, transformState, pixelsToTileUnits, posMatrix); } } @@ -104,7 +110,8 @@ std::unordered_map> FeatureIndex::lookupSymbol }); for (const auto& symbolFeature : sortedFeatures) { - addFeature(result, symbolFeature, queryOptions, tileID.canonical, layers, GeometryCoordinates(), 0, 0); + mat4 unusedMatrix; + addFeature(result, symbolFeature, queryOptions, tileID.canonical, layers, GeometryCoordinates(), {}, 0, unusedMatrix); } return result; } @@ -116,8 +123,9 @@ void FeatureIndex::addFeature( const CanonicalTileID& tileID, const std::vector& layers, const GeometryCoordinates& queryGeometry, - const float bearing, - const float pixelsToTileUnits) const { + const TransformState& transformState, + const float pixelsToTileUnits, + const mat4& posMatrix) const { auto getRenderLayer = [&] (const std::string& layerID) -> const RenderLayer* { for (const auto& layer : layers) { @@ -147,7 +155,7 @@ void FeatureIndex::addFeature( } if (!renderLayer->is() && - !renderLayer->queryIntersectsFeature(queryGeometry, *geometryTileFeature, tileID.z, bearing, pixelsToTileUnits)) { + !renderLayer->queryIntersectsFeature(queryGeometry, *geometryTileFeature, tileID.z, transformState, pixelsToTileUnits, posMatrix)) { continue; } diff --git a/src/mbgl/geometry/feature_index.hpp b/src/mbgl/geometry/feature_index.hpp index 5a15a379c41..cc91791d36b 100644 --- a/src/mbgl/geometry/feature_index.hpp +++ b/src/mbgl/geometry/feature_index.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -14,6 +15,7 @@ namespace mbgl { class RenderedQueryOptions; class RenderLayer; +class TransformState; class CollisionIndex; @@ -56,13 +58,14 @@ class FeatureIndex { void query( std::unordered_map>& result, const GeometryCoordinates& queryGeometry, - const float bearing, + const TransformState&, + const mat4& posMatrix, const double tileSize, const double scale, const RenderedQueryOptions& options, const UnwrappedTileID&, const std::vector&, - const float additionalQueryRadius) const; + const float additionalQueryPadding) const; static optional translateQueryGeometry( const GeometryCoordinates& queryGeometry, @@ -88,8 +91,9 @@ class FeatureIndex { const CanonicalTileID&, const std::vector&, const GeometryCoordinates& queryGeometry, - const float bearing, - const float pixelsToTileUnits) const; + const TransformState& transformState, + const float pixelsToTileUnits, + const mat4& posMatrix) const; GridIndex grid; unsigned int sortIndex = 0; diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp index 18d2c24aee5..a85b251fb45 100644 --- a/src/mbgl/map/transform_state.cpp +++ b/src/mbgl/map/transform_state.cpp @@ -421,4 +421,17 @@ float TransformState::getCameraToTileDistance(const UnwrappedTileID& tileID) con return projectedCenter[3]; } +float TransformState::maxPitchScaleFactor() const { + if (size.isEmpty()) { + return {}; + } + auto latLng = screenCoordinateToLatLng({ 0, static_cast(getSize().height) }); + mat4 mat = coordinatePointMatrix(getZoom()); + Point pt = Projection::project(latLng, scale) / double(util::tileSize); + vec4 p = {{ pt.x, pt.y, 0, 1 }}; + vec4 topPoint; + matrix::transformMat4(topPoint, p, mat); + return topPoint[3] / getCameraToCenterDistance(); +} + } // namespace mbgl diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp index 451802034d6..b6f8ae44249 100644 --- a/src/mbgl/map/transform_state.hpp +++ b/src/mbgl/map/transform_state.hpp @@ -87,6 +87,7 @@ class TransformState { } float getCameraToTileDistance(const UnwrappedTileID&) const; + float maxPitchScaleFactor() const; private: bool rotatedNorth() const; diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp index 4c96137143e..b433a9d3fa4 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.cpp +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -108,27 +108,75 @@ void RenderCircleLayer::render(PaintParameters& parameters, RenderSource*) { } } +GeometryCoordinate projectPoint(const GeometryCoordinate& p, const mat4& posMatrix, const Size& size) { + vec4 pos = {{ static_cast(p.x), static_cast(p.y), 0, 1 }}; + matrix::transformMat4(pos, pos, posMatrix); + return { + static_cast((static_cast(pos[0] / pos[3]) + 1) * size.width * 0.5), + static_cast((static_cast(pos[1] / pos[3]) + 1) * size.height * 0.5) + }; +} + +GeometryCoordinates projectQueryGeometry(const GeometryCoordinates& queryGeometry, const mat4& posMatrix, const Size& size) { + GeometryCoordinates projectedGeometry; + for (auto& p : queryGeometry) { + projectedGeometry.push_back(projectPoint(p, posMatrix, size)); + } + return projectedGeometry; +} + bool RenderCircleLayer::queryIntersectsFeature( const GeometryCoordinates& queryGeometry, const GeometryTileFeature& feature, const float zoom, - const float bearing, - const float pixelsToTileUnits) const { + const TransformState& transformState, + const float pixelsToTileUnits, + const mat4& posMatrix) const { // Translate query geometry - auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( + const GeometryCoordinates& translatedQueryGeometry = FeatureIndex::translateQueryGeometry( queryGeometry, evaluated.get(), evaluated.get(), - bearing, - pixelsToTileUnits); + transformState.getAngle(), + pixelsToTileUnits).value_or(queryGeometry); // Evaluate functions - auto radius = evaluated.evaluate(zoom, feature) * pixelsToTileUnits; - auto stroke = evaluated.evaluate(zoom, feature) * pixelsToTileUnits; + auto radius = evaluated.evaluate(zoom, feature); + auto stroke = evaluated.evaluate(zoom, feature); + auto size = radius + stroke; + + // For pitch-alignment: map, compare feature geometry to query geometry in the plane of the tile + // Otherwise, compare geometry in the plane of the viewport + // A circle with fixed scaling relative to the viewport gets larger in tile space as it moves into the distance + // A circle with fixed scaling relative to the map gets smaller in viewport space as it moves into the distance + bool alignWithMap = evaluated.evaluate(zoom, feature) == AlignmentType::Map; + const GeometryCoordinates& transformedQueryGeometry = alignWithMap ? + translatedQueryGeometry : + projectQueryGeometry(translatedQueryGeometry, posMatrix, transformState.getSize()); + auto transformedSize = alignWithMap ? size * pixelsToTileUnits : size; + + auto geometry = feature.getGeometries(); + for (auto& ring : geometry) { + for (auto& point : ring) { + const GeometryCoordinate& transformedPoint = alignWithMap ? point : projectPoint(point, posMatrix, transformState.getSize()); + + float adjustedSize = transformedSize; + vec4 center = {{ static_cast(point.x), static_cast(point.y), 0, 1 }}; + matrix::transformMat4(center, center, posMatrix); + auto pitchScale = evaluated.evaluate(zoom, feature); + auto pitchAlignment = evaluated.evaluate(zoom, feature); + if (pitchScale == CirclePitchScaleType::Viewport && pitchAlignment == AlignmentType::Map) { + adjustedSize *= center[3] / transformState.getCameraToCenterDistance(); + } else if (pitchScale == CirclePitchScaleType::Map && pitchAlignment == AlignmentType::Viewport) { + adjustedSize *= transformState.getCameraToCenterDistance() / center[3]; + } + + if (util::polygonIntersectsBufferedPoint(transformedQueryGeometry, transformedPoint, adjustedSize)) return true; + } + } - // Test intersection - return util::polygonIntersectsBufferedMultiPoint(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries(), radius + stroke); + return false; } } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_circle_layer.hpp b/src/mbgl/renderer/layers/render_circle_layer.hpp index f31715f98f1..c9eeae46520 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.hpp +++ b/src/mbgl/renderer/layers/render_circle_layer.hpp @@ -20,8 +20,9 @@ class RenderCircleLayer: public RenderLayer { const GeometryCoordinates&, const GeometryTileFeature&, const float, + const TransformState&, const float, - const float) const override; + const mat4&) const override; std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const override; diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp index 00ab05858f5..d5282c9b0d8 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp @@ -198,14 +198,15 @@ bool RenderFillExtrusionLayer::queryIntersectsFeature( const GeometryCoordinates& queryGeometry, const GeometryTileFeature& feature, const float, - const float bearing, - const float pixelsToTileUnits) const { + const TransformState& transformState, + const float pixelsToTileUnits, + const mat4&) const { auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( queryGeometry, evaluated.get(), evaluated.get(), - bearing, + transformState.getAngle(), pixelsToTileUnits); return util::polygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries()); diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp index 838494cf911..f7ba13c267b 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp @@ -22,8 +22,9 @@ class RenderFillExtrusionLayer: public RenderLayer { const GeometryCoordinates&, const GeometryTileFeature&, const float, + const TransformState&, const float, - const float) const override; + const mat4&) const override; std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const override; diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index 2607ebc170a..c59ca6f906f 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -218,14 +218,15 @@ bool RenderFillLayer::queryIntersectsFeature( const GeometryCoordinates& queryGeometry, const GeometryTileFeature& feature, const float, - const float bearing, - const float pixelsToTileUnits) const { + const TransformState& transformState, + const float pixelsToTileUnits, + const mat4&) const { auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( queryGeometry, evaluated.get(), evaluated.get(), - bearing, + transformState.getAngle(), pixelsToTileUnits); return util::polygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries()); diff --git a/src/mbgl/renderer/layers/render_fill_layer.hpp b/src/mbgl/renderer/layers/render_fill_layer.hpp index a51865698fb..bd195fb828e 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.hpp +++ b/src/mbgl/renderer/layers/render_fill_layer.hpp @@ -20,8 +20,9 @@ class RenderFillLayer: public RenderLayer { const GeometryCoordinates&, const GeometryTileFeature&, const float, + const TransformState&, const float, - const float) const override; + const mat4&) const override; std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const override; diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.cpp b/src/mbgl/renderer/layers/render_heatmap_layer.cpp index 86884b01a4f..dec9edb3180 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.cpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.cpp @@ -201,12 +201,12 @@ bool RenderHeatmapLayer::queryIntersectsFeature( const GeometryCoordinates& queryGeometry, const GeometryTileFeature& feature, const float zoom, - const float bearing, - const float pixelsToTileUnits) const { + const TransformState&, + const float pixelsToTileUnits, + const mat4&) const { (void) queryGeometry; (void) feature; (void) zoom; - (void) bearing; (void) pixelsToTileUnits; return false; } diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.hpp b/src/mbgl/renderer/layers/render_heatmap_layer.hpp index 3f0b1f91b48..29fad7d8b8e 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.hpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.hpp @@ -22,8 +22,9 @@ class RenderHeatmapLayer: public RenderLayer { const GeometryCoordinates&, const GeometryTileFeature&, const float, + const TransformState&, const float, - const float) const override; + const mat4&) const override; void updateColorRamp(); diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp index e7fe4d34b2b..361ad0c76b3 100644 --- a/src/mbgl/renderer/layers/render_line_layer.cpp +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -177,15 +177,16 @@ bool RenderLineLayer::queryIntersectsFeature( const GeometryCoordinates& queryGeometry, const GeometryTileFeature& feature, const float zoom, - const float bearing, - const float pixelsToTileUnits) const { + const TransformState& transformState, + const float pixelsToTileUnits, + const mat4&) const { // Translate query geometry auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( queryGeometry, evaluated.get(), evaluated.get(), - bearing, + transformState.getAngle(), pixelsToTileUnits); // Evaluate function diff --git a/src/mbgl/renderer/layers/render_line_layer.hpp b/src/mbgl/renderer/layers/render_line_layer.hpp index 8bf7e2329d4..5d5d79c0444 100644 --- a/src/mbgl/renderer/layers/render_line_layer.hpp +++ b/src/mbgl/renderer/layers/render_line_layer.hpp @@ -29,8 +29,9 @@ class RenderLineLayer: public RenderLayer { const GeometryCoordinates&, const GeometryTileFeature&, const float, + const TransformState&, const float, - const float) const override; + const mat4&) const override; std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const override; diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp index 5b92ffa4dba..3e2f1d7525d 100644 --- a/src/mbgl/renderer/render_layer.hpp +++ b/src/mbgl/renderer/render_layer.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -17,6 +18,7 @@ class PropertyEvaluationParameters; class PaintParameters; class RenderSource; class RenderTile; +class TransformState; class RenderLayer { protected: @@ -69,8 +71,9 @@ class RenderLayer { const GeometryCoordinates&, const GeometryTileFeature&, const float, + const TransformState&, const float, - const float) const { return false; }; + const mat4&) const { return false; }; virtual std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const = 0; diff --git a/src/mbgl/renderer/render_source.hpp b/src/mbgl/renderer/render_source.hpp index 54a0b5db435..dc80cb1dc69 100644 --- a/src/mbgl/renderer/render_source.hpp +++ b/src/mbgl/renderer/render_source.hpp @@ -64,7 +64,8 @@ class RenderSource : protected TileObserver { queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector& layers, - const RenderedQueryOptions& options) const = 0; + const RenderedQueryOptions& options, + const mat4& projMatrix) const = 0; virtual std::vector querySourceFeatures(const SourceQueryOptions&) const = 0; diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 4348dfca75f..359a674a143 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -717,10 +717,13 @@ std::vector Renderer::Impl::queryRenderedFeatures(const ScreenLineStrin sourceIDs.emplace(layer->baseImpl->source); } + mat4 projMatrix; + transformState.getProjMatrix(projMatrix); + std::unordered_map> resultsByLayer; for (const auto& sourceID : sourceIDs) { if (RenderSource* renderSource = getRenderSource(sourceID)) { - auto sourceResults = renderSource->queryRenderedFeatures(geometry, transformState, layers, options); + auto sourceResults = renderSource->queryRenderedFeatures(geometry, transformState, layers, options, projMatrix); std::move(sourceResults.begin(), sourceResults.end(), std::inserter(resultsByLayer, resultsByLayer.begin())); } } diff --git a/src/mbgl/renderer/sources/render_custom_geometry_source.cpp b/src/mbgl/renderer/sources/render_custom_geometry_source.cpp index 88792db00b9..2d28b8dd849 100644 --- a/src/mbgl/renderer/sources/render_custom_geometry_source.cpp +++ b/src/mbgl/renderer/sources/render_custom_geometry_source.cpp @@ -67,8 +67,9 @@ std::unordered_map> RenderCustomGeometrySource::queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector& layers, - const RenderedQueryOptions& options) const { - return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options); + const RenderedQueryOptions& options, + const mat4& projMatrix) const { + return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, projMatrix); } std::vector RenderCustomGeometrySource::querySourceFeatures(const SourceQueryOptions& options) const { diff --git a/src/mbgl/renderer/sources/render_custom_geometry_source.hpp b/src/mbgl/renderer/sources/render_custom_geometry_source.hpp index 9e47b9e392b..5533fe2b83a 100644 --- a/src/mbgl/renderer/sources/render_custom_geometry_source.hpp +++ b/src/mbgl/renderer/sources/render_custom_geometry_source.hpp @@ -27,7 +27,8 @@ class RenderCustomGeometrySource : public RenderSource { queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector& layers, - const RenderedQueryOptions& options) const final; + const RenderedQueryOptions& options, + const mat4& projMatrix) const final; std::vector querySourceFeatures(const SourceQueryOptions&) const final; diff --git a/src/mbgl/renderer/sources/render_geojson_source.cpp b/src/mbgl/renderer/sources/render_geojson_source.cpp index 7492a4cf162..0e265efff47 100644 --- a/src/mbgl/renderer/sources/render_geojson_source.cpp +++ b/src/mbgl/renderer/sources/render_geojson_source.cpp @@ -85,8 +85,9 @@ std::unordered_map> RenderGeoJSONSource::queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector& layers, - const RenderedQueryOptions& options) const { - return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options); + const RenderedQueryOptions& options, + const mat4& projMatrix) const { + return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, projMatrix); } std::vector RenderGeoJSONSource::querySourceFeatures(const SourceQueryOptions& options) const { diff --git a/src/mbgl/renderer/sources/render_geojson_source.hpp b/src/mbgl/renderer/sources/render_geojson_source.hpp index bcdc1099531..297fa09a292 100644 --- a/src/mbgl/renderer/sources/render_geojson_source.hpp +++ b/src/mbgl/renderer/sources/render_geojson_source.hpp @@ -31,7 +31,8 @@ class RenderGeoJSONSource : public RenderSource { queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector& layers, - const RenderedQueryOptions& options) const final; + const RenderedQueryOptions& options, + const mat4& projMatrix) const final; std::vector querySourceFeatures(const SourceQueryOptions&) const final; diff --git a/src/mbgl/renderer/sources/render_image_source.cpp b/src/mbgl/renderer/sources/render_image_source.cpp index 8506dd1ab51..dce5e401850 100644 --- a/src/mbgl/renderer/sources/render_image_source.cpp +++ b/src/mbgl/renderer/sources/render_image_source.cpp @@ -92,7 +92,8 @@ std::unordered_map> RenderImageSource::queryRenderedFeatures(const ScreenLineString&, const TransformState&, const std::vector&, - const RenderedQueryOptions&) const { + const RenderedQueryOptions&, + const mat4&) const { return std::unordered_map> {}; } diff --git a/src/mbgl/renderer/sources/render_image_source.hpp b/src/mbgl/renderer/sources/render_image_source.hpp index 7dc89d3591e..cf14e180fd5 100644 --- a/src/mbgl/renderer/sources/render_image_source.hpp +++ b/src/mbgl/renderer/sources/render_image_source.hpp @@ -32,7 +32,8 @@ class RenderImageSource : public RenderSource { queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector& layers, - const RenderedQueryOptions& options) const final; + const RenderedQueryOptions& options, + const mat4& projMatrix) const final; std::vector querySourceFeatures(const SourceQueryOptions&) const final; diff --git a/src/mbgl/renderer/sources/render_raster_dem_source.cpp b/src/mbgl/renderer/sources/render_raster_dem_source.cpp index 58bdba18400..fbf2c09d197 100644 --- a/src/mbgl/renderer/sources/render_raster_dem_source.cpp +++ b/src/mbgl/renderer/sources/render_raster_dem_source.cpp @@ -146,7 +146,8 @@ std::unordered_map> RenderRasterDEMSource::queryRenderedFeatures(const ScreenLineString&, const TransformState&, const std::vector&, - const RenderedQueryOptions&) const { + const RenderedQueryOptions&, + const mat4&) const { return std::unordered_map> {}; } diff --git a/src/mbgl/renderer/sources/render_raster_dem_source.hpp b/src/mbgl/renderer/sources/render_raster_dem_source.hpp index 512fe6367cd..48c7803e92b 100644 --- a/src/mbgl/renderer/sources/render_raster_dem_source.hpp +++ b/src/mbgl/renderer/sources/render_raster_dem_source.hpp @@ -27,7 +27,8 @@ class RenderRasterDEMSource : public RenderSource { queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector& layers, - const RenderedQueryOptions& options) const final; + const RenderedQueryOptions& options, + const mat4& projMatrix) const final; std::vector querySourceFeatures(const SourceQueryOptions&) const final; diff --git a/src/mbgl/renderer/sources/render_raster_source.cpp b/src/mbgl/renderer/sources/render_raster_source.cpp index 3162acc7b47..f97ce4e65b6 100644 --- a/src/mbgl/renderer/sources/render_raster_source.cpp +++ b/src/mbgl/renderer/sources/render_raster_source.cpp @@ -76,7 +76,8 @@ std::unordered_map> RenderRasterSource::queryRenderedFeatures(const ScreenLineString&, const TransformState&, const std::vector&, - const RenderedQueryOptions&) const { + const RenderedQueryOptions&, + const mat4&) const { return std::unordered_map> {}; } diff --git a/src/mbgl/renderer/sources/render_raster_source.hpp b/src/mbgl/renderer/sources/render_raster_source.hpp index c60a51c63b0..32539a046d1 100644 --- a/src/mbgl/renderer/sources/render_raster_source.hpp +++ b/src/mbgl/renderer/sources/render_raster_source.hpp @@ -27,7 +27,8 @@ class RenderRasterSource : public RenderSource { queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector& layers, - const RenderedQueryOptions& options) const final; + const RenderedQueryOptions& options, + const mat4& projMatrix) const final; std::vector querySourceFeatures(const SourceQueryOptions&) const final; diff --git a/src/mbgl/renderer/sources/render_vector_source.cpp b/src/mbgl/renderer/sources/render_vector_source.cpp index c9c47359f46..4de4f01e3fe 100644 --- a/src/mbgl/renderer/sources/render_vector_source.cpp +++ b/src/mbgl/renderer/sources/render_vector_source.cpp @@ -79,8 +79,9 @@ std::unordered_map> RenderVectorSource::queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector& layers, - const RenderedQueryOptions& options) const { - return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options); + const RenderedQueryOptions& options, + const mat4& projMatrix) const { + return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, projMatrix); } std::vector RenderVectorSource::querySourceFeatures(const SourceQueryOptions& options) const { diff --git a/src/mbgl/renderer/sources/render_vector_source.hpp b/src/mbgl/renderer/sources/render_vector_source.hpp index a0351c226c0..6fd2425aa3c 100644 --- a/src/mbgl/renderer/sources/render_vector_source.hpp +++ b/src/mbgl/renderer/sources/render_vector_source.hpp @@ -27,7 +27,8 @@ class RenderVectorSource : public RenderSource { queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector& layers, - const RenderedQueryOptions& options) const final; + const RenderedQueryOptions& options, + const mat4& projMatrix) const final; std::vector querySourceFeatures(const SourceQueryOptions&) const final; diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp index e2d4d9829f0..d28e95181b5 100644 --- a/src/mbgl/renderer/tile_pyramid.cpp +++ b/src/mbgl/renderer/tile_pyramid.cpp @@ -241,7 +241,8 @@ void TilePyramid::update(const std::vector>& layer std::unordered_map> TilePyramid::queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector& layers, - const RenderedQueryOptions& options) const { + const RenderedQueryOptions& options, + const mat4& projMatrix) const { std::unordered_map> result; if (renderTiles.empty() || geometry.empty()) { return result; @@ -263,14 +264,19 @@ std::unordered_map> TilePyramid::queryRendered std::tie(b.id.canonical.z, b.id.canonical.y, b.id.wrap, b.id.canonical.x); }); + auto maxPitchScaleFactor = transformState.maxPitchScaleFactor(); + for (const RenderTile& renderTile : sortedTiles) { + const float scale = std::pow(2, transformState.getZoom() - renderTile.id.canonical.z); + auto queryPadding = maxPitchScaleFactor * renderTile.tile.getQueryPadding(layers) * util::EXTENT / util::tileSize / scale; + GeometryCoordinate tileSpaceBoundsMin = TileCoordinate::toGeometryCoordinate(renderTile.id, box.min); - if (tileSpaceBoundsMin.x >= util::EXTENT || tileSpaceBoundsMin.y >= util::EXTENT) { + if (tileSpaceBoundsMin.x - queryPadding >= util::EXTENT || tileSpaceBoundsMin.y - queryPadding >= util::EXTENT) { continue; } GeometryCoordinate tileSpaceBoundsMax = TileCoordinate::toGeometryCoordinate(renderTile.id, box.max); - if (tileSpaceBoundsMax.x < 0 || tileSpaceBoundsMax.y < 0) { + if (tileSpaceBoundsMax.x + queryPadding < 0 || tileSpaceBoundsMax.y + queryPadding < 0) { continue; } @@ -284,7 +290,8 @@ std::unordered_map> TilePyramid::queryRendered tileSpaceQueryGeometry, transformState, layers, - options); + options, + projMatrix); } return result; diff --git a/src/mbgl/renderer/tile_pyramid.hpp b/src/mbgl/renderer/tile_pyramid.hpp index bf3ba0d7b8a..0cef9e2c40d 100644 --- a/src/mbgl/renderer/tile_pyramid.hpp +++ b/src/mbgl/renderer/tile_pyramid.hpp @@ -53,7 +53,8 @@ class TilePyramid { queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector&, - const RenderedQueryOptions& options) const; + const RenderedQueryOptions& options, + const mat4& projMatrix) const; std::vector querySourceFeatures(const SourceQueryOptions&) const; diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index b0b898e61a1..af28fe39637 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -200,33 +200,43 @@ Bucket* GeometryTile::getBucket(const Layer::Impl& layer) const { return it->second.get(); } +float GeometryTile::getQueryPadding(const std::vector& layers) { + float queryPadding = 0; + for (const RenderLayer* layer : layers) { + auto bucket = getBucket(*layer->baseImpl); + if (bucket && bucket->hasData()) { + queryPadding = std::max(queryPadding, bucket->getQueryRadius(*layer)); + } + } + return queryPadding; +} + void GeometryTile::queryRenderedFeatures( std::unordered_map>& result, const GeometryCoordinates& queryGeometry, const TransformState& transformState, const std::vector& layers, - const RenderedQueryOptions& options) { + const RenderedQueryOptions& options, + const mat4& projMatrix) { if (!getData()) return; - // Determine the additional radius needed factoring in property functions - float additionalRadius = 0; - for (const RenderLayer* layer : layers) { - auto bucket = getBucket(*layer->baseImpl); - if (bucket) { - additionalRadius = std::max(additionalRadius, bucket->getQueryRadius(*layer)); - } - } + const float queryPadding = getQueryPadding(layers); + + mat4 posMatrix; + transformState.matrixFor(posMatrix, id.toUnwrapped()); + matrix::multiply(posMatrix, projMatrix, posMatrix); latestFeatureIndex->query(result, queryGeometry, - transformState.getAngle(), + transformState, + posMatrix, util::tileSize * id.overscaleFactor(), std::pow(2, transformState.getZoom() - id.overscaledZ), options, id.toUnwrapped(), layers, - additionalRadius); + queryPadding * transformState.maxPitchScaleFactor()); } void GeometryTile::querySourceFeatures( diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp index a3b2eb6492e..d0490f10097 100644 --- a/src/mbgl/tile/geometry_tile.hpp +++ b/src/mbgl/tile/geometry_tile.hpp @@ -54,12 +54,15 @@ class GeometryTile : public Tile, public GlyphRequestor, ImageRequestor { const GeometryCoordinates& queryGeometry, const TransformState&, const std::vector& layers, - const RenderedQueryOptions& options) override; + const RenderedQueryOptions& options, + const mat4& projMatrix) override; void querySourceFeatures( std::vector& result, const SourceQueryOptions&) override; + float getQueryPadding(const std::vector&) override; + void cancel() override; class LayoutResult { diff --git a/src/mbgl/tile/tile.cpp b/src/mbgl/tile/tile.cpp index e65bc395405..b95944f10e2 100644 --- a/src/mbgl/tile/tile.cpp +++ b/src/mbgl/tile/tile.cpp @@ -37,7 +37,12 @@ void Tile::queryRenderedFeatures( const GeometryCoordinates&, const TransformState&, const std::vector&, - const RenderedQueryOptions&) {} + const RenderedQueryOptions&, + const mat4&) {} + +float Tile::getQueryPadding(const std::vector&) { + return 0; +} void Tile::querySourceFeatures( std::vector&, diff --git a/src/mbgl/tile/tile.hpp b/src/mbgl/tile/tile.hpp index a0effa29a15..23d6864205a 100644 --- a/src/mbgl/tile/tile.hpp +++ b/src/mbgl/tile/tile.hpp @@ -57,12 +57,15 @@ class Tile : private util::noncopyable { const GeometryCoordinates& queryGeometry, const TransformState&, const std::vector&, - const RenderedQueryOptions& options); + const RenderedQueryOptions& options, + const mat4& projMatrix); virtual void querySourceFeatures( std::vector& result, const SourceQueryOptions&); + virtual float getQueryPadding(const std::vector&); + void setTriedCache(); // Returns true when the tile source has received a first response, regardless of whether a load diff --git a/src/mbgl/util/intersection_tests.cpp b/src/mbgl/util/intersection_tests.cpp index e6ce245c0e2..780fce98f92 100644 --- a/src/mbgl/util/intersection_tests.cpp +++ b/src/mbgl/util/intersection_tests.cpp @@ -82,11 +82,16 @@ bool lineIntersectsBufferedLine(const GeometryCoordinates& lineA, const Geometry return false; } +bool polygonIntersectsBufferedPoint(const GeometryCoordinates& polygon, const GeometryCoordinate& point, float radius) { + if (polygonContainsPoint(polygon, point)) return true; + if (pointIntersectsBufferedLine(point, polygon, radius)) return true; + return false; +} + bool polygonIntersectsBufferedMultiPoint(const GeometryCoordinates& polygon, const GeometryCollection& rings, float radius) { for (auto& ring : rings) { for (auto& point : ring) { - if (polygonContainsPoint(polygon, point)) return true; - if (pointIntersectsBufferedLine(point, polygon, radius)) return true; + if (polygonIntersectsBufferedPoint(polygon, point, radius)) return true; } } return false; diff --git a/src/mbgl/util/intersection_tests.hpp b/src/mbgl/util/intersection_tests.hpp index 5bcb29c7679..c105fe4dd0a 100644 --- a/src/mbgl/util/intersection_tests.hpp +++ b/src/mbgl/util/intersection_tests.hpp @@ -9,6 +9,7 @@ bool polygonIntersectsBufferedMultiPoint(const GeometryCoordinates&, const Geome bool polygonIntersectsBufferedMultiLine(const GeometryCoordinates&, const GeometryCollection&, float radius); bool polygonIntersectsPolygon(const GeometryCoordinates&, const GeometryCoordinates&); bool polygonIntersectsMultiPolygon(const GeometryCoordinates&, const GeometryCollection&); +bool polygonIntersectsBufferedPoint(const GeometryCoordinates& polygon, const GeometryCoordinate& point, float radius); } // namespace util } // namespace mbgl