mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-10 22:15:34 +08:00
Ref T111, lat/lng/angle changes
* get struct CAngle::DegMinSecFractionalSec to obtain parts * round to epsilon utility functions and fix (qint64)
This commit is contained in:
committed by
Mathew Sutcliffe
parent
77546a46b1
commit
e55480737e
@@ -212,6 +212,13 @@ namespace BlackMisc
|
||||
CCoordinateGeodetic::CCoordinateGeodetic(double latitudeDegrees, double longitudeDegrees, double heightFeet) :
|
||||
CCoordinateGeodetic( { latitudeDegrees, BlackMisc::PhysicalQuantities::CAngleUnit::deg() }, { longitudeDegrees, BlackMisc::PhysicalQuantities::CAngleUnit::deg() }, { heightFeet, BlackMisc::PhysicalQuantities::CLengthUnit::ft() }) {}
|
||||
|
||||
CCoordinateGeodetic::CCoordinateGeodetic(const ICoordinateGeodetic &coordinate) :
|
||||
m_x(coordinate.normalVectorDouble()[0]),
|
||||
m_y(coordinate.normalVectorDouble()[1]),
|
||||
m_z(coordinate.normalVectorDouble()[2]),
|
||||
m_geodeticHeight(coordinate.geodeticHeight())
|
||||
{ }
|
||||
|
||||
CLatitude CCoordinateGeodetic::latitude() const
|
||||
{
|
||||
return { std::atan2(m_z, std::hypot(m_x, m_y)), PhysicalQuantities::CAngleUnit::rad() };
|
||||
|
||||
@@ -187,8 +187,7 @@ namespace BlackMisc
|
||||
{
|
||||
public:
|
||||
//! Default constructor
|
||||
CCoordinateGeodetic() :
|
||||
CCoordinateGeodetic(0, 0, 0) {}
|
||||
CCoordinateGeodetic() : CCoordinateGeodetic(0, 0, 0) {}
|
||||
|
||||
//! Constructor by normal vector
|
||||
CCoordinateGeodetic(const QVector3D &normal) : m_x(normal.x()), m_y(normal.y()), m_z(normal.z()) {}
|
||||
@@ -202,6 +201,9 @@ namespace BlackMisc
|
||||
//! Constructor by values
|
||||
CCoordinateGeodetic(double latitudeDegrees, double longitudeDegrees, double heightFeet);
|
||||
|
||||
//! Constructor by interface
|
||||
CCoordinateGeodetic(const ICoordinateGeodetic &coordinate);
|
||||
|
||||
//! \copydoc ICoordinateGeodetic::latitude
|
||||
virtual CLatitude latitude() const override;
|
||||
|
||||
|
||||
@@ -17,11 +17,12 @@
|
||||
#include <QtGlobal>
|
||||
#include <QtMath>
|
||||
|
||||
using namespace BlackMisc::PhysicalQuantities;
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace Geo
|
||||
{
|
||||
|
||||
template <class LATorLON>
|
||||
CEarthAngle<LATorLON> &CEarthAngle<LATorLON>::operator +=(const CEarthAngle &latOrLon)
|
||||
{
|
||||
@@ -70,49 +71,64 @@ namespace BlackMisc
|
||||
template <class LATorLON>
|
||||
LATorLON CEarthAngle<LATorLON>::fromWgs84(const QString &wgsCoordinate)
|
||||
{
|
||||
// http://www.regular-expressions.info/floatingpoint.html
|
||||
const QString wgs = wgsCoordinate.simplified().trimmed();
|
||||
thread_local const QRegularExpression rx("([-+]?[0-9]*\\.?[0-9]+)");
|
||||
qint32 deg = 0;
|
||||
qint32 min = 0;
|
||||
double sec = 0.0;
|
||||
double secFragment = 0.0;
|
||||
int fragmentLength = 0;
|
||||
int c = 0;
|
||||
int pos = 0;
|
||||
QRegularExpressionMatch match = rx.match(wgs, pos);
|
||||
while (match.hasMatch())
|
||||
if (wgs.isEmpty()) { return LATorLON(); }
|
||||
|
||||
// support for 5deg, 1.2rad
|
||||
if (CAngleUnit::deg().endsStringWithNameOrSymbol(wgs) || CAngleUnit::rad().endsStringWithNameOrSymbol(wgs))
|
||||
{
|
||||
QString cap = match.captured(1);
|
||||
pos += match.capturedLength(1);
|
||||
switch (c++)
|
||||
{
|
||||
case 0:
|
||||
deg = cap.toInt();
|
||||
break;
|
||||
case 1:
|
||||
min = cap.toInt();
|
||||
break;
|
||||
case 2:
|
||||
sec = cap.toDouble();
|
||||
break;
|
||||
case 3:
|
||||
secFragment = cap.toDouble();
|
||||
fragmentLength = cap.length();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
match = rx.match(wgs, pos);
|
||||
}
|
||||
if (fragmentLength > 0)
|
||||
{
|
||||
// we do have given ms in string
|
||||
sec += secFragment / qPow(10, fragmentLength);
|
||||
LATorLON latOrLon;
|
||||
latOrLon.parseFromString(wgs);
|
||||
return latOrLon;
|
||||
}
|
||||
|
||||
if (wgs.contains('S', Qt::CaseInsensitive) ||
|
||||
wgs.contains('W', Qt::CaseInsensitive)) deg *= -1;
|
||||
// number only -> parsed as degrees
|
||||
bool isDouble;
|
||||
const double valueDegrees = wgs.toDouble(&isDouble);
|
||||
if (isDouble)
|
||||
{
|
||||
CAngle a(valueDegrees, CAngleUnit::deg());
|
||||
return LATorLON(a);
|
||||
}
|
||||
|
||||
// http://www.regular-expressions.info/floatingpoint.html
|
||||
thread_local const QRegularExpression rx("[+-]?\\d+(?:\\.\\d+)?");
|
||||
int deg = 0;
|
||||
int min = 0;
|
||||
double sec = 0.0;
|
||||
int c = 0;
|
||||
QRegularExpressionMatchIterator i = rx.globalMatch(wgs);
|
||||
while (i.hasNext() && c < 3)
|
||||
{
|
||||
const QRegularExpressionMatch match = i.next();
|
||||
bool ok;
|
||||
if (match.hasMatch())
|
||||
{
|
||||
const QString cap = match.captured(0);
|
||||
switch (c++)
|
||||
{
|
||||
case 0:
|
||||
deg = cap.toInt(&ok);
|
||||
break;
|
||||
case 1:
|
||||
min = cap.toInt(&ok);
|
||||
break;
|
||||
case 2:
|
||||
sec = cap.toDouble(&ok);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
Q_UNUSED(ok); // ok for debugging purposes
|
||||
}
|
||||
|
||||
if (wgs.contains('S', Qt::CaseInsensitive) || wgs.contains('W', Qt::CaseInsensitive))
|
||||
{
|
||||
deg *= -1;
|
||||
min *= -1;
|
||||
sec *= -1;
|
||||
}
|
||||
|
||||
PhysicalQuantities::CAngle a(deg, min, sec);
|
||||
return LATorLON(a);
|
||||
@@ -151,6 +167,19 @@ namespace BlackMisc
|
||||
return BlackMisc::CIcon::iconByIndex(CIcons::GeoPosition);
|
||||
}
|
||||
|
||||
template<class LATorLON>
|
||||
QString CEarthAngle<LATorLON>::toWgs84(const QChar pos, const QChar neg, int fractionalDigits) const
|
||||
{
|
||||
const CAngle::DegMinSecFractionalSec v = this->asSexagesimalDegMinSec(true);
|
||||
const QChar pn = v.sign < 0 ? neg : pos;
|
||||
|
||||
static const QString vs("%1° %2' %3\" %4");
|
||||
if (fractionalDigits < 1) { return vs.arg(v.deg).arg(v.min).arg(v.sec).arg(pn); }
|
||||
|
||||
static const QString vsf("%1° %2' %3.%4\" %5");
|
||||
return vsf.arg(v.deg).arg(v.min).arg(v.sec).arg(v.fractionalSecAsString(fractionalDigits)).arg(pn);
|
||||
}
|
||||
|
||||
// see here for the reason of thess forward instantiations
|
||||
// https://isocpp.org/wiki/faq/templates#separate-template-fn-defn-from-decl
|
||||
//! \cond PRIVATE
|
||||
|
||||
@@ -18,7 +18,6 @@ namespace BlackMisc
|
||||
{
|
||||
namespace Geo
|
||||
{
|
||||
|
||||
class CLatitude;
|
||||
class CLongitude;
|
||||
|
||||
@@ -66,6 +65,9 @@ namespace BlackMisc
|
||||
//! Init by CAngle value
|
||||
CEarthAngle(const BlackMisc::PhysicalQuantities::CAngle &angle);
|
||||
|
||||
//! To WGS84 string
|
||||
QString toWgs84(const QChar pos, const QChar neg, int fractionalDigits = 3) const;
|
||||
|
||||
public:
|
||||
//! \copydoc BlackMisc::Mixin::String::toQString
|
||||
QString convertToQString(bool i18n = false) const;
|
||||
@@ -82,8 +84,7 @@ namespace BlackMisc
|
||||
extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE CEarthAngle<CLatitude>;
|
||||
extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE CEarthAngle<CLongitude>;
|
||||
//! \endcond
|
||||
|
||||
}
|
||||
}
|
||||
} // ns
|
||||
} // ns
|
||||
|
||||
#endif // guard
|
||||
|
||||
@@ -19,7 +19,6 @@ namespace BlackMisc
|
||||
{
|
||||
namespace Geo
|
||||
{
|
||||
|
||||
//! Latitude
|
||||
class BLACKMISC_EXPORT CLatitude :
|
||||
public CEarthAngle<CLatitude>,
|
||||
@@ -36,6 +35,12 @@ namespace BlackMisc
|
||||
BLACKMISC_DECLARE_USING_MIXIN_STRING(CLatitude)
|
||||
BLACKMISC_DECLARE_USING_MIXIN_INDEX(CLatitude)
|
||||
|
||||
//! To WGS84 string
|
||||
QString toWgs84(int fractionalDigits = 3) const
|
||||
{
|
||||
return CEarthAngle<CLatitude>::toWgs84('N', 'S', fractionalDigits);
|
||||
}
|
||||
|
||||
//! \copydoc BlackMisc::Mixin::String::toQString
|
||||
QString convertToQString(bool i18n = false) const
|
||||
{
|
||||
@@ -54,11 +59,11 @@ namespace BlackMisc
|
||||
explicit CLatitude(const BlackMisc::PhysicalQuantities::CAngle &angle) : CEarthAngle(angle) {}
|
||||
|
||||
//! Init by double value
|
||||
//! \remark Latitude measurements range from 0° to (+/–)90°
|
||||
CLatitude(double value, const BlackMisc::PhysicalQuantities::CAngleUnit &unit) : CEarthAngle(value, unit) {}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // ns
|
||||
} // ns
|
||||
|
||||
Q_DECLARE_METATYPE(BlackMisc::Geo::CLatitude)
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ namespace BlackMisc
|
||||
{
|
||||
namespace Geo
|
||||
{
|
||||
|
||||
//! Longitude
|
||||
class BLACKMISC_EXPORT CLongitude :
|
||||
public CEarthAngle<CLongitude>,
|
||||
@@ -36,12 +35,20 @@ namespace BlackMisc
|
||||
BLACKMISC_DECLARE_USING_MIXIN_STRING(CLongitude)
|
||||
BLACKMISC_DECLARE_USING_MIXIN_INDEX(CLongitude)
|
||||
|
||||
//! To WGS84 string
|
||||
QString toWgs84(int withFragmentSecDigits = 3) const
|
||||
{
|
||||
return CEarthAngle<CLongitude>::toWgs84('E', 'W', withFragmentSecDigits);
|
||||
}
|
||||
|
||||
//! \copydoc BlackMisc::Mixin::String::toQString
|
||||
QString convertToQString(bool i18n = false) const
|
||||
{
|
||||
QString s(CEarthAngle::convertToQString(i18n));
|
||||
if (!this->isZeroEpsilonConsidered())
|
||||
{
|
||||
s.append(this->isNegativeWithEpsilonConsidered() ? " W" : " E");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -52,11 +59,11 @@ namespace BlackMisc
|
||||
explicit CLongitude(const BlackMisc::PhysicalQuantities::CAngle &angle) : CEarthAngle(angle) {}
|
||||
|
||||
//! Init by double value
|
||||
//! Longitude measurements range from 0° to (+/–)180°.
|
||||
CLongitude(double value, const BlackMisc::PhysicalQuantities::CAngleUnit &unit) : CEarthAngle(value, unit) {}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // ns
|
||||
} // ns
|
||||
|
||||
Q_DECLARE_METATYPE(BlackMisc::Geo::CLongitude)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user