Inspection: multi-threaded calculation

This commit is contained in:
wmayer
2020-01-29 11:55:49 +01:00
parent 8ef469a60a
commit 4e02de80c0
2 changed files with 110 additions and 27 deletions

View File

@@ -653,6 +653,7 @@ unsigned int PropertyDistanceList::getMemSize (void) const
// ----------------------------------------------------------------
namespace Inspection {
// helper class to use Qt's concurrent framework
struct DistanceInspection
{
@@ -686,6 +687,25 @@ struct DistanceInspection
std::vector<InspectNominalGeometry*> nominal;
};
// Helper internal class for QtConcurrent map operation. Holds sums-of-squares and counts for RMS calculation
class DistanceInspectionRMS {
public:
DistanceInspectionRMS() : m_numv(0), m_sumsq(0.0) {};
DistanceInspectionRMS& operator += (const DistanceInspectionRMS& rhs)
{
this->m_numv += rhs.m_numv;
this->m_sumsq += rhs.m_sumsq;
return *this;
}
double getRMS()
{
return sqrt(this->m_sumsq / (double)this->m_numv);
}
int m_numv;
double m_sumsq;
};
}
PROPERTY_SOURCE(Inspection::Feature, App::DocumentObject)
Feature::Feature()
@@ -759,8 +779,8 @@ App::DocumentObjectExecReturn* Feature::execute(void)
inspectNominal.push_back(nominal);
}
#if 0 // test with some huge data sets
Standard::SetReentrant(Standard_True);
#if 0
#if 1 // test with some huge data sets
std::vector<unsigned long> index(actual->countPoints());
std::generate(index.begin(), index.end(), Base::iotaGen<unsigned long>(0));
DistanceInspection check(this->SearchRadius.getValue(), actual, inspectNominal);
@@ -771,16 +791,17 @@ App::DocumentObjectExecReturn* Feature::execute(void)
QFutureWatcher<float> watcher;
QObject::connect(&watcher, SIGNAL(progressValueChanged(int)),
&progress, SLOT(progressValueChanged(int)));
watcher.setFuture(future);
// keep it responsive during computation
QEventLoop loop;
QObject::connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit()));
watcher.setFuture(future);
loop.exec();
std::vector<float> vals;
vals.insert(vals.end(), future.begin(), future.end());
#else
DistanceInspection insp(this->SearchRadius.getValue(), actual, inspectNominal);
unsigned long count = actual->countPoints();
std::stringstream str;
str << "Inspecting " << this->Label.getValue() << "...";
@@ -788,19 +809,7 @@ App::DocumentObjectExecReturn* Feature::execute(void)
std::vector<float> vals(count);
for (unsigned long index = 0; index < count; index++) {
Base::Vector3f pnt = actual->getPoint(index);
float fMinDist=FLT_MAX;
for (std::vector<InspectNominalGeometry*>::iterator it = inspectNominal.begin(); it != inspectNominal.end(); ++it) {
float fDist = (*it)->getDistance(pnt);
if (fabs(fDist) < fabs(fMinDist))
fMinDist = fDist;
}
if (fMinDist > this->SearchRadius.getValue())
fMinDist = FLT_MAX;
else if (-fMinDist > this->SearchRadius.getValue())
fMinDist = -FLT_MAX;
float fMinDist = insp.mapped(index);
vals[index] = fMinDist;
seq.next();
}
@@ -822,8 +831,72 @@ App::DocumentObjectExecReturn* Feature::execute(void)
fRMS = sqrt(fRMS);
}
Base::Console().Message("RMS value for '%s' with search radius=%.4f is: %.4f\n",
this->Label.getValue(), this->SearchRadius.getValue(), fRMS);
Base::Console().Message("RMS value for '%s' with search radius [%.4f,%.4f] is: %.4f\n",
this->Label.getValue(), -this->SearchRadius.getValue(), this->SearchRadius.getValue(), fRMS);
#else
bool useMultithreading = true;
unsigned long count = actual->countPoints();
std::vector<float> vals(count);
std::function<DistanceInspectionRMS(int)> fMap = [&](unsigned int index)
{
DistanceInspectionRMS res;
Base::Vector3f pnt = actual->getPoint(index);
float fMinDist = FLT_MAX;
for (std::vector<InspectNominalGeometry*>::iterator it = inspectNominal.begin(); it != inspectNominal.end(); ++it) {
float fDist = (*it)->getDistance(pnt);
if (fabs(fDist) < fabs(fMinDist))
fMinDist = fDist;
}
if (fMinDist > this->SearchRadius.getValue())
fMinDist = FLT_MAX;
else if (-fMinDist > this->SearchRadius.getValue())
fMinDist = -FLT_MAX;
else {
res.m_sumsq += fMinDist * fMinDist;
res.m_numv++;
}
vals[index] = fMinDist;
return res;
};
DistanceInspectionRMS res;
if (useMultithreading) {
// Build vector of increasing indices
std::vector<unsigned long> index(count);
std::iota(index.begin(), index.end(), 0);
// Perform map-reduce operation : compute distances and update sum of squares for RMS computation
QFuture<DistanceInspectionRMS> future = QtConcurrent::mappedReduced(
index, fMap, &DistanceInspectionRMS::operator+=);
// Setup progress bar
Base::FutureWatcherProgress progress("Inspecting...", actual->countPoints());
QFutureWatcher<DistanceInspectionRMS> watcher;
QObject::connect(&watcher, SIGNAL(progressValueChanged(int)),
&progress, SLOT(progressValueChanged(int)));
// Keep UI responsive during computation
QEventLoop loop;
QObject::connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit()));
watcher.setFuture(future);
loop.exec();
res = future.result();
}
else {
// Single-threaded operation
std::stringstream str;
str << "Inspecting " << this->Label.getValue() << "...";
Base::SequencerLauncher seq(str.str().c_str(), count);
for (unsigned int i = 0; i < count; i++)
res += fMap(i);
}
Base::Console().Message("RMS value for '%s' with search radius [%.4f,%.4f] is: %.4f\n",
this->Label.getValue(), -this->SearchRadius.getValue(), this->SearchRadius.getValue(), res.getRMS());
Distances.setValues(vals);
#endif
delete actual;
for (std::vector<InspectNominalGeometry*>::iterator it = inspectNominal.begin(); it != inspectNominal.end(); ++it)

