[core] Rewrite TileCoordinate in terms of geometry.hpp point
This commit is contained in:
@@ -109,14 +109,9 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim
|
||||
// Find the shortest path otherwise.
|
||||
else startLatLng.unwrapForShortestPath(latLng);
|
||||
|
||||
const ScreenCoordinate startPoint = {
|
||||
state.lngX(startLatLng.longitude),
|
||||
state.latY(startLatLng.latitude),
|
||||
};
|
||||
const ScreenCoordinate endPoint = {
|
||||
state.lngX(latLng.longitude),
|
||||
state.latY(latLng.latitude),
|
||||
};
|
||||
const Point<double> startPoint = state.project(startLatLng);
|
||||
const Point<double> endPoint = state.project(latLng);
|
||||
|
||||
ScreenCoordinate center = getScreenCoordinate(padding);
|
||||
center.y = state.height - center.y;
|
||||
|
||||
@@ -145,11 +140,8 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim
|
||||
state.rotating = angle != startAngle;
|
||||
|
||||
startTransition(camera, animation, [=](double t) {
|
||||
ScreenCoordinate framePoint = util::interpolate(startPoint, endPoint, t);
|
||||
LatLng frameLatLng = {
|
||||
state.yLat(framePoint.y, startWorldSize),
|
||||
state.xLng(framePoint.x, startWorldSize)
|
||||
};
|
||||
Point<double> framePoint = util::interpolate(startPoint, endPoint, t);
|
||||
LatLng frameLatLng = state.unproject(framePoint, startWorldSize);
|
||||
double frameScale = util::interpolate(startScale, scale, t);
|
||||
state.setLatLngZoom(frameLatLng, state.scaleZoom(frameScale));
|
||||
|
||||
@@ -191,14 +183,9 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima
|
||||
LatLng startLatLng = getLatLng(padding).wrapped();
|
||||
startLatLng.unwrapForShortestPath(latLng);
|
||||
|
||||
const ScreenCoordinate startPoint = {
|
||||
state.lngX(startLatLng.longitude),
|
||||
state.latY(startLatLng.latitude),
|
||||
};
|
||||
const ScreenCoordinate endPoint = {
|
||||
state.lngX(latLng.longitude),
|
||||
state.latY(latLng.latitude),
|
||||
};
|
||||
const Point<double> startPoint = state.project(startLatLng);
|
||||
const Point<double> endPoint = state.project(latLng);
|
||||
|
||||
ScreenCoordinate center = getScreenCoordinate(padding);
|
||||
center.y = state.height - center.y;
|
||||
|
||||
@@ -316,14 +303,11 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima
|
||||
double us = u(s);
|
||||
|
||||
// Calculate the current point and zoom level along the flight path.
|
||||
ScreenCoordinate framePoint = util::interpolate(startPoint, endPoint, us);
|
||||
Point<double> framePoint = util::interpolate(startPoint, endPoint, us);
|
||||
double frameZoom = startZoom + state.scaleZoom(1 / w(s));
|
||||
|
||||
// Convert to geographic coordinates and set the new viewpoint.
|
||||
LatLng frameLatLng = {
|
||||
state.yLat(framePoint.y, startWorldSize),
|
||||
state.xLng(framePoint.x, startWorldSize),
|
||||
};
|
||||
LatLng frameLatLng = state.unproject(framePoint, startWorldSize);
|
||||
state.setLatLngZoom(frameLatLng, frameZoom);
|
||||
|
||||
if (angle != startAngle) {
|
||||
|
||||
@@ -201,22 +201,20 @@ bool TransformState::isGestureInProgress() const {
|
||||
|
||||
#pragma mark - Projection
|
||||
|
||||
double TransformState::lngX(double lng) const {
|
||||
return (util::LONGITUDE_MAX + lng) * worldSize() / util::DEGREES_MAX;
|
||||
Point<double> TransformState::project(const LatLng& ll) const {
|
||||
return Point<double>(
|
||||
(util::LONGITUDE_MAX + ll.longitude),
|
||||
(util::LONGITUDE_MAX - util::RAD2DEG * std::log(std::tan(M_PI / 4 + ll.latitude * M_PI / util::DEGREES_MAX)))
|
||||
) * worldSize() / util::DEGREES_MAX;
|
||||
}
|
||||
|
||||
double TransformState::latY(double lat) const {
|
||||
double y_ = util::RAD2DEG * std::log(std::tan(M_PI / 4 + lat * M_PI / util::DEGREES_MAX));
|
||||
return (util::LONGITUDE_MAX - y_) * worldSize() / util::DEGREES_MAX;
|
||||
}
|
||||
|
||||
double TransformState::xLng(double x_, double worldSize_) const {
|
||||
return x_ * util::DEGREES_MAX / worldSize_ - util::LONGITUDE_MAX;
|
||||
}
|
||||
|
||||
double TransformState::yLat(double y_, double worldSize_) const {
|
||||
double y2 = util::LONGITUDE_MAX - y_ * util::DEGREES_MAX / worldSize_;
|
||||
return util::DEGREES_MAX / M_PI * std::atan(std::exp(y2 * util::DEG2RAD)) - 90.0f;
|
||||
LatLng TransformState::unproject(const Point<double>& p, double worldSize, LatLng::WrapMode wrapMode) const {
|
||||
Point<double> p2 = p * util::DEGREES_MAX / worldSize;
|
||||
return LatLng(
|
||||
util::DEGREES_MAX / M_PI * std::atan(std::exp((util::LONGITUDE_MAX - p2.y) * util::DEG2RAD)) - 90.0f,
|
||||
p2.x - util::LONGITUDE_MAX,
|
||||
wrapMode
|
||||
);
|
||||
}
|
||||
|
||||
double TransformState::zoomScale(double zoom) const {
|
||||
@@ -234,7 +232,8 @@ double TransformState::worldSize() const {
|
||||
ScreenCoordinate TransformState::latLngToScreenCoordinate(const LatLng& latLng) const {
|
||||
mat4 mat = coordinatePointMatrix(getZoom());
|
||||
vec4 p;
|
||||
vec4 c = {{ lngX(latLng.longitude) / util::tileSize, latY(latLng.latitude) / util::tileSize, 0, 1 }};
|
||||
Point<double> pt = project(latLng) / double(util::tileSize);
|
||||
vec4 c = {{ pt.x, pt.y, 0, 1 }};
|
||||
matrix::transformMat4(p, c, mat);
|
||||
return { p[0] / p[3], height - p[1] / p[3] };
|
||||
}
|
||||
@@ -263,19 +262,15 @@ LatLng TransformState::screenCoordinateToLatLng(const ScreenCoordinate& point, L
|
||||
|
||||
double w0 = coord0[3];
|
||||
double w1 = coord1[3];
|
||||
double x0 = coord0[0] / w0;
|
||||
double x1 = coord1[0] / w1;
|
||||
double y0 = coord0[1] / w0;
|
||||
double y1 = coord1[1] / w1;
|
||||
|
||||
Point<double> p0 = Point<double>(coord0[0], coord0[1]) / w0;
|
||||
Point<double> p1 = Point<double>(coord1[0], coord1[1]) / w1;
|
||||
|
||||
double z0 = coord0[2] / w0;
|
||||
double z1 = coord1[2] / w1;
|
||||
|
||||
double t = z0 == z1 ? 0 : (targetZ - z0) / (z1 - z0);
|
||||
return {
|
||||
yLat(util::interpolate(y0, y1, t), scale),
|
||||
xLng(util::interpolate(x0, x1, t), scale),
|
||||
wrapMode
|
||||
};
|
||||
|
||||
return unproject(util::interpolate(p0, p1, t), scale, wrapMode);
|
||||
}
|
||||
|
||||
mat4 TransformState::coordinatePointMatrix(double z) const {
|
||||
@@ -322,18 +317,10 @@ void TransformState::constrain(double& scale_, double& x_, double& y_) const {
|
||||
}
|
||||
|
||||
void TransformState::moveLatLng(const LatLng& latLng, const ScreenCoordinate& anchor) {
|
||||
auto latLngToTileCoord = [&](const LatLng& ll) -> Point<double> {
|
||||
return { lngX(ll.longitude), latY(ll.latitude) };
|
||||
};
|
||||
|
||||
auto tileCoordToLatLng = [&](const Point<double> coord) -> LatLng {
|
||||
return { yLat(coord.y, worldSize()), xLng(coord.x, worldSize()) };
|
||||
};
|
||||
|
||||
auto centerCoord = latLngToTileCoord(getLatLng(LatLng::Unwrapped));
|
||||
auto latLngCoord = latLngToTileCoord(latLng);
|
||||
auto anchorCoord = latLngToTileCoord(screenCoordinateToLatLng(anchor));
|
||||
setLatLngZoom(tileCoordToLatLng(centerCoord + latLngCoord - anchorCoord), getZoom());
|
||||
auto centerCoord = project(getLatLng(LatLng::Unwrapped));
|
||||
auto latLngCoord = project(latLng);
|
||||
auto anchorCoord = project(screenCoordinateToLatLng(anchor));
|
||||
setLatLngZoom(unproject(centerCoord + latLngCoord - anchorCoord, worldSize()), getZoom());
|
||||
}
|
||||
|
||||
void TransformState::setLatLngZoom(const LatLng &latLng, double zoom) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <mbgl/map/mode.hpp>
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
#include <mbgl/util/constants.hpp>
|
||||
#include <mbgl/util/mat4.hpp>
|
||||
|
||||
@@ -69,10 +70,8 @@ public:
|
||||
ScreenCoordinate latLngToScreenCoordinate(const LatLng&) const;
|
||||
LatLng screenCoordinateToLatLng(const ScreenCoordinate&, LatLng::WrapMode = LatLng::Unwrapped) const;
|
||||
|
||||
double xLng(double x, double worldSize) const;
|
||||
double yLat(double y, double worldSize) const;
|
||||
double lngX(double lon) const;
|
||||
double latY(double lat) const;
|
||||
Point<double> project(const LatLng&) const;
|
||||
LatLng unproject(const Point<double>&, double worldSize, LatLng::WrapMode = LatLng::Unwrapped) const;
|
||||
|
||||
private:
|
||||
bool rotatedNorth() const;
|
||||
|
||||
@@ -335,10 +335,10 @@ std::vector<TileCoordinate> pointsToCoordinates(const std::vector<ScreenCoordina
|
||||
static Point<int16_t> coordinateToTilePoint(const CanonicalTileID& tileID, const TileCoordinate& coord) {
|
||||
auto zoomedCoord = coord.zoomTo(tileID.z);
|
||||
return {
|
||||
int16_t(util::clamp<int64_t>((zoomedCoord.x - tileID.x) * util::EXTENT,
|
||||
int16_t(util::clamp<int64_t>((zoomedCoord.p.x - tileID.x) * util::EXTENT,
|
||||
std::numeric_limits<int16_t>::min(),
|
||||
std::numeric_limits<int16_t>::max())),
|
||||
int16_t(util::clamp<int64_t>((zoomedCoord.y - tileID.y) * util::EXTENT,
|
||||
int16_t(util::clamp<int64_t>((zoomedCoord.p.y - tileID.y) * util::EXTENT,
|
||||
std::numeric_limits<int16_t>::min(),
|
||||
std::numeric_limits<int16_t>::max()))
|
||||
};
|
||||
@@ -364,10 +364,10 @@ std::unordered_map<std::string, std::vector<Feature>> Source::queryRenderedFeatu
|
||||
double z = queryGeometry[0].z;
|
||||
|
||||
for (const auto& c : queryGeometry) {
|
||||
minX = util::min(minX, c.x);
|
||||
minY = util::min(minY, c.y);
|
||||
maxX = util::max(maxX, c.x);
|
||||
maxY = util::max(maxY, c.y);
|
||||
minX = util::min(minX, c.p.x);
|
||||
minY = util::min(minY, c.p.y);
|
||||
maxX = util::max(maxX, c.p.x);
|
||||
maxY = util::max(maxY, c.p.y);
|
||||
}
|
||||
|
||||
std::map<CanonicalTileID, TileQuery> tileQueries;
|
||||
@@ -375,8 +375,8 @@ std::unordered_map<std::string, std::vector<Feature>> Source::queryRenderedFeatu
|
||||
for (const auto& tilePtr : tiles) {
|
||||
const auto& tile = tilePtr.second;
|
||||
|
||||
auto tileSpaceBoundsMin = coordinateToTilePoint(tile.id.canonical, { minX, minY, z });
|
||||
auto tileSpaceBoundsMax = coordinateToTilePoint(tile.id.canonical, { maxX, maxY, z });
|
||||
auto tileSpaceBoundsMin = coordinateToTilePoint(tile.id.canonical, { { minX, minY }, z });
|
||||
auto tileSpaceBoundsMax = coordinateToTilePoint(tile.id.canonical, { { maxX, maxY }, z });
|
||||
|
||||
if (tileSpaceBoundsMin.x >= util::EXTENT || tileSpaceBoundsMin.y >= util::EXTENT ||
|
||||
tileSpaceBoundsMax.x < 0 || tileSpaceBoundsMax.y < 0) continue;
|
||||
|
||||
@@ -1,27 +1,20 @@
|
||||
#ifndef MBGL_UTIL_TILE_COORDINATE
|
||||
#define MBGL_UTIL_TILE_COORDINATE
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/style/types.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
#include <mbgl/map/transform_state.hpp>
|
||||
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class TransformState;
|
||||
|
||||
// Has floating point x/y coordinates.
|
||||
// Used for computing the tiles that need to be visible in the viewport.
|
||||
class TileCoordinate {
|
||||
public:
|
||||
double x, y, z;
|
||||
Point<double> p;
|
||||
double z;
|
||||
|
||||
static TileCoordinate fromLatLng(const TransformState& state, double zoom, const LatLng& latLng) {
|
||||
const double scale = std::pow(2, zoom - state.getZoom());
|
||||
return {
|
||||
state.lngX(latLng.longitude) * scale / util::tileSize,
|
||||
state.latY(latLng.latitude) * scale / util::tileSize,
|
||||
zoom
|
||||
};
|
||||
return { state.project(latLng) * scale / double(util::tileSize), zoom };
|
||||
}
|
||||
|
||||
static TileCoordinate fromScreenCoordinate(const TransformState& state, double zoom, const ScreenCoordinate& point) {
|
||||
@@ -29,11 +22,8 @@ public:
|
||||
}
|
||||
|
||||
TileCoordinate zoomTo(double zoom) const {
|
||||
double scale = std::pow(2, zoom - z);
|
||||
return { x * scale, y * scale, zoom };
|
||||
return { p * std::pow(2, zoom - z), zoom };
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,7 +16,7 @@ struct edge {
|
||||
double x1 = 0, y1 = 0;
|
||||
double dx = 0, dy = 0;
|
||||
|
||||
edge(TileCoordinate a, TileCoordinate b) {
|
||||
edge(Point<double> a, Point<double> b) {
|
||||
if (a.y > b.y) std::swap(a, b);
|
||||
x0 = a.x;
|
||||
y0 = a.y;
|
||||
@@ -54,7 +54,7 @@ static void scanSpans(edge e0, edge e1, int32_t ymin, int32_t ymax, ScanLine sca
|
||||
}
|
||||
|
||||
// scan-line conversion
|
||||
static void scanTriangle(const TileCoordinate& a, const TileCoordinate& b, const TileCoordinate& c, int32_t ymin, int32_t ymax, ScanLine& scanLine) {
|
||||
static void scanTriangle(const Point<double>& a, const Point<double>& b, const Point<double>& c, int32_t ymin, int32_t ymax, ScanLine& scanLine) {
|
||||
edge ab = edge(a, b);
|
||||
edge bc = edge(b, c);
|
||||
edge ca = edge(c, a);
|
||||
@@ -75,17 +75,12 @@ namespace util {
|
||||
|
||||
namespace {
|
||||
|
||||
std::vector<UnwrappedTileID> tileCover(const TileCoordinate& tl,
|
||||
const TileCoordinate& tr,
|
||||
const TileCoordinate& br,
|
||||
const TileCoordinate& bl,
|
||||
const TileCoordinate& c,
|
||||
std::vector<UnwrappedTileID> tileCover(const Point<double>& tl,
|
||||
const Point<double>& tr,
|
||||
const Point<double>& br,
|
||||
const Point<double>& bl,
|
||||
const Point<double>& c,
|
||||
int32_t z) {
|
||||
assert(tl.z == z);
|
||||
assert(tr.z == z);
|
||||
assert(br.z == z);
|
||||
assert(bl.z == z);
|
||||
assert(c.z == z);
|
||||
const int32_t tiles = 1 << z;
|
||||
|
||||
struct ID {
|
||||
@@ -154,11 +149,11 @@ std::vector<UnwrappedTileID> tileCover(const LatLngBounds& bounds_, int32_t z) {
|
||||
|
||||
const TransformState state;
|
||||
return tileCover(
|
||||
TileCoordinate::fromLatLng(state, z, bounds.northwest()),
|
||||
TileCoordinate::fromLatLng(state, z, bounds.northeast()),
|
||||
TileCoordinate::fromLatLng(state, z, bounds.southeast()),
|
||||
TileCoordinate::fromLatLng(state, z, bounds.southwest()),
|
||||
TileCoordinate::fromLatLng(state, z, bounds.center()),
|
||||
TileCoordinate::fromLatLng(state, z, bounds.northwest()).p,
|
||||
TileCoordinate::fromLatLng(state, z, bounds.northeast()).p,
|
||||
TileCoordinate::fromLatLng(state, z, bounds.southeast()).p,
|
||||
TileCoordinate::fromLatLng(state, z, bounds.southwest()).p,
|
||||
TileCoordinate::fromLatLng(state, z, bounds.center()).p,
|
||||
z);
|
||||
}
|
||||
|
||||
@@ -166,11 +161,11 @@ std::vector<UnwrappedTileID> tileCover(const TransformState& state, int32_t z) {
|
||||
const double w = state.getWidth();
|
||||
const double h = state.getHeight();
|
||||
return tileCover(
|
||||
TileCoordinate::fromScreenCoordinate(state, z, { 0, 0 }),
|
||||
TileCoordinate::fromScreenCoordinate(state, z, { w, 0 }),
|
||||
TileCoordinate::fromScreenCoordinate(state, z, { w, h }),
|
||||
TileCoordinate::fromScreenCoordinate(state, z, { 0, h }),
|
||||
TileCoordinate::fromScreenCoordinate(state, z, { w/2, h/2 }),
|
||||
TileCoordinate::fromScreenCoordinate(state, z, { 0, 0 }).p,
|
||||
TileCoordinate::fromScreenCoordinate(state, z, { w, 0 }).p,
|
||||
TileCoordinate::fromScreenCoordinate(state, z, { w, h }).p,
|
||||
TileCoordinate::fromScreenCoordinate(state, z, { 0, h }).p,
|
||||
TileCoordinate::fromScreenCoordinate(state, z, { w/2, h/2 }).p,
|
||||
z);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user