From bcb5e3664de7977363348c4855e0876a826260da Mon Sep 17 00:00:00 2001 From: Paul Leroy Date: Tue, 23 May 2023 00:06:22 +0200 Subject: [PATCH] bug correction in progress: crash when dupplicated features are configured in the parameter file --- ContextBasedFeature.cpp | 2 ++ NeighborhoodFeature.cpp | 30 +++++++++++++++++++++++------- NeighborhoodFeature.h | 1 + q3DMASC.cpp | 3 ++- q3DMASCTools.cpp | 7 +++++-- 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/ContextBasedFeature.cpp b/ContextBasedFeature.cpp index 8d42836..3a52d4a 100644 --- a/ContextBasedFeature.cpp +++ b/ContextBasedFeature.cpp @@ -128,6 +128,8 @@ bool ContextBasedFeature::prepare( const CorePoints& corePoints, sf = corePoints.cloud->getScalarField(sfIdx); generatedScalarFields->push(corePoints.cloud, sf, SFCollector::ALWAYS_KEEP); this->valueAlreadyComputed = true; + source.name = sf->getName(); + return true; } } diff --git a/NeighborhoodFeature.cpp b/NeighborhoodFeature.cpp index 09b1db8..f6ea0ed 100644 --- a/NeighborhoodFeature.cpp +++ b/NeighborhoodFeature.cpp @@ -21,9 +21,12 @@ #include #include #include +#include using namespace masc; +bool NeighborhoodFeature::sf2ExistenceInitialTestAlreadyPerformed = false; + bool NeighborhoodFeature::checkValidity(QString corePointRole, QString &error) const { if (!Feature::checkValidity(corePointRole, error)) @@ -94,10 +97,12 @@ bool NeighborhoodFeature::prepare( const CorePoints& corePoints, { if (useExistingScalarFields) { - ccLog::Warning("use existing scalar field: " + resultSFName); + ccLog::Warning("[sf1] use existing scalar field: " + resultSFName); sf1 = corePoints.cloud->getScalarField(sfIdx); generatedScalarFields->push(corePoints.cloud, sf1, SFCollector::ALWAYS_KEEP); this->value1AlreadyComputed = true; + source.name = sf1->getName(); + return true; } } @@ -116,24 +121,33 @@ bool NeighborhoodFeature::prepare( const CorePoints& corePoints, if (cloud2 && op != Feature::NO_OPERATION) { QString resultSFName2 = ToString(type) + "_" + cloud2Label + "@" + QString::number(scale); - keepSF2 = (corePoints.cloud->getScalarFieldIndexByName(qPrintable(resultSFName2)) >= 0); //we remember that the scalar field was already existing! +// keepSF2 = (corePoints.cloud->getScalarFieldIndexByName(qPrintable(resultSFName2)) >= 0); //we remember that the scalar field was already existing! - // check if there exists a scalar field with the same name, if so, use it - int sfIdx = corePoints.cloud->getScalarFieldIndexByName(qPrintable(resultSFName)); + // check if there exists a scalar field with the same name, and use it if required + int sfIdx = corePoints.cloud->getScalarFieldIndexByName(qPrintable(resultSFName2)); if (sfIdx >= 0) { if (useExistingScalarFields) { - ccLog::Warning("use existing scalar field: " + resultSFName); + ccLog::Warning("[sf2] use existing scalar field: " + resultSFName2); sf2 = corePoints.cloud->getScalarField(sfIdx); - generatedScalarFields->push(corePoints.cloud, sf2, SFCollector::ALWAYS_KEEP); this->value2AlreadyComputed = true; + if (!NeighborhoodFeature::sf2ExistenceInitialTestAlreadyPerformed) + { + keepSF2 = true; + generatedScalarFields->push(corePoints.cloud, sf2, SFCollector::ALWAYS_KEEP); + } + else + { + NeighborhoodFeature::sf2ExistenceInitialTestAlreadyPerformed = true; + generatedScalarFields->push(corePoints.cloud, sf2, SFCollector::ALWAYS_REMOVE); + } } } if (!sf2) // prepare the scalar field if needed { - sf2 = PrepareSF(corePoints.cloud, qPrintable(resultSFName), generatedScalarFields, SFCollector::ALWAYS_REMOVE); + sf2 = PrepareSF(corePoints.cloud, qPrintable(resultSFName2), generatedScalarFields, SFCollector::ALWAYS_REMOVE); } if (!sf2) @@ -175,6 +189,8 @@ bool NeighborhoodFeature::finish(const CorePoints& corePoints, QString& error) if (sf2) { //now perform the math operation + std::cout << sf2->getName() << std::endl; + std::cout << "operation " << OpToString(op).toStdString() << std::endl; if (op != Feature::NO_OPERATION) { if (!PerformMathOp(sf1, sf2, op)) diff --git a/NeighborhoodFeature.h b/NeighborhoodFeature.h index f873659..5d69901 100644 --- a/NeighborhoodFeature.h +++ b/NeighborhoodFeature.h @@ -179,6 +179,7 @@ namespace masc //! Feature values CCCoreLib::ScalarField *sf1, *sf2; bool keepSF2; + static bool sf2ExistenceInitialTestAlreadyPerformed; bool value1AlreadyComputed; bool value2AlreadyComputed; }; diff --git a/q3DMASC.cpp b/q3DMASC.cpp index b549745..39c27d1 100644 --- a/q3DMASC.cpp +++ b/q3DMASC.cpp @@ -392,7 +392,6 @@ void q3DMASCPlugin::doTrainAction() trainDlg.testDataRatioSpinBox->setEnabled(testCloud == nullptr); trainDlg.setInputFilePath(inputFilename); static bool s_keepAttributes = trainDlg.checkBox_useExistingScalarFields->isChecked(); - bool useExistingScalarFields = trainDlg.checkBox_useExistingScalarFields->isChecked(); //display the loaded features and let the user select the ones to use trainDlg.setResultText("Select features and press 'Run'"); @@ -477,6 +476,7 @@ void q3DMASCPlugin::doTrainAction() //we will train + evaluate the classifier, then display the results //then let the user change parameters and (potentially) start again + bool useExistingScalarFields = trainDlg.checkBox_useExistingScalarFields->isChecked(); for (int iteration = 0; ; ++iteration) { //look for selected features @@ -769,6 +769,7 @@ void q3DMASCPlugin::doTrainAction() } //we are going to restart the classification process + useExistingScalarFields = trainDlg.checkBox_useExistingScalarFields->isChecked(); } } diff --git a/q3DMASCTools.cpp b/q3DMASCTools.cpp index 213c657..1665458 100644 --- a/q3DMASCTools.cpp +++ b/q3DMASCTools.cpp @@ -39,6 +39,7 @@ #include #include #include +#include //system #include @@ -285,7 +286,7 @@ static bool CreateFeaturesFromCommand(const QString& command, QString corePoints } else { - //read the specific scale index + //read the specific scale index (is it really an index? it looks like a scale value!) bool ok = true; feature->scale = scaleStr.mid(2).toDouble(&ok); if (!ok) @@ -1274,7 +1275,8 @@ bool Tools::PrepareFeatures(const CorePoints& corePoints, Feature::Set& features feature->sf1->setValue(i, v1); } - if (feature->cloud2 == sourceCloud && feature->sf2 && !feature->value2AlreadyComputed) + // remember that if value1 is already computed, it is not necessary to compute value2! + if (feature->cloud2 == sourceCloud && feature->sf2 && !feature->value2AlreadyComputed && !feature->value1AlreadyComputed) { assert(feature->op != Feature::NO_OPERATION); double outputValue = 0; @@ -1339,6 +1341,7 @@ bool Tools::PrepareFeatures(const CorePoints& corePoints, Feature::Set& features for (const Feature::Shared& feature : features) { + std::cout << feature->toString().toStdString() << std::endl; //we have to 'finish' the process for scaled features if (feature->scaled() && !feature->finish(corePoints, errorStr)) {