Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
Executable
+184
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* LtsCoordinate
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, ESVG, 2024-08-27
|
||||
*/
|
||||
|
||||
|
||||
#include "lts_coordinate.h"
|
||||
#include <QLineF>
|
||||
|
||||
namespace LtsCoordTrans
|
||||
{
|
||||
|
||||
static long s_conversion_counter = 0; // counts conversion
|
||||
|
||||
//
|
||||
std::function<double(double, double, double, bool*)> LtsCoordinate::m_getElevationCB;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// class LtsCoordinate
|
||||
//------------------------------------------------------------------------------
|
||||
void LtsCoordinate::setElevationCallback(const elevationCbFunc &elevationCB)
|
||||
{
|
||||
m_getElevationCB = elevationCB;
|
||||
}
|
||||
|
||||
bool LtsCoordinate::hasElevationCallback()
|
||||
{
|
||||
return m_getElevationCB != nullptr;
|
||||
}
|
||||
|
||||
double LtsCoordinate::elevationAt(double defaultElevation, bool *bIsCovered) const
|
||||
{
|
||||
// shall we cache bIsCovered also?
|
||||
// no. If bIsCovered is provided, we explicitly call m_getElevationCB
|
||||
// if not, we benefit from cache (m_elevation);
|
||||
if (!bIsCovered)
|
||||
if (!std::isnan(m_elevation))
|
||||
return m_elevation;
|
||||
if (m_getElevationCB)
|
||||
m_elevation = m_getElevationCB(m_geo.lon(), m_geo.lat(), defaultElevation, bIsCovered);
|
||||
return m_elevation;
|
||||
}
|
||||
|
||||
void LtsCoordinate::setZValueAccordingElevation(double defaultElevation)
|
||||
{
|
||||
m_geo.z(elevationAt(defaultElevation));
|
||||
}
|
||||
|
||||
double LtsCoordinate::elevationAt(const LtsCoordinate &coordinate, double defaultElevation, bool *bIsCovered)
|
||||
{
|
||||
return coordinate.elevationAt(defaultElevation, bIsCovered);
|
||||
}
|
||||
|
||||
void LtsCoordinate::replaceZValueByElevationIfValue(double zValueToBeReplaced, double defaultElevation)
|
||||
{
|
||||
// 2024-10: Norbert Thoden
|
||||
// if (qFuzzyCompare(m_geo.z(), zValueToBeReplaced)) did not work with NaN as expected
|
||||
// qFuzzyCompare(std::nan(""), std::nan("")) will return 'false' !!!
|
||||
// so check NaN explicit:
|
||||
|
||||
if ((std::isnan(zValueToBeReplaced) && std::isnan(m_geo.z())) ||
|
||||
qFuzzyCompare(m_geo.z(), zValueToBeReplaced))
|
||||
setZValueAccordingElevation(defaultElevation);
|
||||
}
|
||||
|
||||
double LtsCoordinate::angleDegreeUtm2D(const LtsCoordinate &coord1, const LtsCoordinate &coord2)
|
||||
{
|
||||
const LtsCoordTrans::UtmCoordinate &utm1 = coord1.utmCoordinate(); // implicit coord1.zone will be set
|
||||
const LtsCoordTrans::UtmCoordinate &utm2 = coord2.utmCoordinateDiffZone(utm1.zone);
|
||||
|
||||
const QPointF& offsetUtm = utm2.toPoint() - utm1.toPoint();
|
||||
QLineF poly(QPointF(), offsetUtm);
|
||||
const double angle = poly.angle();
|
||||
|
||||
|
||||
// QLineF::angle()
|
||||
// 270
|
||||
// |
|
||||
// |
|
||||
// 180 --------- 0
|
||||
// |
|
||||
// |
|
||||
// 90
|
||||
|
||||
// desired:
|
||||
// 0
|
||||
// |
|
||||
// |
|
||||
// 270 --------- 90
|
||||
// |
|
||||
// |
|
||||
// 180
|
||||
|
||||
return fmod(angle+90.0, 360);
|
||||
}
|
||||
|
||||
const UtmCoordinate &LtsCoordinate::utmCoordinateInternal(int zone) const
|
||||
{
|
||||
if (zone == -1)
|
||||
{
|
||||
if (!hasUtm())
|
||||
convertGeoToUtm();
|
||||
return m_utm2D; // <- return
|
||||
}
|
||||
utmCoordinateDiffZone(zone); // ensure m_utm2D_differentZone
|
||||
return m_utm2D_differentZone; // <- return
|
||||
}
|
||||
|
||||
void LtsCoordinate::convertGeoToUtm() const
|
||||
{
|
||||
// geo -> utm
|
||||
int zone = -1;
|
||||
// avoid working with NaN
|
||||
if (std::isnan(m_geo.lon()) || std::isnan(m_geo.lat()))
|
||||
{
|
||||
fprintf(stderr, "Error while fromGeographic, value is NaN\n");
|
||||
m_utm2D = LtsCoordTrans::UtmCoordinate();
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef LTS_DEBUG
|
||||
++s_conversion_counter;
|
||||
#endif // LTS_DEBUG
|
||||
|
||||
m_utm2D = LtsCoordTrans::UtmCoordinate::fromGeographic(m_geo.lon(), m_geo.lat(), zone);
|
||||
Q_ASSERT_X(m_utm2D.zone > 0, "LtsCoordinate", "zone has to be set");
|
||||
}
|
||||
|
||||
QString LtsCoordinate::mgrs(int prec, bool withSpaces) const
|
||||
{
|
||||
utmCoordinateInternal(); // ensure m_utm2D
|
||||
QString tmp = m_utm2D.mgrs(prec, withSpaces);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
QString LtsCoordinate::mgrsWithZ(int prec, bool withSpaces) const
|
||||
{
|
||||
double ele = elevationAt();
|
||||
QString tmp = mgrs(prec, withSpaces) + QStringLiteral(" z=") + QString::number(ele, 'f', 2);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
QString LtsCoordinate::toString(bool fullAndExpensive) const
|
||||
{
|
||||
if (fullAndExpensive)
|
||||
{
|
||||
utmCoordinateInternal(); // ensure m_utm2D
|
||||
elevationAt(); // ensure m_elevation
|
||||
}
|
||||
std::ostringstream stream;
|
||||
stream << "LtsCoordinate(m_geo=" << m_geo
|
||||
<< ", m_utm2D.x " << m_utm2D.x << ", m_utm2D.y " << m_utm2D.y << ", m_utm2D.zone " << m_utm2D.zone;
|
||||
if (!qFuzzyIsNull(m_utm2D.x) || !qFuzzyIsNull(m_utm2D.y))
|
||||
stream << ", m_utm2D.mgrs '" << m_utm2D.mgrs().toUtf8().constData() << "'";
|
||||
stream << ", elevation " << std::fixed << std::setprecision(3) << m_elevation // << std::fixed << std::setprecision(3) -> 3 decimal places
|
||||
<< ")";
|
||||
return QString::fromStdString(stream.str());
|
||||
}
|
||||
|
||||
void LtsCoordinate::resetConversionCounter()
|
||||
{
|
||||
s_conversion_counter = 0;
|
||||
}
|
||||
long LtsCoordinate::getConversionCounter()
|
||||
{
|
||||
return s_conversion_counter;
|
||||
}
|
||||
|
||||
|
||||
// output operator:
|
||||
std::ostream &operator<<(std::ostream &stream, const LtsCoordinate &value)
|
||||
{
|
||||
stream << value.toString().toStdString();
|
||||
return stream;
|
||||
}
|
||||
|
||||
} // namespace LtsCoordTrans
|
||||
|
||||
|
||||
Reference in new issue
Block a user