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

[ios] Fix for #2259 - perspective tilt and cameraForLatLngs #2987

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/mbgl/map/map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ class Map : private util::noncopyable {
};

RenderState renderState = RenderState::never;

CameraOptions cameraForLatLngsHelper(std::vector<LatLng> latLngs, EdgeInsets padding);
};

}
Expand Down
49 changes: 48 additions & 1 deletion src/mbgl/map/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,31 @@ CameraOptions Map::cameraForLatLngBounds(LatLngBounds bounds, EdgeInsets padding
};
return cameraForLatLngs(segment, padding);
}



CameraOptions Map::cameraForLatLngs(std::vector<LatLng> latLngs, EdgeInsets padding) {
if (getPitch() < 0.01f) {
return cameraForLatLngsHelper(latLngs, padding);
} else {
TransformState oldTransform = this->transform->getState();
double oldZoom = getZoom();

//10 is a magic number; the process is iterative, so we get closer with each call,
//and 10 was chosen to produce good results without taking overly long. It could
//probably be lower, like 4 or 5, without affecting much.
for (int i = 0; i < 10; ++i) {
CameraOptions o = cameraForLatLngsHelper(latLngs, padding);
easeTo(o);
}
CameraOptions result = cameraForLatLngsHelper(latLngs, padding);
this->transform->restoreState(oldTransform);
setZoom(oldZoom);
return result;
}
}


CameraOptions Map::cameraForLatLngsHelper(std::vector<LatLng> latLngs, EdgeInsets padding) {
CameraOptions options;
if (latLngs.empty()) {
return options;
Expand Down Expand Up @@ -259,6 +282,30 @@ CameraOptions Map::cameraForLatLngs(std::vector<LatLng> latLngs, EdgeInsets padd

options.center = centerLatLng;
options.zoom = zoom;

if (getPitch() > 0.f) {
TransformState oldTransform = this->transform->getState();
double oldZoom = getZoom();
//Now set that camera
easeTo(options);

//Now calculate the x dimension size relative to the screen width
for (LatLng latLng : latLngs) {
vec2<> pixel = pixelForLatLng(latLng);
swPixel.x = std::min(swPixel.x, pixel.x);
nePixel.x = std::max(nePixel.x, pixel.x);
swPixel.y = std::min(swPixel.y, pixel.y);
nePixel.y = std::max(nePixel.y, pixel.y);
}
size = nePixel - swPixel;
scaleX = (getWidth() - padding.left - padding.right) / size.x;
zoom = ::log2(getScale() * scaleX);
zoom = ::fmax(::fmin(zoom, getMaxZoom()), getMinZoom());
options.zoom = zoom;

this->transform->restoreState(oldTransform);
setZoom(oldZoom);
}
return options;
}

Expand Down
1 change: 1 addition & 0 deletions src/mbgl/map/transform.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class Transform : private util::noncopyable {

// Transform state
const TransformState getState() const { return state; }
void restoreState(TransformState oldState) { state = oldState; }
bool isRotating() const { return state.isRotating(); }
bool isScaling() const { return state.isScaling(); }
bool isPanning() const { return state.isPanning(); }
Expand Down
13 changes: 8 additions & 5 deletions src/mbgl/map/transform_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,17 @@ void TransformState::matrixFor(mat4& matrix, const TileID& id, const int8_t z) c
}

void TransformState::getProjMatrix(mat4& projMatrix) const {
double halfFov = std::atan(0.5 / getAltitude());
double topHalfSurfaceDistance = std::sin(halfFov) * getAltitude() /
double halfFov = FOV * 0.5f * M_PI / 180.f;//std::atan(0.5 / getAltitude());
double altitude = 0.5 / std::tan(halfFov);
double topHalfSurfaceDistance = std::sin(halfFov) * altitude /
std::sin(M_PI / 2.0f - getPitch() - halfFov);
// Calculate z value of the farthest fragment that should be rendered.
double farZ = std::cos(M_PI / 2.0f - getPitch()) * topHalfSurfaceDistance + getAltitude();
double farZ = std::cos(M_PI / 2.0f - getPitch()) * topHalfSurfaceDistance + altitude;

matrix::perspective(projMatrix, 2.0f * std::atan((getHeight() / 2.0f) / getAltitude()),
matrix::perspective(projMatrix, 2.0f * std::atan((getHeight() / 2.0f) / altitude),
double(getWidth()) / getHeight(), 0.1, farZ);

matrix::translate(projMatrix, projMatrix, 0, 0, -getAltitude());
matrix::translate(projMatrix, projMatrix, 0, 0, -altitude);

// After the rotateX, z values are in pixel units. Convert them to
// altitude unites. 1 altitude unit = the screen height.
Expand Down Expand Up @@ -157,6 +158,8 @@ float TransformState::getAngle() const {
}

float TransformState::getAltitude() const {
double halfFov = FOV * 0.5f * M_PI / 180.f;//std::atan(0.5 / getAltitude());
double altitude = 0.5 / std::tan(halfFov);
return altitude;
}

Expand Down
2 changes: 1 addition & 1 deletion src/mbgl/map/transform_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class TransformState {
double x = 0, y = 0;
double angle = 0;
double scale = 1;
double altitude = 1.5;
double FOV = 36.87;
Copy link
Contributor

Choose a reason for hiding this comment

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

As of #3362, iOS-specific calculations assume a vertical FOV of 30°, which is consistent with MapKit.

double pitch = 0.0;

// cache values for spherical mercator math
Expand Down