Skip to content

Commit

Permalink
CMake: Fetch geographiclib
Browse files Browse the repository at this point in the history
  • Loading branch information
HTRamsey committed May 5, 2024
1 parent a0fa603 commit dacd3c2
Show file tree
Hide file tree
Showing 29 changed files with 279 additions and 223 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.22.1 FATAL_ERROR)
cmake_minimum_required(VERSION 3.22.1)

set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug;Release")
if(NOT CMAKE_BUILD_TYPE)
Expand Down
21 changes: 21 additions & 0 deletions QGCExternalLibs.pri
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,24 @@ contains (DEFINES, CONFIG_UTM_ADAPTER){
INCLUDEPATH += $$PWD/libs/libevents/libevents/libs/cpp/parse/nlohmann_json/include
LIBS += -lboost_system -lboost_thread -lssl -lcrypto
}

HEADERS += \
libs/GeographicLib/Constants.hpp \
libs/GeographicLib/Math.hpp \
libs/GeographicLib/Utility.hpp \
libs/GeographicLib/UTMUPS.hpp \
libs/GeographicLib/MGRS.hpp \
libs/GeographicLib/TransverseMercator.hpp \
libs/GeographicLib/PolarStereographic.hpp \

SOURCES += \
libs/GeographicLib/Math.cpp \
libs/GeographicLib/Utility.cpp \
libs/GeographicLib/UTMUPS.cpp \
libs/GeographicLib/MGRS.cpp \
libs/GeographicLib/TransverseMercator.cpp \
libs/GeographicLib/PolarStereographic.cpp \

INCLUDEPATH += \
libs \
libs/GeographicLib
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
13 changes: 0 additions & 13 deletions qgroundcontrol.pro
Original file line number Diff line number Diff line change
Expand Up @@ -493,13 +493,6 @@ HEADERS += \
src/PositionManager/PositionManager.h \
src/PositionManager/SimulatedPosition.h \
src/Geo/QGCGeo.h \
src/Geo/Constants.hpp \
src/Geo/Math.hpp \
src/Geo/Utility.hpp \
src/Geo/UTMUPS.hpp \
src/Geo/MGRS.hpp \
src/Geo/TransverseMercator.hpp \
src/Geo/PolarStereographic.hpp \
src/Utilities/QGC.h \
src/QGCApplication.h \
src/Utilities/QGCCachedFileDownload.h \
Expand Down Expand Up @@ -763,12 +756,6 @@ SOURCES += \
src/PositionManager/PositionManager.cpp \
src/PositionManager/SimulatedPosition.cc \
src/Geo/QGCGeo.cc \
src/Geo/Math.cpp \
src/Geo/Utility.cpp \
src/Geo/UTMUPS.cpp \
src/Geo/MGRS.cpp \
src/Geo/TransverseMercator.cpp \
src/Geo/PolarStereographic.cpp \
src/Utilities/QGC.cc \
src/QGCApplication.cc \
src/Utilities/QGCCachedFileDownload.cc \
Expand Down
44 changes: 21 additions & 23 deletions src/Geo/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,36 +1,34 @@
find_package(Qt6 REQUIRED COMPONENTS Core Positioning)

# include(FetchContent)
# FetchContent_Declare(geographiclib
# GIT_REPOSITORY https://github.com/geographiclib/geographiclib.git
# GIT_TAG v2.3
# GIT_SHALLOW TRUE
# )
# FetchContent_MakeAvailable(geographiclib)

qt_add_library(Geo STATIC
Constants.hpp
Math.cpp
Math.hpp
MGRS.cpp
MGRS.hpp
PolarStereographic.cpp
PolarStereographic.hpp
QGCGeo.cc
QGCGeo.h
TransverseMercator.cpp
TransverseMercator.hpp
Utility.cpp
Utility.h
Utility.hpp
UTMUPS.cpp
UTMUPS.hpp
)

set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "")
set(BUILD_BOTH_LIBS OFF CACHE INTERNAL "")
set(BUILD_DOCUMENTATION OFF CACHE INTERNAL "")
set(BUILD_MANPAGES OFF CACHE INTERNAL "")

