ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
qClassify3DMASCDialog.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
9 
10 // qCC_plugins
11 #include <ecvMainAppInterface.h>
12 
13 // qCC_db
14 #include <ecvPointCloud.h>
15 
16 // Qt
17 #include <QComboBox>
18 #include <QMainWindow>
19 #include <QPushButton>
20 #include <QSettings>
21 
22 static ccPointCloud* GetCloudFromCombo(QComboBox* comboBox, ccHObject* dbRoot) {
23  assert(comboBox && dbRoot);
24  if (!comboBox || !dbRoot) {
25  assert(false);
26  return 0;
27  }
28 
29  // return the cloud currently selected in the combox box
30  int index = comboBox->currentIndex();
31  if (index < 0) {
32  assert(false);
33  return 0;
34  }
35  unsigned uniqueID = comboBox->itemData(index).toUInt();
36  ccHObject* item = dbRoot->find(uniqueID);
37  if (!item || !item->isA(CV_TYPES::POINT_CLOUD)) {
38  assert(false);
39  return 0;
40  }
41  return static_cast<ccPointCloud*>(item);
42 }
43 
45  bool trainMode /*=false*/)
46  : QDialog(app ? app->getMainWindow() : 0),
48  m_app(app) {
49  setupUi(this);
50 
51  if (m_app) {
52  // add list of clouds to the combo-boxes
53  ccHObject::Container clouds;
54  if (m_app->dbRootObject()) {
55  m_app->dbRootObject()->filterChildren(clouds, true,
56  CV_TYPES::POINT_CLOUD, true);
57  }
58 
59  unsigned cloudCount = 0;
60  for (size_t i = 0; i < clouds.size(); ++i) {
61  QString name = clouds[i]->getName() +
62  QString(" [%1]").arg(clouds[i]->getUniqueID());
63  QVariant uniqueID(clouds[i]->getUniqueID());
64  cloud1ComboBox->addItem(name, uniqueID);
65  cloud2ComboBox->addItem(name, uniqueID);
66  cloud3ComboBox->addItem(name, uniqueID);
67  cloud4ComboBox->addItem(name, uniqueID);
68  testCloudComboBox->addItem(name, uniqueID);
69  ++cloudCount;
70  }
71 
72  testCloudComboBox->addItem("", 0);
73 
74  // if 3 clouds are loaded, then there's chances that the first one is
75  // the global cloud!
76  cloud1ComboBox->setCurrentIndex(
77  /*cloudCount > 0 ? (cloudCount > 2 ? 1 : 0) : */ -1);
78  connect(cloud1ComboBox, SIGNAL(currentIndexChanged(int)), this,
79  SLOT(onCloudChanged(int)));
80  cloud2ComboBox->setCurrentIndex(
81  /*cloudCount > 1 ? (cloudCount > 2 ? 2 : 1) : */ -1);
82  connect(cloud2ComboBox, SIGNAL(currentIndexChanged(int)), this,
83  SLOT(onCloudChanged(int)));
84  cloud3ComboBox->setCurrentIndex(/*cloudCount > 2 ? 0 : */ -1);
85  connect(cloud3ComboBox, SIGNAL(currentIndexChanged(int)), this,
86  SLOT(onCloudChanged(int)));
87  cloud4ComboBox->setCurrentIndex(/*cloudCount > 3 ? 0 : */ -1);
88  connect(cloud4ComboBox, SIGNAL(currentIndexChanged(int)), this,
89  SLOT(onCloudChanged(int)));
90  testCloudComboBox->setCurrentIndex(-1);
91 
92  if (cloudCount == 0 && app) {
93  app->dispToConsole(QString("You need at least 1 loaded cloud to ") +
94  (trainMode ? "train a classifier"
95  : "classify it..."),
97  }
98  }
99 
100  if (trainMode) {
101  label->setText(tr("Trainer file"));
102  warningLabel->setVisible(false);
103  warningLabel->setText(
104  "Assign each role to the right cloud, and select the cloud on "
105  "which to train the classifier");
106  }
107 
108  onCloudChanged(0);
109 
110  readSettings();
111 }
112 
114 
116  QSettings settings;
117  settings.beginGroup("3DMASC");
118  bool keepAttributes = settings.value("keepAttributes", false).toBool();
119  this->keepAttributesCheckBox->setChecked(keepAttributes);
120 }
121 
123  QSettings settings;
124  settings.beginGroup("3DMASC");
125  settings.setValue("keepAttributes", keepAttributesCheckBox->isChecked());
126 }
127 
129  const QMap<QString, QString>& rolesAndNames,
130  QLabel* label,
131  const QMap<QString, QVariant>& namesAndUniqueIds,
132  QComboBox* comboBox) {
133  QString name = label == testLabel
134  ? QString("TEST")
135  : label->text(); // testLabel is specific, the role
136  // is always TEST
137 
138  QMap<QString, QVariant>::const_iterator it(namesAndUniqueIds.find(name));
139  if (it != namesAndUniqueIds.end()) {
140  int index = comboBox->findData(it.value());
141  if (index != -1) {
142  comboBox->setCurrentIndex(index);
143  }
144  }
145 }
146 
148  const QList<QString>& roles,
149  QString& corePointsLabel,
150  const QMap<QString, QString>& rolesAndNames) {
151  int index = 0;
152  for (const QString& role : roles) {
153  if (role != "TEST") {
154  switch (index) {
155  case 0:
156  cloud1Label->setText(role);
157  if (corePointsLabel
158  .isEmpty()) // if "core_points:" is not in the
159  // parameter file, the
160  // corePointsLabel is the first
161  // encountered role
162  {
163  corePointsLabel = role;
164  }
165  break;
166  case 1:
167  cloud2Label->setText(role);
168  break;
169  case 2:
170  cloud3Label->setText(role);
171  break;
172  case 3:
173  cloud4Label->setText(role);
174  break;
175  default:
176  // this dialog can't handle more than 3 roles!
177  break;
178  }
179  ++index;
180  }
181  }
182 
183  if (index < 1) {
184  cloud1ComboBox->setEnabled(false);
185  }
186  if (index < 2) {
187  cloud2ComboBox->setEnabled(false);
188  cloud2ComboBox->setVisible(false);
189  cloud2Label->setVisible(false);
190  }
191  if (index < 3) {
192  cloud3ComboBox->setEnabled(false);
193  cloud3ComboBox->setVisible(false);
194  cloud3Label->setVisible(false);
195  }
196  if (index < 4) {
197  cloud4ComboBox->setEnabled(false);
198  cloud4ComboBox->setVisible(false);
199  cloud4Label->setVisible(false);
200  }
201 
202  // now we will try to preset the combo boxes depending on the names which
203  // are in the parameter file
204  QMap<QString, QVariant> namesAndUniqueIds;
205 
206  // build a map 'name : uniqueId' of the available clouds in the database
207  // tree (duplicate names are not handled, simply keep the first occurrence)
208  ccHObject::Container clouds;
209  if (m_app->dbRootObject()) {
210  m_app->dbRootObject()->filterChildren(clouds, true,
212  }
213  for (size_t i = 0; i < clouds.size(); ++i) {
214  if (clouds[i]->isA(CV_TYPES::POINT_CLOUD)) // as filterChildren only
215  // tests 'isKindOf'
216  {
217  QVariant uniqueID(clouds[i]->getUniqueID());
218  namesAndUniqueIds[clouds[i]->getName().toUpper()] = uniqueID;
219  }
220  }
221 
222  // preset the combo boxes if possible
223  setComboBoxIndex(rolesAndNames, cloud1Label, namesAndUniqueIds,
224  cloud1ComboBox);
225  setComboBoxIndex(rolesAndNames, cloud2Label, namesAndUniqueIds,
226  cloud2ComboBox);
227  setComboBoxIndex(rolesAndNames, cloud3Label, namesAndUniqueIds,
228  cloud3ComboBox);
229  setComboBoxIndex(rolesAndNames, cloud4Label, namesAndUniqueIds,
230  cloud4ComboBox);
231  setComboBoxIndex(rolesAndNames, testLabel, namesAndUniqueIds,
232  testCloudComboBox);
233 }
234 
236  QMap<QString, ccPointCloud*>& clouds) const {
237  if (!m_app) {
238  assert(false);
239  return;
240  }
241 
242  if (cloud1ComboBox->isEnabled()) {
243  clouds.insert(cloud1Label->text(),
244  GetCloudFromCombo(cloud1ComboBox, m_app->dbRootObject()));
245  }
246 
247  if (cloud2ComboBox->isEnabled()) {
248  clouds.insert(cloud2Label->text(),
249  GetCloudFromCombo(cloud2ComboBox, m_app->dbRootObject()));
250  }
251 
252  if (cloud3ComboBox->isEnabled()) {
253  clouds.insert(cloud3Label->text(),
254  GetCloudFromCombo(cloud3ComboBox, m_app->dbRootObject()));
255  }
256 
257  if (cloud4ComboBox->isEnabled()) {
258  clouds.insert(cloud4Label->text(),
259  GetCloudFromCombo(cloud4ComboBox, m_app->dbRootObject()));
260  }
261 
262  if (testCloudComboBox->currentIndex() >= 0) {
263  clouds.insert("TEST", GetCloudFromCombo(testCloudComboBox,
264  m_app->dbRootObject()));
265  }
266 }
267 
269  if (!cloud1ComboBox->isEnabled()) {
270  // this means that no role has been defined yet
271  buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
272  return;
273  }
274 
275  buttonBox->button(QDialogButtonBox::Ok)
276  ->setEnabled(cloud1ComboBox->currentIndex() >= 0);
277 }
std::string name
3DMASC plugin 'classify' dialog
void writeSettings()
write settings
void setCloudRoles(const QList< QString > &roles, QString &corePointsLabel, const QMap< QString, QString > &rolesAndNames)
Sets the clouds roles.
Classify3DMASCDialog(ecvMainAppInterface *app, bool trainMode=false)
Default constructor.
ecvMainAppInterface * m_app
Gives access to the application (data-base, UI, etc.)
void getClouds(QMap< QString, ccPointCloud * > &clouds) const
Returns the selected point clouds.
void setComboBoxIndex(const QMap< QString, QString > &rolesAndNames, QLabel *label, const QMap< QString, QVariant > &namesAndUniqueIds, QComboBox *comboBox)
void readSettings()
read settings
Hierarchical CLOUDVIEWER Object.
Definition: ecvHObject.h:25
ccHObject * find(unsigned uniqueID)
Finds an entity in this object hierarchy.
unsigned filterChildren(Container &filteredChildren, bool recursive=false, CV_CLASS_ENUM filter=CV_TYPES::OBJECT, bool strict=false) const
Collects the children corresponding to a certain pattern.
std::vector< ccHObject * > Container
Standard instances container (for children, etc.)
Definition: ecvHObject.h:337
bool isA(CV_CLASS_ENUM type) const
Definition: ecvObject.h:131
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
Main application interface (for plugins)
virtual ccHObject * dbRootObject()=0
Returns DB root (as a ccHObject)
virtual void dispToConsole(QString message, ConsoleMessageLevel level=STD_CONSOLE_MESSAGE)=0
@ POINT_CLOUD
Definition: CVTypes.h:104
static ccPointCloud * GetCloudFromCombo(QComboBox *comboBox, ccHObject *dbRoot)