From f98078528b82251429543056760e6288a5a1ca69 Mon Sep 17 00:00:00 2001 From: Varun Talwar Date: Fri, 12 Sep 2014 17:51:44 -0400 Subject: [PATCH 1/4] start work: geoUtil --- core/mapTile/mapTile.h | 3 --- core/util/projection.h | 6 ++++++ 2 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 core/util/projection.h diff --git a/core/mapTile/mapTile.h b/core/mapTile/mapTile.h index 962a6e761b..5b76cfb76f 100644 --- a/core/mapTile/mapTile.h +++ b/core/mapTile/mapTile.h @@ -19,9 +19,6 @@ class MapTile { //Helper Functions bool setVBO(std::vector _vboData); glm::vec2 GetBoundingBox(); - //Maybe these should be moved 2 functions to sceneDefinition - glm::vec3 MercToPix(); - glm::vec2 MercToLatLong(); ~MapTile() { m_Vertices.clear(); } diff --git a/core/util/projection.h b/core/util/projection.h new file mode 100644 index 0000000000..f14a003fb0 --- /dev/null +++ b/core/util/projection.h @@ -0,0 +1,6 @@ +#pragma one + +class MercatorProjection { + +} + From 6280e2d274c1db0a0e4c4cc4e23cf60cb8a25815 Mon Sep 17 00:00:00 2001 From: Varun Talwar Date: Mon, 15 Sep 2014 22:21:36 -0400 Subject: [PATCH 2/4] a utility projection class and mercprojection class --- core/util/projection.cpp | 80 ++++++++++++++++++++++++++++++++++++++++ core/util/projection.h | 49 +++++++++++++++++++++++- 2 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 core/util/projection.cpp diff --git a/core/util/projection.cpp b/core/util/projection.cpp new file mode 100644 index 0000000000..8e3d7eb17a --- /dev/null +++ b/core/util/projection.cpp @@ -0,0 +1,80 @@ +#include + +#include "projection.h" + + +//Constructor for MercProjection +MercProjection::MercProjection(ProjectionType _type, int _tileSize) : MapProjection(_type), m_TileSize(_tileSize) { + float invTileSize = 1.0/m_TileSize; + m_Res = 2.0 * HALF_CIRCUMFERENCE * invTileSize; +} + +glm::vec2 MercProjection::LatLonToMeters(glm::vec2 _latLon) { + glm::vec2 meters; + float inv180 = 1.0/180.0; + float inv360 = 1.0/360.0; + //Lon -> origin shift, as parallel lines + meters.x = _latLon.y * HALF_CIRCUMFERENCE * inv180; + //Lat -> first do scaling as per mercator then origin shift + meters.y = glm::log( glm::tan(90.0 + _latLon.x) * PI * inv360) * PI * inv180; + meters.y = meters.y * HALF_CIRCUMFERENCE * inv180; + return meters; +} + +glm::vec2 MercProjection::MetersToLatLon(glm::vec2 _meters) { + glm::vec2 latLon; + float invHalfCircum = 1.0/HALF_CIRCUMFERENCE; + float inv180 = 1.0/180.0; + float invPI = 1.0/PI; + latLon.y = _meters.x * invHalfCircum * 180.0; + latLon.x = _meters.y * invHalfCircum * 180.0; + latLon.x = 180.0 * invPI * (2.0 * glm::atan( glm::exp(latLon.x * PI * inv180) ) - PI * 0.5); + return latLon; +} + +glm::vec2 MercProjection::PixelsToMeters(glm::vec2 _pix, int _zoom) { + glm::vec2 meters; + // resolution: meters/pixel for a given zoom level + float res = m_Res * pow(2, -_zoom); + meters.x = _pix.x * res - HALF_CIRCUMFERENCE; + meters.y = _pix.y * res - HALF_CIRCUMFERENCE; + return meters; +} + +glm::vec2 MercProjection::MetersToPixel(glm::vec2 _meters, int _zoom) { + glm::vec2 pix; + float res = m_Res * pow(2, -_zoom); + float invRes = 1.0/res; + pix.x = ( _meters.x + HALF_CIRCUMFERENCE ) * invRes; + pix.y = ( _meters.y + HALF_CIRCUMFERENCE ) * invRes; + return pix; +} + +glm::ivec2 MercProjection::PixelsToTileXY(glm::vec2 _pix) { + //returns the tile covering a region of a pixel + glm::ivec2 tileXY; + float invTileSize = 1.0/m_TileSize; + tileXY.x = int(glm::ceil( _pix.x * invTileSize) - 1); + tileXY.y = int(glm::ceil( _pix.y * invTileSize) - 1); + return tileXY; +} + +glm::ivec2 MercProjection::MetersToTileXY(glm::vec2 _meters, int _zoom) { + return PixelsToTileXY( MetersToPixel(_meters, _zoom)); +} + +glm::vec4 MercProjection::TileBounds(glm::ivec3 _tileCoord) { + glm::vec2 boundMin, boundMax; + boundMin = PixelsToMeters( glm::vec2(_tileCoord.x*m_TileSize, _tileCoord.y*m_TileSize), _tileCoord.z); + boundMax = PixelsToMeters( glm::vec2((_tileCoord.x+1)*m_TileSize, (_tileCoord.y+1)*m_TileSize), _tileCoord.z); + return glm::vec4(boundMin.x, boundMin.y, boundMax.x, boundMax.y); +} + +glm::vec4 MercProjection::TileLatLonBounds(glm::ivec3 _tileCoord) { + glm::vec4 bounds = TileBounds(_tileCoord); + glm::vec2 minBound, maxBound; + minBound = MetersToLatLon(glm::vec2(bounds.x, bounds.y)); + maxBound = MetersToLatLon(glm::vec2(bounds.z, bounds.w)); + return glm::vec4(minBound.x, minBound.y, maxBound.x, maxBound.y); +} + diff --git a/core/util/projection.h b/core/util/projection.h index f14a003fb0..a68375a6d3 100644 --- a/core/util/projection.h +++ b/core/util/projection.h @@ -1,6 +1,51 @@ #pragma one -class MercatorProjection { +//Define global constants +#define PI 3.1415926535 +#define HALF_CIRCUMFERENCE 20037508.342789244 -} +#include "glm/glm.hpp" + +const glm::vec2 ORIGIN(HALF_CIRCUMFERENCE, HALF_CIRCUMFERENCE); + +enum class ProjectionType { + mercator +}; + +class MapProjection { +protected: + /* m_type: type of map projection: example: mercator*/ + ProjectionType m_type; +public: + MapProjection(ProjectionType _type) : m_type(_type) {}; + virtual glm::vec2 LatLonToMeters(glm::vec2 _latLon) = 0; + virtual glm::vec2 MetersToLatLon(glm::vec2 _meters) = 0; + virtual glm::vec2 PixelsToMeters(glm::vec2 _pix, int _zoom) = 0; + virtual glm::vec2 MetersToPixel(glm::vec2 _meters, int _zoom) = 0; + virtual glm::ivec2 PixelsToTileXY(glm::vec2 _pix) = 0; + virtual glm::ivec2 MetersToTileXY(glm::vec2 _meters, int _zoom) = 0; + virtual glm::vec4 TileBounds(glm::ivec3 _tileCoord) = 0; + virtual glm::vec4 TileLatLonBounds(glm::ivec3 _tileCoord) = 0; + virtual ProjectionType GetMapProjectionType() {return m_type;} + virtual ~MapProjection() {} +}; + +class MercProjection : public MapProjection { + /* + * Following define the boundry covered by this mercator projection + */ + float m_TileSize; + float m_Res; +public: + MercProjection(ProjectionType _type, int _tileSize=256); + virtual glm::vec2 LatLonToMeters(glm::vec2 _latLon); + virtual glm::vec2 MetersToLatLon(glm::vec2 _meters); + virtual glm::vec2 PixelsToMeters(glm::vec2 _pix, int _zoom); + virtual glm::vec2 MetersToPixel(glm::vec2 _meters, int _zoom); + virtual glm::ivec2 PixelsToTileXY(glm::vec2 _pix); + virtual glm::ivec2 MetersToTileXY(glm::vec2 _meters, int _zoom); + virtual glm::vec4 TileBounds(glm::ivec3 _tileCoord); + virtual glm::vec4 TileLatLonBounds(glm::ivec3 _tileCoord); + virtual ~MercProjection() {} +}; From 9429c6f4ae17e165311db43f78bc6ddfd92714f0 Mon Sep 17 00:00:00 2001 From: Varun Talwar Date: Tue, 16 Sep 2014 16:37:21 -0400 Subject: [PATCH 3/4] revision to projection utility class --- core/util/projection.cpp | 12 ++---- core/util/projection.h | 89 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 85 insertions(+), 16 deletions(-) diff --git a/core/util/projection.cpp b/core/util/projection.cpp index 8e3d7eb17a..4b7c4d2e3a 100644 --- a/core/util/projection.cpp +++ b/core/util/projection.cpp @@ -3,7 +3,6 @@ #include "projection.h" -//Constructor for MercProjection MercProjection::MercProjection(ProjectionType _type, int _tileSize) : MapProjection(_type), m_TileSize(_tileSize) { float invTileSize = 1.0/m_TileSize; m_Res = 2.0 * HALF_CIRCUMFERENCE * invTileSize; @@ -11,24 +10,21 @@ MercProjection::MercProjection(ProjectionType _type, int _tileSize) : MapProject glm::vec2 MercProjection::LatLonToMeters(glm::vec2 _latLon) { glm::vec2 meters; - float inv180 = 1.0/180.0; - float inv360 = 1.0/360.0; //Lon -> origin shift, as parallel lines - meters.x = _latLon.y * HALF_CIRCUMFERENCE * inv180; + meters.x = _latLon.y * HALF_CIRCUMFERENCE * INV_180; //Lat -> first do scaling as per mercator then origin shift - meters.y = glm::log( glm::tan(90.0 + _latLon.x) * PI * inv360) * PI * inv180; - meters.y = meters.y * HALF_CIRCUMFERENCE * inv180; + meters.y = glm::log( glm::tan(90.0 + _latLon.x) * PI * INV_360) * PI * INV_180; + meters.y = meters.y * HALF_CIRCUMFERENCE * INV_180; return meters; } glm::vec2 MercProjection::MetersToLatLon(glm::vec2 _meters) { glm::vec2 latLon; float invHalfCircum = 1.0/HALF_CIRCUMFERENCE; - float inv180 = 1.0/180.0; float invPI = 1.0/PI; latLon.y = _meters.x * invHalfCircum * 180.0; latLon.x = _meters.y * invHalfCircum * 180.0; - latLon.x = 180.0 * invPI * (2.0 * glm::atan( glm::exp(latLon.x * PI * inv180) ) - PI * 0.5); + latLon.x = 180.0 * invPI * (2.0 * glm::atan( glm::exp(latLon.x * PI * INV_180) ) - PI * 0.5); return latLon; } diff --git a/core/util/projection.h b/core/util/projection.h index a68375a6d3..b919a5af13 100644 --- a/core/util/projection.h +++ b/core/util/projection.h @@ -3,6 +3,9 @@ //Define global constants #define PI 3.1415926535 #define HALF_CIRCUMFERENCE 20037508.342789244 +#define INV_180 0.005555555 +#define INV_360 0.002777777 + #include "glm/glm.hpp" @@ -18,14 +21,79 @@ class MapProjection { ProjectionType m_type; public: MapProjection(ProjectionType _type) : m_type(_type) {}; + + /*LatLong to ProjectionType-Meter + * Arguments: + * _latlon: glm::vec2 having lat and lon info. x: lon, y: lat + * Return value: + * meter (glm::vec2). + */ virtual glm::vec2 LatLonToMeters(glm::vec2 _latLon) = 0; + + /* ProjectionType-Meters to Lat Lon + * Arguments: + * _meter: glm::vec2 having the projection units in meters. x: lon, y:lat + * Return value: + * latlon (glm::vec2) + */ virtual glm::vec2 MetersToLatLon(glm::vec2 _meters) = 0; + + /* Screen pixels to Meters + * (TODO: Update description based on usage in the native app, might be moved to viewModule + * Arguments: + * _pix: screen pixels defined as glm::vec2 + * _zoom: zoom level to determine the projection-meters + * Return value: + * projection-meters (glm::vec2) + */ virtual glm::vec2 PixelsToMeters(glm::vec2 _pix, int _zoom) = 0; + + /* Meters to Screen Pixels + * (TODO: Update description based on usage in the native app, might be moved to viewModule + * Arguments: + * _meters: projection-meters (glm::vec2) + * _zoom: zoom level to determine screen pixels + * Return Value: + * screen pixels (glm::vec2) + */ virtual glm::vec2 MetersToPixel(glm::vec2 _meters, int _zoom) = 0; + + /* TODO: Define when more clear on the use case for this. Might be moved to viewModule + */ virtual glm::ivec2 PixelsToTileXY(glm::vec2 _pix) = 0; + + /* Projection-meters to TILEXY + * Arguments: + * _meters: projection-meters (glm::vec2) + * _zoom: zoom level for which tile coordinates need to be determined + * Return Value: + * Tile coordinates (x and y) (glm::ivec2) + */ virtual glm::ivec2 MetersToTileXY(glm::vec2 _meters, int _zoom) = 0; + + /* bounds of space in projection-meters + * Arguments: + * _tileCoord: glm::ivec3 (x,y and zoom) + * Return value: + * bounds in projection-meters (glm::vec4) + * x,y : min bounds in projection meters + * z,w : max bounds in projection meters + */ virtual glm::vec4 TileBounds(glm::ivec3 _tileCoord) = 0; + + /* bounds of space in lat lon + * Arguments: + * _tileCoord: glm::ivec3 (x,y and zoom) + * Return value: + * bounds in lat lon (glm::vec4) + * x,y: min bounds in lat lon + * z,w: max bounds in lat lon + */ virtual glm::vec4 TileLatLonBounds(glm::ivec3 _tileCoord) = 0; + + /* Returns the projection type of a given projection instance + * (example: ProjectionType::Mercator) + */ virtual ProjectionType GetMapProjectionType() {return m_type;} virtual ~MapProjection() {} }; @@ -37,15 +105,20 @@ class MercProjection : public MapProjection { float m_TileSize; float m_Res; public: + /*Constructor for MercProjection + * _type: type of map projection, example ProjectionType::Mercator + * _tileSize: size of the map tile, default is 256 + */ MercProjection(ProjectionType _type, int _tileSize=256); - virtual glm::vec2 LatLonToMeters(glm::vec2 _latLon); - virtual glm::vec2 MetersToLatLon(glm::vec2 _meters); - virtual glm::vec2 PixelsToMeters(glm::vec2 _pix, int _zoom); - virtual glm::vec2 MetersToPixel(glm::vec2 _meters, int _zoom); - virtual glm::ivec2 PixelsToTileXY(glm::vec2 _pix); - virtual glm::ivec2 MetersToTileXY(glm::vec2 _meters, int _zoom); - virtual glm::vec4 TileBounds(glm::ivec3 _tileCoord); - virtual glm::vec4 TileLatLonBounds(glm::ivec3 _tileCoord); + + virtual glm::vec2 LatLonToMeters(glm::vec2 _latLon) override; + virtual glm::vec2 MetersToLatLon(glm::vec2 _meters) override; + virtual glm::vec2 PixelsToMeters(glm::vec2 _pix, int _zoom) override; + virtual glm::vec2 MetersToPixel(glm::vec2 _meters, int _zoom) override; + virtual glm::ivec2 PixelsToTileXY(glm::vec2 _pix) override; + virtual glm::ivec2 MetersToTileXY(glm::vec2 _meters, int _zoom) override; + virtual glm::vec4 TileBounds(glm::ivec3 _tileCoord) override; + virtual glm::vec4 TileLatLonBounds(glm::ivec3 _tileCoord) override; virtual ~MercProjection() {} }; From 52e30621b3ed255bb79d18580ea9e0181fef0abb Mon Sep 17 00:00:00 2001 From: Varun Talwar Date: Thu, 18 Sep 2014 17:14:28 -0400 Subject: [PATCH 4/4] typo correction from #pragma one to #pragma once --- core/util/projection.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/util/projection.h b/core/util/projection.h index b919a5af13..bcbd47c122 100644 --- a/core/util/projection.h +++ b/core/util/projection.h @@ -1,4 +1,4 @@ -#pragma one +#pragma once //Define global constants #define PI 3.1415926535