diff --git a/FeaturesInterface.cpp b/FeaturesInterface.cpp index 5f4ad30..912caad 100644 --- a/FeaturesInterface.cpp +++ b/FeaturesInterface.cpp @@ -51,13 +51,12 @@ CCCoreLib::ScalarField* Feature::PrepareSF(ccPointCloud* cloud, const char* resu int sfIdx = cloud->getScalarFieldIndexByName(resultSFName); if (sfIdx >= 0) { - ccLog::Warning("Existing SF: " + QString(resultSFName) + ", SFCollector::Behavior " + QString::number(behavior)); + ccLog::Warning("Existing SF: " + QString(resultSFName) + ", do not store in generatedScalarFields"); resultSF = cloud->getScalarField(sfIdx); } else { ccLog::Warning("SF does not exist, create it: " + QString(resultSFName) + ", SFCollector::Behavior " + QString::number(behavior)); - resultSF = cloud->getScalarField(sfIdx); ccScalarField* newSF = new ccScalarField(resultSFName); if (!newSF->resizeSafe(cloud->size())) { diff --git a/NeighborhoodFeature.cpp b/NeighborhoodFeature.cpp index 0dc917e..9483ed6 100644 --- a/NeighborhoodFeature.cpp +++ b/NeighborhoodFeature.cpp @@ -91,7 +91,11 @@ bool NeighborhoodFeature::prepare( const CorePoints& corePoints, assert(!sf1); sf1WasAlreadyExisting = CheckSFExistence(corePoints.cloud, qPrintable(resultSFName)); if (sf1WasAlreadyExisting) + { sf1 = PrepareSF(corePoints.cloud, qPrintable(resultSFName), generatedScalarFields, SFCollector::ALWAYS_KEEP); + if (generatedScalarFields->scalarFields.contains(sf1)) // i.e. the SF is existing but was not present at the startup of the plugin + generatedScalarFields->setBehavior(sf1, SFCollector::CAN_REMOVE); + } else sf1 = PrepareSF(corePoints.cloud, qPrintable(resultSFName), generatedScalarFields, SFCollector::CAN_REMOVE); if (!sf1) diff --git a/PointFeature.cpp b/PointFeature.cpp index 572a516..b33c601 100644 --- a/PointFeature.cpp +++ b/PointFeature.cpp @@ -579,7 +579,12 @@ bool PointFeature::prepare( const CorePoints& corePoints, //prepare the corresponding scalar field statSF1WasAlreadyExisting = CheckSFExistence(corePoints.cloud, qPrintable(resultSFName)); if (statSF1WasAlreadyExisting) + { + // if the SF is not existing, it is not added to generatedScalarFields statSF1 = PrepareSF(corePoints.cloud, qPrintable(resultSFName), generatedScalarFields, SFCollector::ALWAYS_KEEP); + if (generatedScalarFields->scalarFields.contains(statSF1)) // i.e. the SF is existing but was not present at the startup of the plugin + generatedScalarFields->setBehavior(statSF1, SFCollector::CAN_REMOVE); + } else statSF1 = PrepareSF(corePoints.cloud, qPrintable(resultSFName), generatedScalarFields, SFCollector::CAN_REMOVE); if (!statSF1) diff --git a/ScalarFieldCollector.cpp b/ScalarFieldCollector.cpp index fefc05a..ad505bb 100644 --- a/ScalarFieldCollector.cpp +++ b/ScalarFieldCollector.cpp @@ -29,6 +29,10 @@ void SFCollector::push(ccPointCloud* cloud, CCCoreLib::ScalarField* sf, Behavior behavior) { assert(!scalarFields.contains(sf)); + if (scalarFields.contains(sf)) + ccLog::Warning(QString("[SFCollector] scalar field '%1' HAS ALREADY BEEN COLLECTED").arg(sf->getName()) + ", behaviour " + QString::number(behavior)); + else + ccLog::Warning(QString("[SFCollector] collect scalar field '%1'").arg(sf->getName()) + ", behaviour " + QString::number(behavior)); SFDesc desc; desc.behavior = behavior; desc.cloud = cloud; @@ -63,3 +67,15 @@ void SFCollector::releaseSFs(bool keepByDefault) scalarFields.clear(); } + +bool SFCollector::setBehavior(CCCoreLib::ScalarField *sf, Behavior behavior) +{ + if (scalarFields.contains(sf)) + { + Behavior previousBehavior = scalarFields[sf].behavior; + scalarFields[sf].behavior = behavior; + ccLog::Warning("behavior of " + QString(sf->getName()) + " changed from " + QString::number(previousBehavior) + " to " + QString::number(behavior)); + } + + return true; +} diff --git a/ScalarFieldCollector.h b/ScalarFieldCollector.h index 6d00b80..4aa2760 100644 --- a/ScalarFieldCollector.h +++ b/ScalarFieldCollector.h @@ -43,6 +43,8 @@ class SFCollector void releaseSFs(bool keepByDefault); + bool setBehavior(CCCoreLib::ScalarField *sf, Behavior behavior); + struct SFDesc { ccPointCloud* cloud = nullptr; diff --git a/confusionmatrix.cpp b/confusionmatrix.cpp index 71ecf98..ccb82ae 100644 --- a/confusionmatrix.cpp +++ b/confusionmatrix.cpp @@ -21,6 +21,10 @@ QColor getColor(double value, double r1, double g1, double b1) double r0 = 255; double g0 = 255; double b0 = 255; + if (value < 0.05) + value = 0.05; + if (value > 0.95) + value = 0.95; int r = int((r1 - r0) * value + r0); int g = int ((g1 - g0) * value + g0); int b = int ((b1 - b0) * value + b0); @@ -42,7 +46,7 @@ ConfusionMatrix::ConfusionMatrix(std::vector &actual, std::vectorui->tableWidget->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); QSize tableSize = this->ui->tableWidget->sizeHint(); QSize labelSize = this->ui->label->sizeHint(); - QSize widgetSize = QSize(tableSize.width(), tableSize.height() + 2 * labelSize.height()); + QSize widgetSize = QSize(tableSize.width() + 10, tableSize.height() + 50); this->setMinimumSize(widgetSize); } @@ -238,7 +242,7 @@ void ConfusionMatrix::compute(std::vector& actual, std::vectorsetFont(f); } else - newItem->setBackground(getColor(val / vec_TP_FN.at(row, 0), 0, 128, 255)); + newItem->setBackground(getColor(val / vec_TP_FN.at(row, 0), 200, 50, 50)); this->ui->tableWidget->setItem(2 + row, + 2 + column, newItem); } diff --git a/q3DMASCTools.cpp b/q3DMASCTools.cpp index cb3d8af..4543343 100644 --- a/q3DMASCTools.cpp +++ b/q3DMASCTools.cpp @@ -427,7 +427,7 @@ static bool CreateFeaturesFromCommand(const QString& command, QString corePoints } else { - ccLog::Warning(QString("ContextBasedFeature: you are using the DEPRECATED syntax").arg(token).arg(lineNumber)); + ccLog::Warning(QString("ContextBasedFeature: you are using the DEPRECATED syntax (for instance, DZ1_SC0_CTX_10 is correct)").arg(token).arg(lineNumber)); qSharedPointerCast(feature)->ctxClassLabel = classLabel; ++i; } @@ -1092,7 +1092,8 @@ bool Tools::PrepareFeatures(const CorePoints& corePoints, Feature::Set& features //build the scaled feature list attached to the second cloud (if any) if (feature->cloud2 && feature->cloud2 != feature->cloud1 && feature->op != Feature::NO_OPERATION - && !static_cast(feature.data())->statSF1WasAlreadyExisting) // nothing to compute if the scalar field was already there + && !static_cast(feature.data())->statSF1WasAlreadyExisting + && !static_cast(feature.data())->statSF2WasAlreadyExisting) // nothing to compute if the scalar field was already there { FeaturesAndScales& fas = cloudsWithScaledFeatures[feature->cloud2]; ++fas.featureCount; @@ -1123,7 +1124,8 @@ bool Tools::PrepareFeatures(const CorePoints& corePoints, Feature::Set& features //build the scaled feature list attached to the second cloud (if any) if (feature->cloud2 && feature->cloud2 != feature->cloud1 && feature->op != Feature::NO_OPERATION - && !static_cast(feature.data())->sf1WasAlreadyExisting) // nothing to compute if the scalar field was already there + && !static_cast(feature.data())->sf1WasAlreadyExisting + && !static_cast(feature.data())->sf2WasAlreadyExisting) // nothing to compute if the scalar field was already there { FeaturesAndScales& fas = cloudsWithScaledFeatures[feature->cloud2]; fas.neighborhoodFeaturesPerScale[feature->scale].push_back(qSharedPointerCast(feature)); @@ -1140,7 +1142,7 @@ bool Tools::PrepareFeatures(const CorePoints& corePoints, Feature::Set& features case Feature::Type::ContextBasedFeature: { //build the scaled feature list attached to the second cloud (the 'context' cloud) - if (feature->cloud2 + if (feature->cloud1 && !static_cast(feature.data())->sfWasAlreadyExisting) // nothing to compute if the scalar field was already there { FeaturesAndScales& fas = cloudsWithScaledFeatures[feature->cloud2]; @@ -1262,7 +1264,7 @@ bool Tools::PrepareFeatures(const CorePoints& corePoints, Feature::Set& features //Point features for (PointFeature::Shared& feature : fas.pointFeaturesPerScale[currentScale]) { - if (feature->cloud1 == sourceCloud && feature->statSF1 && feature->field1) + if (feature->cloud1 == sourceCloud && feature->statSF1 && feature->field1) { double outputValue = 0; if (!feature->computeStat(nNSS.pointsInNeighbourhood, feature->field1, outputValue)) @@ -1276,7 +1278,7 @@ bool Tools::PrepareFeatures(const CorePoints& corePoints, Feature::Set& features feature->statSF1->setValue(i, v1); } - if (feature->cloud2 == sourceCloud && feature->statSF2 && feature->field2) + if (feature->cloud2 == sourceCloud && feature->statSF2 && feature->field2) { assert(feature->op != Feature::NO_OPERATION); double outputValue = 0;