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

Commit

Permalink
[core] Fix collision with content insets
Browse files Browse the repository at this point in the history
Viewport center offset usage was wrongly submitted in #14664. It was part of alternative approach that used enlarged viewport. Existing and added tests were not sufficient to spot the regression, since the collision check padding is usually larger than the center offset x and y. Annotation picking has tolerance of only 10 pixels but no annotation integration test was using content insets.

Usage of offset is not needed because `posMatrix` in e.g. `CollisionIndex::projectPoint(const mat4& posMatrix, const Point<float>& point)` already incorporates center offset (projection matrix) and the code in current master was just offsetting all by the value.

Modified [ios] MGLAnnotationViewIntegrationTests.testSelectingAnnotationWithCenterOffset to use different insets. It verifies the fix.

Fixes [iOS] Annotations are not selectable (added via iosapp menu) #15106:

In case of #15106, view's original content insets is {top:88, bottom:34}, causing that center offset is {x:0, y:27} and selection with tolerance of 10 wouldn't select annotation.
After tapping the view, so that the header gets removed, view's content insets get changed to {top:44, bottom:34}, center offset is {x:0, y:5} and annotation selection would work, as described in #15106.

Fixes: #15106
  • Loading branch information
astojilj authored and friedbunny committed Jul 17, 2019
1 parent 8fe469f commit ae38a22
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -401,15 +401,17 @@ - (void)testSelectingAnnotationWithCenterOffset {
for (CGFloat dx = -100.0; dx <= 100.0; dx += 100.0 ) {
for (CGFloat dy = -100.0; dy <= 100.0; dy += 100.0 ) {
CGVector offset = CGVectorMake(dx, dy);
[self internalTestSelectingAnnotationWithCenterOffsetWithOffset:offset];
UIEdgeInsets edgeInsets = UIEdgeInsetsMake(fmax(-dy, 0.0), fmax(-dy, 0.0), fmax(dy, 0.0), fmax(dx, 0.0));
[self internalTestSelectingAnnotationWithCenterOffsetWithOffset:offset edgeInsets:edgeInsets];
}
}
}

- (void)internalTestSelectingAnnotationWithCenterOffsetWithOffset:(CGVector)offset {
- (void)internalTestSelectingAnnotationWithCenterOffsetWithOffset:(CGVector)offset edgeInsets:(UIEdgeInsets)edgeInsets {

NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReuseIdentifer";

self.mapView.contentInset = edgeInsets;
CGSize size = self.mapView.bounds.size;

CGSize annotationSize = CGSizeMake(40.0, 40.0);
Expand Down Expand Up @@ -449,8 +451,8 @@ - (void)internalTestSelectingAnnotationWithCenterOffsetWithOffset:(CGVector)offs

// Check that the annotation is in the center of the view
CGPoint annotationPoint = [self.mapView convertCoordinate:point.coordinate toPointToView:self.mapView];
XCTAssertEqualWithAccuracy(annotationPoint.x, size.width/2.0, 0.25);
XCTAssertEqualWithAccuracy(annotationPoint.y, size.height/2.0, 0.25);
XCTAssertEqualWithAccuracy(annotationPoint.x, (size.width - edgeInsets.right + edgeInsets.left)/2.0, 0.25);
XCTAssertEqualWithAccuracy(annotationPoint.y, (size.height - edgeInsets.bottom + edgeInsets.top)/2.0, 0.25);

// Now test taps around the annotation
CGPoint tapPoint = CGPointMake(annotationPoint.x + offset.dx, annotationPoint.y + offset.dy);
Expand Down
8 changes: 4 additions & 4 deletions src/mbgl/map/transform_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,6 @@ double TransformState::getMaxZoom() const {
return scaleZoom(max_scale);
}

ScreenCoordinate TransformState::getCenterOffset() const {
return { 0.5 * (edgeInsets.left() - edgeInsets.right()), 0.5 * (edgeInsets.top() - edgeInsets.bottom()) };
}

#pragma mark - Rotation

float TransformState::getBearing() const {
Expand Down Expand Up @@ -377,6 +373,10 @@ void TransformState::constrain(double& scale_, double& x_, double& y_) const {
}
}

ScreenCoordinate TransformState::getCenterOffset() const {
return { 0.5 * (edgeInsets.left() - edgeInsets.right()), 0.5 * (edgeInsets.top() - edgeInsets.bottom()) };
}

void TransformState::moveLatLng(const LatLng& latLng, const ScreenCoordinate& anchor) {
auto centerCoord = Projection::project(getLatLng(LatLng::Unwrapped), scale);
auto latLngCoord = Projection::project(latLng, scale);
Expand Down
8 changes: 4 additions & 4 deletions src/mbgl/map/transform_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,6 @@ class TransformState {
void setMaxZoom(double);
double getMaxZoom() const;

// Viewport center offset, from [size.width / 2, size.height / 2], defined
// by |edgeInsets| in screen coordinates, with top left origin.
ScreenCoordinate getCenterOffset() const;

// Rotation
float getBearing() const;
float getFieldOfView() const;
Expand Down Expand Up @@ -100,6 +96,10 @@ class TransformState {
bool rotatedNorth() const;
void constrain(double& scale, double& x, double& y) const;

// Viewport center offset, from [size.width / 2, size.height / 2], defined
// by |edgeInsets| in screen coordinates, with top left origin.
ScreenCoordinate getCenterOffset() const;

LatLngBounds bounds;

// Limit the amount of zooming possible on the map.
Expand Down
10 changes: 4 additions & 6 deletions src/mbgl/text/collision_index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,12 +348,11 @@ std::pair<float,float> CollisionIndex::projectAnchor(const mat4& posMatrix, cons
std::pair<Point<float>,float> CollisionIndex::projectAndGetPerspectiveRatio(const mat4& posMatrix, const Point<float>& point) const {
vec4 p = {{ point.x, point.y, 0, 1 }};
matrix::transformMat4(p, p, posMatrix);
auto offset = transformState.getCenterOffset();
auto size = transformState.getSize();
return std::make_pair(
Point<float>(
(((p[0] / p[3] + 1) / 2) * size.width) + viewportPadding + offset.x,
(((-p[1] / p[3] + 1) / 2) * size.height) + viewportPadding + offset.y
(((p[0] / p[3] + 1) / 2) * size.width) + viewportPadding,
(((-p[1] / p[3] + 1) / 2) * size.height) + viewportPadding
),
// See perspective ratio comment in symbol_sdf.vertex
// We're doing collision detection in viewport space so we need
Expand All @@ -365,11 +364,10 @@ std::pair<Point<float>,float> CollisionIndex::projectAndGetPerspectiveRatio(cons
Point<float> CollisionIndex::projectPoint(const mat4& posMatrix, const Point<float>& point) const {
vec4 p = {{ point.x, point.y, 0, 1 }};
matrix::transformMat4(p, p, posMatrix);
auto offset = transformState.getCenterOffset();
auto size = transformState.getSize();
return Point<float> {
static_cast<float>((((p[0] / p[3] + 1) / 2) * size.width) + viewportPadding + offset.x),
static_cast<float>((((-p[1] / p[3] + 1) / 2) * size.height) + viewportPadding + offset.y) };
static_cast<float>((((p[0] / p[3] + 1) / 2) * size.width) + viewportPadding),
static_cast<float>((((-p[1] / p[3] + 1) / 2) * size.height) + viewportPadding) };
}

} // namespace mbgl

0 comments on commit ae38a22

Please sign in to comment.