View File

@@ -43,6 +43,7 @@
#include <Inventor/nodes/SoMaterialBinding.h>
#include <Inventor/nodes/SoNormal.h>
#include <Inventor/errors/SoDebugError.h>
#include <Inventor/actions/SoSearchAction.h>
#include <Base/Exception.h>
#include <App/PropertyLinks.h>
@@ -585,15 +586,24 @@ QString ViewProviderInspection::inspectDistance(const SoPickedPoint* pp) const
info = QObject::tr("Distance: < %1").arg(-fSearchRadius);
}
else {
const SbVec3f& v1 = this->pcCoords->point[index1];
const SbVec3f& v2 = this->pcCoords->point[index2];
const SbVec3f& v3 = this->pcCoords->point[index3];
const SbVec3f& p = pp->getObjectPoint();
// get the weights
float w1, w2, w3;
calcWeights(v1,v2,v3,p,w1,w2,w3);
float fVal = w1*fVal1+w2*fVal2+w3*fVal3;
info = QObject::tr("Distance: %1").arg(fVal);
SoSearchAction searchAction;
searchAction.setType(SoCoordinate3::getClassTypeId());
searchAction.setInterest(SoSearchAction::FIRST);
searchAction.apply(pp->getPath()->getNodeFromTail(1));
SoPath* selectionPath = searchAction.getPath();
if (selectionPath) {
SoCoordinate3* coords = static_cast<SoCoordinate3*>(selectionPath->getTail());
const SbVec3f& v1 = coords->point[index1];
const SbVec3f& v2 = coords->point[index2];
const SbVec3f& v3 = coords->point[index3];
const SbVec3f& p = pp->getObjectPoint();
// get the weights
float w1, w2, w3;
calcWeights(v1, v2, v3, p, w1, w2, w3);
float fVal = w1 * fVal1 + w2 * fVal2 + w3 * fVal3;
info = QObject::tr("Distance: %1").arg(fVal);
}
}
}
}