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

Commit

Permalink
[ios] Fix for #2259 - perspective tilt and cameraForLatLngs
Browse files Browse the repository at this point in the history
  • Loading branch information
adam-mapbox committed Oct 26, 2015
1 parent bb62418 commit c382292
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 7 deletions.
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;
double pitch = 0.0;

// cache values for spherical mercator math
Expand Down

0 comments on commit c382292

Please sign in to comment.