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

[core] Guard against camera's minScale being NaN #5693

Merged
merged 1 commit into from
Jul 15, 2016

Conversation

friedbunny
Copy link
Contributor

@friedbunny friedbunny commented Jul 14, 2016

Fixes a bug where calculating a camera's padded bounds for a single point would cause division by zero, resulting in NaN for minScale. This invalid minScale would then be used to create an invalid padded centerPixel.

This was introduced by 8e30a4a in #4285, where the scale and padding calculations were split.

The “Add Custom Callout Point” option in ios-app exercises this bug, where the map zooms in on a single annotation, à la:

[self.mapView showAnnotations:@[ oneSingularAnnotation ] animated:NO];

/cc @brunoabinader @1ec5

@friedbunny friedbunny added bug Core The cross-platform C++ core, aka mbgl labels Jul 14, 2016
@friedbunny friedbunny added this to the ios-v3.3.1 milestone Jul 14, 2016
@friedbunny friedbunny self-assigned this Jul 14, 2016
@@ -509,7 +509,7 @@ CameraOptions Map::cameraForLatLngs(const std::vector<LatLng>& latLngs, optional
scaleX -= (padding->left + padding->right) / width;
scaleY -= (padding->top + padding->bottom) / height;
}
double minScale = ::fmin(scaleX, scaleY);
double minScale = (isnan(scaleX) && isnan(scaleY)) ? INFINITY : ::fmin(scaleX, scaleY);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of checking for NaN here, I think perhaps we should condition some of the logic above on whether width or height is zero.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, this is probably better:

    // Calculate the zoom level.
    double minScale = INFINITY;
    if (width > 0 || height > 0) {
        double scaleX = getWidth() / width;
        double scaleY = getHeight() / height;
        if (padding && *padding) {
            scaleX -= (padding->left + padding->right) / width;
            scaleY -= (padding->top + padding->bottom) / height;
        }
        minScale = ::fmin(scaleX, scaleY);
    }
    double zoom = util::log2(getScale() * minScale);
    zoom = util::clamp(zoom, getMinZoom(), getMaxZoom());

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

friedbunny added a commit to mapbox/ios-sdk-examples that referenced this pull request Jul 14, 2016
`-showAnnotations:animated:` is broken for a single point: mapbox/mapbox-gl-native#5693.
scaleX -= (padding->left + padding->right) / width;
scaleY -= (padding->top + padding->bottom) / height;
}
minScale = ::fmin(scaleX, scaleY);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: We have a generic util::min in mbgl/math/minmax.hpp.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched in b92a2f3.

@brunoabinader
Copy link
Member

Good catch @friedbunny 👍

Fixes a bug where calculating the padded bounds for a single point would cause division by zero, resulting in NaN for `minScale`. This invalid `minScale` would then be used to create an invalid padded `centerPixel`.
@friedbunny friedbunny merged commit 09221ec into release-ios-v3.3.0 Jul 15, 2016
@friedbunny friedbunny deleted the fb-delicious-camera-nan branch July 15, 2016 16:56
@friedbunny
Copy link
Contributor Author

For posterity, the symptoms of this bug were: using -showAnnotations:animated: on a single point would fail silently and the map would not move to show the annotation.

1ec5 added a commit that referenced this pull request Jul 18, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Core The cross-platform C++ core, aka mbgl
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants