Ref T397, checks on vector to find root cause NaN/inf issue

* sometimes very large numbers (xxE38) in vector
* sometimes vectors which look correct, but exceed [-1,1]
This commit is contained in:
Klaus Basan
2018-10-10 15:03:31 +02:00
parent 4038729e82
commit dec0b12ea2
10 changed files with 98 additions and 9 deletions

View File

@@ -46,10 +46,12 @@ namespace BlackMisc
if (coordinate1.isNull() || coordinate2.isNull()) { return CLength::null(); }
// if (coordinate1.equalNormalVectorDouble(coordinate2)) { return CLength(0, CLengthUnit::defaultUnit()); }
static const float earthRadiusMeters = 6371000.8f;
const QVector3D v1 = coordinate1.normalVector();
const QVector3D v2 = coordinate2.normalVector();
Q_ASSERT_X(std::isfinite(v1.x()) && std::isfinite(v1.y()) && std::isfinite(v1.z()), Q_FUNC_INFO, "Distance calculation: v1 non-finite argument");
Q_ASSERT_X(std::isfinite(v2.x()) && std::isfinite(v2.y()) && std::isfinite(v2.z()), Q_FUNC_INFO, "Distance calculation: v2 non-finite argument");
Q_ASSERT_X(!std::isnan(v1.x()) && !std::isnan(v1.y()) && !std::isnan(v1.z()) && !std::isnan(v2.x()) && !std::isnan(v2.y()) && !std::isnan(v2.z()), Q_FUNC_INFO, "Distance calculation: NaN in argument");
const float d = earthRadiusMeters * std::atan2(QVector3D::crossProduct(v1, v2).length(), QVector3D::dotProduct(v1, v2));
BLACK_VERIFY_X(!std::isnan(d), Q_FUNC_INFO, "Distance calculation: NaN in result");
@@ -183,6 +185,44 @@ namespace BlackMisc
this->geodeticHeight().valueRoundedWithUnit(CLengthUnit::ft(), 2, i18n));
}
bool ICoordinateGeodetic::isNaNVector() const
{
const QVector3D v = this->normalVector();
return std::isnan(v.x()) || std::isnan(v.y()) || std::isnan(v.z());
}
bool ICoordinateGeodetic::isNaNVectorDouble() const
{
const std::array<double, 3> v = this->normalVectorDouble();
return std::isnan(v[0]) || std::isnan(v[1]) || std::isnan(v[2]);
}
bool ICoordinateGeodetic::isInfVector() const
{
const QVector3D v = this->normalVector();
return std::isinf(v.x()) || std::isinf(v.y()) || std::isinf(v.z());
}
bool ICoordinateGeodetic::isInfVectorDouble() const
{
const std::array<double, 3> v = this->normalVectorDouble();
return std::isinf(v[0]) || std::isinf(v[1]) || std::isinf(v[2]);
}
bool ICoordinateGeodetic::isValidVectorRange() const
{
// inf is out of range, comparing nans is always false
const std::array<double, 3> v = this->normalVectorDouble();
return isValidVector(v);
}
bool ICoordinateGeodetic::isValidVector(const std::array<double, 3> &v)
{
constexpr double l = 1.00001; // because of interpolation
return v[0] <= l && v[1] <= l && v[2] <= l &&
v[0] >= -l && v[1] >= -l && v[2] >= -l;
}
CVariant CCoordinateGeodetic::propertyByIndex(const BlackMisc::CPropertyIndex &index) const
{
if (index.isMyself()) { return CVariant::from(*this); }