[core] Avoid NaNs in TransformState unit conversions
Fix cases where e.g. state has either zero width or height, causing the unit convertion functions would return NaNs.
This commit is contained in:
@@ -45,24 +45,23 @@ Transform::Transform(std::function<void(MapChange)> callback_,
|
||||
#pragma mark - Map View
|
||||
|
||||
bool Transform::resize(const std::array<uint16_t, 2> size) {
|
||||
if (state.width != size[0] || state.height != size[1]) {
|
||||
|
||||
if (callback) {
|
||||
callback(MapChangeRegionWillChange);
|
||||
}
|
||||
|
||||
state.width = size[0];
|
||||
state.height = size[1];
|
||||
state.constrain(state.scale, state.x, state.y);
|
||||
|
||||
if (callback) {
|
||||
callback(MapChangeRegionDidChange);
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
if (state.width == size[0] && state.height == size[1]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback(MapChangeRegionWillChange);
|
||||
}
|
||||
|
||||
state.width = size[0];
|
||||
state.height = size[1];
|
||||
state.constrain(state.scale, state.x, state.y);
|
||||
|
||||
if (callback) {
|
||||
callback(MapChangeRegionDidChange);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma mark - Camera
|
||||
|
||||
@@ -230,6 +230,10 @@ double TransformState::worldSize() const {
|
||||
}
|
||||
|
||||
ScreenCoordinate TransformState::latLngToScreenCoordinate(const LatLng& latLng) const {
|
||||
if (width == 0 || height == 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
mat4 mat = coordinatePointMatrix(getZoom());
|
||||
vec4 p;
|
||||
Point<double> pt = project(latLng) / double(util::tileSize);
|
||||
@@ -239,6 +243,10 @@ ScreenCoordinate TransformState::latLngToScreenCoordinate(const LatLng& latLng)
|
||||
}
|
||||
|
||||
LatLng TransformState::screenCoordinateToLatLng(const ScreenCoordinate& point, LatLng::WrapMode wrapMode) const {
|
||||
if (width == 0 || height == 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
float targetZ = 0;
|
||||
mat4 mat = coordinatePointMatrix(getZoom());
|
||||
|
||||
|
||||
@@ -474,3 +474,43 @@ TEST(Transform, Camera) {
|
||||
transform.updateTransitions(transform.getTransitionStart() + transform.getTransitionDuration());
|
||||
ASSERT_FALSE(transform.inTransition());
|
||||
}
|
||||
|
||||
TEST(Transform, DefaultTransform) {
|
||||
Transform transform;
|
||||
const TransformState& state = transform.getState();
|
||||
|
||||
LatLng nullIsland, latLng = {};
|
||||
ScreenCoordinate center, point = {};
|
||||
const uint16_t min = std::numeric_limits<uint16_t>::min();
|
||||
const uint16_t max = std::numeric_limits<uint16_t>::max();
|
||||
|
||||
auto testConversions = [&](const LatLng& coord, const ScreenCoordinate& screenCoord) {
|
||||
latLng = state.screenCoordinateToLatLng(center);
|
||||
ASSERT_NEAR(latLng.latitude, coord.latitude, 0.000001);
|
||||
ASSERT_NEAR(latLng.longitude, coord.longitude, 0.000001);
|
||||
point = state.latLngToScreenCoordinate(nullIsland);
|
||||
ASSERT_DOUBLE_EQ(point.x, screenCoord.x);
|
||||
ASSERT_DOUBLE_EQ(point.y, screenCoord.y);
|
||||
};
|
||||
|
||||
testConversions(nullIsland, center);
|
||||
|
||||
// Cannot assign the current size.
|
||||
ASSERT_FALSE(transform.resize({{}}));
|
||||
|
||||
ASSERT_TRUE(transform.resize({{ min, max }}));
|
||||
testConversions(nullIsland, center);
|
||||
|
||||
ASSERT_TRUE(transform.resize({{ max, min }}));
|
||||
testConversions(nullIsland, center);
|
||||
|
||||
ASSERT_TRUE(transform.resize({{ min, min }}));
|
||||
testConversions(nullIsland, center);
|
||||
|
||||
center = { max / 2., max / 2. };
|
||||
|
||||
// -1 evaluates to UINT_MAX.
|
||||
ASSERT_TRUE(transform.resize({{ static_cast<uint16_t>(-1), static_cast<uint16_t>(-1) }}));
|
||||
ASSERT_FALSE(transform.resize({{ max, max }}));
|
||||
testConversions(nullIsland, center);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user