ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ecvFilterByLabelDlg.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 
8 #include "ecvFilterByLabelDlg.h"
9 
10 // LOCAL
11 #include "MainWindow.h"
12 #include "db_tree/ecvDBRoot.h"
13 
14 // CV_CORE_LIB
15 #include <CVLog.h>
16 #include <CVTools.h>
17 #include <ClassMap.h>
18 
19 // CV_DB_LIB
20 #include <ecvDisplayTools.h>
21 #include <ecvHObjectCaster.h>
22 #include <ecvMesh.h>
23 #include <ecvPointCloud.h>
24 #include <ecvScalarField.h>
25 #include <ecvSubMesh.h>
26 
27 // QT
28 #include <QCheckBox>
29 
30 // SYSTEM
31 #include <unordered_set>
32 
34  : ccOverlayDialog(parent),
35  Ui::FilterByLabelDialog(),
36  m_mode(CANCEL),
37  m_minVald(0.0),
38  m_maxVald(1.0) {
39  setupUi(this);
40 
41  connect(splitPushButton, &QAbstractButton::clicked, this,
43  connect(exportSelectedToolButton, &QAbstractButton::clicked, this,
45  connect(exportUnselectedToolButton, &QAbstractButton::clicked, this,
47  connect(selectAllRadioButton, &QAbstractButton::clicked, this,
49  connect(unselectAllRadioButton, &QAbstractButton::clicked, this,
51  connect(cancelToolButton, &QAbstractButton::clicked, this,
53  connect(toggleSelectedToolButton, &QAbstractButton::clicked, this,
55 }
56 
58 
60  if (!ecvDisplayTools::GetCurrentScreen()) return false;
61 
62  ccHObject* ent = m_toFilter.first;
63  ccPointCloud* pc = m_toFilter.second;
64  if (!ent || !pc) {
65  return false;
66  }
67 
68  labelGroupBox->setEnabled(true);
70  Q_ASSERT(sf->currentSize() == pc->size());
71 
72  clear();
73  std::unordered_set<size_t> labels_set;
74  for (unsigned j = 0; j < pc->size(); j++) {
75  ScalarType value = sf->getValue(j);
76  size_t valueId = static_cast<size_t>(value);
77  if (value - valueId != 0) {
79  "[ecvFilterByLabelDlg::start] only support int type scalar "
80  "fields!");
81  clear();
82  return false;
83  }
84 
85  labels_set.insert(valueId);
86  }
87  m_labels.assign(labels_set.begin(), labels_set.end());
88  std::sort(m_labels.begin(), m_labels.end());
90 
91  return ccOverlayDialog::start();
92 }
93 
95  if (m_labels.empty()) {
96  return;
97  }
98 
99  if (gridLayout && !gridLayout->isEmpty()) {
100  clearLayoutWidgets(gridLayout);
101  }
102 
103  for (size_t i = 0; i < m_labels.size(); ++i) {
104  size_t label = m_labels[i];
105  const std::string& labelName = ClassMap::SemanticMap[label];
106  QCheckBox* labelCheckBox = new QCheckBox(labelGroupBox);
107  labelCheckBox->setObjectName(QString::fromUtf8(labelName.c_str()));
108  labelCheckBox->setText(QString::fromUtf8(labelName.c_str()));
109  bool isChecked = label >= m_minVald && label <= m_maxVald;
110  if (label == 0) {
111  isChecked = false;
112  }
113 
114  labelCheckBox->setChecked(isChecked);
115  ecvColor::Rgb col;
116  if (m_toFilter.second) {
117  col = *m_toFilter.second->getScalarValueColor(
118  static_cast<ScalarType>(label));
119  } else {
120  col = ecvColor::LookUpTable::at(label);
121  }
122 
123  QString styleSheet = QString("background-color: rgb(%1, %2, %3, %4)")
124  .arg(col.r)
125  .arg(col.g)
126  .arg(col.b)
127  .arg(125);
128  labelCheckBox->setStyleSheet(styleSheet);
129  // labelCheckBox->setAutoFillBackground(true);
130  // QPalette pal = labelCheckBox->palette();
131  // QColor backColor(col.r, col.g, col.b);
132  // pal.setColor(QPalette::Base, backColor);
133  // labelCheckBox->setPalette(pal);
134 
135  int rowIndex = static_cast<int>(i / 2);
136  int colIndex = static_cast<int>(i % 2);
137 
138  gridLayout->addWidget(labelCheckBox, rowIndex, colIndex, 1, 1,
139  Qt::AlignLeft | Qt::AlignVCenter);
140  }
141 }
142 
144 
145 bool ecvFilterByLabelDlg::linkWith(QWidget* win) {
146  if (!ccOverlayDialog::linkWith(win)) {
147  return false;
148  }
149 
150  return true;
151 }
152 
154  std::vector<ScalarType>& filteredClasses) {
155  if (!filteredClasses.empty()) {
156  filteredClasses.clear();
157  }
158  QList<QCheckBox*> list = labelGroupBox->findChildren<QCheckBox*>();
159 
160  foreach (QCheckBox* ncheckBox, list) {
161  if (ncheckBox && ncheckBox->isChecked()) {
162  int index = ClassMap::FindindexByValue(
163  CVTools::FromQString(ncheckBox->text()));
164  filteredClasses.push_back(static_cast<ScalarType>(index));
165  }
166  }
167 }
168 
170  bool state = selectAllRadioButton->isChecked();
171  QList<QCheckBox*> list = labelGroupBox->findChildren<QCheckBox*>();
172 
173  foreach (QCheckBox* ncheckBox, list) {
174  if (ncheckBox) {
175  ncheckBox->setChecked(state);
176  }
177  }
178 }
179 
181 
183  stop(false);
184  clear();
185 }
186 
188 
191  if (!cloud || !cloud->isKindOf(CV_TYPES::POINT_CLOUD)) return false;
192 
193  ccPointCloud* pc = static_cast<ccPointCloud*>(cloud);
195  if (!sf) {
196  CVLog::Warning(tr("Entity [%1] has no active scalar field !")
197  .arg(pc->getName()));
198  return false;
199  } else {
200  m_minVald = static_cast<double>(sf->displayRange().start());
201  m_maxVald = static_cast<double>(sf->displayRange().stop());
202  if (m_maxVald >= 20) {
203  CVLog::Warning(tr("Entity [%1] scalar field value range is bigger "
204  "than 20!")
205  .arg(pc->getName()));
206  return false;
207  }
208  }
209 
210  int pointNumber = static_cast<int>(pc->size());
211  if (pointNumber < 10) {
212  CVLog::Warning(QString("[ecvFilterByLabelDlg::setInputEntity] "
213  "Skip entity [%1] as the point number of it is "
214  "%2 lower than min limit 10!")
215  .arg(entity->getName(), pointNumber));
216  return false;
217  }
218 
219  m_toFilter = EntityAndVerticesType(entity, pc);
220 
221  return true;
222 }
223 
226  ccHObject* ent = m_toFilter.first;
227  ccPointCloud* pc = m_toFilter.second;
228  if (!ent || !pc) {
229  return;
230  }
231 
232  std::vector<ScalarType> selectedLabels;
233  getSelectedFilterClasses(selectedLabels);
234  if (selectedLabels.empty()) {
236  "[ecvFilterByLabelDlg::apply] no filter labels selected, "
237  "please select some and try again!");
238  return;
239  }
240 
241  // we set as output (OUT) the currently displayed scalar field
242  int outSfIdx = pc->getCurrentDisplayedScalarFieldIndex();
243  assert(outSfIdx >= 0);
244  pc->setCurrentOutScalarField(outSfIdx);
245 
246  ccHObject* resultInside = nullptr;
247  ccHObject* resultOutside = nullptr;
248  ccHObject::Container results;
249  if (ent->isKindOf(CV_TYPES::MESH)) {
250  pc->hidePointsByScalarValue(selectedLabels);
251 
254  if (ent->isA(
255  CV_TYPES::
256  MESH) /*|| ent->isKindOf(CV_TYPES::PRIMITIVE)*/) // TODO
257  resultInside = ccHObjectCaster::ToMesh(ent)
259  else if (ent->isA(CV_TYPES::SUB_MESH))
260  resultInside = ccHObjectCaster::ToSubMesh(ent)
262  }
263 
266  pc->invertVisibilityArray();
267  if (ent->isA(
268  CV_TYPES::
269  MESH) /*|| ent->isKindOf(CV_TYPES::PRIMITIVE)*/) // TODO
270  resultOutside = ccHObjectCaster::ToMesh(ent)
272  else if (ent->isA(CV_TYPES::SUB_MESH))
273  resultOutside = ccHObjectCaster::ToSubMesh(ent)
275  }
276 
278  } else if (ent->isKindOf(CV_TYPES::POINT_CLOUD)) {
281  // shortcut, as we know here that the point cloud is a
282  // "ccPointCloud"
283  resultInside = pc->filterPointsByScalarValue(selectedLabels, false);
284  }
285 
288  resultOutside = pc->filterPointsByScalarValue(selectedLabels, true);
289  }
290  }
291 
292  if (resultInside) {
293  ent->setEnabled(false);
294  // resultInside->setDisplay(ent->getDisplay());
295  // resultInside->prepareDisplayForRefresh();
296  MainWindow::TheInstance()->addToDB(resultInside);
297 
298  results.push_back(resultInside);
299  }
300  if (resultOutside) {
301  ent->setEnabled(false);
302  // resultOutside->setDisplay(ent->getDisplay());
303  // resultOutside->prepareDisplayForRefresh();
304  resultOutside->setName(resultOutside->getName() + ".outside");
305  MainWindow::TheInstance()->addToDB(resultOutside);
306 
307  results.push_back(resultOutside);
308  }
309 
310  if (!results.empty()) {
312  tr("Previously selected entities (sources) have been hidden!"));
313  if (MainWindow::TheInstance()->db()) {
315  }
316  }
317 
318  stop(true);
319  clear();
320  return;
321 }
322 
324  if (gridLayout && !gridLayout->isEmpty()) {
325  QLayoutItem* item;
326  while ((item = layout->takeAt(0)) != 0) {
327  // delete widget
328  if (item->widget()) {
329  delete item->widget();
330  // item->widget()->deleteLater();
331  }
332  // delete layout
333  QLayout* childLayout = item->layout();
334  if (childLayout) {
335  clearLayoutWidgets(childLayout);
336  }
337  delete item;
338  }
339  }
340 }
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
Definition: CVLog.cpp:133
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Definition: CVLog.cpp:143
static std::string FromQString(const QString &qs)
Definition: CVTools.cpp:100
static MainWindow * TheInstance()
Returns the unique instance of this object.
ccDBRoot * db()
Returns real 'dbRoot' object.
Definition: MainWindow.h:193
void addToDB(const QStringList &filenames, QString fileFilter=QString(), bool displayDialog=true)
void selectEntities(std::unordered_set< int > entIDs)
Selects multiple entities at once (shortcut to the other version)
Definition: ecvDBRoot.cpp:1109
A 3D cloud interface with associated features (color, normals, octree, etc.)
virtual void invertVisibilityArray()
Inverts the visibility array.
virtual void unallocateVisibilityArray()
Erases the points visibility information.
static ccMesh * ToMesh(ccHObject *obj)
Converts current object to ccMesh (if possible)
static ccGenericPointCloud * ToGenericPointCloud(ccHObject *obj, bool *isLockedVertices=nullptr)
Converts current object to 'equivalent' ccGenericPointCloud.
static ccSubMesh * ToSubMesh(ccHObject *obj)
Converts current object to ccSubMesh (if possible)
Hierarchical CLOUDVIEWER Object.
Definition: ecvHObject.h:25
std::vector< ccHObject * > Container
Standard instances container (for children, etc.)
Definition: ecvHObject.h:337
ccMesh * createNewMeshFromSelection(bool removeSelectedTriangles, std::vector< int > *newIndexesOfRemainingTriangles=nullptr, bool withChildEntities=false)
Creates a new mesh with the selected vertices only.
virtual QString getName() const
Returns object name.
Definition: ecvObject.h:72
bool isA(CV_CLASS_ENUM type) const
Definition: ecvObject.h:131
virtual void setName(const QString &name)
Sets object name.
Definition: ecvObject.h:75
virtual void setEnabled(bool state)
Sets the "enabled" property.
Definition: ecvObject.h:102
bool isKindOf(CV_CLASS_ENUM type) const
Definition: ecvObject.h:128
Generic overlay dialog interface.
virtual void stop(bool accepted)
Stops process/dialog.
virtual bool start()
Starts process.
virtual bool linkWith(QWidget *win)
Links the overlay dialog with a MDI window.
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void hidePointsByScalarValue(ScalarType minVal, ScalarType maxVal)
Hides points whose scalar values falls into an interval.
int getCurrentDisplayedScalarFieldIndex() const
Returns the currently displayed scalar field index (or -1 if none)
ccScalarField * getCurrentDisplayedScalarField() const
Returns the currently displayed scalar (or 0 if none)
ccPointCloud * filterPointsByScalarValue(ScalarType minVal, ScalarType maxVal, bool outside=false)
Filters out points whose scalar values falls into an interval.
ScalarType stop() const
ScalarType start() const
A scalar field associated to display-related parameters.
const Range & displayRange() const
Access to the range of displayed values.
ccSubMesh * createNewSubMeshFromSelection(bool removeSelectedTriangles, const std::vector< int > &selectedTriangleIndexes, IndexMap *newRemainingTriangleIndexes=nullptr)
Creates a new sub mesh with the visible vertices only.
void setCurrentOutScalarField(int index)
Sets the OUTPUT scalar field.
unsigned size() const override
Definition: PointCloudTpl.h:38
A simple scalar field (to be associated to a point cloud)
Definition: ScalarField.h:25
ScalarType & getValue(std::size_t index)
Definition: ScalarField.h:92
unsigned currentSize() const
Definition: ScalarField.h:100
RGB color structure.
Definition: ecvColorTypes.h:49
static QWidget * GetCurrentScreen()
bool setInputEntity(ccHObject *entity)
Adds an entity to the 'selected' entities set.
virtual bool start() override
Starts process.
EntityAndVerticesType m_toFilter
void clearLayoutWidgets(QLayout *layout)
std::pair< ccHObject *, ccPointCloud * > EntityAndVerticesType
ecvFilterByLabelDlg(QWidget *parent=nullptr)
Default constructor.
virtual void stop(bool state) override
Stops process/dialog.
virtual bool linkWith(QWidget *win) override
Links the overlay dialog with a MDI window.
void getSelectedFilterClasses(std::vector< ScalarType > &filteredClasses)
std::vector< size_t > m_labels
cloudViewer object type flags
Definition: CVTypes.h:100
@ MESH
Definition: CVTypes.h:105
@ POINT_CLOUD
Definition: CVTypes.h:104
@ SUB_MESH
Definition: CVTypes.h:106
static std::map< size_t, std::string > SemanticMap
Definition: ClassMap.h:15
static int FindindexByValue(const std::string &value)
Definition: ClassMap.h:36
Rgb at(size_t color_id)