ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ecvAnnotationsTool.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 "ecvAnnotationsTool.h"
9 
10 // LOCAL
11 #include "MainWindow.h"
12 #include "ecvEntityAction.h"
13 #include "ecvFileUtils.h"
14 #include "ecvPersistentSettings.h"
15 #include "ecvSettingManager.h"
16 
17 // ECV_CORE_LIB
18 #include <CVConst.h>
19 #include <CVLog.h>
20 #include <CVTools.h>
21 
22 // CV_DB_LIB
24 #include <ecvPointCloud.h>
25 #include <ecvPolyline.h>
26 #include <ecvProgressDialog.h>
27 
28 // QT
29 #include <QMessageBox>
30 
32  : ccOverlayDialog(parent),
33  Ui::AnnotationsDlg(),
34  m_entityContainer("entities"),
35  m_editMode(false) {
36  setupUi(this);
37  m_disabledCombEvent = false;
38 
39  connect(importClassSetsButton, &QToolButton::clicked, this,
41  connect(saveButton, &QToolButton::clicked, this,
43  connect(resetButton, &QToolButton::clicked, this,
45  connect(closeButton, &QToolButton::clicked, this,
47  connect(exportCloudWithAnnotations, &QToolButton::clicked, this,
49 
50  connect(editToolButton, &QToolButton::toggled, this,
52 
53  connect(pauseToolButton, &QToolButton::toggled, this,
55  connect(showBoxToolButton, &QToolButton::toggled, this,
57  connect(showOriginToolButton, &QToolButton::toggled, this,
59 
60  connect(minusXShiftToolButton, &QToolButton::clicked, this,
62  connect(plusXShiftToolButton, &QToolButton::clicked, this,
64  connect(minusYShiftToolButton, &QToolButton::clicked, this,
66  connect(plusYShiftToolButton, &QToolButton::clicked, this,
68  connect(minusZShiftToolButton, &QToolButton::clicked, this,
70  connect(plusZShiftToolButton, &QToolButton::clicked, this,
72 
73  viewButtonsFrame->setEnabled(true);
74  connect(viewUpToolButton, &QToolButton::clicked, this,
76  connect(viewDownToolButton, &QToolButton::clicked, this,
78  connect(viewFrontToolButton, &QToolButton::clicked, this,
80  connect(viewBackToolButton, &QToolButton::clicked, this,
82  connect(viewLeftToolButton, &QToolButton::clicked, this,
84  connect(viewRightToolButton, &QToolButton::clicked, this,
86 
87  connect(newModeButton, &QToolButton::clicked, this,
89  connect(unionModeButton, &QToolButton::clicked, this,
91  connect(trimModeButton, &QToolButton::clicked, this,
93  connect(intersectModeButton, &QToolButton::clicked, this,
95  connect(labelSelectedButton, &QToolButton::clicked, this,
97  connect(labelsComboBox,
98  static_cast<void (QComboBox::*)(int)>(
99  &QComboBox::currentIndexChanged),
101 
102  // add shortcuts
104  Qt::Key_I); //'I' key for the "intersect selection mode" button
106  Qt::Key_U); //'U' key for the "union selection mode" button
108  Qt::Key_N); //'N' key for the "new selection mode" button
110  Qt::Key_T); //'T' key for the "trim selection mode" button
112  Qt::Key_R); //'R' key for the "reset annotations" button
114  Qt::Key_S); //'S' key for the "save annotation file" button
116  Qt::Key_H); //'H' key for the "show or hide annotation mode" button
117  addOverridenShortcut(Qt::Key_L); //'L' key for the "label selected with
118  // current class sets" button
119  addOverridenShortcut(Qt::Key_Space); // space bar for the "pause" button
120  connect(this, &ccOverlayDialog::shortcutTriggered, this,
122 }
123 
125 
127  ecvGenericAnnotationTool* annotationTool) {
128  if (annotationTool) {
129  m_annotationTool = annotationTool;
132  return true;
133  }
134  return false;
135 }
136 
138  switch (key) {
139  case Qt::Key_H:
140  showBoxToolButton->toggle();
141  return;
142 
143  case Qt::Key_Space:
144  pauseToolButton->toggle();
145  return;
146 
147  case Qt::Key_L:
148  labelSelectedButton->click();
149  return;
150 
151  case Qt::Key_R:
152  resetButton->click();
153  return;
154 
155  case Qt::Key_S:
156  saveButton->click();
157  return;
158 
159  case Qt::Key_I:
160  intersectModeButton->click();
161  return;
162 
163  case Qt::Key_U:
164  unionModeButton->click();
165  return;
166 
167  case Qt::Key_N:
168  newModeButton->click();
169  return;
170  case Qt::Key_T:
171  trimModeButton->click();
172  return;
173 
174  default:
175  // nothing to do
176  break;
177  }
178 }
179 
181  if (m_annotationTool) {
183  }
184 }
185 
187  if (m_annotationTool) {
189  }
190 }
191 
193  if (m_annotationTool) {
195  }
196 }
197 
199  if (m_annotationTool) {
201  }
202 }
203 
205 
207  Q_UNUSED(index);
208  int curIndex = labelsComboBox->currentIndex();
209  if (curIndex < 0 || m_disabledCombEvent) {
210  return;
211  }
212 
213  QColor backColor;
214  if (curIndex == 0) {
215  backColor = QColor(Qt::white);
216  } else {
217  ecvColor::Rgb col =
218  ecvColor::LookUpTable::at(static_cast<size_t>(curIndex));
219  backColor = QColor(col.r, col.g, col.b);
220  }
221 
222  QPalette pal = labelsComboBox->palette();
223  pal.setColor(QPalette::Base, backColor);
224  labelsComboBox->setPalette(pal);
225 
226  QString text = labelsComboBox->currentText();
227  labelsComboBox->clearFocus();
228 
229  if (m_annotationTool) {
230  if (m_editMode) {
231  editToolButton->toggle();
232  m_annotationTool->selectExistedAnnotation(text.toStdString());
233  } else {
234  m_annotationTool->changeAnnotationType(text.toStdString());
235  }
236  }
237 }
238 
239 void ecvAnnotationsTool::onItemPicked(bool isPicked) { Q_UNUSED(isPicked); }
240 
242  Q_UNUSED(state);
243  if (m_annotationTool) {
245  }
246 }
247 
249  if (m_annotationTool) {
251  }
252 }
253 
255  if (m_annotationTool) {
256  // default output path (+ filename)
257  QString currentPath = ecvSettingManager::getValue(
260  .toString();
261  QString filters = "*.classes";
262  QString selectedFilter = filters;
263  QString selectedFilename = QFileDialog::getOpenFileName(
264  this, tr("import class sets"), currentPath, filters,
265  &selectedFilter);
266 
267  if (selectedFilename.isEmpty()) {
268  // process cancelled by the user
269  return;
270  }
271 
272  // we update current file path
273  currentPath = QFileInfo(selectedFilename).absolutePath();
275  currentPath);
277  CVTools::FromQString(selectedFilename))) {
278  return;
279  }
280 
281  std::vector<std::string> labels;
283  updateLabelsCombox(labels);
284  }
285 }
286 
288  if (!m_annotationTool) {
290  "[ecvAnnotationsTool::toggleBox] Annotations tool has not been "
291  "initialized!");
292  return;
293  }
294 
295  if (state) {
297  } else {
299  }
301 }
302 
304  if (!m_annotationTool) {
306  "[ecvAnnotationsTool::toggleBox] Annotations tool has not been "
307  "initialized!");
308  return;
309  }
310 
311  if (showOriginToolButton->isChecked()) {
313  } else {
315  }
317 }
318 
321 }
322 
324  if (!entity) {
325  assert(false);
326  return false;
327  }
328 
329  if (!m_annotationTool) {
330  CVLog::Error(
331  QString("[ecvAnnotationsTool::addAssociatedEntity] No "
332  "associated annotation Tool!"));
333  return false;
334  }
335 
336  if (entity->isKindOf(CV_TYPES::POINT_CLOUD)) {
338  classSetsGroupBox->setEnabled(true);
339  }
340 
341  if (entity->getBB_recursive().isValid()) {
342  reset();
343  }
344 
345  // force visibility
346  entity->setVisible(true);
347  entity->setEnabled(true);
348  return true;
349 }
350 
353 }
354 
355 void ecvAnnotationsTool::toggleEditMode(bool state) { m_editMode = state; }
356 
357 bool ecvAnnotationsTool::linkWith(QWidget* win) {
358  if (!ccOverlayDialog::linkWith(win)) {
359  return false;
360  }
361 
362  return true;
363 }
364 
366  assert(!m_processing);
367  if (!m_annotationTool) return false;
368 
369  ccPointCloud* cloud =
371  bool suceess = cloud && m_annotationTool->setInputCloud(cloud);
372  if (!suceess) {
373  CVLog::Error("no point cloud can be processed!");
374  return false;
375  }
376 
377  std::vector<std::string> labels;
379  updateLabelsCombox(labels);
380  if (pauseToolButton->isChecked()) {
381  pauseToolButton->setChecked(false);
382  }
383 
384  if (showOriginToolButton->isChecked()) {
385  showOriginToolButton->setChecked(false);
386  }
387 
388  // custom settings according to different annotation mode
389  switch (m_annotationTool->getAnnotationMode()) {
391  exportCloudWithAnnotations->setEnabled(false);
392  break;
394  exportCloudWithAnnotations->setEnabled(true);
395  break;
396  default:
397  break;
398  }
399 
401  return ccOverlayDialog::start();
402 }
403 
404 void ecvAnnotationsTool::stop(bool state) {
405  if (m_annotationTool) {
406  if (!pauseToolButton->isChecked()) {
407  pauseToolButton->setChecked(true);
408  }
409 
410  if (!showOriginToolButton->isChecked()) {
411  showOriginToolButton->setChecked(true);
412  }
413 
415  delete m_annotationTool;
416  m_annotationTool = nullptr;
417  }
419  ccOverlayDialog::stop(state);
420 }
421 
423  const std::vector<std::string>& labels) {
424  if (labels.empty()) return;
425 
426  // just for avoid dummy triggering event
427  m_disabledCombEvent = true;
428  labelsComboBox->clear();
429  for (size_t i = 0; i < labels.size(); ++i) {
430  QString name = CVTools::ToQString(labels[i]);
431  labelsComboBox->addItem(name);
432  if (i == 0) {
433  continue;
434  }
436  QColor backColor(col.r, col.g, col.b);
437  labelsComboBox->setItemData(static_cast<int>(i), backColor,
438  Qt::BackgroundRole);
439  }
440 
441  QPalette pal = labelsComboBox->palette();
442  pal.setColor(QPalette::Base, QColor(Qt::white));
443  labelsComboBox->setPalette(pal);
444  m_disabledCombEvent = false;
445 }
446 
447 void ecvAnnotationsTool::shiftBox(unsigned char dim, bool minus) {
448  Q_UNUSED(dim);
449  Q_UNUSED(minus);
450 }
451 
453  m_box.clear();
456  }
457  if (m_annotationTool) {
459  }
460 }
461 
463  if (QMessageBox::question(this, tr("Quit"),
464  tr("Are you sure you want to quit Annotation?"),
465  QMessageBox::Ok,
466  QMessageBox::Cancel) == QMessageBox::Ok) {
467  stop(true);
468  }
469 }
470 
472  if (m_annotationTool) {
473  std::vector<int> annotations;
474  if (!m_annotationTool->getCurrentAnnotations(annotations)) {
476  "[ecvAnnotationsTool::exportAnnotationToSF] Export "
477  "Annotation To SF failed!");
478  return;
479  }
480  std::vector<std::vector<int>> annosVector;
481  annosVector.push_back(annotations);
482  std::vector<std::vector<ScalarType>> scalarsVector;
483  ccEntityAction::ConvertToScalarType<int>(annosVector, scalarsVector);
484 
485  ccHObject::Container container;
486  container.push_back(m_entityContainer.getFirstChild());
487  if (!ccEntityAction::importToSF(container, scalarsVector, "Clusters")) {
488  CVLog::Error(
489  "[ecvAnnotationsTool::exportAnnotationToSF] Import sf "
490  "failed!");
491  } else {
493  CVLog::Print(
494  "[ecvAnnotationsTool::exportAnnotationToSF] "
495  "Export annotations to sf successfully, please change the "
496  "colors mode to scalar filed!");
497  }
498  }
499 }
500 
502 
504 
506 
508 
510 
512 
514  ccBBox box;
515  if (getNumberOfAssociatedEntity() != 0) {
517  }
518  return box;
519 }
520 
522  // ccBBox* bbox = nullptr;
523  // ccBBox box = getSelectedEntityBbox();
524  // if (box.isValid()) {
525  // bbox = &box;
526  // }
527  ecvDisplayTools::SetView(orientation);
528 }
CC_VIEW_ORIENTATION
View orientation.
Definition: CVConst.h:102
@ CC_FRONT_VIEW
Definition: CVConst.h:105
@ CC_TOP_VIEW
Definition: CVConst.h:103
@ CC_RIGHT_VIEW
Definition: CVConst.h:108
@ CC_BOTTOM_VIEW
Definition: CVConst.h:104
@ CC_BACK_VIEW
Definition: CVConst.h:106
@ CC_LEFT_VIEW
Definition: CVConst.h:107
std::string name
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
Definition: CVLog.cpp:133
static bool Print(const char *format,...)
Prints out a formatted message in console.
Definition: CVLog.cpp:113
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 QString ToQString(const std::string &s)
Definition: CVTools.cpp:92
Bounding box structure.
Definition: ecvBBox.h:25
virtual void setVisible(bool state)
Sets entity visibility.
virtual void showSF(bool state)
Sets active scalarfield visibility.
static ccPointCloud * ToPointCloud(ccHObject *obj, bool *isLockedVertices=nullptr)
Converts current object to 'equivalent' ccPointCloud.
Hierarchical CLOUDVIEWER Object.
Definition: ecvHObject.h:25
void removeAllChildren()
Removes all children.
virtual ccBBox getDisplayBB_recursive(bool relative)
Returns the bounding-box of this entity and it's children WHEN DISPLAYED.
ccHObject * getFirstChild() const
Shortcut: returns first child.
Definition: ecvHObject.h:396
unsigned getChildrenNumber() const
Returns the number of children.
Definition: ecvHObject.h:312
virtual bool addChild(ccHObject *child, int dependencyFlags=DP_PARENT_OF_OTHER, int insertIndex=-1)
Adds a child.
virtual ccBBox getBB_recursive(bool withGLFeatures=false, bool onlyEnabledChildren=true)
Returns the bounding-box of this entity and it's children.
std::vector< ccHObject * > Container
Standard instances container (for children, etc.)
Definition: ecvHObject.h:337
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.
void shortcutTriggered(int key)
Signal emitted when an overridden key shortcut is pressed.
virtual void stop(bool accepted)
Stops process/dialog.
virtual bool start()
Starts process.
bool m_processing
Running/processing state.
virtual bool linkWith(QWidget *win)
Links the overlay dialog with a MDI window.
void addOverridenShortcut(Qt::Key key)
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void clear()
Resets the bounding box.
Definition: BoundingBox.h:125
bool isValid() const
Returns whether bounding box is valid or not.
Definition: BoundingBox.h:203
ecvGenericAnnotationTool * m_annotationTool
Annotation tool.
bool addAssociatedEntity(ccHObject *anObject)
Adds an entity.
void toggleOrigin(bool dummy)
virtual void stop(bool state) override
Stops process/dialog.
virtual bool linkWith(QWidget *win) override
Links the overlay dialog with a MDI window.
ecvAnnotationsTool(QWidget *parent)
Default constructor.
void toggleInteractors(bool state)
void onLabelChanged(int index)
bool m_disabledCombEvent
for solving dummy event trigger
virtual bool start() override
Starts process.
void updateLabelsCombox(const std::vector< std::string > &labels)
virtual ~ecvAnnotationsTool() override
Default destructor.
void onShortcutTriggered(int)
To capture overridden shortcuts (pause button, etc.)
ccHObject m_entityContainer
Associated entities container.
void shiftBox(unsigned char dim, bool minus)
Shift box.
void setView(CC_VIEW_ORIENTATION orientation)
Sets predefined view.
void onItemPicked(bool isPicked)
unsigned getNumberOfAssociatedEntity() const
Returns the current number of associated entities.
void toggleEditMode(bool state)
ccBBox m_box
bounding box
bool setAnnotationsTool(ecvGenericAnnotationTool *annotationTool)
RGB color structure.
Definition: ecvColorTypes.h:49
static void SetView(CC_VIEW_ORIENTATION orientation, ccBBox *bbox)
static void UpdateScreen()
Generic Annotation Tool interface.
virtual void hideAnnotation()=0
virtual void selectExistedAnnotation(const std::string &type)=0
virtual bool getCurrentAnnotations(std::vector< int > &annos) const =0
virtual void reset()=0
virtual void stop()=0
virtual void hideOrigin()=0
virtual bool setInputCloud(ccPointCloud *pointCloud, int viewport=0)=0
virtual void intersectMode()=0
void objectPicked(bool isPicked)
virtual void resetMode()=0
virtual void getAnnotationLabels(std::vector< std::string > &labelList)=0
virtual bool loadClassesFromFile(const std::string &file)=0
virtual void changeAnnotationType(const std::string &type)=0
virtual void start()=0
virtual void toggleInteractor()=0
virtual void unionMode()=0
virtual void showOrigin()=0
virtual void showAnnotation()=0
virtual void trimMode()=0
virtual void exportAnnotations()=0
static const QString CurrentPath()
static const QString LoadFile()
static QVariant getValue(const QString &section, const QString &key, const QVariant &defaultValue=QVariant())
static void setValue(const QString &section, const QString &key, const QVariant &value)
@ POINT_CLOUD
Definition: CVTypes.h:104
bool importToSF(const ccHObject::Container &selectedEntities, const std::vector< std::vector< ScalarType >> &scalarsVector, const std::string &name)
Rgb at(size_t color_id)
constexpr Rgb white(MAX, MAX, MAX)
QString defaultDocPath()
Shortcut for getting the documents location path.
Definition: ecvFileUtils.h:30