#include "lts_coordinate.h" #include namespace LtsCoordTrans { static long s_conversion_counter = 0; std::function LtsCoordinate::m_getElevationCB; void LtsCoordinate::setElevationCallback(const elevationCbFunc &elevationCB) { m_getElevationCB = elevationCB; } bool LtsCoordinate::hasElevationCallback() { return m_getElevationCB != nullptr; } double LtsCoordinate::elevationAt(double defaultElevation, bool *bIsCovered) const { 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) { 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(); const LtsCoordTrans::UtmCoordinate &utm2 = coord2.utmCoordinateDiffZone(utm1.zone); const QPointF& offsetUtm = utm2.toPoint() - utm1.toPoint(); QLineF poly(QPointF(), offsetUtm); const double angle = poly.angle(); return fmod(angle+90.0, 360); } const UtmCoordinate &LtsCoordinate::utmCoordinateInternal(int zone) const { if (zone == -1) { if (!hasUtm()) convertGeoToUtm(); return m_utm2D; } utmCoordinateDiffZone(zone); return m_utm2D_differentZone; } void LtsCoordinate::convertGeoToUtm() const { int zone = -1; 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 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(); 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(); elevationAt(); } 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 << ")"; return QString::fromStdString(stream.str()); } void LtsCoordinate::resetConversionCounter() { s_conversion_counter = 0; } long LtsCoordinate::getConversionCounter() { return s_conversion_counter; } std::ostream &operator<<(std::ostream &stream, const LtsCoordinate &value) { stream << value.toString().toStdString(); return stream; } }