diff --git a/src/blackmisc/geo/coordinategeodetic.cpp b/src/blackmisc/geo/coordinategeodetic.cpp index 778745720..af4b2f8b9 100644 --- a/src/blackmisc/geo/coordinategeodetic.cpp +++ b/src/blackmisc/geo/coordinategeodetic.cpp @@ -44,7 +44,7 @@ namespace BlackMisc const QVector3D v1 = coordinate1.normalVector(); const QVector3D v2 = coordinate2.normalVector(); const float d = earthRadiusMeters * std::atan2(QVector3D::crossProduct(v1, v2).length(), QVector3D::dotProduct(v1, v2)); - return { d, CLengthUnit::m() }; + return { static_cast(d), CLengthUnit::m() }; } CAngle calculateBearing(const ICoordinateGeodetic &coordinate1, const ICoordinateGeodetic &coordinate2) @@ -56,17 +56,17 @@ namespace BlackMisc const float sinTheta = std::copysign(cross.length(), QVector3D::dotProduct(cross, coordinate1.normalVector())); const float cosTheta = QVector3D::dotProduct(c1, c2); const float theta = std::atan2(sinTheta, cosTheta); - return { theta, CAngleUnit::rad() }; + return { static_cast(theta), CAngleUnit::rad() }; } double calculateEuclideanDistance(const ICoordinateGeodetic &coordinate1, const ICoordinateGeodetic &coordinate2) { - return coordinate1.normalVector().distanceToPoint(coordinate2.normalVector()); + return static_cast(coordinate1.normalVector().distanceToPoint(coordinate2.normalVector())); } double calculateEuclideanDistanceSquared(const ICoordinateGeodetic &coordinate1, const ICoordinateGeodetic &coordinate2) { - return (coordinate1.normalVector() - coordinate2.normalVector()).lengthSquared(); + return static_cast((coordinate1.normalVector() - coordinate2.normalVector()).lengthSquared()); } bool ICoordinateGeodetic::equalNormalVectorDouble(const std::array &otherVector) const diff --git a/src/blackmisc/geo/coordinategeodetic.h b/src/blackmisc/geo/coordinategeodetic.h index dcb9248fa..d404136fc 100644 --- a/src/blackmisc/geo/coordinategeodetic.h +++ b/src/blackmisc/geo/coordinategeodetic.h @@ -12,17 +12,18 @@ #ifndef BLACKMISC_GEO_COORDINATEGEODETIC_H #define BLACKMISC_GEO_COORDINATEGEODETIC_H -#include "blackmisc/blackmiscexport.h" #include "blackmisc/aviation/altitude.h" #include "blackmisc/geo/latitude.h" #include "blackmisc/geo/longitude.h" -#include "blackmisc/metaclass.h" #include "blackmisc/pq/angle.h" #include "blackmisc/pq/length.h" #include "blackmisc/pq/units.h" +#include "blackmisc/math/mathutils.h" +#include "blackmisc/metaclass.h" #include "blackmisc/propertyindex.h" #include "blackmisc/valueobject.h" #include "blackmisc/variant.h" +#include "blackmisc/blackmiscexport.h" #include #include @@ -209,7 +210,7 @@ namespace BlackMisc CCoordinateGeodetic() {} //! Constructor by normal vector - CCoordinateGeodetic(const QVector3D &normal) : m_x(normal.x()), m_y(normal.y()), m_z(normal.z()) {} + CCoordinateGeodetic(const QVector3D &normal) : m_x(static_cast(normal.x())), m_y(static_cast(normal.y())), m_z(static_cast(normal.z())) {} //! Constructor by normal vector CCoordinateGeodetic(const std::array &normalVector); @@ -269,7 +270,7 @@ namespace BlackMisc void setGeodeticHeightToNull(); //! Set normal vector - void setNormalVector(const QVector3D &normal) { m_x = normal.x(); m_y = normal.y(); m_z = normal.z(); } + void setNormalVector(const QVector3D &normal) { m_x = static_cast(normal.x()); m_y = static_cast(normal.y()); m_z = static_cast(normal.z()); } //! Set normal vector void setNormalVector(double x, double y, double z) { m_x = x; m_y = y; m_z = z; } @@ -285,7 +286,7 @@ namespace BlackMisc } //! Is null? - virtual bool isNull() const override { return m_x == 0 && m_y == 0 && m_z == 0; } + virtual bool isNull() const override { return Math::CMathUtils::epsilonZeroLimits(m_x) && Math::CMathUtils::epsilonZeroLimits(m_y) && Math::CMathUtils::epsilonZeroLimits(m_z); } //! Coordinate by WGS84 position data static CCoordinateGeodetic fromWgs84(const QString &latitudeWgs84, const QString &longitudeWgs84, const Aviation::CAltitude &geodeticHeight = {}); diff --git a/src/blackmisc/math/mathutils.cpp b/src/blackmisc/math/mathutils.cpp index 580e8743c..024d37cde 100644 --- a/src/blackmisc/math/mathutils.cpp +++ b/src/blackmisc/math/mathutils.cpp @@ -22,21 +22,19 @@ namespace BlackMisc { namespace Math { - double CMathUtils::hypot(double x, double y) { x = qAbs(x); y = qAbs(y); - double max = std::max(x, y); - double min = std::min(x, y); + const double max = std::max(x, y); + const double min = std::min(x, y); double r = min / max; return max * sqrt(1 + r * r); } double CMathUtils::cubicRootReal(double x) { - double result; - result = std::pow(qAbs(x), 1.0 / 3.0); + const double result = std::pow(qAbs(x), 1.0 / 3.0); return x < 0 ? -result : result; } @@ -45,10 +43,10 @@ namespace BlackMisc // 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 = qRound64(value * m); // do not loose any range here - double rv = static_cast(ri) / m; + if (epsilonZeroLimits(fractpart)) { return value; } // do not mess any "integers" to the worse + const double m = pow(10.0, digits); + const qint64 ri = qRound64(value * m); // do not loose any range here + const double rv = static_cast(ri) / m; return rv; } @@ -59,19 +57,18 @@ namespace BlackMisc double CMathUtils::roundEpsilon(double value, double epsilon) { - if (epsilon == 0) { return value; } // avoid division by 0 + if (epsilonZeroLimits(epsilon)) { return value; } // avoid division by 0 double fractpart, intpart; fractpart = modf(value, &intpart); - if (fractpart == 0) { return value; } // do not mess any "integers" to the worse + if (epsilonZeroLimits(fractpart)) { return value; } // do not mess any "integers" to the worse const double roundValue = value / epsilon; - qint64 ri = qRound64(roundValue); - double rv = static_cast(ri) * epsilon; // do not loose any range here + const qint64 ri = qRound64(roundValue); + const double rv = static_cast(ri) * epsilon; // do not loose any range here return rv; } bool CMathUtils::epsilonEqual(double v1, double v2, double epsilon) { - if (v1 == v2) return true; return qAbs(v1 - v2) <= epsilon; } diff --git a/src/blackmisc/math/mathutils.h b/src/blackmisc/math/mathutils.h index 2b136e1c2..367b1c6af 100644 --- a/src/blackmisc/math/mathutils.h +++ b/src/blackmisc/math/mathutils.h @@ -17,6 +17,7 @@ #include #include #include +#include namespace BlackMisc { @@ -56,8 +57,16 @@ namespace BlackMisc //! Round by given epsilon static double roundEpsilon(double value, double epsilon); - //! Epsilon safe equal + //! Epsilon safe equal @{ static bool epsilonEqual(double v1, double v2, double epsilon = 1E-06); + static bool epsilonEqualLimits(double v1, double v2) { return qAbs(v1 - v2) <= std::numeric_limits::epsilon(); } + //! @} + + //! Epsilon safe zero @{ + static bool epsilonZero(double v, double epsilon) { return epsilonEqual(v, 0.0, epsilon); } + static bool epsilonZero(double v) { return epsilonEqual(v, 0.0, 1E-09); } + static inline bool epsilonZeroLimits(double v) { return qAbs(v) <= std::numeric_limits::epsilon(); } + //! @} //! Nearest integer not greater in magnitude than value, correcting for epsilon static inline double trunc(double value, double epsilon = 1e-10)