368 lines
7.9 KiB
C++
Executable File
368 lines
7.9 KiB
C++
Executable File
|
|
|
|
|
|
#pragma once
|
|
|
|
#include <LtsCoordinate/ltscoordinate_export.h>
|
|
|
|
#include <Core/core.hpp>
|
|
#include <LtsCoordTrans/lts_coord_trans.h>
|
|
#include <LtsUtils/LtsUtilsCore/qpoint3d.h>
|
|
|
|
#include <QPointF>
|
|
#include <QDebug>
|
|
|
|
#include <functional>
|
|
#include <iosfwd>
|
|
#include <type_traits>
|
|
|
|
|
|
namespace LtsCoordTrans
|
|
{
|
|
|
|
using UtmCoordinate2D = LtsCoordTrans::UtmCoordinate;
|
|
using QPoint3D = LtsUtils::QPoint3D;
|
|
|
|
|
|
|
|
|
|
|
|
class LTSCOORDINATE_EXPORT LtsCoordinate
|
|
{
|
|
public:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
explicit LtsCoordinate(double lon = 0, double lat = 0, double z = std::nan(""))
|
|
: m_geo(Core::GeoPosition(lon, lat, z))
|
|
{}
|
|
|
|
explicit LtsCoordinate(const QPointF &lonLat, double z = std::nan(""))
|
|
: m_geo(Core::GeoPosition(lonLat.x(), lonLat.y(), z))
|
|
{}
|
|
|
|
explicit LtsCoordinate(const Core::GeoPosition &geoPos)
|
|
: m_geo(geoPos)
|
|
{}
|
|
|
|
explicit LtsCoordinate(const Core::GeoPosition2D &geoPos2D)
|
|
: m_geo(geoPos2D.lon(), geoPos2D.lat(), std::nan(""))
|
|
{}
|
|
|
|
|
|
|
|
LtsCoordinate(const LtsCoordTrans::UtmCoordinate &utm2D, double zValue) = delete;
|
|
|
|
static LtsCoordinate fromGeoPosition(double lon, double lat, double z = std::nan(""))
|
|
{
|
|
return LtsCoordinate(lon, lat, z);
|
|
}
|
|
|
|
|
|
static LtsCoordinate fromUtmCoordinate(const LtsCoordTrans::UtmCoordinate &utm2D, double zValue)
|
|
{
|
|
Q_ASSERT_X(utm2D.zone > 0, "LtsCoordinate", "zone has to be set");
|
|
|
|
|
|
|
|
const QPointF &geoPnt = utm2D.geographic();
|
|
|
|
return LtsCoordinate(geoPnt.x(), geoPnt.y(), zValue);
|
|
}
|
|
|
|
static LtsCoordinate fromUtm(const QPointF &utm2d, int zone, double zValue)
|
|
{
|
|
const LtsCoordTrans::UtmCoordinate utmCoord(zone, utm2d.x(), utm2d.y());
|
|
const QPointF &geoPnt = utmCoord.geographic();
|
|
return LtsCoordinate(geoPnt.x(), geoPnt.y(), zValue);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool isValid() const { return hasGeo() || hasUtm(); }
|
|
bool hasGeo() const { return !(valueIsNullOrNan(m_geo.lon()) ||
|
|
valueIsNullOrNan(m_geo.lat())); }
|
|
bool hasUtm() const { return m_utm2D.isValid(); }
|
|
|
|
static bool valueIsNullOrNan(double value) { return qFuzzyIsNull(value) || std::isnan(value); }
|
|
|
|
QString mgrs(int prec = 5, bool withSpaces = true) const;
|
|
QString mgrsWithZ(int prec = 5, bool withSpaces = true) const;
|
|
|
|
QString toString(bool fullAndExpensive = false) const;
|
|
|
|
|
|
|
|
static void resetConversionCounter();
|
|
static long getConversionCounter();
|
|
|
|
|
|
|
|
|
|
|
|
const Core::GeoPosition &geoPosition() const
|
|
{
|
|
return m_geo;
|
|
}
|
|
const Core::GeoPosition2D &geoPosition2D() const
|
|
{
|
|
return m_geo;
|
|
}
|
|
|
|
const LtsCoordTrans::UtmCoordinate &utmCoordinate() const
|
|
{
|
|
if (!hasUtm())
|
|
convertGeoToUtm();
|
|
return m_utm2D;
|
|
}
|
|
|
|
|
|
double &rz() { return m_geo.z(); }
|
|
double z() const { return m_geo.z(); }
|
|
void setZ(double value) { m_geo.z(value); }
|
|
|
|
|
|
LtsCoordTrans::UtmCoordinate utmCoordinateDiffZone(int zone) const
|
|
{
|
|
|
|
|
|
m_utm2D_differentZone = LtsCoordTrans::UtmCoordinate::fromGeographic(m_geo.lon(), m_geo.lat(), zone);
|
|
return m_utm2D_differentZone;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
T toUtm(int zone = -1) const
|
|
{
|
|
T obj;
|
|
helperToUtm(obj, zone);
|
|
return obj;
|
|
|
|
|
|
|
|
}
|
|
|
|
QPointF toUtmPointF() const { return toUtm<QPointF>(); }
|
|
QPoint3D toUtmPoint3D() const { return toUtm<QPoint3D>(); }
|
|
|
|
QPointF toGeoPointF() const { return QPointF (m_geo.lon(), m_geo.lat()); }
|
|
QPoint3D toGeoPoint3D() const { return QPoint3D(m_geo.lon(), m_geo.lat(), m_geo.z() ); }
|
|
|
|
|
|
UtmCoordinate3D toUtmCoordinate3D() const
|
|
{
|
|
return UtmCoordinate3D(utmCoordinate(), m_geo.z());
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
using elevationCbFunc = std::function<double(double, double, double, bool*)>;
|
|
|
|
|
|
|
|
|
|
static void setElevationCallback(const elevationCbFunc &elevationCB);
|
|
static bool hasElevationCallback();
|
|
|
|
|
|
|
|
|
|
double elevationAt(double defaultElevation = 0.0, bool *bIsCovered = nullptr) const;
|
|
void setZValueAccordingElevation(double defaultElevation = 0.0);
|
|
|
|
static double elevationAt(const LtsCoordinate &coordinate, double defaultElevation = 0.0, bool *bIsCovered = nullptr);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void replaceZValueByElevationIfValue(double zValueToBeReplaced = std::nan(""), double defaultElevation = 0.0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double heightOverElevation() const { return m_geo.z() - elevationAt(); }
|
|
|
|
|
|
double distanceUtm2D(const LtsCoordinate &other) const
|
|
{
|
|
|
|
|
|
const LtsCoordTrans::UtmCoordinate &thisUtm2D = utmCoordinate();
|
|
const LtsCoordTrans::UtmCoordinate &otherUtm2D = other.utmCoordinateDiffZone(m_utm2D.zone);
|
|
return LtsCoordTrans::distance(thisUtm2D, otherUtm2D);
|
|
}
|
|
|
|
double distanceUtm3D(const LtsCoordinate &other) const
|
|
{
|
|
|
|
|
|
const QPoint3D &thisUtm3D = toUtm<QPoint3D>();
|
|
const QPoint3D &otherUtm3D = other.toUtm<QPoint3D>(m_utm2D.zone);
|
|
const double dist3D = (thisUtm3D - otherUtm3D).length();
|
|
|
|
Q_ASSERT_X(!std::isnan(dist3D), "LtsCoordinate", "ERROR, distance3D is NaN");
|
|
|
|
return dist3D;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static double angleDegreeUtm2D(const LtsCoordinate &coord1, const LtsCoordinate &coord2);
|
|
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void clearGeo() const { clearGeoLonLat(); m_geo.z(std::nan("")); }
|
|
void clearGeoLonLat() const { m_geo.lon(0); m_geo.lat(0); }
|
|
void clearUtm() const { m_utm2D = m_utm2D_differentZone = UtmCoordinate2D(); }
|
|
void clearElevation() const { m_elevation = std::nan(""); }
|
|
void clear() const { clearGeo(); clearUtm(); clearElevation(); }
|
|
|
|
const LtsCoordTrans::UtmCoordinate &utmCoordinateInternal(int zone = -1) const;
|
|
void convertGeoToUtm() const;
|
|
|
|
protected:
|
|
|
|
void helperToUtm(QPointF &pntRef, int zone = -1) const
|
|
{
|
|
const auto &utmTemp = utmCoordinateInternal(zone);
|
|
pntRef.rx() = utmTemp.x;
|
|
pntRef.ry() = utmTemp.y;
|
|
}
|
|
void helperToUtm(QPoint3D &pntRef, int zone = -1) const
|
|
{
|
|
const auto &utmTemp = utmCoordinateInternal(zone);
|
|
pntRef.rx() = utmTemp.x;
|
|
pntRef.ry() = utmTemp.y;
|
|
pntRef.rz() = m_geo.z();
|
|
}
|
|
|
|
protected:
|
|
mutable Core::GeoPosition m_geo;
|
|
mutable UtmCoordinate2D m_utm2D;
|
|
mutable UtmCoordinate2D m_utm2D_differentZone;
|
|
mutable double m_elevation{std::nan("")};
|
|
|
|
static elevationCbFunc m_getElevationCB;
|
|
};
|
|
|
|
|
|
|
|
|
|
class LTSCOORDINATE_EXPORT LtsCoordinateNoImplicitCopy : public LtsCoordinate
|
|
{
|
|
public:
|
|
using BaseClass = LtsCoordinate;
|
|
|
|
|
|
|
|
LtsCoordinateNoImplicitCopy() = default;
|
|
explicit LtsCoordinateNoImplicitCopy (const LtsCoordinateNoImplicitCopy &) = default;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
~LtsCoordinateNoImplicitCopy() = default;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
explicit LtsCoordinateNoImplicitCopy(const QPointF &lonLat, double z = std::nan(""))
|
|
: BaseClass(Core::GeoPosition(lonLat.x(), lonLat.y(), z))
|
|
{}
|
|
|
|
explicit LtsCoordinateNoImplicitCopy(const Core::GeoPosition &geoPos)
|
|
: BaseClass(geoPos)
|
|
{}
|
|
|
|
explicit LtsCoordinateNoImplicitCopy(const Core::GeoPosition2D &geoPos2D)
|
|
: BaseClass(geoPos2D)
|
|
{}
|
|
|
|
|
|
|
|
|
|
void updateGeoPosition(const Core::GeoPosition &geoPos) const
|
|
{
|
|
clear();
|
|
m_geo = geoPos;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T_OUT, typename T_IN>
|
|
T_OUT convert(const T_IN& contIn)
|
|
{
|
|
T_OUT out;
|
|
out.reserve(contIn.size());
|
|
for (const Core::GeoPosition &posGeo : qAsConst(contIn))
|
|
out.push_back(LtsCoordinate(posGeo));
|
|
return out;
|
|
}
|
|
|
|
|
|
|
|
LTSCOORDINATE_EXPORT std::ostream &operator<< (std::ostream &stream,
|
|
const LtsCoordinate &value);
|
|
|
|
|
|
}
|
|
|