From 30d3dddf08eb24dccc868e72772e7b7890cb7575 Mon Sep 17 00:00:00 2001 From: mbs Date: Wed, 5 Jun 2024 19:14:38 +0100 Subject: [PATCH] using a better solution to do compare doubles for shape physical properties --- .../ModelHighAPI_FeatureStore.cpp | 80 +++++++++++-------- src/ModelHighAPI/ModelHighAPI_FeatureStore.h | 6 +- 2 files changed, 52 insertions(+), 34 deletions(-) diff --git a/src/ModelHighAPI/ModelHighAPI_FeatureStore.cpp b/src/ModelHighAPI/ModelHighAPI_FeatureStore.cpp index ff5ce5435..b404f9e41 100644 --- a/src/ModelHighAPI/ModelHighAPI_FeatureStore.cpp +++ b/src/ModelHighAPI/ModelHighAPI_FeatureStore.cpp @@ -54,6 +54,7 @@ #include #include +#define MAX_PRECISION 12 #define PRECISION 5 #define TOLERANCE (1.e-6) @@ -132,7 +133,13 @@ std::string ModelHighAPI_FeatureStore::compareData(std::shared_ptrfirst) == theAttrs.end()) { return "original model had no attribute '" + aThisIter->first + "'"; } - if (theAttrs[aThisIter->first] != aThisIter->second) { + if (aThisIter->first == "__shape__") { + // Compare the shape dump + if (theAttrs[aThisIter->first] != aThisIter->second) { + return compareShape(theAttrs[aThisIter->first], aThisIter->second); + } + } + else if (theAttrs[aThisIter->first] != aThisIter->second) { return "attribute '" + aThisIter->first + "' is different (original != current) '" + theAttrs[aThisIter->first] + "' != '" + aThisIter->second + "'"; } @@ -147,25 +154,34 @@ std::string ModelHighAPI_FeatureStore::compareData(std::shared_ptr= nDigits) - { - int idx = numdigits - nDigits; - theOutput << std::fixed << std::setprecision(0) << (0 < idx && idx < 20 ? std::round(x / pow10[idx]) * pow10[idx] : x); - } - else - { - int prec = (numdigits < 0 ? nDigits : nDigits - numdigits); - theOutput << std::fixed << std::setprecision(prec) << x; + std::istringstream issOrig(theOrig), issCurr(theCurrent); + std::string strOrig, strCurr; + + // Compare the topological information (as a single string) + bool bDifferent = (!std::getline(issOrig, strOrig) || !std::getline(issCurr, strCurr) || strOrig != strCurr); + + if (!bDifferent) { + auto cmpDouble = [](double aOrig, double aCurr, double tol=1.e-5) { + return (fabs(aOrig) < tol ? fabs(aCurr) < tol : ((fabs(aOrig-aCurr) / fabs(aOrig)) < tol)); + }; + auto cmpPoint = [](double pOrig[], double pCurr[], double tol=1.e-4) { + return (sqrt((pOrig[0]-pCurr[0])*(pOrig[0]-pCurr[0]) + (pOrig[1]-pCurr[1])*(pOrig[1]-pCurr[1]) + (pOrig[2]-pCurr[2])*(pOrig[2]-pCurr[2])) < tol); + }; + + // Compare the physical properties (Volume, Area, Center of Mass as doubles with tolerance) + double volOrig{}, areaOrig{}, pntOrig[3]={0.,0.,0.}; + double volCurr{}, areaCurr{}, pntCurr[3]={0.,0.,0.}; + issOrig >> volOrig >> areaOrig >> pntOrig[0] >> pntOrig[1] >> pntOrig[2]; + issCurr >> volCurr >> areaCurr >> pntCurr[0] >> pntCurr[1] >> pntCurr[2]; + bDifferent = (!cmpDouble(volOrig, volCurr) || !cmpDouble(areaOrig, areaCurr) || !cmpPoint(pntOrig, pntCurr)); } -} + if (bDifferent) + return "attribute '__shape__' is different (original != current) '" + theOrig + "' != '" + theCurrent + "'"; + return ""; +} static void dumpArray(std::ostringstream& theOutput, const double theArray[], int theSize, int thePrecision = PRECISION) @@ -175,7 +191,6 @@ static void dumpArray(std::ostringstream& theOutput, const double theArray[], theOutput << " "; theOutput << std::fixed << std::setprecision(thePrecision) << (fabs(theArray[i]) < TOLERANCE ? 0.0 : theArray[i]); - //dumpFloat(theOutput, (fabs(theArray[i]) < TOLERANCE ? 0.0 : theArray[i]), thePrecision); } } @@ -436,28 +451,27 @@ std::string ModelHighAPI_FeatureStore::dumpShape(std::shared_ptr& std::string aTypeStr = anExp.current()->shapeTypeStr(); int aCount = 0; for (; anExp.more(); anExp.next()) aCount++; - aResult << aTypeStr.c_str() << ": " << aCount << std::endl; + aResult << aCount << " "; + } + else + { + aResult << "0 "; } } + aResult << "\n"; // output the main characteristics double aVolume = GeomAlgoAPI_ShapeTools::volume(theShape); if (aVolume > 1.e-5) { - aResult<<"Volume: "; - // volumes of too huge shapes write in the scientific format - dumpFloat(aResult, aVolume, 6); - aResult< 1.e-5) { - aResult << "Area: "; - // volumes of too huge shapes write in the scientific format - dumpFloat(aResult, anArea, 6); - aResult << std::endl; - } + if (anArea > 1.e-5) + aResult << std::fixed << std::setprecision(MAX_PRECISION) << anArea << " "; + else + aResult << "0.0 "; std::shared_ptr aCenter = GeomAlgoAPI_ShapeTools::centreOfMass(theShape); - aResult<<"Center of mass: "; - double aCenterVals[3] = {aCenter->x(), aCenter->y(), aCenter->z()}; - dumpArray(aResult, aCenterVals, 3, 5); - aResult<x() << " " << aCenter->y() << " " << aCenter->z() << std::endl; return aResult.str(); } diff --git a/src/ModelHighAPI/ModelHighAPI_FeatureStore.h b/src/ModelHighAPI/ModelHighAPI_FeatureStore.h index 2d09b68ac..c44446251 100644 --- a/src/ModelHighAPI/ModelHighAPI_FeatureStore.h +++ b/src/ModelHighAPI/ModelHighAPI_FeatureStore.h @@ -60,9 +60,13 @@ private: /// returns not empty string with error if something is different std::string compareData(std::shared_ptr theData, std::map& theAttrs); + /// compares the main characteristics of a shape + /// returns not empty string with error if something is different + std::string compareShape(const std::string &theOrig, + const std::string &theCurrent); /// dumps the attribute content to the string std::string dumpAttr(const AttributePtr& theAttr); - /// dumps the shape main charatceristics to string + /// dumps the shape main characteristics to string std::string dumpShape(std::shared_ptr& theShape); }; -- 2.39.2