Continues migration with DDS, Common

This commit is contained in:
torsten committed 2026-07-17 12:41:42 +02:00
1 parent 9b15cee841
commit fa48db111e
668 files changed
+111841 -2

No files matched your search

+78
View File
@@ -0,0 +1,78 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Christian Ehrlicher, SLSE, 2016-08-31
#
FIND_PACKAGE(GeographicLib REQUIRED)
NGL_ADD_LIBRARY2(LtsCoordTrans WS AAR SV HLA SHARED
lts_coord_trans.h
lts_coord_trans.cpp
)
NGL_TARGET_LINK_LIBRARIES(LtsCoordTrans
PRIVATE
GeographicLib
PUBLIC
Qt5::Core
)
NGL_TARGET_INCLUDE_DIRECTORIES(LtsCoordTrans
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
)
SET(ltsCoordWidget_SRCS
lts_coord_widget.cpp
lts_coord_widget.h
lts_coord_widget_p.cpp
lts_coord_widget_p.h
)
NGL_WRAP_UI(ltsCoordWidget_SRCS
lts_coord_widget_mgrs.ui
lts_coord_widget_wgs84.ui
)
NGL_ADD_LIBRARY2(ltsCoordWidget WS AAR SV SHARED ${ltsCoordWidget_SRCS})
NGL_TARGET_LINK_LIBRARIES(ltsCoordWidget
PRIVATE
LtsCoordTrans
PUBLIC
Qt5::Core
Qt5::Widgets
)
NGL_TARGET_INCLUDE_DIRECTORIES(ltsCoordWidget
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
)
IF(TARGET LtsCoordTrans)
SET(_tools lonlat2mgrs mgrs2lonlat)
FOREACH(_tool ${_tools})
NGL_ADD_EXECUTABLE(ALL ${_tool} ${_tool}.cpp)
NGL_TARGET_LINK_LIBRARIES(${_tool}
Qt5::Core
GeographicLib
)
NGL_INSTALL_TARGET(${_tool})
ENDFOREACH()
ENDIF()
IF(BUILD_TESTING AND TARGET ltsCoordWidget)
ADD_EXECUTABLE(lts_coord_widget_test lts_coord_widget_test.cpp)
TARGET_LINK_LIBRARIES(lts_coord_widget_test
ltsCoordWidget
LtsCoordTrans
)
ENDIF()
IF(BUILD_TESTING AND TARGET LtsCoordTrans)
ADD_EXECUTABLE(lts_coord_trans_unit_test
lts_coord_trans_unit_test.cpp
lts_coord_trans_unit_test.h
)
TARGET_LINK_LIBRARIES(lts_coord_trans_unit_test
LtsCoordTrans
Qt5::Test
GeographicLib
)
ADD_TEST(NAME lts_coord_trans_unit_test COMMAND $<TARGET_FILE:lts_coord_trans_unit_test>)
ENDIF()
+67
View File
@@ -0,0 +1,67 @@
#include <GeographicLib/UTMUPS.hpp>
#include <GeographicLib/MGRS.hpp>
#include <cstring>
#include <string>
int main(int argc, char **argv)
{
if (argc < 3 || argc > 5)
{
fprintf(stderr, "Usage: %s <lon_degree> <lat_degree> [<precision>]\n", argv[0]);
fprintf(stderr, "Usage: %s <lon_rad> <lat_rad> -r [<precision>]\n", argv[0]);
return -1;
}
bool lonLatInRad = false;
double lon = atof(argv[1]);
double lat = atof(argv[2]);
int prec = 5;
if (argc >= 4)
{
int precArgId = -1;
if (strcmp(argv[3], "-r") == 0)
{
lonLatInRad = true;
if (argc == 5)
precArgId = 4;
}
else
precArgId = 3;
if (precArgId > 0)
prec = atoi(argv[precArgId]);
}
std::string mgrs;
int zone;
bool northp;
double x, y;
try
{
const double latDeg = lonLatInRad ? lat * 180 / M_PI : lat;
const double lonDeg = lonLatInRad ? lon * 180 / M_PI : lon;
GeographicLib::UTMUPS::Forward(latDeg, lonDeg, zone, northp, x, y);
GeographicLib::MGRS::Forward(zone, northp, x, y, prec, mgrs);
}
catch (...)
{
fprintf(stderr, "Error converting %9.6f, %9.6f to MGRS coords\n", lat, lon);
return -2;
}
std::string part1, part2, part3, part4;
part1 = mgrs.substr(0, 3);
part2 = mgrs.substr(3, 2);
if (prec > 0)
{
part3 = mgrs.substr(5, prec);
part4 = mgrs.substr(5 + prec, prec);
}
fprintf(stdout, "%13.10f, %13.10f = %s %s %s %s (UTM: %d %.2f, %.2f %c)\n",
lon, lat,
part1.c_str(), part2.c_str(), part3.c_str(), part4.c_str(),
zone, x, y, northp ? 'N' : 'S');
return 0;
}
+445
View File
@@ -0,0 +1,445 @@
#include "lts_coord_trans.h"
#include <GeographicLib/Geocentric.hpp>
#include <GeographicLib/UTMUPS.hpp>
#include <GeographicLib/MGRS.hpp>
#include <QPointF>
#include <QRectF>
#include <QString>
#include <QStringList>
#include <iomanip>
namespace LtsCoordTrans
{
static long s_conversion_counter_MGRS_Forward = 0;
static long s_conversion_counter_MGRS_Reverse = 0;
static long s_conversion_counter_WGS84_Forward = 0;
static long s_conversion_counter_WGS84_Reverse = 0;
static long s_conversion_counter_UTMUPS_Forward = 0;
static long s_conversion_counter_UTMUPS_Reverse = 0;
inline void incrementCounter(long &counterRef)
{
#ifdef LTS_DEBUG
++counterRef;
#endif
}
static inline std::string cleanupMgrsString(const QString &in)
{
const QByteArray ba(in.toLatin1());
std::string ret;
ret.reserve(ba.size());
for (const char c : ba)
{
if (c != ' ')
ret += c;
}
return ret;
}
QString UtmCoordinate::mgrs(int prec, bool withSpaces) const
{
if (prec < 0)
prec = 0;
if (prec > 11)
prec = 11;
std::string mgrs;
try
{
GeographicLib::MGRS::Forward(zone, northp, x, y, prec, mgrs);
incrementCounter(s_conversion_counter_MGRS_Forward);
}
catch (const std::exception &e)
{
fprintf(stderr, "Error while calculating mgrs from utm %d, %9.6f, %9.6f: %s\n", zone, x, y, e.what());
mgrs.clear();
}
QString ret;
if (withSpaces && mgrs.size() == static_cast<size_t>(5 + 2 * prec))
{
const char *ptr = mgrs.c_str();
ret = QString::fromLatin1(ptr, 3) + QLatin1Char(' ') +
QString::fromLatin1(ptr + 3, 2);
if (prec > 0)
{
ret += QLatin1Char(' ') + QString::fromLatin1(ptr + 5, prec) +
QLatin1Char(' ') + QString::fromLatin1(ptr + 5 + prec, prec);
}
}
else
ret = QString::fromLatin1(mgrs.c_str(), mgrs.size());
return ret;
}
QPointF UtmCoordinate::toPoint() const
{
return {x,y};
}
QPointF UtmCoordinate::geographic(double offsetX, double offsetY) const
{
QPointF ret;
try
{
GeographicLib::UTMUPS::Reverse(zone, northp, x + offsetX, y + offsetY, ret.ry(), ret.rx());
incrementCounter(s_conversion_counter_UTMUPS_Reverse);
}
catch (const std::exception &e)
{
fprintf(stderr, "Error while calculating geographic from utm %d, %9.6f, %9.6f: %s\n", zone, x + offsetX, y + offsetY, e.what());
ret = QPointF();
}
return ret * deg2rad();
}
QPointF UtmCoordinate::geographic(const QPointF &offset) const
{
return geographic(offset.x(), offset.y());
}
QPointF UtmCoordinate::relativeTo(const UtmCoordinate &other) const
{
if (zone == other.zone)
return QPointF(x - other.x, y - other.y);
UtmCoordinate otherInMyZone = fromGeographic(other.geographic(), zone);
return QPointF(x - otherInMyZone.x, y - otherInMyZone.y);
}
UtmCoordinate UtmCoordinate::fromGeographic(double lon, double lat, int setZone)
{
lon *= rad2deg();
lat *= rad2deg();
UtmCoordinate ret;
try
{
GeographicLib::UTMUPS::Forward(lat, lon, ret.zone, ret.northp, ret.x, ret.y, setZone);
incrementCounter(s_conversion_counter_UTMUPS_Forward);
}
catch (const std::exception &e)
{
fprintf(stderr, "Error while calculating mgrs base point from %9.6f, %9.6f: %s\n", lat, lon, e.what());
ret = UtmCoordinate();
}
return ret;
}
UtmCoordinate UtmCoordinate::fromGeographic(const QPointF &lonLat, int setZone)
{
return fromGeographic(lonLat.x(), lonLat.y(), setZone);
}
UtmCoordinate UtmCoordinate::fromMgrs(const QString &mgrs)
{
UtmCoordinate utm;
try
{
int prec;
GeographicLib::MGRS::Reverse(cleanupMgrsString(mgrs), utm.zone, utm.northp, utm.x, utm.y, prec, true);
incrementCounter(s_conversion_counter_MGRS_Reverse);
}
catch (const std::exception &e)
{
fprintf(stderr, "Error while converting mgrs coordinate %s to utm: %s\n", qPrintable(mgrs), e.what());
utm = UtmCoordinate();
}
return utm;
}
QString mgrsFromGeographic(double lon, double lat, int prec, bool withSpaces)
{
return UtmCoordinate::fromGeographic(lon, lat, -1).mgrs(prec, withSpaces);
}
QPointF geographicFromMgrs(const QString &mgrs)
{
return UtmCoordinate::fromMgrs(mgrs).geographic();
}
QVector<UtmCoordinate> &staticDefaultSquaresHelper()
{
static QVector<UtmCoordinate> s_defaultMgrsSquares;
return s_defaultMgrsSquares;
}
UtmCoordinate &staticPreferedMgrsSquareHelper()
{
static UtmCoordinate s_preferedMgrsSquare;
return s_preferedMgrsSquare;
}
QVector<UtmCoordinate> &staticMgrsSquaresWithOffsetsHelper()
{
static QVector<UtmCoordinate> s_mgrsSquaresWithOffsets;
return s_mgrsSquaresWithOffsets;
}
QRectF addMarginToArea(const QRectF &rect_LatLon_radiant, const QSize &marginMeter)
{
double lonMin, lonMax, latMin, latMmax;
rect_LatLon_radiant.normalized().getCoords(&lonMin, &latMin, &lonMax, &latMmax);
LtsCoordTrans::UtmCoordinate basePoint;
{
const QPointF centerRad = rect_LatLon_radiant.center();
QString mgrs = LtsCoordTrans::mgrsFromGeographic(centerRad.x(), centerRad.y(), -1);
mgrs += QStringLiteral("00000000000000");
basePoint = LtsCoordTrans::UtmCoordinate::fromMgrs(mgrs);
}
const UtmCoordinate lowerLeft(UtmCoordinate::fromGeographic(lonMin, latMin, basePoint.zone));
const UtmCoordinate upperRight(UtmCoordinate::fromGeographic(lonMax, latMmax, basePoint.zone));
int offsetX = marginMeter.width();
int offsetY = marginMeter.height();
const QPointF topLeft(lowerLeft.geographic(-offsetX, -offsetY));
const QPointF bottomRight(upperRight.geographic(offsetX, offsetY));
QRectF res = QRectF(topLeft, bottomRight);
return res;
}
QVector<UtmCoordinate> getMgrsSquares(const QRectF &rect, bool setAsDefaultSquares, bool setAsPreferedSquare, bool setAsSquareWithMargin)
{
QVector<UtmCoordinate> ret = getMgrsSquaresInternal(rect);
if (setAsDefaultSquares)
staticDefaultSquaresHelper() = ret;
if (setAsPreferedSquare)
staticPreferedMgrsSquareHelper() = LtsCoordTrans::UtmCoordinate::fromGeographic(rect.center());
if (setAsSquareWithMargin)
staticMgrsSquaresWithOffsetsHelper() = ret;
return ret;
}
QVector<UtmCoordinate> getMgrsSquaresInternal(const QRectF &rect)
{
QVector<UtmCoordinate> ret;
QVector<QString> tmpMgrsSquares;
double lonMin, lonMax, latMin, latMmax;
rect.normalized().getCoords(&lonMin, &latMin, &lonMax, &latMmax);
bool withInSingleUtmSquare = true;
{
const UtmCoordinate upperRight(UtmCoordinate::fromGeographic(lonMax, latMmax));
const UtmCoordinate lowerLeft(UtmCoordinate::fromGeographic(lonMin, latMin));
withInSingleUtmSquare = upperRight.zone == lowerLeft.zone;
}
LtsCoordTrans::UtmCoordinate basePoint;
{
QPointF centerRad = rect.center();
QString mgrs = LtsCoordTrans::mgrsFromGeographic(centerRad.x(), centerRad.y(), -1);
mgrs += QStringLiteral("00000000000000");
basePoint = LtsCoordTrans::UtmCoordinate::fromMgrs(mgrs);
}
const UtmCoordinate upperRight(UtmCoordinate::fromGeographic(lonMax, latMmax, basePoint.zone));
const UtmCoordinate lowerLeft(UtmCoordinate::fromGeographic(lonMin, latMin, basePoint.zone));
const double maxX(upperRight.x - lowerLeft.x);
const double maxY(upperRight.y - lowerLeft.y);
const int increment = withInSingleUtmSquare ? 10000 : 1000;
for (double x = 0; x <= maxX + increment; x += increment)
{
const double xOfs = std::min(x, maxX);
for (double y = 0; y <= maxY + increment; y += increment)
{
const double yOfs = std::min(y, maxY);
const UtmCoordinate utm(UtmCoordinate::fromGeographic(lowerLeft.geographic(xOfs, yOfs)));
const QString mgrs(utm.mgrs(0));
if (!tmpMgrsSquares.contains(mgrs))
{
tmpMgrsSquares += mgrs;
ret += utm;
}
}
}
return ret;
}
QStringList getMgrsSurroundingSquares(const QRectF &geoRect, const QSize &offsetMeter)
{
const QVector<UtmCoordinate> mainUtms = getMgrsSquaresInternal(geoRect);
QStringList mainSquares;
mainSquares.reserve(mainUtms.count());
for (const auto &utm : mainUtms)
mainSquares.append(utm.mgrs(0));
const QRectF rectWithOffset = addMarginToArea(geoRect,offsetMeter);
QVector<UtmCoordinate> mainUtmsWithOffset = getMgrsSquaresInternal(rectWithOffset);
QStringList mainSquaresWithOffset;
mainSquaresWithOffset.reserve(mainUtmsWithOffset.count());
for (const auto &utm : qAsConst(mainUtmsWithOffset))
mainSquaresWithOffset.append(utm.mgrs(0));
QStringList surroundingSquares;
surroundingSquares.reserve(mainSquaresWithOffset.count());
for (const auto & mgrs0 : mainSquaresWithOffset)
{
if (!mainSquares.contains(mgrs0))
surroundingSquares.append(mgrs0);
}
return surroundingSquares;
}
QVector<UtmCoordinate> defaultMgrsSquareWithOffsets()
{
return staticMgrsSquaresWithOffsetsHelper();
}
void setDefaultMgrsSquares(const QVector<QString> &squares)
{
QVector<UtmCoordinate> coords;
coords.reserve(squares.size());
for (const QString &s : squares)
coords += UtmCoordinate::fromMgrs(s + QStringLiteral("00000000000000"));
staticDefaultSquaresHelper() = coords;
}
QVector<UtmCoordinate> defaultMgrsSquares()
{
return staticDefaultSquaresHelper();
}
UtmCoordinate preferedMgrsSquare()
{
return staticPreferedMgrsSquareHelper();
}
bool lonLatAltToGeocentric(double lon, double lat, double altitude, double &xOut, double &yOut, double &zOut)
{
lon *= rad2deg();
lat *= rad2deg();
try
{
GeographicLib::Geocentric::WGS84().Forward(lat, lon, altitude, xOut, yOut, zOut);
incrementCounter(s_conversion_counter_WGS84_Forward);
}
catch (...)
{
xOut = 0;
yOut = 0;
zOut = 0;
return false;
}
return true;
}
bool geocentric2LonLatAlt(double x, double y, double z,
double &lon, double &lat, double &altitude)
{
try
{
GeographicLib::Geocentric::WGS84().Reverse(x, y, z, lat, lon, altitude);
incrementCounter(s_conversion_counter_WGS84_Reverse);
}
catch (...)
{
lon = 0;
lat = 0;
altitude = 0;
return false;
}
lon *= deg2rad();
lat *= deg2rad();
return true;
}
double distance(const QPointF &p1, const QPointF &p2)
{
return distance(p1.x(), p1.y(), p2.x(), p2.y());
}
double squareDistance(const QPointF &p1, const QPointF &p2)
{
return squareDistance(p1.x(), p1.y(), p2.x(), p2.y());
}
std::ostream &operator<< (std::ostream &stream,
const UtmCoordinate &coord)
{
stream << "UtmCoordinate(" << std::setprecision(8) << coord.x
<< "#" << std::setprecision(8) << coord.y
<< " zone=" << coord.zone << ")";
return stream;
}
void dumpConversionCounter()
{
fprintf(stderr, "LtsCoordTrans: s_conversion_counter_MGRS_Forward : - mgrs : %ld\n" , s_conversion_counter_MGRS_Forward);
fprintf(stderr, "LtsCoordTrans: s_conversion_counter_MGRS_Reverse - fromMgrs : %ld\n" , s_conversion_counter_MGRS_Reverse);
fprintf(stderr, "LtsCoordTrans: s_conversion_counter_WGS84_Forward - lonLatAltToGeocentric : %ld\n" , s_conversion_counter_WGS84_Forward);
fprintf(stderr, "LtsCoordTrans: s_conversion_counter_WGS84_Reverse - geocentric2LonLatAlt : %ld\n" , s_conversion_counter_WGS84_Reverse);
fprintf(stderr, "LtsCoordTrans: s_conversion_counter_UTMUPS_Forward - fromGeographic : %ld\n" , s_conversion_counter_UTMUPS_Forward);
fprintf(stderr, "LtsCoordTrans: s_conversion_counter_UTMUPS_Reverse - geographic : %ld\n" , s_conversion_counter_UTMUPS_Reverse);
}
long getConversionCounter_MGRS_Forward() { return s_conversion_counter_MGRS_Forward; }
long getConversionCounter_MGRS_Reverse() { return s_conversion_counter_MGRS_Reverse; }
long getConversionCounter_WGS84_Forward() { return s_conversion_counter_WGS84_Forward; }
long getConversionCounter_WGS84_Reverse() { return s_conversion_counter_WGS84_Reverse; }
long getConversionCounter_UTMUPS_Forward() { return s_conversion_counter_UTMUPS_Forward; }
long getConversionCounter_UTMUPS_Reverse() { return s_conversion_counter_UTMUPS_Reverse; }
}
+249
View File
@@ -0,0 +1,249 @@
#pragma once
#include <LtsCoordTrans/ltscoordtrans_export.h>
#include <string>
#include <cmath>
#include <QVector>
class QPointF;
class QRectF;
class QSize;
class QString;
namespace LtsCoordTrans
{
inline Q_CONSTEXPR double pi() { return M_PI; }
inline Q_CONSTEXPR double deg2rad() { return pi() / 180.; }
inline Q_CONSTEXPR double rad2deg() { return 1. / deg2rad(); }
struct LTSCOORDTRANS_EXPORT UtmCoordinate
{
int zone = -1;
bool northp = true;
double x = 0.;
double y = 0.;
UtmCoordinate() = default;
UtmCoordinate(int zone_, double x_, double y_, bool northp_ = true)
: zone(zone_)
, northp(northp_)
, x(x_)
, y(y_)
{}
bool isValid() const { return zone > 0 && zone <= 60; }
QString mgrs(int prec = 5, bool withSpaces = true) const;
QPointF toPoint() const;
QPointF geographic(double offsetX = 0., double offsetY = 0.) const;
QPointF geographic(const QPointF &offset) const;
QPointF relativeTo(const UtmCoordinate &other) const;
static UtmCoordinate fromGeographic(double lon, double lat, int setZone = -1);
static UtmCoordinate fromGeographic(const QPointF &lonLat, int setZone = -1);
static UtmCoordinate fromMgrs(const QString &mgrs);
};
LTSCOORDTRANS_EXPORT QString mgrsFromGeographic(double lon, double lat, int prec = 5, bool withSpaces = true);
LTSCOORDTRANS_EXPORT QPointF geographicFromMgrs(const QString &mgrs);
LTSCOORDTRANS_EXPORT QRectF addMarginToArea(const QRectF &rect_LatLon_radiant, const QSize &marginMeter);
LTSCOORDTRANS_EXPORT QVector<UtmCoordinate> getMgrsSquares(const QRectF &rect, bool setAsDefaultSquares, bool setAsPreferedSquare, bool setAsSquareWithMargin = false);
QVector<UtmCoordinate> getMgrsSquaresInternal(const QRectF &rect);
QStringList getMgrsSurroundingSquares(const QRectF &geoRect, const QSize &offsetMeter);
LTSCOORDTRANS_EXPORT QVector<UtmCoordinate> defaultMgrsSquareWithOffsets();
LTSCOORDTRANS_EXPORT void setDefaultMgrsSquares(const QVector<QString> &squares);
LTSCOORDTRANS_EXPORT QVector<UtmCoordinate> defaultMgrsSquares();
LTSCOORDTRANS_EXPORT UtmCoordinate preferedMgrsSquare();
LTSCOORDTRANS_EXPORT bool lonLatAltToGeocentric(double lon, double lat, double altitude, double &xOut, double &yOut, double &zOut);
LTSCOORDTRANS_EXPORT bool geocentric2LonLatAlt(double x, double y, double z,
double &lon, double &lat, double &altitude);
inline double squareDistance(const UtmCoordinate &p1, const UtmCoordinate &p2)
{
if (p1.zone != p2.zone)
{
Q_ASSERT(false);
return std::nan("");
}
return std::pow(p1.x - p2.x, 2) + std::pow(p1.y - p2.y, 2);
}
LTSCOORDTRANS_EXPORT double squareDistance(const QPointF &p1, const QPointF &p2);
inline double squareDistance(const double lon1, const double lat1, const double lon2, const double lat2)
{
const auto p1(UtmCoordinate::fromGeographic(lon1, lat1));
const auto p2(UtmCoordinate::fromGeographic(lon2, lat2, p1.zone));
return squareDistance(p1, p2);
}
inline double squareDistance(const UtmCoordinate &p1, const double lon2, const double lat2)
{
const auto p2(UtmCoordinate::fromGeographic(lon2, lat2, p1.zone));
return squareDistance(p1, p2);
}
inline double distance(const UtmCoordinate &p1, const UtmCoordinate &p2)
{
if (p1.zone != p2.zone)
{
Q_ASSERT(false);
return std::nan("");
}
return sqrt(squareDistance(p1, p2));
}
LTSCOORDTRANS_EXPORT double distance(const QPointF &p1, const QPointF &p2);
inline double distance(const double lon1, const double lat1, const double lon2, const double lat2)
{
return sqrt(squareDistance(lon1, lat1, lon2, lat2));
}
inline double distance(const UtmCoordinate &p1, const double lon2, const double lat2)
{
return sqrt(squareDistance(p1, lon2, lat2));
}
LTSCOORDTRANS_EXPORT void dumpConversionCounter();
LTSCOORDTRANS_EXPORT long getConversionCounter_MGRS_Forward();
LTSCOORDTRANS_EXPORT long getConversionCounter_MGRS_Reverse();
LTSCOORDTRANS_EXPORT long getConversionCounter_WGS84_Forward();
LTSCOORDTRANS_EXPORT long getConversionCounter_WGS84_Reverse();
LTSCOORDTRANS_EXPORT long getConversionCounter_UTMUPS_Forward();
LTSCOORDTRANS_EXPORT long getConversionCounter_UTMUPS_Reverse();
LTSCOORDTRANS_EXPORT std::ostream &operator<< (std::ostream &stream,
const UtmCoordinate &coord);
class LTSCOORDTRANS_EXPORT UtmCoordinate3D : public LtsCoordTrans::UtmCoordinate
{
using BaseClass = LtsCoordTrans::UtmCoordinate;
public:
UtmCoordinate3D()
{
reset();
}
explicit UtmCoordinate3D(const LtsCoordTrans::UtmCoordinate &utm2d, double _zValue = std::nan(""))
:BaseClass()
{
zone = utm2d.zone;
northp = utm2d.northp;
x = utm2d.x;
y = utm2d.y;
zValue = _zValue;
}
void reset()
{
zone = -1;
northp = true;
x = 0.;
y = 0.;
zValue = std::nan("");
}
double z() const { return zValue; }
protected:
double zValue{std::nan("")};
};
}
+469
View File
@@ -0,0 +1,469 @@
#include "lts_coord_trans_unit_test.h"
#include "lts_coord_trans.h"
#include <GeographicLib/Math.hpp>
#include <QTest>
#include <QDebug>
QTEST_MAIN(coordtrans_test)
void coordtrans_test::initTestCase()
{
qDebug("sizeof(UtmCoordinate) = %lu", sizeof(LtsCoordTrans::UtmCoordinate));
}
void coordtrans_test::cleanupTestCase()
{}
void coordtrans_test::testFromGeographic()
{
LtsCoordTrans::UtmCoordinate utm;
QPointF lonlat;
lonlat = QPointF(8.6264954126, 53.1138437183) * LtsCoordTrans::deg2rad();
utm = LtsCoordTrans::UtmCoordinate::fromGeographic(lonlat.x(), lonlat.y(), -1);
QCOMPARE(utm.mgrs(0), QStringLiteral("32U MD"));
utm = LtsCoordTrans::UtmCoordinate::fromGeographic(lonlat.x(), lonlat.y());
QCOMPARE(utm.mgrs(8), QStringLiteral("32U MD 74999999 84999999"));
lonlat = QPointF(11.3003696521, 52.8224535191) * LtsCoordTrans::deg2rad();
utm = LtsCoordTrans::UtmCoordinate::fromGeographic(lonlat.x(), lonlat.y(), -1);
QCOMPARE(utm.mgrs(0), QStringLiteral("32U PD"));
utm = LtsCoordTrans::UtmCoordinate::fromGeographic(lonlat.x(), lonlat.y());
QCOMPARE(utm.mgrs(5), QStringLiteral("32U PD 55000 55000"));
lonlat = QPointF(54.8821607021, 24.2631973752) * LtsCoordTrans::deg2rad();
utm = LtsCoordTrans::UtmCoordinate::fromGeographic(lonlat.x(), lonlat.y(), -1);
QCOMPARE(utm.mgrs(0), QStringLiteral("40R BM"));
utm = LtsCoordTrans::UtmCoordinate::fromGeographic(lonlat.x(), lonlat.y());
QCOMPARE(utm.mgrs(5), QStringLiteral("40R BM 85000 85000"));
utm = LtsCoordTrans::UtmCoordinate::fromMgrs(QStringLiteral("40R BM 00000 00000"));
QCOMPARE(utm.mgrs(0), QStringLiteral("40Q BM"));
}
void coordtrans_test::testMgrsFromGeographic()
{
QString mgrs;
QPointF lonlat;
lonlat = QPointF(8.6191049344, 53.1048309844) * LtsCoordTrans::deg2rad();
mgrs = LtsCoordTrans::mgrsFromGeographic(lonlat.x(), lonlat.y(), 9);
QCOMPARE(mgrs, QStringLiteral("32U MD 745000000 840000000"));
mgrs = LtsCoordTrans::mgrsFromGeographic(lonlat.x(), lonlat.y(), 8, false);
QCOMPARE(mgrs, QStringLiteral("32UMD7450000084000000"));
}
void coordtrans_test::testRelativeMetricalOffet_data()
{
QTest::addColumn<QPoint>("offset");
QTest::addColumn<QString>("correctMgrs");
QTest::newRow("set 1") << QPoint( 5, 5) << QStringLiteral("32U PD 99995 99995");
QTest::newRow("set 2") << QPoint(100, 100) << QStringLiteral("32U QE 00090 00090");
QTest::newRow("set 3") << QPoint(500, 500) << QStringLiteral("32U QE 00490 00490");
}
void coordtrans_test::testRelativeMetricalOffet()
{
QFETCH(QPoint, offset);
QFETCH(QString, correctMgrs);
const LtsCoordTrans::UtmCoordinate &utmRef = LtsCoordTrans::UtmCoordinate::fromMgrs(QStringLiteral("32U PD 99990 99990"));
qDebug() << "utmRef = " << utmRef.mgrs();
{
LtsCoordTrans::UtmCoordinate utmRaw;
utmRaw.x = utmRef.x + offset.x();
utmRaw.y = utmRef.y + offset.y();
utmRaw.zone = utmRef.zone;
qDebug() << "offset = " << offset << " - utmRaw = " << utmRaw.mgrs();
QCOMPARE(utmRaw.mgrs(), correctMgrs);
}
{
const LtsCoordTrans::UtmCoordinate utmSimple(utmRef.zone,
utmRef.x + offset.x(),
utmRef.y + offset.y());
qDebug() << "offset = " << offset << " - utmSimple = " << utmSimple.mgrs();
QCOMPARE(utmSimple.mgrs(), correctMgrs);
}
}
QRectF createArea(const QString &base,
int xCenter, int yCenter, int width, int height)
{
QRectF areaRect = QRectF(xCenter - width / 2, yCenter - height / 2, width, height);
LtsCoordTrans::UtmCoordinate utmBase(LtsCoordTrans::UtmCoordinate::fromGeographic(LtsCoordTrans::geographicFromMgrs(base)));
const QPointF topLeft(utmBase.geographic(areaRect.left(), areaRect.top()));
const QPointF bottomRight(utmBase.geographic(areaRect.right(), areaRect.bottom()));
QRectF rect (topLeft, bottomRight);
return rect;
}
void coordtrans_test::testAddMarginToArea()
{
{
qDebug() << "Altmark";
QRectF area = createArea(QStringLiteral("32U PD 0000000000"), 50000, 10000, 30000, 30000);
QRectF area1Increased = LtsCoordTrans::addMarginToArea(area, QSize(5000, 20000));
qDebug() << "topLeft : " << qSetRealNumberPrecision(15) << area.topLeft() << " - degree:" << area.topLeft()*LtsCoordTrans::rad2deg();
qDebug() << "topLeftInc : " << qSetRealNumberPrecision(15) << area1Increased.topLeft() << " - degree:" << area1Increased.topLeft()*LtsCoordTrans::rad2deg();
qDebug() << "bottomRight : " << qSetRealNumberPrecision(15) << area.bottomRight() << " - degree:" << area.bottomRight()*LtsCoordTrans::rad2deg();
qDebug() << "bottomRightInc : " << qSetRealNumberPrecision(15) << area1Increased.bottomRight() << " - degree:" << area1Increased.bottomRight()*LtsCoordTrans::rad2deg();
QVERIFY2( area1Increased.topLeft().x() < area.topLeft().x(), "addMarginToArea topLeft X failed");
QVERIFY2( area1Increased.topLeft().y() < area.topLeft().y(), "addMarginToArea topLeft Y failed");
QVERIFY2( area1Increased.bottomRight().x() > area.bottomRight().x(), "addMarginToArea bottomRight X failed");
QVERIFY2( area1Increased.bottomRight().y() > area.bottomRight().y(), "addMarginToArea bottomRight Y failed");
}
{
qDebug() << "Luxemburg";
QRectF area = createArea(QStringLiteral("32U LA 0000000000"), 100, 100, 5000, 5000);
QRectF area1Increased = LtsCoordTrans::addMarginToArea(area, QSize(50000, 20000));
qDebug() << "topLeft : " << qSetRealNumberPrecision(15) << area.topLeft() << " - degree:" << area.topLeft()*LtsCoordTrans::rad2deg();
qDebug() << "topLeftInc : " << qSetRealNumberPrecision(15) << area1Increased.topLeft() << " - degree:" << area1Increased.topLeft()*LtsCoordTrans::rad2deg();
qDebug() << "bottomRight : " << qSetRealNumberPrecision(15) << area.bottomRight() << " - degree:" << area.bottomRight()*LtsCoordTrans::rad2deg();
qDebug() << "bottomRightInc : " << qSetRealNumberPrecision(15) << area1Increased.bottomRight() << " - degree:" << area1Increased.bottomRight()*LtsCoordTrans::rad2deg();
QVERIFY2( area1Increased.topLeft().x() < area.topLeft().x(), "addMarginToArea topLeft X failed");
QVERIFY2( area1Increased.topLeft().y() < area.topLeft().y(), "addMarginToArea topLeft Y failed");
QVERIFY2( area1Increased.bottomRight().x() > area.bottomRight().x(), "addMarginToArea bottomRight X failed");
QVERIFY2( area1Increased.bottomRight().y() > area.bottomRight().y(), "addMarginToArea bottomRight Y failed");
}
}
void coordtrans_test::testIncreaseRect()
{
QPointF lonlat = QPointF(8.6191049344, 53.1048309844) * LtsCoordTrans::deg2rad();
QString mgrs = LtsCoordTrans::mgrsFromGeographic(lonlat.x(), lonlat.y(), 9);
QCOMPARE(mgrs, QStringLiteral("32U MD 745000000 840000000"));
const LtsCoordTrans::UtmCoordinate centerPoint = LtsCoordTrans::UtmCoordinate::fromGeographic(lonlat.x(), lonlat.y());
LtsCoordTrans::UtmCoordinate topLeftUtm;
LtsCoordTrans::UtmCoordinate topLeftUtm2;
{
QPointF topLeftGeo = centerPoint.geographic(-1111, 2222);
QPointF bottomRightGeo = centerPoint.geographic( 3000, -4000);
topLeftUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(topLeftGeo);
const LtsCoordTrans::UtmCoordinate bottomRightUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(bottomRightGeo);
qDebug() << "topLeftUtm: " << topLeftUtm.x << " - " << qSetRealNumberPrecision(15) << topLeftUtm.y;
qDebug() << "bottomRightUtm: " << bottomRightUtm.x << " - " << qSetRealNumberPrecision(15) << bottomRightUtm.y;
}
{
topLeftUtm2.x = centerPoint.x - 1111;
topLeftUtm2.y = centerPoint.y + 2222;
LtsCoordTrans::UtmCoordinate bottomRightUtm2;
bottomRightUtm2.x = centerPoint.x + 3000;
bottomRightUtm2.y = centerPoint.y - 4000;
qDebug() << "topLeftUtm2: " << topLeftUtm2.x << " - " << qSetRealNumberPrecision(15) << topLeftUtm2.y;
qDebug() << "bottomRightUtm2: " << bottomRightUtm2.x << " - " << qSetRealNumberPrecision(15) << bottomRightUtm2.y;
}
QVERIFY2(qFuzzyCompare(topLeftUtm.x, topLeftUtm2.x), "testIncreaseRect x failed");
QVERIFY2(qFuzzyCompare(topLeftUtm.y, topLeftUtm2.y), "testIncreaseRect y failed");
}
void coordtrans_test::testIncreaseRect2()
{
QPointF lonlat = QPointF(8.6191049344, 53.1048309844) * LtsCoordTrans::deg2rad();
QString mgrs = LtsCoordTrans::mgrsFromGeographic(lonlat.x(), lonlat.y(), 9);
QCOMPARE(mgrs, QStringLiteral("32U MD 745000000 840000000"));
QRectF myRect;
QRectF myRectIncreased;
{
const LtsCoordTrans::UtmCoordinate centerPoint = LtsCoordTrans::UtmCoordinate::fromGeographic(lonlat.x(), lonlat.y());
QPointF topLeftGeo = centerPoint.geographic(-3000, 2000);
QPointF bottomRightGeo = centerPoint.geographic( 3000, -2000);
myRect = QRectF(topLeftGeo, bottomRightGeo).normalized();
qDebug() << "myRect : " << myRect;
qDebug() << "myRect center : " << myRect.center();
qDebug() << "myRect height : " << myRect.height();
}
{
const QPointF centerGeo = myRect.center();
const LtsCoordTrans::UtmCoordinate centerUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(centerGeo);
QPointF topLeftGeo = centerUtm.geographic(-6000, 4000);
QPointF bottomRightGeo = centerUtm.geographic( 6000, -4000);
myRectIncreased = QRectF(topLeftGeo, bottomRightGeo).normalized();
qDebug() << "myRectIncreased : " << myRectIncreased;
qDebug() << "myRectIncreased center: " << myRectIncreased.center();
qDebug() << "myRectIncreased height: " << myRectIncreased.height();
}
QVERIFY2( (int)(myRectIncreased.center().x()*10000) == (int)(myRect.center().x()*10000), "testIncreaseRect2 centerX failed");
QVERIFY2( (int)(myRectIncreased.center().y()*10000) == (int)(myRect.center().y()*10000), "testIncreaseRect2 centerY failed");
QVERIFY2(myRectIncreased.width() > myRect.width(), "testIncreaseRect2 width failed");
QVERIFY2(myRectIncreased.height() > myRect.height(), "testIncreaseRect2 height failed");
}
void coordtrans_test::testGeographicFromMgrs()
{
QString mgrs(QStringLiteral("32UPD7654398765"));
QPointF geographic = LtsCoordTrans::geographicFromMgrs(mgrs);
QCOMPARE(geographic, QPointF(11.6436815550, 53.2088411454) * LtsCoordTrans::deg2rad());
}
void coordtrans_test::testMgrsSquares()
{
checkArea(QStringLiteral("32U PD 0000000000"), 50000, 10000, 30000, 30000, { QStringLiteral("32U PC"),
QStringLiteral("32U PD")
});
checkArea(QStringLiteral("32U MD 0000000000"), 50000, 10000, 30000, 30000, { QStringLiteral("32U MC"),
QStringLiteral("32U MD")
});
checkArea(QStringLiteral("32U MD 0000000000"), 89999, 89999, 21000, 21000, { QStringLiteral("32U MD"),
QStringLiteral("32U ME"),
QStringLiteral("32U ND"),
QStringLiteral("32U NE")
});
checkArea(QStringLiteral("39Q XG 0000000000"), 40000, 35000, 60000, 70000, { QStringLiteral("39Q XG"),
QStringLiteral("39R XG")
});
checkArea(QStringLiteral("40R CP 0000000000"), 94000, 9000, 7000, 16000, { QStringLiteral("40R CP") });
checkArea(QStringLiteral("40R DN 0000000000"), 500, 95500, 12000, 7000, { QStringLiteral("40R CN"),
QStringLiteral("40R DN")
});
checkArea(QStringLiteral("40R DN 0000000000"), 500, 96760, 30000, 30000, { QStringLiteral("40R CN"),
QStringLiteral("40R CP"),
QStringLiteral("40R DN"),
QStringLiteral("40R DP")
});
checkArea(QStringLiteral("40R BM 0000000000"), 59000, 59500, 46000, 40000, { QStringLiteral("40Q BM"),
QStringLiteral("40R BM")
});
checkArea(QStringLiteral("32U LA 0000000000"), 10000, 10000, 5000, 5000, { QStringLiteral("32U LA"),
});
checkArea(QStringLiteral("32U LA 0000000000"), 100, 100, 60000, 60000, { QStringLiteral("31U GQ"),
QStringLiteral("31U GR"),
QStringLiteral("32U KA"),
QStringLiteral("32U KV"),
QStringLiteral("32U LA"),
QStringLiteral("32U LV")
});
checkArea(QStringLiteral("32U LA 0000000000"), 100, 100,150000,150000, { QStringLiteral("31U FQ"),
QStringLiteral("31U FR"),
QStringLiteral("31U GQ"),
QStringLiteral("31U GR"),
QStringLiteral("32U KA"),
QStringLiteral("32U KV"),
QStringLiteral("32U LA"),
QStringLiteral("32U LV")
});
checkArea(QStringLiteral("32U LA 0000000000"), 100, 100,200000,200000, { QStringLiteral("31U FP"),
QStringLiteral("31U FQ"),
QStringLiteral("31U FR"),
QStringLiteral("31U GP"),
QStringLiteral("31U GQ"),
QStringLiteral("31U GR"),
QStringLiteral("31U GS"),
QStringLiteral("32U KA"),
QStringLiteral("32U KB"),
QStringLiteral("32U KV"),
QStringLiteral("32U LA"),
QStringLiteral("32U LB"),
QStringLiteral("32U LV"),
QStringLiteral("32U MA"),
QStringLiteral("32U MB"),
QStringLiteral("32U MV")
});
}
QVector<LtsCoordTrans::UtmCoordinate> checkAreaGetMgrsSquares(const QString &base,
int xCenter, int yCenter, int width, int height)
{
QRectF areaRect = QRectF(xCenter - width / 2, yCenter - height / 2, width, height);
LtsCoordTrans::UtmCoordinate utmBase(LtsCoordTrans::UtmCoordinate::fromGeographic(LtsCoordTrans::geographicFromMgrs(base)));
const QPointF topLeft(utmBase.geographic(areaRect.left(), areaRect.top()));
const QPointF bottomRight(utmBase.geographic(areaRect.right(), areaRect.bottom()));
const auto squares = LtsCoordTrans::getMgrsSquares(QRectF(topLeft, bottomRight), false, false);
QStringList src;
src.reserve(squares.size());
for (const auto &utm : squares)
src += utm.mgrs(0);
src.sort();
return squares;
}
void coordtrans_test::testMgrsSquaresWithSurrounding()
{
int initialSize = 5000;
QVector<LtsCoordTrans::UtmCoordinate> squares1 = checkAreaGetMgrsSquares(QStringLiteral("32U NC 0000000000"), 50000, 50000, initialSize, initialSize);
QVERIFY2(squares1.size() == 1, "checkAreaGetMgrsSquares failed");
int biggerSize = initialSize + (1*110000);
QVector<LtsCoordTrans::UtmCoordinate> squares9 = checkAreaGetMgrsSquares(QStringLiteral("32U NC 0000000000"), 50000, 50000, biggerSize, biggerSize);
QVERIFY2(squares9.size() == 9, "checkAreaGetMgrsSquares biggerSize failed");
int muchBiggerSize = initialSize + (3*110000);
QVector<LtsCoordTrans::UtmCoordinate> square33 = checkAreaGetMgrsSquares(QStringLiteral("32U NC 0000000000"), 50000, 50000, muchBiggerSize, muchBiggerSize);
QVERIFY2(square33.size() == 33, "checkAreaGetMgrsSquares muchBiggerSize failed");
QStringList string1;
string1.reserve(squares1.size());
for (const LtsCoordTrans::UtmCoordinate &item : qAsConst(squares1))
string1.append(item.mgrs(0));
QStringList string9;
string9.reserve(squares9.size());
for (const LtsCoordTrans::UtmCoordinate &item : qAsConst(squares9))
string9.append(item.mgrs(0));
QStringList string33;
string33.reserve(square33.size());
for (const LtsCoordTrans::UtmCoordinate &item : qAsConst(square33))
string33.append(item.mgrs(0));
{
QStringList surroundingStrings;
surroundingStrings.reserve(squares9.size());
for (const QString &str : qAsConst(string9))
if (!string1.contains(str))
surroundingStrings.append(str);
QVERIFY2(surroundingStrings.size() == 8, "checkAreaGetMgrsSquares squaresDiff failed");
}
{
QStringList surroundingStrings;
surroundingStrings.reserve(string33.size());
for (const QString &str : qAsConst(string33))
if (!string1.contains(str))
surroundingStrings.append(str);
QVERIFY2(surroundingStrings.size() == 32, "checkAreaGetMgrsSquares squaresDiff failed");
}
}
void coordtrans_test::checkArea(const QString &base,
int xCenter, int yCenter, int width, int height,
const QStringList &coords)
{
qDebug() << "checkArea : base: " << base;
QRectF areaRect = QRectF(xCenter - width / 2, yCenter - height / 2, width, height);
LtsCoordTrans::UtmCoordinate utmBase(LtsCoordTrans::UtmCoordinate::fromGeographic(LtsCoordTrans::geographicFromMgrs(base)));
const QPointF topLeft(utmBase.geographic(areaRect.left(), areaRect.top()));
const QPointF bottomRight(utmBase.geographic(areaRect.right(), areaRect.bottom()));
qDebug() << "TopLeft: " << topLeft * LtsCoordTrans::rad2deg();
qDebug() << "BottomRight: " << bottomRight * LtsCoordTrans::rad2deg();
const auto squares = LtsCoordTrans::getMgrsSquares(QRectF(topLeft, bottomRight), false, false);
QStringList src;
src.reserve(squares.size());
for (const auto &utm : squares)
src += utm.mgrs(0);
src.sort();
qDebug() << "src: '" << src << "' expected: '" << coords << "'";
QCOMPARE(src, coords);
}
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include <QObject>
#include <QStringList>
class coordtrans_test : public QObject
{
Q_OBJECT
private Q_SLOTS:
void initTestCase();
void cleanupTestCase();
void testFromGeographic();
void testMgrsFromGeographic();
void testRelativeMetricalOffet_data();
void testRelativeMetricalOffet();
void testAddMarginToArea();
void testIncreaseRect();
void testIncreaseRect2();
void testGeographicFromMgrs();
void testMgrsSquares();
void testMgrsSquaresWithSurrounding();
private:
void checkArea(const QString &base,
int xCenter, int yCenter, int width, int height,
const QStringList &coords);
};
+196
View File
@@ -0,0 +1,196 @@
#include "lts_coord_widget.h"
#include "lts_coord_widget_p.h"
#include <LtsCoordTrans/lts_coord_trans.h>
#include <QToolButton>
namespace LtsCoordWidget
{
LtsCoordWidget::LtsCoordWidget(DisplayType dt, QWidget *parent)
: QWidget(parent)
, m_displayType(dt)
{
setFocusPolicy(Qt::StrongFocus);
rebuildUi();
}
void LtsCoordWidget::setCoordinate(const QPointF &geoCoord, bool bUseAsDefaultValue)
{
if (m_coordinate != geoCoord)
emit coordinateChanged(geoCoord);
if (bUseAsDefaultValue)
m_defaultCoordinate = geoCoord;
if (m_inputWidgetHandler)
m_inputWidgetHandler->setCoordinate(geoCoord);
}
void LtsCoordWidget::clear()
{
if (m_inputWidgetHandler)
m_inputWidgetHandler->clear();
}
void LtsCoordWidget::setCoordinate(double lon, double lat, bool bUseAsDefaultValue)
{
setCoordinate(QPointF(lon, lat), bUseAsDefaultValue);
}
QPointF LtsCoordWidget::coordinate() const
{
if (!m_inputWidgetHandler)
return QPointF();
return m_inputWidgetHandler->coordinate();
}
LtsCoordWidget::DisplayType LtsCoordWidget::displayType() const
{
return m_displayType;
}
void LtsCoordWidget::setDisplayType(LtsCoordWidget::DisplayType dt)
{
if (m_displayType == dt)
return;
m_displayType = dt;
rebuildUi();
}
bool LtsCoordWidget::withResetButton() const
{
return m_bWithResetButton;
}
void LtsCoordWidget::setWithResetButton(bool bWith)
{
if (m_bWithResetButton == bWith)
return;
m_bWithResetButton = bWith;
if (m_inputWidgetHandler)
m_inputWidgetHandler->resetButton()->setVisible(m_bWithResetButton);
}
bool LtsCoordWidget::showToolTip() const
{
return m_bShowToolTip;
}
void LtsCoordWidget::setShowToolTip(bool bShow)
{
if (m_bShowToolTip == bShow)
return;
m_bShowToolTip = bShow;
updateToolTip();
}
bool LtsCoordWidget::mgrsSquareEditable() const
{
return m_bMgrsSquareEditable;
}
void LtsCoordWidget::setMgrsSquareEditable(bool bEditable)
{
if (m_bMgrsSquareEditable == bEditable)
return;
m_bMgrsSquareEditable = bEditable;
if (m_inputWidgetHandler)
m_inputWidgetHandler->setSquaresEditable(bEditable);
}
void LtsCoordWidget::setWithSurroundingMgrsSquares(bool bEnable)
{
if (m_inputWidgetHandler)
m_inputWidgetHandler->setWithSurroundingSquare(bEnable);
}
void LtsCoordWidget::setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate> &geoCoords)
{
if (m_inputWidgetHandler)
m_inputWidgetHandler->setMgrsSquares(geoCoords);
}
bool LtsCoordWidget::event(QEvent *event)
{
if (event->type() == QEvent::ToolTip)
updateToolTip();
return QWidget::event(event);
}
void LtsCoordWidget::rebuildUi()
{
if (m_inputWidgetHandler)
{
m_inputWidgetHandler->cleanup();
delete m_inputWidgetHandler;
delete layout();
}
switch (m_displayType)
{
case DisplayType::MGRS5:
m_inputWidgetHandler = new MgrsEdit(5, this);
break;
case DisplayType::MGRS7:
m_inputWidgetHandler = new MgrsEdit(7, this);
break;
case DisplayType::UTM:
qt_assert("DisplayType::UTM not yet implemented", __FILE__, __LINE__);
break;
case DisplayType::WGS84:
m_inputWidgetHandler = new Wgs84Edit(this);
break;
}
if (!m_inputWidgetHandler)
return;
m_inputWidgetHandler->setSquaresEditable(m_bMgrsSquareEditable);
m_inputWidgetHandler->resetButton()->setVisible(m_bWithResetButton);
connect(m_inputWidgetHandler->resetButton(), &QToolButton::clicked,
this, &LtsCoordWidget::onResetToDefaultCoordinate);
connect(m_inputWidgetHandler, &LtsCoordInputWidgetHandler::coordinateChanged,
this, &LtsCoordWidget::coordinateChanged);
connect(m_inputWidgetHandler, &LtsCoordInputWidgetHandler::invalidCoordinate,
this, &LtsCoordWidget::invalidCoordinate);
if (!m_defaultCoordinate.isNull())
m_inputWidgetHandler->setCoordinate(m_defaultCoordinate);
}
void LtsCoordWidget::updateToolTip()
{
QString tt;
if (m_bShowToolTip)
{
const QPointF p(coordinate());
if (!p.isNull())
{
const QString mgrs = LtsCoordTrans::mgrsFromGeographic(p.x(), p.y());
const QPointF p2(p * LtsCoordTrans::rad2deg());
tt = tr("MGRS: %1\nlat/lon: %2/%3").arg(mgrs).arg(p2.y(), 0, 'f', 10).arg(p2.x(), 0, 'f', 10);
}
}
setToolTip(tt);
}
void LtsCoordWidget::onResetToDefaultCoordinate()
{
if (!m_inputWidgetHandler)
return;
if (m_defaultCoordinate.isNull())
m_inputWidgetHandler->clear();
m_inputWidgetHandler->setCoordinate(m_defaultCoordinate);
}
}
+78
View File
@@ -0,0 +1,78 @@
#pragma once
#include <LtsCoordTrans/ltscoordwidget_export.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <QWidget>
class QToolButton;
namespace LtsCoordWidget
{
class LtsCoordInputWidgetHandler;
class LTSCOORDWIDGET_EXPORT LtsCoordWidget : public QWidget
{
Q_OBJECT
public:
enum class DisplayType
{
MGRS5,
MGRS7,
UTM,
WGS84,
MGRS = DisplayType::MGRS5
};
Q_ENUM(DisplayType)
Q_PROPERTY(DisplayType displayType READ displayType WRITE setDisplayType)
Q_PROPERTY(bool withResetButton READ withResetButton WRITE setWithResetButton)
Q_PROPERTY(bool showToolTip READ showToolTip WRITE setShowToolTip)
Q_PROPERTY(bool mgrsSquareEditable READ mgrsSquareEditable WRITE setMgrsSquareEditable)
explicit LtsCoordWidget(QWidget *parent = nullptr)
: LtsCoordWidget(LtsCoordWidget::DisplayType::MGRS, parent)
{}
explicit LtsCoordWidget(DisplayType dt, QWidget *parent = nullptr);
QPointF coordinate() const;
DisplayType displayType() const;
bool withResetButton() const;
bool showToolTip() const;
bool mgrsSquareEditable() const;
bool event(QEvent *event) override;
public Q_SLOTS:
void setCoordinate(const QPointF &geoCoord, bool bUseAsDefaultValue = true);
void setCoordinate(double lon, double lat, bool bUseAsDefaultValue = true);
void setDisplayType(LtsCoordWidget::DisplayType dt);
void setWithResetButton(bool bWith);
void setShowToolTip(bool bShow);
void setMgrsSquareEditable(bool bEditable);
void setWithSurroundingMgrsSquares(bool bEnable);
void setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate> &geoCoords);
void clear();
Q_SIGNALS:
void coordinateChanged(const QPointF &newGeoCoord);
void invalidCoordinate();
private:
void rebuildUi();
void updateToolTip();
private Q_SLOTS:
void onResetToDefaultCoordinate();
private:
bool m_bWithResetButton = false;
bool m_bShowToolTip = true;
bool m_bMgrsSquareEditable = false;
LtsCoordWidget::DisplayType m_displayType = LtsCoordWidget::DisplayType::MGRS;
LtsCoordInputWidgetHandler *m_inputWidgetHandler = nullptr;
QPointF m_coordinate;
QPointF m_defaultCoordinate;
};
}
+55
View File
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Mgrs</class>
<widget class="QWidget" name="Mgrs">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>322</width>
<height>32</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QComboBox" name="cbxZone"/>
</item>
<item>
<widget class="QLineEdit" name="leEast">
<property name="toolTip">
<string>Pos X</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="leNorth">
<property name="toolTip">
<string>Pos Y</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbReset">
<property name="icon">
<iconset>
<normaloff>:/style/arrow_back.svg</normaloff>:/style/arrow_back.svg</iconset>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+325
View File
@@ -0,0 +1,325 @@
#include "lts_coord_widget_p.h"
namespace LtsCoordWidget
{
void LtsCoordInputWidgetHandler::onCoordinateDataChanged()
{
const QPointF coord(coordinate());
if (coord.isNull())
{
emit invalidCoordinate();
return;
}
emit coordinateChanged(coord);
}
MgrsEdit::MgrsEdit(int precision, QWidget *widget)
: LtsCoordInputWidgetHandler(widget)
, m_precision(precision)
, m_ui(new Ui::Mgrs)
{
m_ui->setupUi(widget);
if (m_precision < 0)
m_precision = 0;
if (m_precision > 11)
m_precision = 11;
const int upperLimit = pow(10, m_precision) - 1;
m_ui->leEast->setValidator(new QIntValidator(0, upperLimit, m_ui->leEast));
m_ui->leNorth->setValidator(new QIntValidator(0, upperLimit, m_ui->leNorth));
setDefaultMgrsSquares();
connect(m_ui->cbxZone, QOverload<const QString &>::of(&QComboBox::currentIndexChanged),
this, &MgrsEdit::onCoordinateDataChanged);
connect(m_ui->leEast, &QLineEdit::editingFinished,
this, &MgrsEdit::onCoordinateDataChanged);
connect(m_ui->leNorth, &QLineEdit::editingFinished,
this, &MgrsEdit::onCoordinateDataChanged);
}
MgrsEdit::~MgrsEdit()
{
delete m_ui;
}
bool MgrsEdit::isValid()
{
const QString &east = m_ui->leEast->text();
if (east.size() != m_precision)
return false;
const QString &north = m_ui->leNorth->text();
if (north.size() != m_precision)
return false;
if (m_ui->cbxZone->currentIndex() < 0)
return false;
if (m_ui->cbxZone->currentText().isEmpty())
return false;
return true;
}
void MgrsEdit::setCoordinate(const QPointF &geoCoord)
{
const QString mgrsString = LtsCoordTrans::mgrsFromGeographic(geoCoord.x(), geoCoord.y(), m_precision, false);
if (mgrsString.isEmpty())
{
m_ui->leEast->clear();
m_ui->leNorth->clear();
return;
}
m_ui->leEast->setText(QString());
m_ui->leNorth->setText(QString());
const QString mgrsSquare = mgrsString.left(3) + QLatin1Char(' ') + mgrsString.mid(3, 2);
QString east = mgrsString.mid(5, m_precision);
QString north = mgrsString.mid(5 + m_precision, m_precision);
int idx = m_ui->cbxZone->findText(mgrsSquare);
if (idx < 0)
{
addMgrsSquare(mgrsSquare);
idx = m_ui->cbxZone->findText(mgrsSquare);
}
m_ui->cbxZone->setCurrentIndex(idx);
m_ui->leEast->setText(east);
m_ui->leNorth->setText(north);
}
static inline QString getMgrsCoord(QLineEdit *le, int prec)
{
QString ret = le->text();
if (ret.isEmpty())
return ret;
while (ret.size() < prec)
ret += QLatin1Char('0');
le->setText(ret);
return ret;
}
QPointF MgrsEdit::coordinate() const
{
const QString east = getMgrsCoord(m_ui->leEast, m_precision);
const QString north = getMgrsCoord(m_ui->leNorth, m_precision);
if (east.isEmpty() || north.isEmpty() || m_ui->cbxZone->currentIndex() < 0)
return QPointF();
const QString mgrsString(m_ui->cbxZone->currentText() + east + north);
return LtsCoordTrans::geographicFromMgrs(mgrsString);
}
QToolButton *MgrsEdit::resetButton()
{
return m_ui->tbReset;
}
void MgrsEdit::cleanup()
{
delete m_ui->horizontalLayout;
delete m_ui->cbxZone;
delete m_ui->leEast;
delete m_ui->leNorth;
delete m_ui->tbReset;
}
void MgrsEdit::clear()
{
m_ui->cbxZone->clear();
m_ui->leEast->clear();
m_ui->leNorth->clear();
setDefaultMgrsSquares();
}
void MgrsEdit::setSquaresEditable(bool bEditable)
{
m_ui->cbxZone->setEditable(bEditable);
}
void MgrsEdit::setWithSurroundingSquare(bool bEnabled)
{
m_withMgrsSquareOffset = bEnabled;
}
static QStringList defaultMgrsSquares()
{
const QVector<LtsCoordTrans::UtmCoordinate> squares(LtsCoordTrans::defaultMgrsSquares());
QStringList sl;
sl.reserve(squares.size());
for (const LtsCoordTrans::UtmCoordinate &c : squares)
sl += c.mgrs(0);
std::sort(sl.begin(), sl.end());
return sl;
}
static QString preferedMgrsSquare()
{
const LtsCoordTrans::UtmCoordinate c(LtsCoordTrans::preferedMgrsSquare());
return c.mgrs(0);
}
void MgrsEdit::setDefaultMgrsSquares()
{
m_ui->cbxZone->addItems(defaultMgrsSquares());
m_ui->cbxZone->setCurrentIndex(m_ui->cbxZone->findText(preferedMgrsSquare()));
}
void MgrsEdit::addMgrsSquare(const QString &newMgrsSquare)
{
QStringList sl = defaultMgrsSquares();
sl += newMgrsSquare;
if (m_withMgrsSquareOffset)
{
QStringList squares = utmCoordsToList(LtsCoordTrans::defaultMgrsSquareWithOffsets());
for (const auto &sq : qAsConst(squares))
if (!sl.contains(sq))
sl.append(sq);
}
std::sort(sl.begin(), sl.end());
m_ui->cbxZone->clear();
m_ui->cbxZone->addItems(sl);
}
QStringList MgrsEdit::utmCoordsToList(const QVector<LtsCoordTrans::UtmCoordinate> &coords)
{
QStringList list;
list.reserve(coords.count());
for (const auto &utm : coords)
list.append(utm.mgrs(0));
return list;
}
void MgrsEdit::setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate> &geoCoords)
{
QStringList sl = utmCoordsToList(geoCoords);
if (sl.isEmpty())
return;
std::sort(sl.begin(), sl.end());
m_ui->cbxZone->clear();
m_ui->cbxZone->addItems(sl);
}
Wgs84Edit::Wgs84Edit(QWidget *widget)
: LtsCoordInputWidgetHandler(widget)
, m_ui(new Ui::Wgs84)
{
m_ui->setupUi(widget);
DoubleValidator *v = new DoubleValidator(-180, 180, 9, m_ui->leLon);
v->setNotation(QDoubleValidator::StandardNotation);
m_ui->leLon->setValidator(v);
v = new DoubleValidator(-180, 180, 9, m_ui->leLat);
v->setNotation(QDoubleValidator::StandardNotation);
m_ui->leLat->setValidator(v);
connect(m_ui->leLon, &QLineEdit::editingFinished,
this, &Wgs84Edit::onCoordinateDataChanged);
connect(m_ui->leLat, &QLineEdit::editingFinished,
this, &Wgs84Edit::onCoordinateDataChanged);
}
Wgs84Edit::~Wgs84Edit()
{
delete m_ui;
}
bool Wgs84Edit::isValid()
{
return (!m_ui->leLon->text().isEmpty()) && (!m_ui->leLat->text().isEmpty());
}
void Wgs84Edit::setCoordinate(const QPointF &geoCoord)
{
const QPointF coord(geoCoord * LtsCoordTrans::rad2deg());
const QLocale l;
m_ui->leLon->setText(l.toString(coord.x(), 'f', 9));
m_ui->leLat->setText(l.toString(coord.y(), 'f', 9));
}
QPointF Wgs84Edit::coordinate() const
{
QPointF ret;
const QLocale l;
const QString lonStr = m_ui->leLon->text().remove(l.groupSeparator());
const QString latStr = m_ui->leLat->text().remove(l.groupSeparator());
if (lonStr.isEmpty() || latStr.isEmpty())
return ret;
ret.rx() = l.toDouble(lonStr);
ret.ry() = l.toDouble(latStr);
return ret * LtsCoordTrans::deg2rad();
}
QToolButton *Wgs84Edit::resetButton()
{
return m_ui->tbReset;
}
void Wgs84Edit::cleanup()
{
delete m_ui->horizontalLayout;
delete m_ui->leLon;
delete m_ui->leLat;
delete m_ui->tbReset;
delete m_ui->lblLon;
delete m_ui->lblLat;
}
void Wgs84Edit::clear()
{
m_ui->leLon->clear();
m_ui->leLat->clear();
}
DoubleValidator::DoubleValidator(double bottom, double top, int decimals, QObject *parent)
: QDoubleValidator(bottom, top, decimals, parent)
{}
QValidator::State DoubleValidator::validate(QString &input, int &pos) const
{
const QValidator::State ret = QDoubleValidator::validate(input, pos);
if (ret != QValidator::Acceptable)
return ret;
QLocale l;
const QChar gs(l.groupSeparator());
if (gs.isNull())
return ret;
if (input.contains(gs))
return QValidator::Invalid;
return ret;
}
}
+93
View File
@@ -0,0 +1,93 @@
#pragma once
#include <QWidget>
#include <QComboBox>
#include <QVBoxLayout>
#include <LtsCoordTrans/lts_coord_trans.h>
#include "ui_lts_coord_widget_mgrs.h"
#include "ui_lts_coord_widget_wgs84.h"
namespace LtsCoordWidget
{
class LtsCoordInputWidgetHandler : public QObject
{
Q_OBJECT
public:
explicit LtsCoordInputWidgetHandler(QObject *parent)
: QObject(parent)
{}
virtual bool isValid() = 0;
virtual void setCoordinate(const QPointF &geoCoord) = 0;
virtual QPointF coordinate() const = 0;
virtual QToolButton *resetButton() = 0;
virtual void cleanup() = 0;
virtual void clear() = 0;
virtual void setSquaresEditable(bool bEditable) = 0;
virtual void setWithSurroundingSquare(bool bEnabled) = 0;
virtual void setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate> &geoCoords) = 0;
protected Q_SLOTS:
void onCoordinateDataChanged();
Q_SIGNALS:
void coordinateChanged(const QPointF &newGeoCoord);
void invalidCoordinate();
};
class MgrsEdit final : public LtsCoordInputWidgetHandler
{
Q_OBJECT
public:
explicit MgrsEdit(int precision, QWidget *widget);
~MgrsEdit();
bool isValid() override;
void setCoordinate(const QPointF &geoCoord) override;
QPointF coordinate() const override;
QToolButton *resetButton() override;
void cleanup() override;
void clear() override;
void setSquaresEditable(bool bEditable) override;
void setWithSurroundingSquare(bool bEnabled) override;
void setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate> &geoCoords) override;
private:
void setDefaultMgrsSquares();
void addMgrsSquare(const QString &newMgrsSquare);
QStringList utmCoordsToList(const QVector<LtsCoordTrans::UtmCoordinate> &coords);
private:
int m_precision;
bool m_withMgrsSquareOffset=false;
Ui::Mgrs *m_ui;
};
class Wgs84Edit final : public LtsCoordInputWidgetHandler
{
Q_OBJECT
public:
explicit Wgs84Edit(QWidget *widget);
~Wgs84Edit();
bool isValid() override;
void setCoordinate(const QPointF &geoCoord) override;
QPointF coordinate() const override;
QToolButton *resetButton() override;
void cleanup() override;
void clear() override;
void setSquaresEditable(bool bEditable) override { Q_UNUSED(bEditable); }
void setWithSurroundingSquare(bool bEnabled) override { Q_UNUSED(bEnabled); }
void setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate> &geoCoords) override { Q_UNUSED(geoCoords); }
private:
Ui::Wgs84 *m_ui;
};
class DoubleValidator final : public QDoubleValidator
{
Q_OBJECT
public:
DoubleValidator(double bottom, double top, int decimals, QObject *parent = nullptr);
QValidator::State validate(QString &input, int &pos) const override;
};
}
+115
View File
@@ -0,0 +1,115 @@
#include <QApplication>
#include <QDialog>
#include <QPushButton>
#include <QVBoxLayout>
#include <QLabel>
#include <LtsCoordTrans/lts_coord_trans.h>
#include "lts_coord_widget.h"
static void updateLabel(const QPointF &coord, QLabel *lbl, int prec)
{
QString mgrs = LtsCoordTrans::mgrsFromGeographic(coord.x(), coord.y(), prec);
QString str = QStringLiteral("mgrs: %1, lon: %2, lat: %3")
.arg(mgrs)
.arg(coord.x() * LtsCoordTrans::rad2deg(), 0, 'f', 10)
.arg(coord.y() * LtsCoordTrans::rad2deg(), 0, 'f', 10);
lbl->setText(str);
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
LtsCoordTrans::UtmCoordinate base(LtsCoordTrans::UtmCoordinate::fromMgrs(QStringLiteral("32UMD00")));
QPointF topLeft(base.geographic(+50000, -50000));
QPointF bottomRight(base.geographic(-50000, 50000));
LtsCoordTrans::getMgrsSquares(QRectF(topLeft, bottomRight), true, true);
QDialog *dialog(new QDialog);
QVBoxLayout *lay(new QVBoxLayout(dialog));
const QPointF defCoord(QPointF(53.0, 8.0) * LtsCoordTrans::deg2rad());
LtsCoordWidget::LtsCoordWidget *wMgrs5(new LtsCoordWidget::LtsCoordWidget(LtsCoordWidget::LtsCoordWidget::DisplayType::MGRS, dialog));
wMgrs5->setWithResetButton(true);
wMgrs5->setCoordinate(defCoord, true);
lay->addWidget(wMgrs5);
QLabel *lbl5(new QLabel(dialog));
lay->addWidget(lbl5);
QObject::connect(wMgrs5, &LtsCoordWidget::LtsCoordWidget::coordinateChanged,
lbl5, [lbl5](const QPointF & coord)
{
updateLabel(coord, lbl5, 5);
});
LtsCoordWidget::LtsCoordWidget *wMgrs7(new LtsCoordWidget::LtsCoordWidget(LtsCoordWidget::LtsCoordWidget::DisplayType::MGRS7, dialog));
wMgrs7->setWithResetButton(true);
wMgrs7->setCoordinate(defCoord, true);
lay->addWidget(wMgrs7);
QLabel *lbl7(new QLabel(dialog));
lay->addWidget(lbl7);
QObject::connect(wMgrs7, &LtsCoordWidget::LtsCoordWidget::coordinateChanged,
wMgrs7, [lbl7](const QPointF & coord)
{
updateLabel(coord, lbl7, 7);
});
LtsCoordWidget::LtsCoordWidget *w84(new LtsCoordWidget::LtsCoordWidget(LtsCoordWidget::LtsCoordWidget::DisplayType::WGS84, dialog));
w84->setWithResetButton(true);
w84->setCoordinate(defCoord, true);
lay->addWidget(w84);
QLabel *lbl84(new QLabel(dialog));
lay->addWidget(lbl84);
QObject::connect(w84, &LtsCoordWidget::LtsCoordWidget::coordinateChanged,
w84, [lbl84](const QPointF & coord)
{
updateLabel(coord, lbl84, 11);
});
QHBoxLayout *hLay = new QHBoxLayout;
lay->addLayout(hLay);
LtsCoordWidget::LtsCoordWidget *wChange(new LtsCoordWidget::LtsCoordWidget(LtsCoordWidget::LtsCoordWidget::DisplayType::WGS84, dialog));
wChange->setWithResetButton(true);
wChange->setCoordinate(defCoord, true);
hLay->addWidget(wChange);
QPushButton *pbReset(new QPushButton(QStringLiteral("With Reset"), dialog));
hLay->addWidget(pbReset);
QObject::connect(pbReset, &QPushButton::clicked,
wChange, [wChange]() { wChange->setWithResetButton(!wChange->withResetButton());});
QPushButton *pbNext(new QPushButton(QStringLiteral("Next Type"), dialog));
hLay->addWidget(pbNext);
QObject::connect(pbNext, &QPushButton::clicked,
wChange, [wChange]()
{
LtsCoordWidget::LtsCoordWidget::DisplayType dt = wChange->displayType();
switch (dt)
{
case LtsCoordWidget::LtsCoordWidget::DisplayType::MGRS5:
dt = LtsCoordWidget::LtsCoordWidget::DisplayType::MGRS7; break;
case LtsCoordWidget::LtsCoordWidget::DisplayType::MGRS7:
dt = LtsCoordWidget::LtsCoordWidget::DisplayType::WGS84; break;
case LtsCoordWidget::LtsCoordWidget::DisplayType::WGS84:
dt = LtsCoordWidget::LtsCoordWidget::DisplayType::MGRS5; break;
default:
break;
}
wChange->setDisplayType(dt);
});
QPushButton *pb(new QPushButton(QStringLiteral("Quit"), dialog));
lay->addWidget(pb);
QObject::connect(pb, &QPushButton::clicked, qApp, QCoreApplication::quit);
dialog->show();
int ret = app.exec();
delete dialog;
return ret;
}
+58
View File
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Wgs84</class>
<widget class="QWidget" name="Wgs84">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>293</width>
<height>32</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="lblLat">
<property name="text">
<string>Lat:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="leLat"/>
</item>
<item>
<widget class="QLabel" name="lblLon">
<property name="text">
<string>Lon:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="leLon"/>
</item>
<item>
<widget class="QToolButton" name="tbReset">
<property name="icon">
<iconset>
<normaloff>icon:arrow_back.svg</normaloff>icon:arrow_back.svg</iconset>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+45
View File
@@ -0,0 +1,45 @@
#include <GeographicLib/UTMUPS.hpp>
#include <GeographicLib/MGRS.hpp>
#include <string>
int main(int argc, char **argv)
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s <mgrs>\n", argv[0]);
return -1;
}
std::string mgrs = argv[1];
mgrs.erase(remove_if(mgrs.begin(), mgrs.end(), isspace), mgrs.end());
int prec;
double lonDeg, latDeg;
try
{
int zone;
bool northp;
double x, y;
GeographicLib::MGRS::Reverse(mgrs, zone, northp, x, y, prec, true);
GeographicLib::UTMUPS::Reverse(zone, northp, x, y, latDeg, lonDeg);
GeographicLib::UTMUPS::Forward(latDeg, lonDeg, zone, northp, x, y);
GeographicLib::MGRS::Forward(zone, northp, x, y, prec, mgrs);
}
catch (...)
{
fprintf(stderr, "Error converting %s to Lon/Lat coords\n", mgrs.c_str());
return -2;
}
std::string part1, part2, part3, part4;
part1 = mgrs.substr(0, 3);
part2 = mgrs.substr(3, 2);
part3 = mgrs.substr(5, prec);
part4 = mgrs.substr(5 + prec, prec);
fprintf(stdout, "%s %s %s %s = %13.10f, %13.10f ( %13.10f, %13.10f )\n",
part1.c_str(), part2.c_str(), part3.c_str(), part4.c_str(), lonDeg, latDeg, lonDeg / 180. * M_PI, latDeg / 180. * M_PI);
return 0;
}