include(FetchContent)
FetchContent_Declare(geographiclib
GIT_REPOSITORY https://github.com/geographiclib/geographiclib.git
GIT_TAG r2.3
GIT_SHALLOW TRUE
)
FetchContent_GetProperties(geographiclib)
if(NOT geographiclib_POPULATED)
FetchContent_Populate(geographiclib)
add_subdirectory(${geographiclib_SOURCE_DIR} ${geographiclib_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
# FetchContent_MakeAvailable(geographiclib)

target_link_libraries(Geo
PRIVATE
Qt6::Core
GeographicLib::GeographicLib
Utilities
PUBLIC
Qt6::Core
Qt6::Positioning
)

Expand Down
224 changes: 114 additions & 110 deletions src/Geo/QGCGeo.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,149 +7,153 @@
*
****************************************************************************/

// TODO: Use GeoCoords from GeographicLib?

#include "QGCGeo.h"
#include "UTMUPS.hpp"
#include "MGRS.hpp"
#include "QGCLoggingCategory.h"

#include <QtCore/QString>
#include <QtCore/QtMath>

#include <GeographicLib/Constants.hpp>
#include <GeographicLib/MGRS.hpp>
#include <GeographicLib/UTMUPS.hpp>

#include <cmath>
#include <limits>

// These defines are private
#define M_DEG_TO_RAD (M_PI / 180.0)
#define M_RAD_TO_DEG (180.0 / M_PI)
#define CONSTANTS_RADIUS_OF_EARTH 6371000 // meters (m)
QGC_LOGGING_CATEGORY(QGCGeoLog, "qgc.geo.qgcgeo")

static const double epsilon = std::numeric_limits<double>::epsilon();
static constexpr double epsilon = std::numeric_limits<double>::epsilon();

void convertGeoToNed(QGeoCoordinate coord, QGeoCoordinate origin, double* x, double* y, double* z)
{
if (coord == origin) {
// Short circuit to prevent NaNs in calculation
*x = *y = *z = 0;
return;
}
namespace QGCGeo {

double lat_rad = coord.latitude() * M_DEG_TO_RAD;
double lon_rad = coord.longitude() * M_DEG_TO_RAD;
void convertGeoToNed(const QGeoCoordinate &coord, const QGeoCoordinate &origin, double &x, double &y, double &z) {
if (coord == origin) {
// Prevent NaNs in calculation
x = y = z = 0;
return;
}

double ref_lon_rad = origin.longitude() * M_DEG_TO_RAD;
double ref_lat_rad = origin.latitude() * M_DEG_TO_RAD;
const double lat_rad = qDegreesToRadians(coord.latitude());
const double lon_rad = qDegreesToRadians(coord.longitude());

double sin_lat = sin(lat_rad);
double cos_lat = cos(lat_rad);
double cos_d_lon = cos(lon_rad - ref_lon_rad);
const double ref_lon_rad = qDegreesToRadians(origin.longitude());
const double ref_lat_rad = qDegreesToRadians(origin.latitude());

double ref_sin_lat = sin(ref_lat_rad);
double ref_cos_lat = cos(ref_lat_rad);
const double sin_lat = sin(lat_rad);
const double cos_lat = cos(lat_rad);
const double cos_d_lon = cos(lon_rad - ref_lon_rad);

double c = acos(ref_sin_lat * sin_lat + ref_cos_lat * cos_lat * cos_d_lon);
double k = (fabs(c) < epsilon) ? 1.0 : (c / sin(c));
const double ref_sin_lat = sin(ref_lat_rad);
const double ref_cos_lat = cos(ref_lat_rad);

*x = k * (ref_cos_lat * sin_lat - ref_sin_lat * cos_lat * cos_d_lon) * CONSTANTS_RADIUS_OF_EARTH;
*y = k * cos_lat * sin(lon_rad - ref_lon_rad) * CONSTANTS_RADIUS_OF_EARTH;
const double c = acos(ref_sin_lat * sin_lat + ref_cos_lat * cos_lat * cos_d_lon);
const double k = (fabs(c) < epsilon) ? 1.0 : (c / sin(c));

*z = -(coord.altitude() - origin.altitude());
}
x = k * (ref_cos_lat * sin_lat - ref_sin_lat * cos_lat * cos_d_lon) * GeographicLib::Constants::WGS84_a();
y = k * cos_lat * sin(lon_rad - ref_lon_rad) * GeographicLib::Constants::WGS84_a();
z = -(coord.altitude() - origin.altitude());
}

void convertNedToGeo(double x, double y, double z, QGeoCoordinate origin, QGeoCoordinate *coord) {
double x_rad = x / CONSTANTS_RADIUS_OF_EARTH;
double y_rad = y / CONSTANTS_RADIUS_OF_EARTH;
double c = sqrt(x_rad * x_rad + y_rad * y_rad);
double sin_c = sin(c);
double cos_c = cos(c);
void convertNedToGeo(double x, double y, double z, const QGeoCoordinate &origin, QGeoCoordinate &coord) {
const double x_rad = x / GeographicLib::Constants::WGS84_a();
const double y_rad = y / GeographicLib::Constants::WGS84_a();
const double c = sqrt(x_rad * x_rad + y_rad * y_rad);
const double sin_c = sin(c);
const double cos_c = cos(c);

double ref_lon_rad = origin.longitude() * M_DEG_TO_RAD;
double ref_lat_rad = origin.latitude() * M_DEG_TO_RAD;
const double ref_lon_rad = qDegreesToRadians(origin.longitude());
const double ref_lat_rad = qDegreesToRadians(origin.latitude());

double ref_sin_lat = sin(ref_lat_rad);
double ref_cos_lat = cos(ref_lat_rad);
const double ref_sin_lat = sin(ref_lat_rad);
const double ref_cos_lat = cos(ref_lat_rad);

double lat_rad;
double lon_rad;
double lat_rad;
double lon_rad;

if (fabs(c) > epsilon) {
lat_rad = asin(cos_c * ref_sin_lat + (x_rad * sin_c * ref_cos_lat) / c);
lon_rad = (ref_lon_rad + atan2(y_rad * sin_c, c * ref_cos_lat * cos_c - x_rad * ref_sin_lat * sin_c));
if (fabs(c) > epsilon) {
lat_rad = asin(cos_c * ref_sin_lat + (x_rad * sin_c * ref_cos_lat) / c);
lon_rad = (ref_lon_rad + atan2(y_rad * sin_c, c * ref_cos_lat * cos_c - x_rad * ref_sin_lat * sin_c));
} else {
lat_rad = ref_lat_rad;
lon_rad = ref_lon_rad;
}

} else {
lat_rad = ref_lat_rad;
lon_rad = ref_lon_rad;
coord.setLatitude(qRadiansToDegrees(lat_rad));
coord.setLongitude(qRadiansToDegrees(lon_rad));
coord.setAltitude(-z + origin.altitude());
}

coord->setLatitude(lat_rad * M_RAD_TO_DEG);
coord->setLongitude(lon_rad * M_RAD_TO_DEG);
int convertGeoToUTM(const QGeoCoordinate& coord, double &easting, double &northing)
{
try {
int zone;
bool northp;
GeographicLib::UTMUPS::Forward(coord.latitude(), coord.longitude(), zone, northp, easting, northing);
return zone;
} catch(GeographicLib::GeographicErr) {
return 0;
}
}

coord->setAltitude(-z + origin.altitude());
}
bool convertUTMToGeo(double easting, double northing, int zone, bool southhemi, QGeoCoordinate &coord)
{
double lat, lon;

int convertGeoToUTM(const QGeoCoordinate& coord, double& easting, double& northing)
{
try {
int zone;
bool northp;
GeographicLib::UTMUPS::Forward(coord.latitude(), coord.longitude(), zone, northp, easting, northing);
return zone;
} catch(...) {
return 0;
}
}
try {
GeographicLib::UTMUPS::Reverse(zone, !southhemi, easting, northing, lat, lon);
} catch(GeographicLib::GeographicErr) {
return false;
}

coord.setLatitude(lat);
coord.setLongitude(lon);

bool convertUTMToGeo(double easting, double northing, int zone, bool southhemi, QGeoCoordinate& coord)
{
double lat, lon;
try {
GeographicLib::UTMUPS::Reverse(zone, !southhemi, easting, northing, lat, lon);
} catch(...) {
return false;
return true;
}
coord.setLatitude(lat);
coord.setLongitude(lon);

return true;
}
QString convertGeoToMGRS(const QGeoCoordinate &coord)
{
std::string mgrs;

try {
int zone;
bool northp;
double x, y;
GeographicLib::UTMUPS::Forward(coord.latitude(), coord.longitude(), zone, northp, x, y);
GeographicLib::MGRS::Forward(zone, northp, x, y, coord.latitude(), 5, mgrs);
} catch(GeographicLib::GeographicErr) {
mgrs = "";
}

QString convertGeoToMGRS(const QGeoCoordinate& coord)
{
int zone;
bool northp;
double x, y;
std::string mgrs;

try {
GeographicLib::UTMUPS::Forward(coord.latitude(), coord.longitude(), zone, northp, x, y);
GeographicLib::MGRS::Forward(zone, northp, x, y, coord.latitude(), 5, mgrs);
} catch(...) {
mgrs = "";
const QString qstr = QString::fromStdString(mgrs);
for (int i = qstr.length() - 1; i >= 0; i--) {
if (!qstr.at(i).isDigit()) {
const int l = (qstr.length() - i) / 2;
return qstr.left(i + 1) + " " + qstr.mid(i + 1, l) + " " + qstr.mid(i + 1 + l);
}
}

return qstr;
}

QString qstr = QString::fromStdString(mgrs);
for (int i = qstr.length() - 1; i >= 0; i--) {
if (!qstr.at(i).isDigit()) {
int l = (qstr.length() - i) / 2;
return qstr.left(i + 1) + " " + qstr.mid(i + 1, l) + " " + qstr.mid(i + 1 + l);
bool convertMGRSToGeo(const QString &mgrs, QGeoCoordinate &coord)
{
double lat, lon;

try {
int zone, prec;
bool northp;
double x, y;
GeographicLib::MGRS::Reverse(mgrs.simplified().replace(" ", "").toStdString(), zone, northp, x, y, prec);
GeographicLib::UTMUPS::Reverse(zone, northp, x, y, lat, lon);
} catch(GeographicLib::GeographicErr) {
return false;
}
}

return qstr;
}
coord.setLatitude(lat);
coord.setLongitude(lon);

bool convertMGRSToGeo(QString mgrs, QGeoCoordinate& coord)
{
int zone, prec;
bool northp;
double x, y;
double lat, lon;

try {
GeographicLib::MGRS::Reverse(mgrs.simplified().replace(" ", "").toStdString(), zone, northp, x, y, prec);
GeographicLib::UTMUPS::Reverse(zone, northp, x, y, lat, lon);
} catch(...) {
return false;
return true;
}
coord.setLatitude(lat);
coord.setLongitude(lon);

return true;
}
Loading

0 comments on commit dacd3c2

Please sign in to comment.