1.1 Azimuthal equidistant map projection definition
1.1.1 Understanding Latitude and Longiutde
1.2 Installation
1.3 Public members
1.3.1 Constructor
1.3.2 Reseting the map's center
1.3.3 Getting the map's center
1.3.4 Calculating the distance from map's center to the map's origin
1.3.5 Calculating the distance from a given GPS coordinates to the map's origin
1.3.6 Converting from GPS coordinates to X and Y distances
1.3.7 Converting from X and Y position to GPS coordinates
1.3.8 Calculating the distance between two GPS coordinates
1.3.9 Calculating the distance X and Y between two GPS coordinates
1.3.10 Changing the earth radius
1.3.11 Converting from radians to degrees and vice versa
1.4 Type definition
1.5 Getting started
The azimuthal equidistant projection is an azimuthal map projection. It has the useful properties that all points on the map are at proportionally correct distances from the center point, and that all points on the map are at the correct azimuth (direction) from the center point. A useful application for this type of projection is a polar projection which shows all meridians (lines of longitude) as straight, with distances from the pole represented correctly. The flag of the United Nations contains an example of a polar azimuthal equidistant projection. [wiki]
You can see an interactive map here, use the mouse to move center of the map projection.
Latitude and Longitude are imaginary lines that separate the globe in sections; latitude are horizontal lines and separate the circunference vertically, they represent values in the Y axis. Longitude in the other hand are vertical lines and separate the circunference horizontally, they represent values in X axis. The origin of XY and Lat-Long coodinate systems are located where the Ecuator and Greenwich (prime meridian) lines intersect.
This library does not require any additional libray, you only need to add the files to your project's folder and add the following lines to your CMakeLists.txt:
# Tripe points (...) represent possible content that may
# already exist in your CMakeLists.txt
...
# Replace <gps_conversor_folder_path> with the actual folder path
add_subdirectory(<gps_conversor_folder_path>)
# Replace <project_name> with the actual project name
target_include_directories(<project_name>
${COORDINATE_INCLUDE_DIRS}
)
...
# Replace <project_name> with the actual project name
target_link_libraries(<project_name>
...
${COORDINATE_LIBRARIES}
...
)
...
And add the next include
line into your code:
#include "ramrod/gps/coordinate_conversor.h"
You could define a different map's center by specifying pointers for latitude
and longitude
so, when you call gps_to_xy()
or xy_to_gps()
, the distances are properly calculated from that center, by default is (0°, 0°). This does not affect distance()
or distances()
. NOTE: the map's center is different to the origin, the later is always located in the coordinates (0°, 0°). The former represents the center position of the azimuthal projection and it can change at your will.
ramrod::gps::coordinate_conversor<T>(const T *latitude = nullptr,
const T *longitude = nullptr);
Parameters
Type | Name | Description |
---|---|---|
const T* |
latitude | Latitude coordinate of the map's center. |
const T* |
longitude | Longitude coordinate of the map's center. |
This function will change the variable's pointer used to define the map center (center position of the azimuthal projection) so, when you call gps_to_xy()
or xy_to_gps()
, the distances are properly calculated from that center. This does not affect distance()
or distances()
bool center(const T *latitude, const T *longitude);
Parameters
Type | Name | Description |
---|---|---|
const T* |
latitude | Latitude coordinate of the map's center. |
const T* |
longitude | Longitude coordinate of the map's center. |
Returns
Type | Description |
---|---|
bool |
false if latitude or longitude are nullptr . |
Call this function to get the map's center coordinates (center of the azimuthal projection)
ramrod::point_ll<T> center();
Returns
Type | Description |
---|---|
ramrod::point_ll<T> |
GPS coordinates of the map's center. |
This function calculates the distance from the map's center (center of azimuthal projection) to the map's origin (latitude and longitude equal to 0° and 0°). The map's center is defined at the constructor
or in center(const T*, const T*)
functions.
ramrod::point_xy<T> gps_to_origin();
Returns
Type | Description |
---|---|
ramrod::point_xy<T> |
Distance in meters on X and Y axes relative to the map's origin (latitude and longitude equal to to 0° and 0°). (see Types for more information about the struct ). |
This function calculates the distance from the given GPS coordinates to the map's origin (latitude and longitude equal to 0° and 0°).
ramrod::point_xy<T> gps_to_origin(const T latitude, const T longitude);
Returns
Type | Description |
---|---|
ramrod::point_xy<T> |
Distance in meters on X and Y axes relative to the map's origin (latitude and longitude equal to 0° and 0°). (see Types for more information about the struct ). |
This function converts GPS degree coordinates to distance in meters from the GPS position to the map's center which was defined in the constructor
or in center(const T*, const T*)
.
ramrod::point_xy<T> gps_to_xy(T latitude, T longitude);
Parameters
Type | Name | Description |
---|---|---|
T |
latitude | Latitude coordinate to convert. |
T |
longitude | Longitude coordinate to convert. |
Returns
Type | Description |
---|---|
ramrod::point_xy<T> |
Distance in meters with coordinates X and Y relative to the map's center defined at the constructor. (see Types for more information about the struct ). |
This function converts X and Y position (in meters) into GPS degree coordinates. The X and Y distances must be relative to the map's center (not the map's origin), the X axis is a line pointing east and the Y axis is a line pointing towards north and map's center defined at the constructor
or in center(const T*, const T*)
.
ramrod::point_ll<T> xy_to_gps(T x, T y);
Parameters
Type | Name | Description |
---|---|---|
T |
x | Distance X relative to the map's center |
T |
y | Distance Y relative to the map's center |
Returns
Type | Description |
---|---|
ramrod::point_ll<T> |
Coordinates latitude and longitude. (see Types for more information about the struct ). |
This function calculates the distance between two GPS points, you must define the start point (latitude, longitude) and end point (latitude, longitude).
T distance(T start_latitude, T start_longitude,
T end_latitude, T end_longitude);
Parameters
Type | Name | Description |
---|---|---|
T |
start_latitude | Latitude of point 1. |
T |
start_longitude | Longitude of point 1. |
T |
end_latitude | Latitude of point 2. |
T |
end_longitude | Longitude of point 2. |
Returns
Type | Description |
---|---|
T |
Distance in meters from start point to end point. |
This function calculates the distance X and Y between two GPS points, you must define a start point (latitude, longitude) and end point (latitude, longitude).
ramrod::point_xy<T> distances(T start_latitude, T start_longitude,
T end_latitude, T end_longitude);
Parameters
Type | Name | Description |
---|---|---|
T |
start_latitude | Latitude of point 1. |
T |
start_longitude | Longitude of point 1. |
T |
end_latitude | Latitude of point 2. |
T |
end_longitude | Longitude of point 2. |
Returns
Type | Description |
---|---|
ramrod::point_xy<T> |
Distance in meters from start point to end point separated in vector components. (see Types for more information about the struct ). |
This function changes the default value of the earth radius (which is 6,378,137.0 meters) for a value you could manually define. It is only recommended if you want more precision.
bool earth_radius(const T new_earth_radius);
Parameters
Type | Name | Description |
---|---|---|
T |
new_earth_radius | New earth radius in meters. |
Returns
Type | Description |
---|---|
bool |
false if the value is lesser or equal to zero. |
This function converts radians into degrees or the other way around:
// Converting from radians to degrees
T to_degrees(const T radians);
// Converting from degrees to radians
T to_radians(const T degrees);
Parameters
Type | Name | Description |
---|---|---|
T |
radians | Angle in radians. |
T |
degrees | Angle in degrees. |
Returns
Type | Description |
---|---|
T |
(first funtion) Value converted into degrees. |
T |
(second function) Value converted into radians. |
There is two different types of structures:
namespace ramrod {
// Position in meters
template<typename T>
union point_xy{
struct{
T x; // Position in meters at the X axis (Longitude axis)
T y; // Position in meters at the Y axis (Latitude axis)
};
T data[2];
};
// Position in degrees
template<typename T>
union point_ll{
struct{
T latitude; // Latitude coordinate in degrees
T longitude; // Longitude coordinate in degrees
};
T data[2];
};
}
You could directly choose a type for the coordinate conversor using the following type definitions:
namespace torero {
typedef coordinate_conversor<float> coordinate_conversor_float;
typedef coordinate_conversor<double> coordinate_conversor_double;
typedef coordinate_conversor<long double> coordinate_conversor_long;
}
Example:
// You could use this:
float map_center_latitude{0.0f};
float map_center_longitude{0.0f};
ramrod::gps::coordinate_conversor_float gps_conversor(&map_center_latitude,
&map_center_longitude);
// Instead of this:
float map_center_latitude{0.0f};
float map_center_longitude{0.0f};
ramrod::gps::coordinate_conversor<float> gps_conversor(&map_center_latitude,
&map_center_longitude);
The use of the coordinate conversor is really easy, here is an example in how to use the library.
#include "ramrod/gps/coordinate_conversor.h"
#include <iostream> // for std::cout, std::endl, std::fixed
#include <iomanip> // for std::setprecision
int main(int argc, char *argv[]){
// ------------------------------------------------------------------------------------ //
// ---------------------------- GPS COORDINATE CONVERSOR ------------------------------ //
// ------------------------------------------------------------------------------------ //
// Defining the map center (which you could move inside your code at any moment)
float map_center_latitude{0.0f};
float map_center_longitude{0.0f};
// Creating our GPS coordinate conversor object
ramrod::gps::coordinate_conversor<float> conversor(&map_center_latitude,
&map_center_longitude);
// -------------------------------------------------------------------------------
// Converting from coordinates to meters (relative to the map center)
ramrod::point_xy<float> point_1 = conversor.gps_to_xy(50.774987f, 6.085083f);
// Printing the values
std::cout << std::setprecision(2) << std::fixed
<< "X: " << point_1.x << "m \n"
<< "Y: " << point_1.y << "m"
<< std::endl;
// -------------------------------------------------------------------------------
// Changing the map's center location (center of the azimuthal projection)
map_center_latitude = 50.0f;
map_center_longitude = 6.0f;
// -------------------------------------------------------------------------------
// Converting from meters to coordinates (relative to the map's center)
ramrod::point_ll<float> point_2 = conversor.xy_to_gps(1000.0f, 2000.0f);
// Printing the values
std::cout << std::setprecision(7)
<< "Latitude: " << point_2.latitude << "° \n"
<< "Longitude: " << point_2.longitude << "°"
<< std::endl;
// -------------------------------------------------------------------------------
// Setting the points A and B
float A_latitude = 50.774987f;
float A_longitude{6.085083f};
float B_latitude{51.774987f};
float B_longitude = 7.085083f;
// Calculating the distance from point A to B
float distance{conversor.distance(A_latitude, A_longitude,
B_latitude, B_longitude)};
// Printing the values
std::cout << std::setprecision(2)
<< "Distance: " << distance << "m"
<< std::endl;
// -------------------------------------------------------------------------------
// Calculating the distance from point A to B
ramrod::point_xy<float> distances = conversor.distances(A_latitude, A_longitude,
B_latitude, B_longitude);
// Printing the values
std::cout << "Distance in X: " << distances.x << "m \n"
<< "Distance in Y: " << distances.y << "m"
<< std::endl;
return 0;
}