Continues migration with DDS, Common
This commit is contained in:
1 parent
9b15cee841
commit
fa48db111e
668 files changed
+111841
-2
No files matched your search
Executable
+78
@@ -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()
|
||||
Executable
+67
@@ -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;
|
||||
}
|
||||
Executable
+445
@@ -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; }
|
||||
|
||||
}
|
||||
Executable
+249
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+78
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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>
|
||||
Executable
+45
@@ -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;
|
||||
}
|
||||
Reference in new issue
Block a user