mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-08 21:05: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
@@ -14,10 +14,60 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
using namespace BlackMisc::Math;
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
CAngle::CAngle(int degrees, int minutes, double seconds) :
|
||||
CPhysicalQuantity(
|
||||
degrees + minutes / 100.0 + seconds / 10000.0,
|
||||
CAngleUnit::sexagesimalDeg())
|
||||
{
|
||||
Q_ASSERT_X((degrees >= 0 && minutes >= 0 && seconds >= 0) ||
|
||||
(degrees <= 0 && minutes <= 0 && seconds <= 0), Q_FUNC_INFO, "Same sign required");
|
||||
}
|
||||
|
||||
CAngle::CAngle(int degrees, double minutes) :
|
||||
CPhysicalQuantity(
|
||||
degrees + minutes / 100.0,
|
||||
CAngleUnit::sexagesimalDeg())
|
||||
{
|
||||
Q_ASSERT_X((degrees >= 0 && minutes >= 0) || (degrees <= 0 && minutes <= 0),
|
||||
Q_FUNC_INFO, "Same sign required");
|
||||
}
|
||||
|
||||
void CAngle::unifySign(int °rees, int &minutes, double &seconds)
|
||||
{
|
||||
if (degrees < 0)
|
||||
{
|
||||
if (minutes > 0) minutes *= -1;
|
||||
if (seconds > 0) seconds *= -1.0;
|
||||
}
|
||||
else if (degrees > 0)
|
||||
{
|
||||
if (minutes < 0) minutes *= -1;
|
||||
if (seconds < 0) seconds *= -1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// degrees was 0
|
||||
if ((minutes > 0 && seconds < 0) || (minutes < 0 && seconds > 0))
|
||||
{
|
||||
seconds *= -1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CAngle::unifySign(int °rees, int &minutes)
|
||||
{
|
||||
if ((degrees > 0 && minutes < 0) || (degrees < 0 && minutes > 0))
|
||||
{
|
||||
minutes *= -1.0;
|
||||
}
|
||||
}
|
||||
|
||||
BlackMisc::CIcon CAngle::toIcon() const
|
||||
{
|
||||
BlackMisc::CIcon i = CIcon::iconByIndex(CIcons::StandardIconArrowMediumNorth16);
|
||||
@@ -25,6 +75,37 @@ namespace BlackMisc
|
||||
return i;
|
||||
}
|
||||
|
||||
CAngle::DegMinSecFractionalSec CAngle::asSexagesimalDegMinSec(bool range180Degrees) const
|
||||
{
|
||||
double v = this->value(CAngleUnit::deg());
|
||||
v = CAngleUnit::deg().roundToEpsilon(v);
|
||||
|
||||
// range -179-180 ?
|
||||
if (range180Degrees)
|
||||
{
|
||||
v = std::fmod(v + 180.0, 360.0);
|
||||
v += (v < 0) ? 180.0 : -180.0;
|
||||
}
|
||||
|
||||
DegMinSecFractionalSec values;
|
||||
if (v < 0)
|
||||
{
|
||||
values.sign = -1;
|
||||
v *= -1.0;
|
||||
}
|
||||
|
||||
values.deg = v;
|
||||
v -= values.deg;
|
||||
v = v * 100.0 * 0.6;
|
||||
values.min = v;
|
||||
v -= values.min;
|
||||
v = v * 100.0 * 0.6;
|
||||
values.sec = v;
|
||||
v -= values.sec;
|
||||
values.fractionalSec = CMathUtils::round(v, 6);
|
||||
return values;
|
||||
}
|
||||
|
||||
double CAngle::piFactor() const
|
||||
{
|
||||
return BlackMisc::Math::CMathUtils::round(this->value(CAngleUnit::rad()) / BlackMisc::Math::CMathUtils::PI() , 6);
|
||||
@@ -49,5 +130,5 @@ namespace BlackMisc
|
||||
{
|
||||
return std::tan(this->value(CAngleUnit::rad()));
|
||||
}
|
||||
}
|
||||
}
|
||||
} // ns
|
||||
} // ns
|
||||
|
||||
@@ -25,7 +25,6 @@ namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
|
||||
//! Physical unit angle (radians, degrees)
|
||||
class BLACKMISC_EXPORT CAngle : public CPhysicalQuantity<CAngleUnit, CAngle>
|
||||
{
|
||||
@@ -39,27 +38,50 @@ namespace BlackMisc
|
||||
//! \copydoc CPhysicalQuantity(const QString &unitString)
|
||||
CAngle(const QString &unitString) : CPhysicalQuantity(unitString) {}
|
||||
|
||||
/*!
|
||||
* \brief Init as sexagesimal degrees, minutes, seconds
|
||||
* The sign of all parameters must be the same, either all positive or all negative.
|
||||
*/
|
||||
CAngle(int degrees, int minutes, double seconds) :
|
||||
CPhysicalQuantity(
|
||||
degrees + minutes / 100.0 + seconds / 10000.0,
|
||||
CAngleUnit::sexagesimalDeg()) {}
|
||||
//! Value as individual values
|
||||
struct DegMinSecFractionalSec
|
||||
{
|
||||
int sign = 1; //!< 1/-1
|
||||
int deg = 0; //!< 0-359
|
||||
int min = 0; //!< 0-59
|
||||
int sec = 0; //!< 0-59
|
||||
double fractionalSec = 0; //!< value < 1.0
|
||||
|
||||
/*!
|
||||
* \brief Init as sexagesimal degrees, minutes
|
||||
* The sign of both parameters must be the same, either both positive or both negative.
|
||||
*/
|
||||
CAngle(int degrees, double minutes) :
|
||||
CPhysicalQuantity(
|
||||
degrees + minutes / 100.0,
|
||||
CAngleUnit::sexagesimalDegMin()) {}
|
||||
//! Degrees as string
|
||||
QString degAsString() const { return QString::number(deg); }
|
||||
|
||||
//! Minutes as string
|
||||
QString minAsString() const { return QString::number(min); }
|
||||
|
||||
//! Seconds as string
|
||||
QString secAsString() const { return QString::number(sec); }
|
||||
|
||||
//! Fractional seconds as string
|
||||
QString fractionalSecAsString(int width = -1) const { return BlackMisc::Math::CMathUtils::fractionalPartAsString(fractionalSec, width); }
|
||||
};
|
||||
|
||||
//! \brief Init as sexagesimal degrees, minutes, seconds
|
||||
//! The sign of all parameters must be the same, either all positive or all negative.
|
||||
//! \see CAngle::unifySign(int &, int &, double &)
|
||||
CAngle(int degrees, int minutes, double seconds);
|
||||
|
||||
//! \brief Init as sexagesimal degrees, minutes
|
||||
//! The sign of both parameters must be the same, either both positive or both negative.
|
||||
//! \see CAngle::unifySign(int &, double &)
|
||||
CAngle(int degrees, double minutes);
|
||||
|
||||
//! Minutes and secods will get same sign as degrees
|
||||
void static unifySign(int °rees, int &minutes, double &seconds);
|
||||
|
||||
//! Minutes will get same sign as degrees
|
||||
void static unifySign(int °rees, int &minutes);
|
||||
|
||||
//! \copydoc BlackMisc::Mixin::Icon::toIcon
|
||||
BlackMisc::CIcon toIcon() const;
|
||||
|
||||
//! As individual values
|
||||
DegMinSecFractionalSec asSexagesimalDegMinSec(bool range180Degrees = false) const;
|
||||
|
||||
//! Value as factor of PI (e.g. 0.5PI)
|
||||
double piFactor() const;
|
||||
|
||||
@@ -75,8 +97,8 @@ namespace BlackMisc
|
||||
//! Tangent of angle
|
||||
double tan() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // ns
|
||||
} // ns
|
||||
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CAngle)
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
|
||||
bool CMeasurementUnit::operator ==(const CMeasurementUnit &other) const
|
||||
{
|
||||
if (this == &other) return true;
|
||||
@@ -43,17 +42,23 @@ namespace BlackMisc
|
||||
|
||||
double CMeasurementUnit::roundValue(double value, int digits) const
|
||||
{
|
||||
if (digits < 0) digits = this->m_data->m_displayDigits;
|
||||
if (digits < 0) { digits = this->m_data->m_displayDigits; }
|
||||
return CMathUtils::round(value, digits);
|
||||
}
|
||||
|
||||
QString CMeasurementUnit::makeRoundedQString(double value, int digits, bool /* i18n */) const
|
||||
double CMeasurementUnit::roundToEpsilon(double value) const
|
||||
{
|
||||
if (digits < 0) digits = this->m_data->m_displayDigits;
|
||||
double v = CMathUtils::round(value, digits);
|
||||
QString s = QLocale::system().toString(v, 'f', digits);
|
||||
return s;
|
||||
if (this->getEpsilon() == 0 || this->isNull()) { return value; }
|
||||
return CMathUtils::roundEpsilon(value, this->getEpsilon());
|
||||
}
|
||||
|
||||
QString CMeasurementUnit::makeRoundedQString(double value, int digits, bool i18n) const
|
||||
{
|
||||
Q_UNUSED(i18n);
|
||||
if (digits < 0) digits = this->m_data->m_displayDigits;
|
||||
const double v = CMathUtils::round(value, digits);
|
||||
const QString s = QLocale::system().toString(v, 'f', digits);
|
||||
return s;
|
||||
}
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
@@ -36,7 +36,6 @@ namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
|
||||
/*!
|
||||
* Base class for all units, such as meter, hertz.
|
||||
*/
|
||||
@@ -219,11 +218,11 @@ namespace BlackMisc
|
||||
: m_name(name), m_symbol(symbol)
|
||||
{}
|
||||
|
||||
QLatin1String m_name; //!< name, e.g. "meter"
|
||||
QLatin1String m_symbol; //!< unit name, e.g. "m"
|
||||
double m_epsilon = 0.0; //!< values with differences below epsilon are the equal
|
||||
int m_displayDigits = 0; //!< standard rounding for string conversions
|
||||
ConverterFunction m_toDefault = nullptr; //!< convert from this unit to default unit
|
||||
QLatin1String m_name; //!< name, e.g. "meter"
|
||||
QLatin1String m_symbol; //!< unit name, e.g. "m"
|
||||
double m_epsilon = 0.0; //!< values with differences below epsilon are the equal
|
||||
int m_displayDigits = 0; //!< standard rounding for string conversions
|
||||
ConverterFunction m_toDefault = nullptr; //!< convert from this unit to default unit
|
||||
ConverterFunction m_fromDefault = nullptr; //!< convert to this unit from default unit
|
||||
};
|
||||
|
||||
@@ -291,16 +290,31 @@ namespace BlackMisc
|
||||
return i18n ? QCoreApplication::translate("CMeasurementUnit", this->m_data->m_symbol.latin1()) : this->m_data->m_symbol;
|
||||
}
|
||||
|
||||
//! Does a string end with name or symbol? E.g. 3meter, 3m, 3deg
|
||||
bool endsStringWithNameOrSymbol(const QString &candidate, Qt::CaseSensitivity cs = Qt::CaseSensitive)
|
||||
{
|
||||
const QString c = candidate.trimmed();
|
||||
return c.endsWith(this->getName(false), cs) || c.endsWith(this->getName(true)) ||
|
||||
c.endsWith(this->getSymbol(false), cs) || c.endsWith(this->getSymbol(true));
|
||||
}
|
||||
|
||||
//! Rounded value
|
||||
//! \note default digits is CMeasurementUnit::getDisplayDigits
|
||||
double roundValue(double value, int digits = -1) const;
|
||||
|
||||
//! Rounded to the nearest CMeasurementUnit::getEpsilon
|
||||
//! \remark uses CMathUtils::roundEpsilon
|
||||
double roundToEpsilon(double value) const;
|
||||
|
||||
//! Rounded string utility method, virtual so units can have specialized formatting
|
||||
//! \note default digits is CMeasurementUnit::getDisplayDigits
|
||||
virtual QString makeRoundedQString(double value, int digits = -1, bool i18n = false) const;
|
||||
|
||||
//! Value rounded with unit, e.g. "5.00m", "30kHz"
|
||||
//! \note default digits is CMeasurementUnit::getDisplayDigits
|
||||
virtual QString makeRoundedQStringWithUnit(double value, int digits = -1, bool i18n = false) const;
|
||||
|
||||
//! Threshold for rounding
|
||||
//! Threshold for comparions
|
||||
double getEpsilon() const
|
||||
{
|
||||
return this->m_data->m_epsilon;
|
||||
@@ -371,8 +385,7 @@ namespace BlackMisc
|
||||
return none;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // ns
|
||||
} // ns
|
||||
|
||||
#endif // guard
|
||||
|
||||
@@ -300,6 +300,13 @@ namespace BlackMisc
|
||||
return this->valueRoundedWithUnit(this->m_unit, digits, i18n);
|
||||
}
|
||||
|
||||
template<class MU, class PQ>
|
||||
void CPhysicalQuantity<MU, PQ>::roundToEpsilon()
|
||||
{
|
||||
if (this->isNull()) { return; }
|
||||
this->m_value = this->m_unit.roundToEpsilon(this->m_value);
|
||||
}
|
||||
|
||||
template <class MU, class PQ>
|
||||
double CPhysicalQuantity<MU, PQ>::valueRounded(MU unit, int digits) const
|
||||
{
|
||||
|
||||
@@ -101,20 +101,28 @@ namespace BlackMisc
|
||||
void setCurrentUnitValue(double value);
|
||||
|
||||
//! Rounded value in given unit
|
||||
//! \note default digits is CMeasurementUnit::getDisplayDigits
|
||||
double valueRounded(MU unit, int digits = -1) const;
|
||||
|
||||
//! As integer value
|
||||
int valueInteger(MU unit) const;
|
||||
|
||||
//! Rounded value in current unit
|
||||
//! \note default digits is CMeasurementUnit::getDisplayDigits
|
||||
double valueRounded(int digits = -1) const;
|
||||
|
||||
//! Value to QString with the given unit, e.g. "5.00m"
|
||||
//! \note default digits is CMeasurementUnit::getDisplayDigits
|
||||
QString valueRoundedWithUnit(MU unit, int digits = -1, bool i18n = false) const;
|
||||
|
||||
//! Value to QString with the current unit, e.g. "5.00m"
|
||||
//! \note default digits is CMeasurementUnit::getDisplayDigits
|
||||
QString valueRoundedWithUnit(int digits = -1, bool i18n = false) const;
|
||||
|
||||
//! Round current value in current unit to epsilon
|
||||
//! \sa CMeasurementUnit::roundToEpsilon
|
||||
void roundToEpsilon();
|
||||
|
||||
//! Change value without changing unit
|
||||
void setValueSameUnit(double value);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user