mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-22 23:05:36 +08:00
Further details on classes like epsilon compare, further unit tests.
This commit is contained in:
@@ -75,8 +75,9 @@ public:
|
||||
|
||||
/*!
|
||||
* \brief Cast as QString
|
||||
* \remarks operator cast caused too many ambiguity trouble
|
||||
*/
|
||||
operator QString() const
|
||||
QString toQString() const
|
||||
{
|
||||
return this->stringForConverter();
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ CCoordinateEcef CCoordinateTransformation::toEcef(const CCoordinateNed &ned)
|
||||
*/
|
||||
CCoordinateEcef CCoordinateTransformation::toEcef(const CCoordinateGeodetic &geo)
|
||||
{
|
||||
// TODO: Clarify the comparions with fixed angles (==90, ==180) -> what happens here
|
||||
// TODO: Clarify the comparisons with fixed angles (==90, ==180) -> what happens here
|
||||
|
||||
CLatitude lat = geo.latitude();
|
||||
CLongitude lon = geo.longitude();
|
||||
|
||||
@@ -34,5 +34,33 @@ qreal CMath::cubicRootReal(qreal x)
|
||||
return x < 0 ? -result : result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Round utility method
|
||||
*/
|
||||
double CMath::round(double value, int digits)
|
||||
{
|
||||
// gosh, is there no Qt method for this??? It's year 2013
|
||||
double fractpart, intpart;
|
||||
fractpart = modf(value, &intpart);
|
||||
if (fractpart == 0) return value; // do not mess any "integers" to the worse
|
||||
double m = pow(10.0, digits);
|
||||
qint64 ri = qRound(value * m); // do not loose any range here
|
||||
double rv = double(ri) / m;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Round by given epsilon value
|
||||
*/
|
||||
double CMath::roundEpsilon(double value, double epsilon)
|
||||
{
|
||||
double fractpart, intpart;
|
||||
fractpart = modf(value, &intpart);
|
||||
if (fractpart == 0) return value; // do not mess any "integers" to the worse
|
||||
qint64 ri = qRound(value / epsilon);
|
||||
double rv = double(ri) * epsilon; // do not loose any range here
|
||||
return rv;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
@@ -15,10 +15,10 @@ namespace Math
|
||||
// Some namespace wide constant values
|
||||
|
||||
//! Mathematical constant Pi
|
||||
const qreal PI = 4.0 * qAtan(1.0);
|
||||
const double PI = 4.0 * qAtan(1.0);
|
||||
|
||||
//! 2 * Pi
|
||||
const qreal TwoPI = 2.0 * PI;
|
||||
const double TwoPI = 2.0 * PI;
|
||||
|
||||
/*!
|
||||
* \brief Math utils
|
||||
@@ -33,14 +33,14 @@ public:
|
||||
* \param y
|
||||
* \return
|
||||
*/
|
||||
static qreal hypot(qreal x, qreal y);
|
||||
static double hypot(double x, double y);
|
||||
|
||||
/*!
|
||||
* \brief Calculates the square of x
|
||||
* \param x
|
||||
* \return
|
||||
*/
|
||||
static inline qreal square(qreal x)
|
||||
static inline double square(double x)
|
||||
{
|
||||
return x * x;
|
||||
}
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
* \param x
|
||||
* \return
|
||||
*/
|
||||
static inline qreal cubic(const qreal x)
|
||||
static inline double cubic(const double x)
|
||||
{
|
||||
return x * x * x;
|
||||
}
|
||||
@@ -60,7 +60,23 @@ public:
|
||||
* \param x
|
||||
* \return
|
||||
*/
|
||||
static qreal cubicRootReal(qreal x);
|
||||
static double cubicRootReal(double x);
|
||||
|
||||
/*!
|
||||
* \brief Utility round method
|
||||
* \param value
|
||||
* \param digits
|
||||
* \return
|
||||
*/
|
||||
static double round(double value, int digits);
|
||||
|
||||
/*!
|
||||
* \brief Round by given epsilon, e.g.
|
||||
* \param value
|
||||
* \param epsilon
|
||||
* \return
|
||||
*/
|
||||
static double roundEpsilon(double value, double epsilon);
|
||||
|
||||
private:
|
||||
/*!
|
||||
|
||||
@@ -69,11 +69,11 @@ template<class ImplMatrix, int Rows, int Columns> bool CMatrixBase<ImplMatrix, R
|
||||
}
|
||||
|
||||
/*
|
||||
* All values zero?
|
||||
* All values equal?
|
||||
*/
|
||||
template<class ImplMatrix, int Rows, int Columns> bool CMatrixBase<ImplMatrix, Rows, Columns>::allValuesEqual() const
|
||||
{
|
||||
double v = this->getElement(0,0);
|
||||
double v = this->getElement(0, 0);
|
||||
for (int r = 0; r < Rows; r++)
|
||||
{
|
||||
for (int c = 0; c < Columns; c++)
|
||||
@@ -84,6 +84,19 @@ template<class ImplMatrix, int Rows, int Columns> bool CMatrixBase<ImplMatrix, R
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Round all values
|
||||
*/
|
||||
template<class ImplMatrix, int Rows, int Columns> void CMatrixBase<ImplMatrix, Rows, Columns>::round()
|
||||
{
|
||||
for (int r = 0; r < Rows; r++)
|
||||
{
|
||||
for (int c = 0; c < Columns; c++)
|
||||
{
|
||||
this->m_matrix(r, c) = CMath::roundEpsilon(this->m_matrix(r, c), 1E-10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert to string
|
||||
|
||||
@@ -203,6 +203,18 @@ public:
|
||||
return this->m_matrix.isIdentity();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Is identity matrix? Epsilon considered.
|
||||
* \return
|
||||
*/
|
||||
bool isIdentityEpsilon() const
|
||||
{
|
||||
ImplMatrix m(0.0);
|
||||
m += (*this);
|
||||
m.round();
|
||||
return m.isIdentity();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Set as identity matrix
|
||||
* \return
|
||||
@@ -228,6 +240,18 @@ public:
|
||||
*/
|
||||
bool isZero() const;
|
||||
|
||||
/*!
|
||||
* \brief Is identity matrix? Epsilon considered.
|
||||
* \return
|
||||
*/
|
||||
bool isZeroEpsilon() const
|
||||
{
|
||||
ImplMatrix m(0.0);
|
||||
m += (*this);
|
||||
m.round();
|
||||
return m.isZero();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief All values equal, if so matirx is not invertible
|
||||
* \return
|
||||
@@ -240,6 +264,11 @@ public:
|
||||
*/
|
||||
void fill(double value) { this->m_matrix.fill(value); }
|
||||
|
||||
/*!
|
||||
* \brief Round all values
|
||||
*/
|
||||
void round();
|
||||
|
||||
/*!
|
||||
* \brief Get element
|
||||
* \param row
|
||||
|
||||
@@ -92,13 +92,13 @@ template <class ImplClass> void CVector3DBase<ImplClass>::setElement(size_t row,
|
||||
}
|
||||
|
||||
/*
|
||||
* Corss product
|
||||
* Cross product
|
||||
*/
|
||||
template <class ImplClass> ImplClass CVector3DBase<ImplClass>::crossProduct(const ImplClass &otherVector) const
|
||||
{
|
||||
ImplClass v(otherVector);
|
||||
v.m_i = this->m_j * otherVector.m_k - this->m_k * otherVector.m_j;
|
||||
v.m_j = this->m_k * otherVector.m_i - this->m_j * otherVector.m_k;
|
||||
v.m_j = this->m_k * otherVector.m_i - this->m_i * otherVector.m_k;
|
||||
v.m_k = this->m_i * otherVector.m_j - this->m_j * otherVector.m_i;
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define BLACKMISC_MATHVECTOR3DBASE_H
|
||||
|
||||
#include "blackmisc/basestreamstringifier.h"
|
||||
#include "blackmisc/mathematics.h"
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
@@ -75,6 +76,26 @@ public:
|
||||
*/
|
||||
void setZero();
|
||||
|
||||
/*!
|
||||
* \brief Set zeros
|
||||
*/
|
||||
bool isZero() const
|
||||
{
|
||||
return this->m_i == 0 && this->m_j == 0 && this->m_k == 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Is identity matrix? Epsilon considered.
|
||||
* \return
|
||||
*/
|
||||
bool isZeroEpsilon() const
|
||||
{
|
||||
ImplClass v;
|
||||
v += (*this);
|
||||
v.round();
|
||||
return v.isZero();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Set zeros
|
||||
*/
|
||||
@@ -370,6 +391,18 @@ public:
|
||||
{
|
||||
return sqrt(this->lengthSquared());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Round this vector
|
||||
*/
|
||||
void round()
|
||||
{
|
||||
const double epsilon = 1E-10;
|
||||
this->m_i = BlackMisc::Math::CMath::roundEpsilon(this->m_i, epsilon);
|
||||
this->m_j = BlackMisc::Math::CMath::roundEpsilon(this->m_j, epsilon);
|
||||
this->m_k = BlackMisc::Math::CMath::roundEpsilon(this->m_k, epsilon);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#ifndef BLACKMISC_PQANGLE_H
|
||||
#define BLACKMISC_PQANGLE_H
|
||||
#include "blackmisc/pqphysicalquantity.h"
|
||||
#include "blackmisc/mathematics.h"
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
@@ -46,15 +47,17 @@ public:
|
||||
* \brief Convenience method PI
|
||||
* \return
|
||||
*/
|
||||
const static double pi() {
|
||||
const static double pi()
|
||||
{
|
||||
return M_PI;
|
||||
}
|
||||
/*!
|
||||
* \brief Value as factor of PI (e.g. 0.5PI)
|
||||
* \return
|
||||
*/
|
||||
double piFactor() const {
|
||||
return CMeasurementUnit::round(this->convertedSiValueToDouble() / M_PI, 6);
|
||||
double piFactor() const
|
||||
{
|
||||
return BlackMisc::Math::CMath::round(this->convertedSiValueToDouble() / M_PI, 6);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
/* Copyright (C) 2013 VATSIM Community
|
||||
/* Copyright (C) 2013 VATSIM Community / contributors
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "blackmisc/pqbase.h"
|
||||
#include "blackmisc/mathematics.h"
|
||||
|
||||
using namespace BlackMisc::Math;
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
@@ -35,7 +38,7 @@ CMeasurementPrefix::CMeasurementPrefix(const CMeasurementPrefix &otherMultiplier
|
||||
/*
|
||||
* Assignment operator
|
||||
*/
|
||||
CMeasurementPrefix& CMeasurementPrefix::operator=(const CMeasurementPrefix &otherMultiplier)
|
||||
CMeasurementPrefix &CMeasurementPrefix::operator=(const CMeasurementPrefix &otherMultiplier)
|
||||
{
|
||||
|
||||
if (this == &otherMultiplier) return *this; // Same object? Yes, so skip assignment, and just return *this
|
||||
@@ -170,7 +173,7 @@ QString CMeasurementUnit::valueRoundedWithUnit(double value, int digits) const
|
||||
double CMeasurementUnit::valueRounded(double value, int digits) const
|
||||
{
|
||||
if (digits < 0) digits = this->m_displayDigits;
|
||||
return CMeasurementUnit::round(value, digits);
|
||||
return CMath::round(value, digits);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -179,30 +182,19 @@ double CMeasurementUnit::valueRounded(double value, int digits) const
|
||||
QString CMeasurementUnit::toQStringRounded(double value, int digits) const
|
||||
{
|
||||
if (digits < 0) digits = this->m_displayDigits;
|
||||
double v = CMeasurementUnit::round(value, digits);
|
||||
double v = CMath::round(value, digits);
|
||||
QString s = QLocale::system().toString(v, 'f', digits);
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Round utility method
|
||||
*/
|
||||
double CMeasurementUnit::round(double value, int digits)
|
||||
{
|
||||
// gosh, is there no Qt method for this???
|
||||
// It's year 2013
|
||||
double m = pow(10.0, digits);
|
||||
double rv = double(qRound(value * m) / m);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Epsilon rounding
|
||||
*/
|
||||
double CMeasurementUnit::epsilonRounding(double value) const
|
||||
double CMeasurementUnit::epsilonUpRounding(double value) const
|
||||
{
|
||||
// does notwork reliable with qRound for some reason
|
||||
double v = floor((value + this->m_epsilon) / this->m_epsilon);
|
||||
// Rounds a little up in order to avoid fractions
|
||||
double eps = value > 0 ? this->m_epsilon : -1.0 * this->m_epsilon;
|
||||
double v = floor((value + eps) / this->m_epsilon);
|
||||
v *= this->m_epsilon;
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -93,10 +93,6 @@ public:
|
||||
/*!
|
||||
* \brief Cast as double
|
||||
*/
|
||||
operator double() const
|
||||
{
|
||||
return this->m_factor;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Factor, e.g.1000 for "kilo"
|
||||
@@ -106,6 +102,16 @@ public:
|
||||
{
|
||||
return this->m_factor;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Factor
|
||||
* \return
|
||||
*/
|
||||
double toDouble() const
|
||||
{
|
||||
return this->getFactor();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Name, e.g. "kilo"
|
||||
* \return
|
||||
@@ -114,6 +120,7 @@ public:
|
||||
{
|
||||
return this->m_name;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Prefix, e.g. "k" for "kilo"
|
||||
* \return
|
||||
@@ -464,25 +471,17 @@ public:
|
||||
*/
|
||||
double conversionToUnit(double value, const CMeasurementUnit &to) const;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// -- static
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/*!
|
||||
* \brief Utility round method
|
||||
* \param value
|
||||
* \param digits
|
||||
* \return
|
||||
*/
|
||||
static double round(double value, int digits);
|
||||
|
||||
/*!
|
||||
* Epsilon rounding. In some conversion rouding is required to avoid
|
||||
* periodical numbers.
|
||||
* \param value
|
||||
* \return
|
||||
*/
|
||||
double epsilonRounding(double value) const;
|
||||
double epsilonUpRounding(double value) const;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// -- static
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/*!
|
||||
* \brief Unit is not specified
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#ifndef BLACKMISC_PQPHYSICALQUANTITY_H
|
||||
#define BLACKMISC_PQPHYSICALQUANTITY_H
|
||||
|
||||
#include "blackmisc/mathematics.h"
|
||||
#include "blackmisc/pqbase.h"
|
||||
#include "blackmisc/pqunits.h"
|
||||
#include "blackmisc/debug.h"
|
||||
@@ -217,7 +218,8 @@ public:
|
||||
*/
|
||||
qint32 convertedSiValueToInteger() const
|
||||
{
|
||||
return static_cast<qint32>(CMeasurementUnit::round(this->m_convertedSiUnitValueD, 0));
|
||||
return static_cast<qint32>(
|
||||
BlackMisc::Math::CMath::round(this->m_convertedSiUnitValueD, 0));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -255,15 +257,7 @@ public:
|
||||
*/
|
||||
void substractUnitValue(double value);
|
||||
|
||||
/*!
|
||||
* \brief Cast as QString
|
||||
*/
|
||||
operator QString() const
|
||||
{
|
||||
return this->unitValueRoundedWithUnit();
|
||||
}
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \brief Multiply operator *=
|
||||
* \param multiply
|
||||
* \return
|
||||
|
||||
@@ -37,7 +37,7 @@ double CAngleUnit::conversionSexagesimalFromSi(const CMeasurementUnit &angleUnit
|
||||
{
|
||||
// using rounding here, since fractions can lead to ugly sexagesimal conversion
|
||||
// e.g. 185.499999 gives 185 29' 59.9999"
|
||||
value = angleUnit.epsilonRounding(value * 180 / M_PI); // degree
|
||||
value = angleUnit.epsilonUpRounding(value * 180 / M_PI); // degree
|
||||
double v = floor(value);
|
||||
double c = value - v;
|
||||
double mr = c * 60.0;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2013 VATSIM Community / authors
|
||||
/* Copyright (C) 2013 VATSIM Community / contributors
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
@@ -649,4 +649,4 @@ public:
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
#endif // BLACKMISC_PQUNITS_H
|
||||
#endif // guard
|
||||
|
||||
Reference in New Issue
Block a user