diff --git a/CMakeLists.txt b/CMakeLists.txt
index de33d8d..68f5992 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,7 +8,7 @@ if (PLUGIN_STANDARD_3DMASC)
project( Q3DMASC_PLUGIN )
AddPlugin( NAME ${PROJECT_NAME} )
- set(Q3DMASC_PLUGIN_VERSION "1.0")
+ set(Q3DMASC_PLUGIN_VERSION "1.0+")
include( CMakePolicies NO_POLICY_SCOPE )
diff --git a/Classify3DMASCDialog.ui b/Classify3DMASCDialog.ui
index 7b147d2..e2c8b25 100644
--- a/Classify3DMASCDialog.ui
+++ b/Classify3DMASCDialog.ui
@@ -65,14 +65,14 @@
-
- PC2
+ -
-
- CTX
+ -
@@ -112,14 +112,14 @@
-
- PC1
+ -
-
- PCX
+ -
diff --git a/q3DMASC.cpp b/q3DMASC.cpp
index fb6252c..65506bf 100644
--- a/q3DMASC.cpp
+++ b/q3DMASC.cpp
@@ -120,7 +120,8 @@ void q3DMASCPlugin::doClassifyAction()
QList cloudLabels;
QString corePointsLabel;
bool filenamesSpecified = false;
- if (!masc::Tools::LoadClassifierCloudLabels(inputFilename, cloudLabels, corePointsLabel, filenamesSpecified))
+ QMap labelMapName;
+ if (!masc::Tools::LoadClassifierCloudLabels(inputFilename, cloudLabels, corePointsLabel, filenamesSpecified, labelMapName))
{
m_app->dispToConsole("Failed to read classifier file (see Console)", ccMainAppInterface::ERR_CONSOLE_MESSAGE);
return;
@@ -138,7 +139,7 @@ void q3DMASCPlugin::doClassifyAction()
//now show a dialog where the user will be able to set the cloud roles
Classify3DMASCDialog classifDlg(m_app);
- classifDlg.setCloudRoles(cloudLabels, corePointsLabel);
+ classifDlg.setCloudRoles(cloudLabels, corePointsLabel, labelMapName);
classifDlg.label_trainOrClassify->setText(corePointsLabel + " will be classified");
classifDlg.classifierFileLineEdit->setText(inputFilename);
classifDlg.testCloudComboBox->hide();
@@ -260,7 +261,8 @@ void q3DMASCPlugin::doTrainAction()
QList cloudLabels;
QString corePointsLabel;
bool filenamesSpecified = false;
- if (!masc::Tools::LoadClassifierCloudLabels(inputFilename, cloudLabels, corePointsLabel, filenamesSpecified))
+ QMap rolesAndNames;
+ if (!masc::Tools::LoadClassifierCloudLabels(inputFilename, cloudLabels, corePointsLabel, filenamesSpecified, rolesAndNames))
{
m_app->dispToConsole("Failed to read classifier file (see Console)", ccMainAppInterface::ERR_CONSOLE_MESSAGE);
return;
@@ -288,7 +290,7 @@ void q3DMASCPlugin::doTrainAction()
//now show a dialog where the user will be able to set the cloud roles
Classify3DMASCDialog classifDlg(m_app, true);
classifDlg.setWindowTitle("3DMASC Train");
- classifDlg.setCloudRoles(cloudLabels, corePointsLabel);
+ classifDlg.setCloudRoles(cloudLabels, corePointsLabel, rolesAndNames);
classifDlg.label_trainOrClassify->setText("The classifier will be trained on " + corePointsLabel);
classifDlg.classifierFileLineEdit->setText(inputFilename);
classifDlg.keepAttributesCheckBox->hide(); // this parameter is set in the trainDlg dialog
diff --git a/q3DMASCCommands.h b/q3DMASCCommands.h
index 223530b..51b6398 100644
--- a/q3DMASCCommands.h
+++ b/q3DMASCCommands.h
@@ -165,7 +165,8 @@ struct Command3DMASCClassif : public ccCommandLineInterface::Command
QList cloudLabels;
QString corePointsLabel;
bool filenamesSpecified = false;
- if (!masc::Tools::LoadClassifierCloudLabels(classifierFilename, cloudLabels, corePointsLabel, filenamesSpecified))
+ QMap labelsAndNames;
+ if (!masc::Tools::LoadClassifierCloudLabels(classifierFilename, cloudLabels, corePointsLabel, filenamesSpecified, labelsAndNames))
{
return cmd.error("Failed to read classifier file");
}
diff --git a/q3DMASCTools.cpp b/q3DMASCTools.cpp
index 7ceb73f..8b1f7b4 100644
--- a/q3DMASCTools.cpp
+++ b/q3DMASCTools.cpp
@@ -112,11 +112,12 @@ bool Tools::SaveClassifier( QString filename,
return true;
}
-bool Tools::LoadClassifierCloudLabels(QString filename, QList& labels, QString& corePointsLabel, bool& filenamesSpecified)
+bool Tools::LoadClassifierCloudLabels(QString filename, QList& labels, QString& corePointsLabel, bool& filenamesSpecified, QMap& labelsAndNames)
{
//just in case
corePointsLabel.clear();
labels.clear();
+ labelsAndNames.clear();
QFile file(filename);
if (!file.open(QFile::Text | QFile::ReadOnly))
@@ -155,6 +156,7 @@ bool Tools::LoadClassifierCloudLabels(QString filename, QList& labels,
return false;
}
labels.push_back(label);
+ labelsAndNames[label] = tokens.back();
if (tokens.size() > 1)
++filenameCount;
diff --git a/q3DMASCTools.h b/q3DMASCTools.h
index bb3eb6c..a3f142a 100644
--- a/q3DMASCTools.h
+++ b/q3DMASCTools.h
@@ -40,7 +40,7 @@ namespace masc
static bool LoadTrainingFile(QString filename, Feature::Set& rawFeatures, std::vector& scales, NamedClouds& loadedClouds, TrainParameters& parameters, CorePoints* corePoints = nullptr, QWidget* parent = nullptr);
- static bool LoadClassifierCloudLabels(QString filename, QList& labels, QString& corePointsLabel, bool& filenamesSpecified);
+ static bool LoadClassifierCloudLabels(QString filename, QList& labels, QString& corePointsLabel, bool& filenamesSpecified, QMap& labelsAndNames);
static bool LoadClassifier(QString filename, NamedClouds& clouds, Feature::Set& rawFeatures, masc::Classifier& classifier, QWidget* parent = nullptr);
diff --git a/qClassify3DMASCDialog.cpp b/qClassify3DMASCDialog.cpp
index d2c825d..d9a6ba9 100644
--- a/qClassify3DMASCDialog.cpp
+++ b/qClassify3DMASCDialog.cpp
@@ -28,10 +28,7 @@
#include
#include
#include
-//#include
-//system
-#include
static ccPointCloud* GetCloudFromCombo(QComboBox* comboBox, ccHObject* dbRoot)
{
@@ -91,6 +88,8 @@ Classify3DMASCDialog::Classify3DMASCDialog(ccMainAppInterface* app, bool trainMo
}
}
+ testCloudComboBox->addItem("", 0);
+
//if 3 clouds are loaded, then there's chances that the first one is the global cloud!
cloud1ComboBox->setCurrentIndex(/*cloudCount > 0 ? (cloudCount > 2 ? 1 : 0) : */-1);
connect(cloud1ComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onCloudChanged(int)));
@@ -140,70 +139,109 @@ void Classify3DMASCDialog::writeSettings()
settings.setValue("keepAttributes", keepAttributesCheckBox->isChecked());
}
-void Classify3DMASCDialog::setCloudRoles(const QList& roles, QString corePointsLabel)
+void Classify3DMASCDialog::setComboBoxIndex(QMap rolesAndNames, QLabel* label, QMap namesAndUniqueIds, QComboBox* comboBox)
+{
+ QString name;
+
+ if (label != testLabel)
+ {
+ name = rolesAndNames[label->text()];
+ }
+ else
+ {
+ name = rolesAndNames[QString("TEST")]; // this is because the label text of testLabel is 'TEST on (optional)'
+ }
+ QMap::iterator it = namesAndUniqueIds.find(name);
+ if (it != namesAndUniqueIds.end())
+ {
+ int index = comboBox->findData(it.value());
+ if (index != -1)
+ {
+ comboBox->setCurrentIndex(index);
+ }
+ }
+}
+
+void Classify3DMASCDialog::setCloudRoles(const QList& roles, QString& corePointsLabel, const QMap& rolesAndNames)
{
int index = 0;
for (const QString& role : roles)
{
- switch (index)
+ if (role != "TEST")
{
- case 0:
- cloud1Label->setText(role);
- if (corePointsLabel.isEmpty()) // if "core_points:" is not in the parameter file, the corePointsLabel is the first encountered role
- corePointsLabel = role;
-// cloud1RadioButton->setChecked(true);
- break;
- case 1:
- cloud2Label->setText(role);
- if (corePointsLabel == role)
-// cloud2RadioButton->setChecked(true);
- break;
- case 2:
- cloud3Label->setText(role);
- if (corePointsLabel == role)
-// cloud3RadioButton->setChecked(true);
- break;
- case 3:
- cloud4Label->setText(role);
- if (corePointsLabel == role)
-// cloud4RadioButton->setChecked(true);
- break;
- default:
- //this dialog can't handle more than 3 roles!
- break;
+ switch (index)
+ {
+ case 0:
+ cloud1Label->setText(role);
+ if (corePointsLabel.isEmpty()) // if "core_points:" is not in the parameter file, the corePointsLabel is the first encountered role
+ {
+ corePointsLabel = role;
+ }
+ break;
+ case 1:
+ cloud2Label->setText(role);
+ break;
+ case 2:
+ cloud3Label->setText(role);
+ break;
+ case 3:
+ cloud4Label->setText(role);
+ break;
+ default:
+ //this dialog can't handle more than 3 roles!
+ break;
+ }
+ ++index;
}
- ++index;
}
if (index < 1)
{
-// cloud1RadioButton->setEnabled(false);
cloud1ComboBox->setEnabled(false);
}
if (index < 2)
{
-// cloud2RadioButton->setEnabled(false);
-// cloud2RadioButton->setVisible(false);
cloud2ComboBox->setEnabled(false);
cloud2ComboBox->setVisible(false);
cloud2Label->setVisible(false);
}
if (index < 3)
{
-// cloud3RadioButton->setEnabled(false);
-// cloud3RadioButton->setVisible(false);
cloud3ComboBox->setEnabled(false);
cloud3ComboBox->setVisible(false);
cloud3Label->setVisible(false);
}
if (index < 4)
{
-// cloud4RadioButton->setEnabled(false);
-// cloud4RadioButton->setVisible(false);
cloud4ComboBox->setEnabled(false);
cloud4ComboBox->setVisible(false);
cloud4Label->setVisible(false);
}
+
+ // now we will try to preset the combo boxes depending on the names which are in the parameter file
+ QMap namesAndUniqueIds;
+
+ // build a map 'name : uniqueId' of the available clouds in the database tree (duplicate names are not handled, simply keep the first occurrence)
+ ccHObject::Container clouds;
+ if (m_app->dbRootObject())
+ {
+ m_app->dbRootObject()->filterChildren(clouds, true, CC_TYPES::POINT_CLOUD);
+ }
+ for (size_t i = 0; i < clouds.size(); ++i)
+ {
+ if (clouds[i]->isA(CC_TYPES::POINT_CLOUD)) //as filterChildren only test 'isKindOf'
+ {
+ QVariant uniqueID(clouds[i]->getUniqueID());
+ namesAndUniqueIds[clouds[i]->getName().toUpper()] = uniqueID;
+ }
+ }
+
+ // preset the combo boxes if possible
+ setComboBoxIndex(rolesAndNames, cloud1Label, namesAndUniqueIds, cloud1ComboBox);
+ setComboBoxIndex(rolesAndNames, cloud2Label, namesAndUniqueIds, cloud2ComboBox);
+ setComboBoxIndex(rolesAndNames, cloud3Label, namesAndUniqueIds, cloud3ComboBox);
+ setComboBoxIndex(rolesAndNames, cloud4Label, namesAndUniqueIds, cloud4ComboBox);
+ setComboBoxIndex(rolesAndNames, testLabel, namesAndUniqueIds, testCloudComboBox);
}
void Classify3DMASCDialog::getClouds(QMap& clouds) const
@@ -214,42 +252,26 @@ void Classify3DMASCDialog::getClouds(QMap& clouds) const
return;
}
-// if (cloud1RadioButton->isEnabled())
if (cloud1ComboBox->isEnabled())
{
clouds.insert(cloud1Label->text(), GetCloudFromCombo(cloud1ComboBox, m_app->dbRootObject()));
-// if (cloud1RadioButton->isChecked())
-// {
-// mainCloud = cloud1Label->text();
-// }
}
-// if (cloud2RadioButton->isEnabled())
+
if (cloud2ComboBox->isEnabled())
{
clouds.insert(cloud2Label->text(), GetCloudFromCombo(cloud2ComboBox, m_app->dbRootObject()));
-// if (cloud2RadioButton->isChecked())
-// {
-// mainCloud = cloud2Label->text();
-// }
}
-// if (cloud3RadioButton->isEnabled())
+
if (cloud3ComboBox->isEnabled())
{
clouds.insert(cloud3Label->text(), GetCloudFromCombo(cloud3ComboBox, m_app->dbRootObject()));
-// if (cloud3RadioButton->isChecked())
-// {
-// mainCloud = cloud3Label->text();
-// }
}
-// if (cloud4RadioButton->isEnabled())
+
if (cloud4ComboBox->isEnabled())
{
clouds.insert(cloud4Label->text(), GetCloudFromCombo(cloud4ComboBox, m_app->dbRootObject()));
-// if (cloud4RadioButton->isChecked())
-// {
-// mainCloud = cloud4Label->text();
-// }
}
+
if (testCloudComboBox->currentIndex() >= 0)
{
clouds.insert("TEST", GetCloudFromCombo(testCloudComboBox, m_app->dbRootObject()));
diff --git a/qClassify3DMASCDialog.h b/qClassify3DMASCDialog.h
index a9599ec..1d6de90 100644
--- a/qClassify3DMASCDialog.h
+++ b/qClassify3DMASCDialog.h
@@ -42,7 +42,10 @@ public:
void writeSettings();
//! Sets the clouds roles
- void setCloudRoles(const QList& roles, QString corePointsLabel);
+ void setCloudRoles(const QList& roles, QString &corePointsLabel, const QMap &rolesAndNames);
+
+ //! Preset the combo boxes if possible with the names specified in the parameter file
+ void setComboBoxIndex(QMap rolesAndNames, QLabel* label, QMap namesAndUniqueIds, QComboBox* comboBox);
//! Returns the selected point clouds
void getClouds(QMap& clouds) const;