ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ecvPropertiesTreeDelegate.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 // Local
11 #include "../MainWindow.h"
12 #include "CommonSettings.h"
13 #include "ecvAxesGridDialog.h"
14 #include "ecvColorScaleEditorDlg.h"
15 #include "ecvColorScaleSelector.h"
16 #include "ecvFileUtils.h"
17 #include "ecvOptions.h"
18 #include "ecvPersistentSettings.h"
19 #include "ecvSettingManager.h"
20 #include "ecvTextureFileSelector.h"
21 #include "matrixDisplayDlg.h"
22 #include "sfEditDlg.h"
23 
24 // Note: PCL Selection Tools includes removed. Selection properties are now
25 // handled by cvFindDataDockWidget in a standalone dock, not integrated into
26 // the properties tree delegate.
27 
28 // CV_DB_LIB
29 #include <ecv2DLabel.h>
30 #include <ecv2DViewportLabel.h>
31 #include <ecv2DViewportObject.h>
32 #include <ecvAdvancedTypes.h>
33 #include <ecvCameraSensor.h>
34 #include <ecvCircle.h>
35 #include <ecvColorScalesManager.h>
36 #include <ecvCone.h>
37 #include <ecvCoordinateSystem.h>
38 #include <ecvDisc.h>
39 #include <ecvDisplayTools.h>
40 #include <ecvDrawContext.h>
41 #include <ecvFacet.h>
42 #include <ecvGBLSensor.h>
43 #include <ecvGenericPrimitive.h>
44 #include <ecvGuiParameters.h>
45 #include <ecvHObject.h>
46 #include <ecvHObjectCaster.h>
47 #include <ecvImage.h>
49 #include <ecvKdTree.h>
50 #include <ecvMaterialSet.h>
51 #include <ecvMesh.h>
52 #include <ecvOctree.h>
53 #include <ecvOctreeProxy.h>
54 #include <ecvPlane.h>
55 #include <ecvPointCloud.h>
56 #include <ecvPolyline.h>
57 #include <ecvScalarField.h>
58 #include <ecvSensor.h>
59 #include <ecvSphere.h>
60 #include <ecvSubMesh.h>
61 
62 // Qt
63 #include <QAbstractItemView>
64 #include <QCheckBox>
65 #include <QComboBox>
66 #include <QFileInfo>
67 #include <QHBoxLayout>
68 #include <QHeaderView>
69 #include <QImageReader>
70 #include <QLineEdit>
71 #include <QLocale>
72 #include <QPushButton>
73 #include <QScrollBar>
74 #include <QSet>
75 #include <QSlider>
76 #include <QSpinBox>
77 #include <QStandardItemModel>
78 #include <QToolButton>
79 #include <QTreeView>
80 
81 // STL
82 #include <algorithm>
83 #include <exception>
84 #include <functional>
85 
86 // System
87 #include <assert.h>
88 
89 #include <cmath>
90 
91 // Default 'None' string
92 const char* ccPropertiesTreeDelegate::s_noneString = QT_TR_NOOP("None");
93 
94 // Default color sources string
95 const char* ccPropertiesTreeDelegate::s_rgbColor = "RGB";
96 const char* ccPropertiesTreeDelegate::s_sfColor = QT_TR_NOOP("Scalar field");
97 
98 // Other strings
99 const char* ccPropertiesTreeDelegate::s_defaultPointSizeString =
100  QT_TR_NOOP("Default");
101 const char* ccPropertiesTreeDelegate::s_defaultPolyWidthSizeString =
102  QT_TR_NOOP("Default Width");
103 
104 // Default separator colors
105 constexpr const char* SEPARATOR_STYLESHEET(
106  "QLabel { background-color : darkGray; color : white; }");
107 
108 // Shortcut to create a delegate item
109 QStandardItem* ITEM(QString name,
110  Qt::ItemFlag additionalFlags = Qt::NoItemFlags,
113  QStandardItem* item = new QStandardItem(name);
114  // flags
115  item->setFlags(Qt::ItemIsEnabled | additionalFlags);
116  // role (if any)
118  item->setData(role);
119 
120  return item;
121 }
122 
123 // Shortcut to create a checkable delegate item
124 QStandardItem* CHECKABLE_ITEM(bool checkState,
126  QStandardItem* item = ITEM("", Qt::ItemIsUserCheckable, role);
127  // check state
128  item->setCheckState(checkState ? Qt::Checked : Qt::Unchecked);
129 
130  return item;
131 }
132 
133 // Shortcut to create a persistent editor item
134 QStandardItem* PERSISTENT_EDITOR(
136  return ITEM(QString(), Qt::ItemIsEditable, role);
137 }
138 
140  QAbstractItemView* view,
141  QObject* parent)
142  : QStyledItemDelegate(parent),
143  m_currentObject(nullptr),
144  m_model(model),
145  m_view(view),
146  m_viewer(nullptr),
147  m_lastFocusItemRole(OBJECT_NO_PROPERTY) {
148  // Note: Selection properties are now handled by cvFindDataDockWidget,
149  // a standalone dock widget that is decoupled from the properties tree.
150  assert(m_model && m_view);
151 }
152 
154 
155 QSize ccPropertiesTreeDelegate::sizeHint(const QStyleOptionViewItem& option,
156  const QModelIndex& index) const {
157  assert(m_model);
158 
159  QStandardItem* item = m_model->itemFromIndex(index);
160 
161  if (item && item->data().isValid()) {
162  switch (item->data().toInt()) {
165  case OBJECT_OCTREE_TYPE:
168  case OBJECT_OPACITY:
169  return QSize(50, 24);
170  case OBJECT_COLOR_SOURCE:
174  return QSize(70, 24);
176  return QSize(250, 200);
180  return QSize(250, 140);
181  // Note: OBJECT_SELECTION_PROPERTIES case removed - selection
182  // properties are now in standalone cvFindDataDockWidget
183  }
184  }
185 
186  return QStyledItemDelegate::sizeHint(option, index);
187 }
188 
190  if (m_model) m_model->disconnect(this);
191  // Clear texture path maps when unbinding
192  // This ensures we don't keep stale references to removed objects
193  m_meshTexturePathMaps.clear();
194 }
195 
197  return m_currentObject;
198 }
199 
201  if (!hObject) {
202  CVLog::Print(
203  "[ccPropertiesTreeDelegate::fillModel] Called with nullptr, "
204  "clearing");
205  unbind();
206  if (m_model) {
207  m_model->removeRows(0, m_model->rowCount());
208  }
209  m_currentObject = nullptr;
210  return;
211  }
212 
213  unbind();
214 
215  m_currentObject = hObject;
216 
217  // save current scroll position
218  int scrollPos = (m_view && m_view->verticalScrollBar()
219  ? m_view->verticalScrollBar()->value()
220  : 0);
221 
222  if (m_model) {
223  m_model->removeRows(0, m_model->rowCount());
224  m_model->setColumnCount(2);
225  m_model->setHeaderData(0, Qt::Horizontal, tr("Property"));
226  m_model->setHeaderData(1, Qt::Horizontal, tr("State/Value"));
227  }
228 
229  // Ensure header is visible when displaying normal properties
230  // (it may have been hidden when showing only selection properties)
231  if (m_view) {
232  QTreeView* treeView = qobject_cast<QTreeView*>(m_view);
233  if (treeView && treeView->header()) {
234  treeView->header()->show();
235  }
236  }
237 
238  // Note: Selection properties are no longer shown in the properties tree.
239  // They are now displayed in the standalone cvFindDataDockWidget.
240 
242  if (!m_currentObject->isA(
243  CV_TYPES::VIEWPORT_2D_LABEL)) // don't need to display this
244  // kind of info for viewport
245  // labels!
247 
248  // View properties (ParaView-style) - added right after ECV Object section
249  if (m_currentObject->getViewId().length() > 0) {
251  }
252 
259  } else if (m_currentObject->isKindOf(CV_TYPES::MESH)) {
261 
264  }
265  } else if (m_currentObject->isA(CV_TYPES::FACET)) {
267  } else if (m_currentObject->isA(CV_TYPES::POLY_LINE)) {
275  } else if (m_currentObject->isA(CV_TYPES::LABEL_2D)) {
297  }
298 
299  // transformation history
305  addSeparator(tr("Transformation history"));
307 
309  addSeparator(tr("Display transformation"));
311  }
312  }
313 
314  // meta-data
316 
317  // go back to original position
318  if (scrollPos > 0)
319  m_view->verticalScrollBar()->setSliderPosition(scrollPos);
320 
321  if (m_model) {
322  connect(m_model, &QStandardItemModel::itemChanged, this,
323  &ccPropertiesTreeDelegate::updateItem);
324  }
325 }
326 
327 void ccPropertiesTreeDelegate::appendRow(QStandardItem* leftItem,
328  QStandardItem* rightItem,
329  bool openPersistentEditor /*=false*/) {
330  assert(leftItem && rightItem);
331  assert(m_model);
332 
333  if (m_model) {
334  // append row
335  QList<QStandardItem*> rowItems;
336  {
337  rowItems.push_back(leftItem);
338  rowItems.push_back(rightItem);
339  }
340  m_model->appendRow(rowItems);
341 
342  // the persistent editor (if any) is always the right one!
343  if (openPersistentEditor)
344  m_view->openPersistentEditor(
345  m_model->index(m_model->rowCount() - 1, 1));
346  }
347 }
348 
350  QStandardItem* item, bool openPersistentEditor /*=true*/) {
351  assert(item);
352  assert(m_model);
353 
354  if (m_model) {
355  m_model->appendRow(item);
356  if (openPersistentEditor && m_view) {
357  QModelIndex index = m_model->index(m_model->rowCount() - 1, 0);
358  if (index.isValid()) {
359  m_view->openPersistentEditor(index);
360  } else {
362  "[ccPropertiesTreeDelegate] Invalid index for "
363  "persistent editor");
364  }
365  }
366  }
367 }
368 
370  if (m_model) {
371  // DGM: we can't use the 'text' of the item as it will be displayed
372  // under the associated editor (label)! So we simply use the 'accessible
373  // description' field
374  QStandardItem* leftItem = new QStandardItem(/*title*/);
375  leftItem->setData(TREE_VIEW_HEADER);
376  leftItem->setAccessibleDescription(title);
377  m_model->appendRow(leftItem);
378  m_view->openPersistentEditor(
379  m_model->index(m_model->rowCount() - 1, 0));
380  }
381 }
382 
384  assert(_obj && m_model);
385 
386  const QVariantMap& metaData = _obj->metaData();
387  if (metaData.size() == 0) return;
388 
389  addSeparator(tr("Meta data"));
390 
391  for (QVariantMap::ConstIterator it = metaData.constBegin();
392  it != metaData.constEnd(); ++it) {
393  QVariant var = it.value();
394  QString value;
395 
396  if (var.canConvert(QVariant::String)) {
397  var.convert(QVariant::String);
398  value = var.toString();
399  } else {
400  value = QString(QVariant::typeToName(static_cast<int>(var.type())));
401  }
402 
403  appendRow(ITEM(it.key()), ITEM(value));
404  }
405 }
406 
408  assert(m_model);
409 
410  // ParaView-style view properties section
411  addSeparator(tr("View (Render View)"));
412 
413  // 1. Light Intensity - ParaView-style direct control (no checkbox)
414  // ParaView uses LightIntensity property (0.0-2.0 range)
415  appendRow(ITEM(tr("Light Intensity")),
417 
418  // 2. Opacity - moved from ECV Object section (ParaView has this in View
419  // properties) Show for renderable objects and folders (to control all
420  // children)
421  if (m_currentObject) {
422  bool isRenderable = (m_currentObject->isKindOf(CV_TYPES::POINT_CLOUD) ||
427  bool isFolder = (m_currentObject->getChildrenNumber() > 0);
428 
429  if (isRenderable || isFolder) {
431  true);
432  }
433  }
434 
435  // 3. Data Axes Grid - ParaView-style: checkbox with integrated Edit button
436  // This shows the coordinate axes for the data bounds of the current object
437  // CRITICAL: Only show axes grid for objects that have valid 3D bounding
438  // boxes Objects without valid bbox: 2D labels, viewport objects, arrays,
439  // material sets
440  if (m_currentObject) {
441  // Check if object has a valid 3D bounding box
442  bool hasValidBBox = false;
443 
444  // First, check object types that definitely don't have 3D bbox
445  bool is2DObject = (m_currentObject->isA(CV_TYPES::LABEL_2D) ||
448  bool isImage = m_currentObject->isKindOf(CV_TYPES::IMAGE);
449  bool isPolyline = m_currentObject->isKindOf(CV_TYPES::POLY_LINE);
454  bool isMaterialSet = m_currentObject->isA(CV_TYPES::MATERIAL_SET);
455 
456  if (!is2DObject && !isImage && !isArray && !isMaterialSet) {
457  // For other objects, check if they have a valid recursive bounding
458  // box
460  hasValidBBox = bbox.isValid();
461  }
462 
463  if (isPolyline) {
465  if (polyline) {
466  if (polyline->size() <= 1 || polyline->is2DMode()) {
467  hasValidBBox = false;
468  }
469  } else {
470  hasValidBBox = false;
471  }
472  }
473 
474  if (hasValidBBox) {
475  // Get current visibility from backend
476  QString viewID = m_currentObject->getViewId();
477  AxesGridProperties props;
479  props);
480 
481  // ParaView-style: Checkbox and Edit button in same row (like
482  // Opacity's slider+spinbox) We create a custom editor that combines
483  // checkbox + button using PERSISTENT_EDITOR
484  appendRow(ITEM(tr("Show Axes Grid")),
486  true);
487  }
488  }
489 }
490 
491 // Note: fillWithSelectionProperties, setSelectionToolsActive, and
492 // showSelectionPropertiesOnly have been removed. Selection properties are now
493 // displayed in the standalone cvFindDataDockWidget, which is decoupled from
494 // the properties tree and selection tool state (following ParaView design).
495 
497  if (!m_model) return;
498 
499  unbind();
500  m_model->removeRows(0, m_model->rowCount());
501  m_currentObject = nullptr;
502 }
503 
505  assert(_obj && m_model);
506 
507  addSeparator(tr("ECV Object"));
508 
509  // name
510  appendRow(ITEM(tr("Name")),
511  ITEM(_obj->getName(), Qt::ItemIsEditable, OBJECT_NAME));
512 
513  // visibility
514  if (!_obj->isVisibilityLocked())
515  appendRow(ITEM(tr("Visible")),
517 
518  // normals
519  if (_obj->hasNormals())
520  appendRow(ITEM(tr("Normals")),
522 
523  // name in 3D
524  appendRow(ITEM(tr("Show name (in 3D)")),
526 
527  // color source
528  if (_obj->hasColors() || _obj->hasScalarFields())
530  true);
531 
532  // Bounding-box
533  {
534  ccBBox box;
535  bool fitBBox = false;
537  ccGLMatrix trans;
538  box = _obj->getOwnFitBB(trans);
539  box += trans.getTranslationAsVec3D();
540  fitBBox = true;
541  } else {
542  box = _obj->getBB_recursive();
543  }
544 
545  if (box.isValid()) {
546  // Box dimensions
547  CCVector3 bboxDiag = box.getDiagVec();
548  appendRow(ITEM(fitBBox ? tr("Local box dimensions")
549  : tr("Box dimensions")),
550  ITEM(QString("X: %0\nY: %1\nZ: %2")
551  .arg(bboxDiag.x)
552  .arg(bboxDiag.y)
553  .arg(bboxDiag.z)));
554 
555  // Box center
556  CCVector3 bboxCenter = box.getCenter();
557 
558  ccShiftedObject* shiftedObj = ccHObjectCaster::ToShifted(_obj);
559 
560  // local bounding box center
561  appendRow(ITEM(shiftedObj ? tr("Shifted box center")
562  : tr("Box center")),
563  ITEM(QStringLiteral("X: %0\nY: %1\nZ: %2")
564  .arg(bboxCenter.x)
565  .arg(bboxCenter.y)
566  .arg(bboxCenter.z)));
567 
568  if (shiftedObj) {
569  CCVector3d globalBBoxCenter =
570  shiftedObj->toGlobal3d(bboxCenter);
571 
572  // global bounding box center
573  appendRow(ITEM(tr("Global box center")),
574  ITEM(QStringLiteral("X: %0\nY: %1\nZ: %2")
575  .arg(globalBBoxCenter.x, 0, 'f')
576  .arg(globalBBoxCenter.y, 0, 'f')
577  .arg(globalBBoxCenter.z, 0, 'f')));
578  }
579  }
580  }
581 
582  // infos (unique ID, children) //DGM: on the same line so as to gain space
583  appendRow(ITEM(tr("Info")), ITEM(tr("Object ID: %1 - Children: %2")
584  .arg(_obj->getUniqueID())
585  .arg(_obj->getChildrenNumber())));
586 
587  // Note: Opacity has been moved to View (Render View) section
588  // following ParaView's property panel layout
589 
590  // display window
591  if (!_obj->isLocked())
592  appendRow(ITEM(tr("Current Display")),
594 }
595 
597  assert(_obj && m_model);
598 
599  // global shift & scale
600  const CCVector3d& shift = _obj->getGlobalShift();
601  appendRow(ITEM(tr("Global shift")), ITEM(QString("(%1;%2;%3)")
602  .arg(shift.x, 0, 'f', 2)
603  .arg(shift.y, 0, 'f', 2)
604  .arg(shift.z, 0, 'f', 2)));
605 
606  double scale = _obj->getGlobalScale();
607  appendRow(ITEM(tr("Global scale")),
608  ITEM(QString("%1").arg(scale, 0, 'f', 6)));
609 }
610 
612  const ccCoordinateSystem* _obj) {
613  assert(_obj && m_model);
614  if (!_obj || !m_model) {
615  return;
616  }
617 
618  CCVector3 origin = _obj->getOrigin();
619  addSeparator(tr("Coordinate System"));
620  appendRow(ITEM(tr("Origin")), ITEM(QStringLiteral("X: %0\nY: %1\nZ: %2")
621  .arg(origin.x)
622  .arg(origin.y)
623  .arg(origin.z)));
624  appendRow(ITEM(tr("Planes Visible")),
627  appendRow(
628  ITEM(tr("Planes Stippled")),
629  CHECKABLE_ITEM(static_cast<const ccMesh*>(_obj)->stipplingEnabled(),
631  appendRow(ITEM(tr("Axis Lines Visible")),
634  appendRow(ITEM(tr("Axis width")),
636  appendRow(ITEM(tr("Display scale")),
638 }
639 
641  assert(_obj && m_model);
642 
643  addSeparator(tr("Cloud"));
644 
645  // number of points
646  appendRow(ITEM(tr("Points")),
647  ITEM(QLocale(QLocale::English).toString(_obj->size())));
648 
649  // global shift & scale
650  fillWithShifted(_obj);
651 
652  // custom point size
653  appendRow(ITEM(tr("Point size")),
655 
656  // scalar field
657  fillSFWithPointCloud(_obj);
658 
659  // scan grid structure(s), waveform, etc.
660  if (_obj->isA(CV_TYPES::POINT_CLOUD)) {
661  ccPointCloud* cloud = static_cast<ccPointCloud*>(_obj);
662 
663  // scan grid(s)
664  size_t gridCount = cloud->gridCount();
665  if (gridCount != 0) {
666  if (gridCount != 1)
667  addSeparator(tr("Scan grids"));
668  else
669  addSeparator(tr("Scan grid"));
670 
671  for (size_t i = 0; i < gridCount; ++i) {
672  // grid size + valid point count
673  ccPointCloud::Grid::Shared grid = cloud->grid(i);
674  appendRow(
675  ITEM(tr("Scan #%1").arg(i + 1)),
676  ITEM(tr("%1 x %2 (%3 points)")
677  .arg(grid->w)
678  .arg(grid->h)
679  .arg(QLocale(QLocale::English)
680  .toString(
681  grid->validCount))));
682  }
683  }
684 
685  // waveform
686  if (cloud->hasFWF()) {
687  addSeparator(tr("Waveform"));
688  appendRow(ITEM(tr("Waves")),
689  ITEM(QString::number(
690  cloud->waveforms()
691  .size()))); // DGM: in fact some of them
692  // might be null/invalid!
693  appendRow(ITEM(tr("Descriptors")),
694  ITEM(QString::number(cloud->fwfDescriptors().size())));
695 
696  double dataSize_mb =
697  (cloud->fwfData() ? cloud->fwfData()->size() : 0) /
698  static_cast<double>(1 << 20);
699  appendRow(ITEM(tr("Data size")),
700  ITEM(QString("%1 Mb").arg(dataSize_mb, 0, 'f', 2)));
701  }
702  }
703 }
704 
706  assert(m_model);
707 
708  // for "real" point clouds only
710  if (!cloud) return;
711 
712  // Scalar fields
713  unsigned sfCount = cloud->getNumberOfScalarFields();
714  if (sfCount != 0) {
715  addSeparator(sfCount > 1 ? tr("Scalar Fields") : tr("Scalar Field"));
716 
717  // fields number
718  appendRow(ITEM(tr("Count")), ITEM(QString::number(sfCount)));
719 
720  // fields list combo
721  appendRow(ITEM(tr("Active")),
723 
724  // no need to go any further if no SF is currently active
726  if (sf) {
727  addSeparator(tr("Color Scale"));
728 
729  // color scale selection combo box
730  appendRow(ITEM(tr("Current")),
732 
733  // color scale steps
734  appendRow(ITEM(tr("Steps")),
736 
737  // scale visible?
738  appendRow(ITEM(tr("Visible")),
741 
742  addSeparator(tr("SF display params"));
743 
744  // SF edit dialog (warning: 2 columns)
746  }
747  }
748 }
749 
751  assert(_obj && m_model);
752 
753  addSeparator(tr("Primitive"));
754 
755  // type
756  appendRow(ITEM(tr("Type")), ITEM(_obj->getTypeName()));
757 
758  // drawing steps
759  if (_obj->hasDrawingPrecision()) {
760  appendRow(ITEM(tr("Drawing precision")),
762  }
763 
764  if (_obj->isA(CV_TYPES::SPHERE)) {
766  true);
767  } else if (_obj->isKindOf(CV_TYPES::CONE)) // cylinders are also cones!
768  {
770  true);
771  if (_obj->isA(CV_TYPES::CYLINDER)) {
772  appendRow(ITEM(tr("Radius")),
774  } else {
775  appendRow(ITEM(tr("Bottom radius")),
777  appendRow(ITEM(tr("Top radius")),
779  }
780  } else if (_obj->isKindOf(CV_TYPES::PLANE)) {
781  // planar entity commons
782  fillWithPlanarEntity(static_cast<ccPlane*>(_obj));
783  } else if (_obj->isA(CV_TYPES::DISC)) {
785  true);
786  }
787 }
788 
790  assert(_obj && m_model);
791 
792  addSeparator(tr("Facet"));
793 
794  // planar entity commons
795  fillWithPlanarEntity(_obj);
796 
797  // surface
798  appendRow(ITEM(tr("Surface")),
799  ITEM(QLocale(QLocale::English).toString(_obj->getSurface())));
800 
801  // RMS
802  appendRow(ITEM(tr("RMS")),
803  ITEM(QLocale(QLocale::English).toString(_obj->getRMS())));
804 
805  // center
806  appendRow(ITEM(tr("Center")), ITEM(QString("(%1 ; %2 ; %3)")
807  .arg(_obj->getCenter().x)
808  .arg(_obj->getCenter().y)
809  .arg(_obj->getCenter().z)));
810 
811  // contour visibility
812  if (_obj->getContour())
813  appendRow(ITEM(tr("Show contour")),
816 
817  // polygon visibility
818  if (_obj->getPolygon())
819  appendRow(ITEM(tr("Show polygon")),
822 }
823 
825  ccPlanarEntityInterface* _obj) {
826  // normal
827  CCVector3 N = _obj->getNormal();
828  appendRow(ITEM(tr("Normal")),
829  ITEM(QString("(%1 ; %2 ; %3)").arg(N.x).arg(N.y).arg(N.z)));
830 
831  // Dip & Dip direction (in degrees)
832  PointCoordinateType dip_deg, dipDir_deg;
833  ccNormalVectors::ConvertNormalToDipAndDipDir(N, dip_deg, dipDir_deg);
834  appendRow(ITEM(tr("Dip / Dip dir.")),
835  ITEM(QString("(%1 ; %2) deg.")
836  .arg(static_cast<int>(dip_deg))
837  .arg(static_cast<int>(dipDir_deg))));
838 
839  // normal vector visibility
840  appendRow(ITEM(tr("Show normal vector")),
843 }
844 
846  assert(_obj && m_model);
847 
848  bool isSubMesh = _obj->isA(CV_TYPES::SUB_MESH);
849 
850  addSeparator(isSubMesh ? tr("Sub-mesh") : tr("Mesh"));
851 
852  // number of facets
853  appendRow(ITEM(tr("Faces")),
854  ITEM(QLocale(QLocale::English).toString(_obj->size())));
855 
856  // wireframe
857  appendRow(ITEM(tr("Wireframe")),
859 
860  // Pointsframe
861  appendRow(ITEM(tr("Pointsframe")),
863 
864  // stippling (ccMesh only)
865  // if (_obj->isA(CV_TYPES::MESH)) //DGM: can't remember why?
866  appendRow(ITEM(tr("Stippling")),
867  CHECKABLE_ITEM(static_cast<ccMesh*>(_obj)->stipplingEnabled(),
869 
870  // material/texture
871  if (_obj->hasMaterials()) {
872  appendRow(ITEM(tr("Materials/textures")),
874  // texture file selection combo box
875  appendRow(ITEM(tr("Texturefile")),
877  }
878 
879  // we also integrate vertices SF into mesh properties
880  ccGenericPointCloud* vertices = _obj->getAssociatedCloud();
881  if (vertices && (!vertices->isLocked() || _obj->isAncestorOf(vertices)))
882  fillSFWithPointCloud(vertices);
883 }
884 
886  assert(_obj && m_model);
887  if (!_obj || !m_model) {
888  return;
889  }
890 
891  if (_obj->isA(CV_TYPES::CIRCLE)) {
892  addSeparator(tr("Circle"));
893 
894  appendRow(ITEM(tr("Drawing precision")),
896 
898  true);
899  }
900 
901  addSeparator(tr("Polyline"));
902 
903  // number of vertices
904  appendRow(ITEM(tr("Vertices")),
905  ITEM(QLocale(QLocale::English).toString(_obj->size())));
906 
907  // polyline length
908  appendRow(ITEM(tr("Length")),
909  ITEM(QLocale(QLocale::English).toString(_obj->computeLength())));
910 
911  // custom line width
913  true);
914 
915  // global shift & scale
916  fillWithShifted(_obj);
917 }
918 
920  assert(_obj && m_model);
921 
922  addSeparator(tr("Octree"));
923 
924  // display mode
925  appendRow(ITEM(tr("Display mode")), PERSISTENT_EDITOR(OBJECT_OCTREE_TYPE),
926  true);
927 
928  // level
929  appendRow(ITEM(tr("Display level")), PERSISTENT_EDITOR(OBJECT_OCTREE_LEVEL),
930  true);
931 
932  addSeparator(tr("Current level"));
933 
934  // current display level
935  int level = _obj->getDisplayedLevel();
936  assert(level > 0 && level <= ccOctree::MAX_OCTREE_LEVEL);
937 
938  // cell size
939  PointCoordinateType cellSize =
940  _obj->getCellSize(static_cast<unsigned char>(level));
941  appendRow(ITEM(tr("Cell size")), ITEM(QString::number(cellSize)));
942 
943  // cell count
944  unsigned cellCount = _obj->getCellNumber(static_cast<unsigned char>(level));
945  appendRow(ITEM(tr("Cell count")),
946  ITEM(QLocale(QLocale::English).toString(cellCount)));
947 
948  // total volume of filled cells
949  appendRow(ITEM(tr("Filled volume")),
950  ITEM(QString::number((double)cellCount *
951  pow((double)cellSize, 3.0))));
952 }
953 
955  assert(_obj && m_model);
956 
957  addSeparator(tr("Kd-tree"));
958 
959  // max error
960  appendRow(ITEM(tr("Max Error")),
961  ITEM(QString::number(_obj->getMaxError())));
962  // max error measure
963  {
964  QString errorMeasure;
965  switch (_obj->getMaxErrorType()) {
967  errorMeasure = tr("RMS");
968  break;
970  errorMeasure = tr("Max dist @ 68%");
971  break;
973  errorMeasure = tr("Max dist @ 95%");
974  break;
976  errorMeasure = tr("Max dist @ 99%");
977  break;
979  errorMeasure = tr("Max distance");
980  break;
981  default:
982  assert(false);
983  errorMeasure = tr("unknown");
984  break;
985  }
986  appendRow(ITEM(tr("Error measure")), ITEM(errorMeasure));
987  }
988 }
989 
991  assert(_obj && m_model);
992 
993  addSeparator(tr("Image"));
994 
995  // image width
996  appendRow(ITEM(tr("Width")), ITEM(QString::number(_obj->getW())));
997 
998  // image height
999  appendRow(ITEM(tr("Height")), ITEM(QString::number(_obj->getH())));
1000 
1001  // transparency
1002  appendRow(ITEM(tr("Alpha")), PERSISTENT_EDITOR(OBJECT_IMAGE_ALPHA), true);
1003 
1004  if (_obj->getAssociatedSensor()) {
1005  addSeparator(tr("Sensor"));
1006  //"Set Viewport" button (shortcut to associated sensor)
1007  appendRow(ITEM(tr("Apply Viewport")),
1009  }
1010 }
1011 
1013  assert(_obj && m_model);
1014 
1015  addSeparator(tr("Label"));
1016 
1017  // Body
1018  QStringList body =
1019  _obj->getLabelContent(ecvGui::Parameters().displayedNumPrecision);
1020  appendRow(ITEM(tr("Body")), ITEM(body.join("\n")));
1021 
1022  // Show label in 2D
1023  appendRow(ITEM(tr("Show 2D label")),
1025 
1026  // Show label in 3D
1027  appendRow(ITEM(tr("Show legend(s)")),
1030 }
1031 
1033  cc2DViewportObject* _obj) {
1034  assert(_obj && m_model);
1035 
1036  addSeparator(tr("Viewport"));
1037 
1038  // Name
1039  appendRow(ITEM(tr("Name")),
1040  ITEM(_obj->getName().isEmpty() ? tr("undefined")
1041  : _obj->getName()));
1042 
1043  //"Apply Viewport" button
1044  appendRow(ITEM(tr("Apply viewport")),
1046 
1047  //"Update Viewport" button
1048  appendRow(ITEM(tr("Update viewport")),
1050 }
1051 
1054  assert(_obj && m_model);
1055 
1056  addSeparator(tr("Trans. buffer"));
1057 
1058  // Associated positions
1059  appendRow(ITEM(tr("Count")), ITEM(QString::number(_obj->size())));
1060 
1061  // Show path as polyline
1062  appendRow(ITEM(tr("Show path")),
1065 
1066  // Show trihedrons
1067  appendRow(ITEM(tr("Show trihedrons")),
1070 
1071  // Trihedrons scale
1072  appendRow(ITEM(tr("Scale")),
1074 }
1075 
1077  assert(_obj && m_model);
1078 
1079  // Sensor drawing scale
1080  appendRow(ITEM(tr("Drawing scale")),
1082 
1083  //"Apply Viewport" button
1084  appendRow(ITEM(tr("Apply Viewport")),
1086 
1087  // sensor aboslute orientation
1088  addSeparator(tr("Position/Orientation"));
1090 
1091  // Associated positions
1092  addSeparator(tr("Associated positions"));
1093 
1094  // number of positions
1095  appendRow(
1096  ITEM(tr("Count")),
1097  ITEM(QString::number(
1098  _obj->getPositions() ? _obj->getPositions()->size() : 0)));
1099 
1100  double minIndex, maxIndex;
1101  _obj->getIndexBounds(minIndex, maxIndex);
1102  if (minIndex != maxIndex) {
1103  // Index span
1104  appendRow(ITEM(tr("Indexes")),
1105  ITEM(QString("%1 - %2").arg(minIndex).arg(maxIndex)));
1106 
1107  // Current index
1108  appendRow(ITEM(tr("Active index")),
1110  }
1111 }
1112 
1114  assert(_obj && m_model);
1115 
1116  addSeparator(tr("TLS/GBL Sensor"));
1117 
1118  // Uncertainty
1119  appendRow(ITEM(tr("Uncertainty")),
1121 
1122  // angles
1123  addSeparator(tr("Angular viewport (degrees)"));
1124  {
1125  // Angular range (yaw)
1126  PointCoordinateType yawMin = _obj->getMinYaw();
1127  PointCoordinateType yawMax = _obj->getMaxYaw();
1128  appendRow(ITEM(tr("Yaw span")),
1129  ITEM(QString("[%1 ; %2]")
1130  .arg(cloudViewer::RadiansToDegrees(yawMin), 0,
1131  'f', 2)
1132  .arg(cloudViewer::RadiansToDegrees(yawMax), 0,
1133  'f', 2)));
1134 
1135  // Angular steps (yaw)
1136  PointCoordinateType yawStep = _obj->getYawStep();
1137  appendRow(ITEM(tr("Yaw step")),
1138  ITEM(QString("%1").arg(cloudViewer::RadiansToDegrees(yawStep),
1139  0, 'f', 4)));
1140 
1141  // Angular range (pitch)
1142  PointCoordinateType pitchMin = _obj->getMinPitch();
1143  PointCoordinateType pitchMax = _obj->getMaxPitch();
1144  appendRow(ITEM(tr("Pitch span")),
1145  ITEM(QString("[%1 ; %2]")
1146  .arg(cloudViewer::RadiansToDegrees(pitchMin), 0,
1147  'f', 2)
1148  .arg(cloudViewer::RadiansToDegrees(pitchMax), 0,
1149  'f', 2)));
1150 
1151  // Angular steps (pitch)
1152  PointCoordinateType pitchStep = _obj->getPitchStep();
1153  appendRow(
1154  ITEM(tr("Pitch step")),
1155  ITEM(QString("%1").arg(cloudViewer::RadiansToDegrees(pitchStep),
1156  0, 'f', 4)));
1157  }
1158 
1159  // Positions
1160  fillWithSensor(_obj);
1161 }
1162 
1164  assert(_obj && m_model);
1165 
1166  addSeparator(tr("Camera Sensor"));
1167 
1169  _obj->getIntrinsicParameters();
1170 
1171  // Focal
1172  appendRow(ITEM(tr("Vert. focal")),
1173  ITEM(QString::number(params.vertFocal_pix) + tr(" pix.")));
1174 
1175  // Array size
1176  appendRow(ITEM(tr("Array size")), ITEM(QString("%1 x %2")
1177  .arg(params.arrayWidth)
1178  .arg(params.arrayHeight)));
1179 
1180  // Principal point
1181  appendRow(ITEM(tr("Principal point")),
1182  ITEM(QString("(%1 ; %2)")
1183  .arg(params.principal_point[0])
1184  .arg(params.principal_point[1])));
1185 
1186  // Pixel size
1187  if (params.pixelSize_mm[0] != 0 || params.pixelSize_mm[1] != 0) {
1188  appendRow(ITEM(tr("Pixel size")),
1189  ITEM(QString("%1 x %2")
1190  .arg(params.pixelSize_mm[0])
1191  .arg(params.pixelSize_mm[1])));
1192  }
1193 
1194  // Field of view
1195  appendRow(ITEM(tr("Field of view")),
1196  ITEM(QString::number(
1198  tr(" deg.")));
1199 
1200  // Skewness
1201  appendRow(ITEM(tr("Skew")), ITEM(QString::number(params.skew)));
1202 
1203  addSeparator(tr("Frustum display"));
1204 
1205  // Draw frustum
1206  appendRow(
1207  ITEM(tr("Show lines")),
1209  appendRow(ITEM(tr("Show side planes")),
1212 
1213  // Positions
1214  fillWithSensor(_obj);
1215 }
1216 
1218  assert(_obj && m_model);
1219 
1220  addSeparator(tr("Material set"));
1221 
1222  // Count
1223  appendRow(ITEM(tr("Count")), ITEM(QString::number(_obj->size())));
1224 
1225  // ccMaterialSet objects are 'shareable'
1226  fillWithShareable(_obj);
1227 }
1228 
1230  assert(_obj && m_model);
1231 
1232  addSeparator(tr("Array"));
1233 
1234  // Link count
1235  unsigned linkCount =
1236  _obj->getLinkCount(); // if we display it, it means it is a member
1237  // of the DB --> i.e. link is already >1
1238  appendRow(
1239  ITEM(tr("Shared")),
1240  ITEM(linkCount < 3 ? tr("No") : tr("Yes (%1)").arg(linkCount - 1)));
1241 }
1242 
1243 template <class Type, int N, class ComponentType>
1246  assert(_obj && m_model);
1247 
1248  addSeparator(tr("Array"));
1249 
1250  // Name
1251  appendRow(ITEM(tr("Name")),
1252  ITEM(_obj->getName().isEmpty() ? tr("undefined")
1253  : _obj->getName()));
1254 
1255  // Count
1256  appendRow(ITEM(tr("Elements")),
1257  ITEM(QLocale(QLocale::English)
1258  .toString(static_cast<qulonglong>(_obj->size()))));
1259 
1260  // Capacity
1261  appendRow(
1262  ITEM(tr("Capacity")),
1263  ITEM(QLocale(QLocale::English)
1264  .toString(static_cast<qulonglong>(_obj->capacity()))));
1265 
1266  // Memory
1267  appendRow(
1268  ITEM(tr("Memory")),
1269  ITEM(QString("%1 Mb").arg(
1270  (_obj->capacity() * sizeof(Type)) / 1048576.0, 0, 'f', 2)));
1271 
1272  // ccArray objects are 'Shareable'
1273  fillWithShareable(_obj);
1274 }
1275 
1276 bool ccPropertiesTreeDelegate::isWideEditor(int itemData) const {
1277  switch (itemData) {
1282  // Note: OBJECT_SELECTION_PROPERTIES removed - selection properties
1283  // are now in standalone cvFindDataDockWidget
1284  case TREE_VIEW_HEADER:
1285  return true;
1286  default:
1287  break;
1288  }
1289 
1290  return false;
1291 }
1292 
1294  QWidget* parent,
1295  const QStyleOptionViewItem& option,
1296  const QModelIndex& index) const {
1297  if (!m_model) return nullptr;
1298 
1299  QStandardItem* item = m_model->itemFromIndex(index);
1300 
1301  if (!item || !item->data().isValid()) return nullptr;
1302 
1303  int itemData = item->data().toInt();
1304 
1305  // All editors require a current object
1306  if (!m_currentObject) {
1307  return nullptr;
1308  }
1309  if (item->column() == 0 && !isWideEditor(itemData)) {
1310  // on the first column, only editors spanning on 2 columns are allowed
1311  return nullptr;
1312  }
1313 
1314  QWidget* outputWidget = nullptr;
1315 
1316  switch (itemData) {
1317  case OBJECT_CURRENT_DISPLAY: {
1318  QComboBox* comboBox = new QComboBox(parent);
1319 
1320  comboBox->addItem(s_noneString);
1321 
1322  connect(comboBox,
1323  static_cast<void (QComboBox::*)(const QString&)>(
1324  &QComboBox::currentTextChanged),
1325  this, &ccPropertiesTreeDelegate::objectDisplayChanged);
1326 
1327  outputWidget = comboBox;
1328  } break;
1330  ccPointCloud* cloud =
1332  assert(cloud);
1333 
1334  QComboBox* comboBox = new QComboBox(parent);
1335 
1336  comboBox->addItem(tr("None"));
1337  int nsf = static_cast<int>(cloud->getNumberOfScalarFields());
1338  for (int i = 0; i < nsf; ++i)
1339  comboBox->addItem(QString(cloud->getScalarFieldName(i)));
1340 
1341  connect(comboBox,
1342  static_cast<void (QComboBox::*)(int)>(
1343  &QComboBox::activated),
1344  this, &ccPropertiesTreeDelegate::scalarFieldChanged);
1345 
1346  outputWidget = comboBox;
1347  } break;
1348  case OBJECT_MESH_TEXTUREFILE: {
1350  parent,
1351  QString::fromUtf8(":/Resources/images/ecvGear.png"));
1352  // Initialize with empty map - will be populated in setEditorData
1353  // based on current mesh object
1354  QMap<QString, QString> emptyMap;
1355  selector->init(emptyMap);
1356 
1358  this, &ccPropertiesTreeDelegate::textureFileChanged);
1359  connect(selector,
1361  &ccPropertiesTreeDelegate::spawnTextureFileEditor);
1362 
1363  outputWidget = selector;
1364  } break;
1368  QString::fromUtf8(":/Resources/images/ecvGear.png"));
1369  // fill combobox box with Color Scales Manager
1370  selector->init();
1371  connect(selector, &ccColorScaleSelector::colorScaleSelected, this,
1372  &ccPropertiesTreeDelegate::colorScaleChanged);
1374  this, &ccPropertiesTreeDelegate::spawnColorRampEditor);
1375 
1376  outputWidget = selector;
1377  } break;
1378  case OBJECT_COLOR_RAMP_STEPS: {
1379  QSpinBox* spinBox = new QSpinBox(parent);
1381  spinBox->setSingleStep(4);
1382 
1383  connect(spinBox,
1384  static_cast<void (QSpinBox::*)(int)>(
1385  &QSpinBox::valueChanged),
1386  this, &ccPropertiesTreeDelegate::colorRampStepsChanged);
1387 
1388  outputWidget = spinBox;
1389  } break;
1390  case OBJECT_CLOUD_SF_EDITOR: {
1391  sfEditDlg* sfd = new sfEditDlg(parent);
1392 
1393  // DGM: why does this widget can't follow its 'policy' ?!
1394  // QSizePolicy pol = sfd->sizePolicy();
1395  // QSizePolicy::Policy hpol = pol.horizontalPolicy();
1396  // sfd->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Maximum);
1397  // parent->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Maximum);
1398 
1399  connect(sfd, &sfEditDlg::entitySFHasChanged, this,
1400  &ccPropertiesTreeDelegate::updateDisplay);
1401 
1402  outputWidget = sfd;
1403  } break;
1407  MatrixDisplayDlg* mdd = new MatrixDisplayDlg(parent);
1408 
1409  // no signal connection, it's a display-only widget
1410 
1411  outputWidget = mdd;
1412  } break;
1413  case TREE_VIEW_HEADER: {
1414  QLabel* headerLabel = new QLabel(parent);
1415  headerLabel->setStyleSheet(SEPARATOR_STYLESHEET);
1416 
1417  // no signal connection, it's a display-only widget
1418 
1419  outputWidget = headerLabel;
1420  } break;
1421  case OBJECT_OCTREE_TYPE: {
1422  QComboBox* comboBox = new QComboBox(parent);
1423 
1424  comboBox->addItem(tr("Wire"), QVariant(ccOctree::WIRE));
1425  comboBox->addItem(tr("Points"), QVariant(ccOctree::MEAN_POINTS));
1426  comboBox->addItem(tr("Plain cubes"),
1427  QVariant(ccOctree::MEAN_CUBES));
1428 
1429  connect(comboBox,
1430  static_cast<void (QComboBox::*)(int)>(
1431  &QComboBox::activated),
1432  this, &ccPropertiesTreeDelegate::octreeDisplayModeChanged);
1433 
1434  outputWidget = comboBox;
1435  } break;
1436  case OBJECT_OCTREE_LEVEL: {
1437  QSpinBox* spinBox = new QSpinBox(parent);
1438  spinBox->setRange(1, cloudViewer::DgmOctree::MAX_OCTREE_LEVEL);
1439 
1440  connect(spinBox,
1441  static_cast<void (QSpinBox::*)(int)>(
1442  &QSpinBox::valueChanged),
1443  this,
1444  &ccPropertiesTreeDelegate::octreeDisplayedLevelChanged);
1445 
1446  outputWidget = spinBox;
1447  } break;
1449  QSpinBox* spinBox = new QSpinBox(parent);
1450  spinBox->setRange(4, 360);
1451  spinBox->setSingleStep(4);
1452 
1453  connect(spinBox,
1454  static_cast<void (QSpinBox::*)(int)>(
1455  &QSpinBox::valueChanged),
1456  this, &ccPropertiesTreeDelegate::primitivePrecisionChanged);
1457 
1458  outputWidget = spinBox;
1459  } break;
1460  case OBJECT_CIRCLE_RESOLUTION: {
1461  QSpinBox* spinBox = new QSpinBox(parent);
1462  spinBox->setRange(4, 1024);
1463  spinBox->setSingleStep(4);
1464 
1465  connect(spinBox,
1466  static_cast<void (QSpinBox::*)(int)>(
1467  &QSpinBox::valueChanged),
1468  this, &ccPropertiesTreeDelegate::circleResolutionChanged);
1469 
1470  outputWidget = spinBox;
1471  } break;
1472  case OBJECT_SPHERE_RADIUS: {
1473  QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent);
1474  spinBox->setDecimals(6);
1475  spinBox->setRange(0, 1.0e6);
1476  spinBox->setSingleStep(1.0);
1477 
1478  connect(spinBox,
1479  static_cast<void (QDoubleSpinBox::*)(double)>(
1480  &QDoubleSpinBox::valueChanged),
1481  this, &ccPropertiesTreeDelegate::sphereRadiusChanged);
1482 
1483  outputWidget = spinBox;
1484  } break;
1485  case OBJECT_CIRCLE_RADIUS: {
1486  QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent);
1487  spinBox->setDecimals(7);
1488  spinBox->setRange(1.0e-6, 1.0e6);
1489  spinBox->setSingleStep(1.0);
1490 
1491  connect(spinBox,
1492  static_cast<void (QDoubleSpinBox::*)(double)>(
1493  &QDoubleSpinBox::valueChanged),
1494  this, &ccPropertiesTreeDelegate::circleRadiusChanged);
1495 
1496  outputWidget = spinBox;
1497  } break;
1498  case OBJECT_DISC_RADIUS: {
1499  QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent);
1500  spinBox->setDecimals(7);
1501  spinBox->setRange(1.0e-6, 1.0e6);
1502  spinBox->setSingleStep(1.0);
1503 
1504  connect(spinBox,
1505  static_cast<void (QDoubleSpinBox::*)(double)>(
1506  &QDoubleSpinBox::valueChanged),
1507  this, &ccPropertiesTreeDelegate::discRadiusChanged);
1508 
1509  outputWidget = spinBox;
1510  } break;
1511  case OBJECT_CONE_HEIGHT: {
1512  QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent);
1513  spinBox->setDecimals(6);
1514  spinBox->setRange(0, 1.0e6);
1515  spinBox->setSingleStep(1.0);
1516 
1517  connect(spinBox,
1518  static_cast<void (QDoubleSpinBox::*)(double)>(
1519  &QDoubleSpinBox::valueChanged),
1520  this, &ccPropertiesTreeDelegate::coneHeightChanged);
1521 
1522  outputWidget = spinBox;
1523  } break;
1525  QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent);
1526  spinBox->setDecimals(6);
1527  spinBox->setRange(0, 1.0e6);
1528  spinBox->setSingleStep(1.0);
1529 
1530  connect(spinBox,
1531  static_cast<void (QDoubleSpinBox::*)(double)>(
1532  &QDoubleSpinBox::valueChanged),
1533  this, &ccPropertiesTreeDelegate::coneBottomRadiusChanged);
1534 
1535  outputWidget = spinBox;
1536  } break;
1537  case OBJECT_CONE_TOP_RADIUS: {
1538  QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent);
1539  spinBox->setDecimals(6);
1540  spinBox->setRange(0, 1.0e6);
1541  spinBox->setSingleStep(1.0);
1542 
1543  connect(spinBox,
1544  static_cast<void (QDoubleSpinBox::*)(double)>(
1545  &QDoubleSpinBox::valueChanged),
1546  this, &ccPropertiesTreeDelegate::coneTopRadiusChanged);
1547 
1548  outputWidget = spinBox;
1549  } break;
1550  case OBJECT_IMAGE_ALPHA: {
1551  QSlider* slider = new QSlider(Qt::Horizontal, parent);
1552  slider->setRange(0, 255);
1553  slider->setSingleStep(1);
1554  slider->setPageStep(16);
1555  slider->setTickPosition(QSlider::NoTicks);
1556  connect(slider, &QAbstractSlider::valueChanged, this,
1557  &ccPropertiesTreeDelegate::imageAlphaChanged);
1558 
1559  outputWidget = slider;
1560  } break;
1562  // ParaView-style light intensity control: Slider + SpinBox
1563  // (0.0-1.0)
1564  QWidget* container = new QWidget(parent);
1565  QHBoxLayout* layout = new QHBoxLayout(container);
1566  layout->setContentsMargins(0, 0, 0, 0);
1567  layout->setSpacing(4);
1568 
1569  // Slider for quick adjustment (0-100 representing 0.0-1.0)
1570  QSlider* slider = new QSlider(Qt::Horizontal, container);
1571  slider->setRange(0, 100); // 0% to 100% intensity
1572  slider->setSingleStep(1);
1573  slider->setPageStep(10);
1574  slider->setTickPosition(QSlider::NoTicks);
1575 
1576  // SpinBox for precise numeric input
1577  QDoubleSpinBox* spinBox = new QDoubleSpinBox(container);
1578  spinBox->setRange(0.0, 1.0);
1579  spinBox->setSingleStep(0.01);
1580  spinBox->setDecimals(2);
1581  spinBox->setMinimumWidth(60);
1582 
1583  // Synchronize slider and spinbox (visual sync only)
1584  connect(slider, &QSlider::valueChanged, this, [spinBox](int value) {
1585  spinBox->blockSignals(true);
1586  spinBox->setValue(value / 100.0);
1587  spinBox->blockSignals(false);
1588  });
1589  connect(spinBox,
1590  QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
1591  [slider](double value) {
1592  slider->blockSignals(true);
1593  slider->setValue(static_cast<int>(value * 100.0));
1594  slider->blockSignals(false);
1595  });
1596 
1597  // Connect BOTH slider and spinbox to light intensity handler (like
1598  // Opacity does) Slider: convert int [0, 100] to double [0.0, 1.0]
1599  // for handler
1600  ccPropertiesTreeDelegate* self =
1601  const_cast<ccPropertiesTreeDelegate*>(this);
1602  connect(slider, &QAbstractSlider::valueChanged, self,
1603  [self](int value) {
1604  self->lightIntensityChanged(value / 100.0);
1605  });
1606  // SpinBox: direct connection (already in [0.0, 1.0] range)
1607  connect(spinBox,
1608  QOverload<double>::of(&QDoubleSpinBox::valueChanged), self,
1609  [self](double value) {
1610  self->lightIntensityChanged(value);
1611  });
1612 
1613  layout->addWidget(slider, 1);
1614  layout->addWidget(spinBox, 0);
1615 
1616  outputWidget = container;
1617  } break;
1618  case OBJECT_OPACITY: {
1619  // ParaView-style opacity control: Slider + SpinBox combination
1620  // Creates a horizontal layout with slider and numeric input
1621  QWidget* container = new QWidget(parent);
1622  QHBoxLayout* layout = new QHBoxLayout(container);
1623  layout->setContentsMargins(0, 0, 0, 0);
1624  layout->setSpacing(4);
1625 
1626  // Slider for quick adjustment
1627  QSlider* slider = new QSlider(Qt::Horizontal, container);
1628  slider->setRange(0, 100); // 0% to 100% opacity
1629  slider->setSingleStep(1);
1630  slider->setPageStep(10);
1631  slider->setTickPosition(QSlider::NoTicks);
1632 
1633  // SpinBox for precise numeric input (ParaView style: shows
1634  // 0.00-1.00)
1635  QDoubleSpinBox* spinBox = new QDoubleSpinBox(container);
1636  spinBox->setRange(0.0, 1.0);
1637  spinBox->setDecimals(2);
1638  spinBox->setSingleStep(0.01);
1639  spinBox->setFixedWidth(60);
1640 
1641  // Synchronize slider and spinbox (visual sync only, no opacity
1642  // update)
1643  connect(slider, &QSlider::valueChanged, this, [spinBox](int value) {
1644  spinBox->blockSignals(true);
1645  spinBox->setValue(value / 100.0);
1646  spinBox->blockSignals(false);
1647  });
1648  connect(spinBox,
1649  QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
1650  [slider](double value) {
1651  slider->blockSignals(true);
1652  slider->setValue(static_cast<int>(value * 100));
1653  slider->blockSignals(false);
1654  });
1655 
1656  // Connect BOTH slider and spinbox to opacity change handler
1657  // Slider: direct connection
1658  connect(slider, &QAbstractSlider::valueChanged, this,
1659  &ccPropertiesTreeDelegate::opacityChanged);
1660  // SpinBox: convert double [0.0, 1.0] to int [0, 100] for handler
1661  // Use const_cast because createEditor is const but opacityChanged
1662  // is not
1663  ccPropertiesTreeDelegate* self =
1664  const_cast<ccPropertiesTreeDelegate*>(this);
1665  connect(spinBox,
1666  QOverload<double>::of(&QDoubleSpinBox::valueChanged), self,
1667  [self](double value) {
1668  self->opacityChanged(static_cast<int>(value * 100));
1669  });
1670 
1671  layout->addWidget(slider, 1); // Stretch factor 1
1672  layout->addWidget(spinBox, 0); // Fixed size
1673 
1674  outputWidget = container;
1675  } break;
1676  case OBJECT_SENSOR_INDEX: {
1678  assert(sensor);
1679 
1680  double minIndex, maxIndex;
1681  sensor->getIndexBounds(minIndex, maxIndex);
1682 
1683  QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent);
1684  spinBox->setRange(minIndex, maxIndex);
1685  spinBox->setSingleStep((maxIndex - minIndex) / 1000.0);
1686 
1687  connect(spinBox,
1688  static_cast<void (QDoubleSpinBox::*)(double)>(
1689  &QDoubleSpinBox::valueChanged),
1690  this, &ccPropertiesTreeDelegate::sensorIndexChanged);
1691 
1692  outputWidget = spinBox;
1693  } break;
1695  QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent);
1696  spinBox->setRange(1.0e-3, 1.0e6);
1697  spinBox->setDecimals(3);
1698  spinBox->setSingleStep(1.0);
1699 
1700  connect(spinBox,
1701  static_cast<void (QDoubleSpinBox::*)(double)>(
1702  &QDoubleSpinBox::valueChanged),
1703  this, &ccPropertiesTreeDelegate::trihedronsScaleChanged);
1704 
1705  outputWidget = spinBox;
1706  } break;
1708  QPushButton* button = new QPushButton(tr("Apply"), parent);
1709  connect(button, &QAbstractButton::clicked, this,
1710  &ccPropertiesTreeDelegate::applySensorViewport);
1711 
1712  button->setMinimumHeight(30);
1713 
1714  outputWidget = button;
1715  } break;
1717  QPushButton* button = new QPushButton(tr("Apply"), parent);
1718  connect(button, &QAbstractButton::clicked, this,
1719  &ccPropertiesTreeDelegate::applyLabelViewport);
1720 
1721  button->setMinimumHeight(30);
1722  outputWidget = button;
1723  } break;
1725  QPushButton* button = new QPushButton(tr("Update"), parent);
1726  connect(button, &QAbstractButton::clicked, this,
1727  &ccPropertiesTreeDelegate::updateLabelViewport);
1728 
1729  button->setMinimumHeight(30);
1730  outputWidget = button;
1731  } break;
1733  QLineEdit* lineEdit = new QLineEdit(parent);
1734  lineEdit->setValidator(
1735  new QDoubleValidator(1.0e-8, 1.0, 8, lineEdit));
1736  connect(lineEdit, &QLineEdit::editingFinished, this,
1737  &ccPropertiesTreeDelegate::sensorUncertaintyChanged);
1738 
1739  outputWidget = lineEdit;
1740  } break;
1742  QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent);
1743  spinBox->setRange(1.0e-3, 1.0e6);
1744  spinBox->setDecimals(3);
1745  spinBox->setSingleStep(1.0e-1);
1746 
1747  connect(spinBox,
1748  static_cast<void (QDoubleSpinBox::*)(double)>(
1749  &QDoubleSpinBox::valueChanged),
1750  this, &ccPropertiesTreeDelegate::sensorScaleChanged);
1751 
1752  outputWidget = spinBox;
1753  } break;
1754  case OBJECT_CLOUD_POINT_SIZE: {
1755  QComboBox* comboBox = new QComboBox(parent);
1756 
1757  comboBox->addItem(s_defaultPointSizeString); // size = 0
1758  for (int i = static_cast<int>(MIN_POINT_SIZE_F);
1759  i <= static_cast<int>(MAX_POINT_SIZE_F); ++i)
1760  comboBox->addItem(QString::number(i));
1761 
1762  connect(comboBox,
1763  static_cast<void (QComboBox::*)(int)>(
1764  &QComboBox::currentIndexChanged),
1765  this, &ccPropertiesTreeDelegate::cloudPointSizeChanged);
1766 
1767  outputWidget = comboBox;
1768  } break;
1769  case OBJECT_POLYLINE_WIDTH: {
1770  QComboBox* comboBox = new QComboBox(parent);
1771 
1772  comboBox->addItem(s_defaultPolyWidthSizeString); // size = 0
1773  for (int i = static_cast<int>(MIN_LINE_WIDTH_F);
1774  i <= static_cast<int>(MAX_LINE_WIDTH_F); ++i)
1775  comboBox->addItem(QString::number(i));
1776 
1777  connect(comboBox,
1778  static_cast<void (QComboBox::*)(int)>(
1779  &QComboBox::currentIndexChanged),
1780  this, &ccPropertiesTreeDelegate::polyineWidthChanged);
1781 
1782  outputWidget = comboBox;
1783  } break;
1784  case OBJECT_COLOR_SOURCE: {
1785  QComboBox* comboBox = new QComboBox(parent);
1786 
1787  comboBox->addItem(s_noneString);
1788  if (m_currentObject) {
1789  if (m_currentObject->hasColors()) {
1790  comboBox->addItem(s_rgbColor);
1791  comboBox->setItemIcon(
1792  comboBox->count() - 1,
1793  QIcon(QString::fromUtf8(
1794  ":/Resources/images/typeRgbCcolor.png")));
1795  }
1797  comboBox->addItem(s_sfColor);
1798  comboBox->setItemIcon(
1799  comboBox->count() - 1,
1800  QIcon(QString::fromUtf8(
1801  ":/Resources/images/typeSF.png")));
1802  }
1803  connect(comboBox,
1804  static_cast<void (QComboBox::*)(const QString&)>(
1805  &QComboBox::currentTextChanged),
1806  this, &ccPropertiesTreeDelegate::colorSourceChanged);
1807  }
1808 
1809  outputWidget = comboBox;
1810  } break;
1812  QComboBox* comboBox = new QComboBox(parent);
1813 
1814  comboBox->addItem(tr(s_defaultPolyWidthSizeString)); // size = 0
1815 
1816  for (int i = static_cast<int>(ccCoordinateSystem::MIN_AXIS_WIDTH_F);
1817  i <= static_cast<int>(ccCoordinateSystem::MAX_AXIS_WIDTH_F);
1818  ++i) {
1819  comboBox->addItem(QString::number(i));
1820  }
1821  ccCoordinateSystem* cs =
1823  if (cs) {
1824  comboBox->setCurrentIndex(static_cast<int>(cs->getAxisWidth()));
1825  }
1826  connect(comboBox,
1827  static_cast<void (QComboBox::*)(int)>(
1828  &QComboBox::currentIndexChanged),
1829  this,
1831  coordinateSystemAxisWidthChanged);
1832 
1833  outputWidget = comboBox;
1834  } break;
1836  QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent);
1837  spinBox->setRange(1.0e-3, 1.0e6);
1838  spinBox->setDecimals(3);
1839  spinBox->setSingleStep(1.0e-1);
1840  ccCoordinateSystem* cs =
1842  if (cs) {
1843  spinBox->setValue(cs->getDisplayScale());
1844  }
1845 
1846  connect(spinBox,
1847  static_cast<void (QDoubleSpinBox::*)(double)>(
1848  &QDoubleSpinBox::valueChanged),
1849  this,
1851  coordinateSystemDisplayScaleChanged);
1852 
1853  outputWidget = spinBox;
1854  } break;
1855  // ParaView-style Data Axes Grid: Checkbox + Edit button in same row
1857  // Create container widget with horizontal layout (like Opacity)
1858  QWidget* container = new QWidget(parent);
1859  QHBoxLayout* layout = new QHBoxLayout(container);
1860  layout->setContentsMargins(0, 0, 0, 0);
1861  layout->setSpacing(4);
1862 
1863  // Checkbox for visibility
1864  QCheckBox* checkbox = new QCheckBox(container);
1865 
1866  // Edit button (compact style)
1867  QPushButton* editButton = new QPushButton(tr("Edit..."), container);
1868  editButton->setMinimumHeight(22);
1869  editButton->setMaximumWidth(80);
1870  connect(editButton, &QPushButton::clicked, this,
1871  &ccPropertiesTreeDelegate::dataAxesGridEditRequested);
1872 
1873  // Add to layout: checkbox (stretch) + button (fixed)
1874  layout->addWidget(checkbox, 1);
1875  layout->addWidget(editButton, 0);
1876 
1877  outputWidget = container;
1878  } break;
1879  // Note: OBJECT_VIEW_DATA_AXES_GRID_EDIT is now integrated into VISIBLE
1880  // case above
1882  // This case is no longer used - keeping for compatibility
1883  QPushButton* button = new QPushButton(tr("Edit..."), parent);
1884  connect(button, &QAbstractButton::clicked, this,
1885  &ccPropertiesTreeDelegate::dataAxesGridEditRequested);
1886  button->setMinimumHeight(22);
1887  button->setMaximumWidth(80);
1888  outputWidget = button;
1889  } break;
1890  // Note: OBJECT_SELECTION_PROPERTIES case removed - selection
1891  // properties are now in standalone cvFindDataDockWidget
1892  default:
1893  return QStyledItemDelegate::createEditor(parent, option, index);
1894  }
1895 
1896  if (outputWidget) {
1897  // Qt doc: << The returned editor widget should have Qt::StrongFocus >>
1898  outputWidget->setFocusPolicy(Qt::StrongFocus);
1899  } else {
1900  // shouldn't happen
1901  assert(false);
1902  }
1903 
1904  return outputWidget;
1905 }
1906 
1908  QWidget* editor,
1909  const QStyleOptionViewItem& option,
1910  const QModelIndex& index) const {
1911  QStyledItemDelegate::updateEditorGeometry(editor, option, index);
1912 
1913  if (!m_model || !editor) return;
1914 
1915  QStandardItem* item = m_model->itemFromIndex(index);
1916 
1917  if (item && item->data().isValid() && item->column() == 0) {
1918  if (isWideEditor(item->data().toInt())) {
1919  QWidget* widget = qobject_cast<QWidget*>(editor);
1920  if (!widget) return;
1921  // we must resize the SF edit widget so that it spans on both
1922  // columns!
1923  QRect rect = m_view->visualRect(
1924  m_model->index(item->row(), 1)); // second column width
1925  widget->resize(option.rect.width() + rect.width(),
1926  widget->height());
1927  }
1928  }
1929 }
1930 
1931 void SetDoubleSpinBoxValue(QWidget* editor,
1932  double value,
1933  bool keyboardTracking = false) {
1934  QDoubleSpinBox* spinBox = qobject_cast<QDoubleSpinBox*>(editor);
1935  if (!spinBox) {
1936  assert(false);
1937  return;
1938  }
1939  spinBox->setKeyboardTracking(keyboardTracking);
1940  spinBox->setValue(value);
1941 }
1942 
1943 void SetSpinBoxValue(QWidget* editor,
1944  int value,
1945  bool keyboardTracking = false) {
1946  QSpinBox* spinBox = qobject_cast<QSpinBox*>(editor);
1947  if (!spinBox) {
1948  assert(false);
1949  return;
1950  }
1951  spinBox->setKeyboardTracking(keyboardTracking);
1952  spinBox->setValue(value);
1953 }
1954 
1955 void SetComboBoxIndex(QWidget* editor, int index) {
1956  QComboBox* comboBox = qobject_cast<QComboBox*>(editor);
1957  if (!comboBox) {
1958  assert(false);
1959  return;
1960  }
1961  assert(index < 0 || index < comboBox->maxCount());
1962  comboBox->setCurrentIndex(index);
1963 }
1964 
1966  const QModelIndex& index) const {
1967  if (!m_model) return;
1968 
1969  QStandardItem* item = m_model->itemFromIndex(index);
1970  if (!item || !item->data().isValid()) return;
1971 
1972  int itemData = item->data().toInt();
1973 
1974  // All properties require a current object
1975  if (!m_currentObject) return;
1976 
1977  if (item->column() == 0 && !isWideEditor(itemData)) return;
1978 
1979  switch (itemData) {
1980  case OBJECT_CURRENT_DISPLAY: {
1981  QComboBox* comboBox = qobject_cast<QComboBox*>(editor);
1982  if (!comboBox) {
1983  assert(false);
1984  return;
1985  }
1986 
1987  int pos = comboBox->findText(Settings::APP_TITLE);
1988 
1989  comboBox->setCurrentIndex(std::max(pos, 0)); // 0 = "NONE"
1990  break;
1991  }
1993  ccPointCloud* cloud =
1995  assert(cloud);
1996 
1997  int pos = cloud->getCurrentDisplayedScalarFieldIndex();
1998  SetComboBoxIndex(editor, pos + 1);
1999  break;
2000  }
2001  case OBJECT_MESH_TEXTUREFILE: {
2002  QFrame* selectorFrame = qobject_cast<QFrame*>(editor);
2003  if (!selectorFrame) return;
2004  ecvTextureFileSelector* selector =
2005  static_cast<ecvTextureFileSelector*>(selectorFrame);
2006 
2007  // get current material
2008  ccGenericMesh* mesh =
2010  assert(mesh);
2011 
2012  // Get or create texture path map for current mesh
2013  QMap<QString, QString>& texturePathMap =
2015 
2016  const ccMaterialSet* materialSet =
2017  mesh ? mesh->getMaterialSet() : nullptr;
2018  if (materialSet) {
2019  if (!materialSet->empty()) {
2020  // Always clear and repopulate selector when switching mesh
2021  // objects This ensures we only show textures for the
2022  // current mesh Clear the combo box by reinitializing with
2023  // empty map
2024  QMap<QString, QString> emptyMap;
2025  selector->init(emptyMap);
2026  texturePathMap.clear();
2027 
2028  // Collect ALL DIFFUSE (map_Kd) textures from all materials
2029  // Include all occurrences from the file, even if the same
2030  // path appears multiple times
2031  for (std::size_t i = 0; i < materialSet->size(); ++i) {
2032  const ccMaterial::CShared& material =
2033  materialSet->at(i);
2034  if (!material) continue;
2035 
2036  // Get ALL DIFFUSE textures for this material using the
2037  // new method This returns all map_Kd textures,
2038  // including duplicates
2039  std::vector<QString> diffuseTextures =
2040  material->getTextureFilenames(
2042 
2043  // Add ALL DIFFUSE textures (map_Kd) - include all
2044  // occurrences
2045  for (const QString& texPath : diffuseTextures) {
2046  if (!texPath.isEmpty()) {
2047  QString texName = QFileInfo(texPath).fileName();
2048  if (texName.isEmpty()) {
2049  texName = material->getName();
2050  }
2051  // Add all textures to show all map_Kd from the
2052  // file
2053  selector->addItem(texName, texPath);
2054  texturePathMap[texName] = texPath;
2055  }
2056  }
2057  }
2058 
2059  // Don't auto-select - let user choose from all available
2060  // textures The selector will show the first item but user
2061  // can change it
2062  } else {
2063  selector->setSelectedTexturefile(QString());
2064  }
2065  }
2066  break;
2067  }
2069  QFrame* selectorFrame = qobject_cast<QFrame*>(editor);
2070  if (!selectorFrame) return;
2071  ccColorScaleSelector* selector =
2072  static_cast<ccColorScaleSelector*>(selectorFrame);
2073 
2074  ccPointCloud* cloud =
2076  assert(cloud);
2077 
2079  if (sf) {
2080  if (sf->getColorScale())
2081  selector->setSelectedScale(sf->getColorScale()->getUuid());
2082  else
2083  selector->setSelectedScale(QString());
2084  }
2085  break;
2086  }
2087  case OBJECT_COLOR_RAMP_STEPS: {
2088  ccPointCloud* cloud =
2090  assert(cloud);
2091  ccScalarField* sf =
2092  cloud ? cloud->getCurrentDisplayedScalarField() : nullptr;
2093  if (sf)
2094  SetSpinBoxValue(editor,
2095  static_cast<int>(sf->getColorRampSteps()),
2096  true);
2097  break;
2098  }
2099  case OBJECT_CLOUD_SF_EDITOR: {
2100  sfEditDlg* sfd = qobject_cast<sfEditDlg*>(editor);
2101  if (!sfd) return;
2102 
2103  ccPointCloud* cloud =
2105  assert(cloud);
2106 
2108  if (sf) sfd->fillDialogWith(sf);
2109  break;
2110  }
2112  MatrixDisplayDlg* mdd = qobject_cast<MatrixDisplayDlg*>(editor);
2113  if (!mdd) return;
2114 
2116  break;
2117  }
2119  MatrixDisplayDlg* mdd = qobject_cast<MatrixDisplayDlg*>(editor);
2120  if (!mdd) return;
2121 
2123  break;
2124  }
2126  MatrixDisplayDlg* mdd = qobject_cast<MatrixDisplayDlg*>(editor);
2127  if (!mdd) return;
2128 
2130  assert(sensor);
2131 
2133  if (sensor->getActiveAbsoluteTransformation(trans)) {
2134  mdd->fillDialogWith(trans);
2135  } else {
2136  mdd->clear();
2137  mdd->setEnabled(false);
2138  }
2139  break;
2140  }
2141  case TREE_VIEW_HEADER: {
2142  QLabel* label = qobject_cast<QLabel*>(editor);
2143  if (label) label->setText(item->accessibleDescription());
2144  break;
2145  }
2146  case OBJECT_OCTREE_TYPE: {
2148  assert(octree);
2149  SetComboBoxIndex(editor,
2150  static_cast<int>(octree->getDisplayMode()));
2151  break;
2152  }
2153  case OBJECT_OCTREE_LEVEL: {
2155  assert(octree);
2156  SetSpinBoxValue(editor, octree ? octree->getDisplayedLevel() : 0);
2157  break;
2158  }
2160  ccGenericPrimitive* primitive =
2162  assert(primitive);
2164  editor,
2165  primitive
2166  ? static_cast<int>(primitive->getDrawingPrecision())
2167  : 0);
2168  break;
2169  }
2170  case OBJECT_CIRCLE_RESOLUTION: {
2172  assert(circle);
2173  SetSpinBoxValue(editor, circle ? circle->getResolution() : 0);
2174  break;
2175  }
2176  case OBJECT_SPHERE_RADIUS: {
2178  assert(sphere);
2180  editor,
2181  sphere ? static_cast<double>(sphere->getRadius()) : 0.0);
2182  break;
2183  }
2184  case OBJECT_CIRCLE_RADIUS: {
2186  assert(circle);
2187  SetDoubleSpinBoxValue(editor, circle ? circle->getRadius() : 0.0);
2188  break;
2189  }
2190  case OBJECT_DISC_RADIUS: {
2192  assert(disc);
2194  editor,
2195  disc ? static_cast<double>(disc->getRadius()) : 0.0);
2196  break;
2197  }
2198  case OBJECT_CONE_HEIGHT: {
2200  assert(cone);
2202  editor,
2203  cone ? static_cast<double>(cone->getHeight()) : 0.0);
2204  break;
2205  }
2208  assert(cone);
2210  editor,
2211  cone ? static_cast<double>(cone->getBottomRadius()) : 0.0);
2212  break;
2213  }
2214  case OBJECT_CONE_TOP_RADIUS: {
2216  assert(cone);
2218  editor,
2219  cone ? static_cast<double>(cone->getTopRadius()) : 0.0);
2220  break;
2221  }
2222  case OBJECT_IMAGE_ALPHA: {
2223  QSlider* slider = qobject_cast<QSlider*>(editor);
2224  if (!slider) return;
2225 
2227  assert(image);
2228  slider->setValue(static_cast<int>(image->getAlpha() * 255.0f));
2229  // slider->setTickPosition(QSlider::NoTicks);
2230  break;
2231  }
2233  // ParaView-style: editor is a container with slider + spinbox
2234  QWidget* container = qobject_cast<QWidget*>(editor);
2235  if (!container) return;
2236 
2237  // Find the slider and spinbox in the container
2238  QSlider* slider = container->findChild<QSlider*>();
2239  QDoubleSpinBox* spinBox = container->findChild<QDoubleSpinBox*>();
2240 
2241  // Get current light intensity from backend (default 1.0 for normal
2242  // intensity)
2243  double intensity = 1.0; // Default
2246  }
2247 
2248  // Set both controls (slider triggers spinbox sync via signal)
2249  if (slider) {
2250  slider->setValue(static_cast<int>(intensity * 100.0));
2251  }
2252  if (spinBox) {
2253  spinBox->setValue(intensity);
2254  }
2255  } break;
2256  case OBJECT_OPACITY: {
2257  // ParaView-style: editor is a container with slider + spinbox
2258  QWidget* container = qobject_cast<QWidget*>(editor);
2259  if (!container) return;
2260 
2261  // Find the slider and spinbox in the container
2262  QSlider* slider = container->findChild<QSlider*>();
2263  QDoubleSpinBox* spinBox = container->findChild<QDoubleSpinBox*>();
2264 
2265  // Get current opacity from the object [0.0, 1.0]
2266  // For folders, calculate average opacity from all renderable
2267  // children
2268  float opacity = m_currentObject->getOpacity();
2269 
2270  if (m_currentObject->getChildrenNumber() > 0) {
2271  // This is a folder - calculate average opacity from renderable
2272  // children
2273  float totalOpacity = 0.0f;
2274  int renderableCount = 0;
2275 
2276  std::function<void(ccHObject*)> collectOpacity =
2277  [&collectOpacity, &totalOpacity,
2278  &renderableCount](ccHObject* obj) {
2279  if (!obj || !obj->isEnabled()) return;
2280 
2281  // Check if this is a renderable object
2282  if (obj->isKindOf(CV_TYPES::POINT_CLOUD) ||
2283  obj->isKindOf(CV_TYPES::MESH) ||
2284  obj->isKindOf(CV_TYPES::PRIMITIVE) ||
2285  obj->isKindOf(CV_TYPES::POLY_LINE) ||
2286  obj->isKindOf(CV_TYPES::FACET)) {
2287  totalOpacity += obj->getOpacity();
2288  renderableCount++;
2289  }
2290 
2291  // Recursively process children
2292  for (unsigned i = 0; i < obj->getChildrenNumber();
2293  ++i) {
2294  collectOpacity(obj->getChild(i));
2295  }
2296  };
2297 
2298  collectOpacity(m_currentObject);
2299 
2300  if (renderableCount > 0) {
2301  opacity = totalOpacity / renderableCount;
2302  }
2303  }
2304 
2305  // Set both controls (slider triggers spinbox sync via signal)
2306  if (slider) {
2307  slider->setValue(static_cast<int>(opacity * 100.0f));
2308  }
2309  if (spinBox) {
2310  spinBox->setValue(static_cast<double>(opacity));
2311  }
2312  break;
2313  }
2315  // ParaView-style: editor is a container with checkbox + edit button
2316  QWidget* container = qobject_cast<QWidget*>(editor);
2317  if (!container || !m_currentObject) return;
2318 
2319  // Find the checkbox in the container
2320  QCheckBox* checkbox = container->findChild<QCheckBox*>();
2321  if (!checkbox) return;
2322 
2323  // Get current visibility from backend
2324  QString viewID = m_currentObject->getViewId();
2325  AxesGridProperties props;
2327  props);
2328 
2329  // Set checkbox state
2330  checkbox->setChecked(props.visible);
2331 
2332  // Connect checkbox signal to update handler (disconnect first to
2333  // avoid duplicates)
2334  disconnect(checkbox, nullptr, this, nullptr);
2335  connect(checkbox, &QCheckBox::toggled, this,
2336  [this, viewID](bool checked) {
2337  if (!ecvDisplayTools::TheInstance()) return;
2338 
2339  // Get current properties using struct-based interface
2340  AxesGridProperties props;
2342  ->getDataAxesGridProperties(viewID, props);
2343 
2344  // Update visibility
2345  props.visible = checked;
2346 
2347  // Bounds will be automatically recalculated in
2348  // SetDataAxesGridProperties if useCustomBounds is false
2349  // For parent nodes/folders, bounds will be calculated
2350  // from getDisplayBB_recursive(false) which includes all
2351  // children
2353  ->setDataAxesGridProperties(viewID, props);
2354 
2355  // Immediately update bbox visibility for all selected
2356  // objects that use this viewID
2357  if (MainWindow::TheInstance()) {
2358  const ccHObject::Container& selectedEntities =
2360  ->getSelectedEntities();
2361  const ecvGui::ParamStruct& params =
2363 
2364  for (ccHObject* entity : selectedEntities) {
2365  if (entity && entity->getViewId() == viewID) {
2367  context.viewID = viewID;
2368 
2369  // If axes grid is now visible, immediately
2370  // hide bbox
2371  if (checked) {
2372  entity->hideBB(context);
2373  } else {
2374  // If axes grid is hidden, check if bbox
2375  // should be shown
2376  if (params.showBBOnSelected) {
2377  entity->showBB(context);
2378  } else {
2379  entity->hideBB(context);
2380  }
2381  }
2382  }
2383  }
2384  }
2385 
2387  });
2388  break;
2389  }
2390  case OBJECT_SENSOR_INDEX: {
2392  assert(sensor);
2393  SetDoubleSpinBoxValue(editor,
2394  sensor ? sensor->getActiveIndex() : 0.0);
2395  break;
2396  }
2398  QLineEdit* lineEdit = qobject_cast<QLineEdit*>(editor);
2399  if (!lineEdit) return;
2400 
2402  assert(sensor);
2403  lineEdit->setText(QString::number(
2404  sensor ? static_cast<double>(sensor->getUncertainty()) : 0,
2405  'g', 8));
2406  break;
2407  }
2410  assert(sensor);
2412  editor,
2413  sensor ? static_cast<double>(sensor->getGraphicScale())
2414  : 0.0);
2415  break;
2416  }
2420  assert(buffer);
2422  editor, buffer ? static_cast<double>(
2423  buffer->triherdonsDisplayScale())
2424  : 0.0);
2425  break;
2426  }
2427  case OBJECT_CLOUD_POINT_SIZE: {
2428  ccGenericPointCloud* cloud =
2430  assert(cloud);
2431  SetComboBoxIndex(editor, static_cast<int>(cloud->getPointSize()));
2432  break;
2433  }
2434  case OBJECT_POLYLINE_WIDTH: {
2436  assert(poly);
2437  SetComboBoxIndex(editor, static_cast<int>(poly->getWidth()));
2438  break;
2439  }
2440  case OBJECT_COLOR_SOURCE: {
2441  int currentIndex = 0; // no color
2442  int lastIndex = currentIndex;
2443  if (m_currentObject->hasColors()) {
2444  ++lastIndex;
2445  if (m_currentObject->colorsShown()) currentIndex = lastIndex;
2446  }
2448  ++lastIndex;
2449  if (m_currentObject->sfShown()) currentIndex = lastIndex;
2450  }
2451  SetComboBoxIndex(editor, currentIndex);
2452  break;
2453  }
2454  // Note: OBJECT_SELECTION_PROPERTIES case removed - selection
2455  // properties are now in standalone cvFindDataDockWidget
2456  default:
2457  QStyledItemDelegate::setEditorData(editor, index);
2458  break;
2459  }
2460 }
2461 
2462 void ccPropertiesTreeDelegate::updateItem(QStandardItem* item) {
2463  if (!m_currentObject || item->column() == 0 || !item->data().isValid())
2464  return;
2465 
2466  bool redraw = false;
2467  switch (item->data().toInt()) {
2468  case OBJECT_NAME: {
2469  m_currentObject->setName(item->text());
2471  } break;
2472  case OBJECT_VISIBILITY: {
2473  bool objectWasDisplayed = m_currentObject->isDisplayed();
2476  if (label) {
2477  label->setVisible(item->checkState() == Qt::Checked);
2478  label->updateLabel();
2479  break;
2480  }
2482  cc2DViewportLabel* label =
2484  if (label) {
2485  label->setVisible(item->checkState() == Qt::Checked);
2486  label->updateLabel();
2487  break;
2488  }
2489  } else if (m_currentObject->isKindOf(CV_TYPES::FACET)) {
2490  ccPlanarEntityInterface* plane =
2492  assert(plane);
2493  if (plane) {
2494  plane->showNormalVector(item->checkState() == Qt::Checked);
2498  break;
2499  }
2500  } else if (m_currentObject->isKindOf(CV_TYPES::SENSOR)) {
2502  if (sensor) {
2503  sensor->setVisible(item->checkState() == Qt::Checked);
2505  context.visible =
2506  sensor->isVisible() && sensor->isEnabled();
2507  sensor->hideShowDrawings(context);
2508  // for bbox
2509  context.viewID = sensor->getViewId();
2510  if (sensor->isSelected() && sensor->isEnabled()) {
2511  // Check if Axes Grid is visible - if so, hide
2512  // BoundingBox
2513  bool shouldShowBB = true;
2515  AxesGridProperties axesGridProps;
2518  axesGridProps);
2519  if (axesGridProps.visible) {
2520  shouldShowBB = false;
2521  }
2522  }
2523  if (shouldShowBB) {
2524  sensor->showBB(context);
2525  } else {
2526  sensor->hideBB(context);
2527  }
2528  } else {
2529  sensor->hideBB(context);
2530  }
2532  break;
2533  }
2535  ccGenericPrimitive* prim =
2537  if (prim) {
2538  prim->setVisible(item->checkState() == Qt::Checked);
2540  context.visible = prim->isVisible() && prim->isEnabled();
2541  prim->hideShowDrawings(context);
2542  // for bbox
2543  context.viewID = prim->getViewId();
2544  if (prim->isSelected() && prim->isEnabled()) {
2545  // Check if Axes Grid is visible - if so, hide
2546  // BoundingBox
2547  bool shouldShowBB = true;
2549  AxesGridProperties axesGridProps;
2552  axesGridProps);
2553  if (axesGridProps.visible) {
2554  shouldShowBB = false;
2555  }
2556  }
2557  if (shouldShowBB) {
2558  prim->showBB(context);
2559  } else {
2560  prim->hideBB(context);
2561  }
2562  } else {
2563  prim->hideBB(context);
2564  }
2566  break;
2567  }
2568  } else {
2569  m_currentObject->setVisible(item->checkState() == Qt::Checked);
2570  }
2571 
2573 
2574  bool objectIsDisplayed = m_currentObject->isDisplayed();
2575  if (objectWasDisplayed != objectIsDisplayed) {
2576  if (m_currentObject->isGroup())
2578  false);
2579  else
2581  }
2582  } break;
2583  case OBJECT_NORMALS_SHOWN: {
2584  m_currentObject->showNormals(item->checkState() == Qt::Checked);
2588  }
2589  }
2590  redraw = true;
2591  break;
2592  case OBJECT_MATERIALS: {
2593  ccGenericMesh* mesh =
2595  assert(mesh);
2596  mesh->showMaterials(item->checkState() == Qt::Checked);
2598  mesh->setRedrawFlagRecursive(true);
2599  }
2600  redraw = true;
2601  break;
2602  case OBJECT_SF_SHOW_SCALE: {
2603  ccPointCloud* cloud =
2605  assert(cloud);
2606  cloud->showSFColorsScale(item->checkState() == Qt::Checked);
2608  cloud->setRedrawFlagRecursive(true);
2610  }
2611  redraw = false;
2612  break;
2614  ccCoordinateSystem* cs =
2616  if (cs) {
2617  cs->ShowAxisLines(item->checkState() == Qt::Checked);
2619  context.visible = cs->isVisible();
2622  }
2623  }
2624  redraw = false;
2625  break;
2627  ccCoordinateSystem* cs =
2629  if (cs) {
2630  cs->ShowAxisPlanes(item->checkState() == Qt::Checked);
2632  cs->setRedrawFlagRecursive(true);
2633  }
2634  }
2635  redraw = true;
2636  break;
2637  case OBJECT_FACET_CONTOUR: {
2639  assert(facet);
2640  if (facet && facet->getContour()) {
2641  facet->getContour()->setVisible(item->checkState() ==
2642  Qt::Checked);
2644  }
2645  }
2646  redraw = true;
2647  break;
2648  case OBJECT_FACET_MESH: {
2650  assert(facet);
2651  if (facet && facet->getPolygon()) {
2652  facet->getPolygon()->setVisible(item->checkState() ==
2653  Qt::Checked);
2655  }
2656  }
2657  redraw = true;
2658  break;
2660  ccPlanarEntityInterface* plane =
2662  assert(plane);
2663  if (plane) {
2664  plane->showNormalVector(item->checkState() == Qt::Checked);
2667  }
2668  }
2669  redraw = true;
2670  break;
2671  case OBJECT_MESH_WIRE: {
2672  ccGenericMesh* mesh =
2674  assert(mesh);
2675  mesh->showWired(item->checkState() == Qt::Checked);
2677 
2678  // unchecked points frame mode
2679  if (mesh->isShownAsWire()) {
2680  QStandardItem* item =
2681  ITEM(tr("Pointsframe"), Qt::ItemIsUserCheckable,
2683  item->setCheckable(true);
2684  item->setCheckState(Qt::Unchecked);
2685  }
2686  }
2687  redraw = true;
2688  break;
2689 
2690  case OBJECT_MESH_POINTS: {
2691  ccGenericMesh* mesh =
2693  assert(mesh);
2694  mesh->showPoints(item->checkState() == Qt::Checked);
2696 
2697  // unchecked wired frame mode
2698  if (mesh->isShownAsPoints()) {
2699  QStandardItem* item =
2700  ITEM(tr("Wireframe"), Qt::ItemIsUserCheckable,
2702  item->setCheckable(true);
2703  item->setCheckState(Qt::Unchecked);
2704  }
2705  }
2706  redraw = true;
2707  break;
2708  case OBJECT_MESH_STIPPLING: {
2709  ccGenericMesh* mesh =
2711  assert(mesh);
2712  mesh->enableStippling(item->checkState() == Qt::Checked);
2714  }
2715  redraw = true;
2716  break;
2717  case OBJECT_LABEL_DISP_2D: {
2719  assert(label);
2720  label->setDisplayedIn2D(item->checkState() == Qt::Checked);
2723  label->update2DLabelView(context);
2724  }
2725  redraw = false;
2726  break;
2729  assert(label);
2730  label->displayPointLegend(item->checkState() == Qt::Checked);
2733  label->update2DLabelView(context);
2734  }
2735  redraw = false;
2736  break;
2737  case OBJECT_NAME_IN_3D: {
2738  m_currentObject->showNameIn3D(item->checkState() == Qt::Checked);
2740  }
2741  redraw = true;
2742  break;
2746  assert(buffer);
2747  buffer->showPathAsPolyline(item->checkState() == Qt::Checked);
2748  }
2749  redraw = true;
2750  break;
2754  assert(buffer);
2755  buffer->showTriherdons(item->checkState() == Qt::Checked);
2756  }
2757  redraw = true;
2758  break;
2760  ccCameraSensor* sensor =
2762  sensor->drawFrustum(item->checkState() == Qt::Checked);
2764  sensor->setRedrawFlagRecursive(true);
2766  }
2767  redraw = false;
2768  break;
2770  ccCameraSensor* sensor =
2772  sensor->drawFrustumPlanes(item->checkState() == Qt::Checked);
2774  sensor->setRedrawFlagRecursive(true);
2776  }
2777  redraw = false;
2778  break;
2779  // ParaView-style View Properties handlers
2781  bool visible = (item->checkState() == Qt::Checked);
2783  CVLog::Print(
2784  QString("[View Properties] Camera Orientation Widget: %1")
2785  .arg(visible ? "ON" : "OFF"));
2786  }
2787  redraw = false;
2788  break;
2790  // Light intensity is handled by editor's signal connection
2791  // The slider/spinbox valueChanged signal triggers the update
2792  // No action needed here in updateItem
2793  }
2794  redraw = false;
2795  break;
2797  // ParaView-style: handled in setEditorData (persistent editor)
2798  // No action needed here in updateItem
2799  }
2800  redraw = false;
2801  break;
2802  }
2803 
2804  if (redraw) {
2805  updateDisplay();
2806  }
2807 }
2808 
2809 void ccPropertiesTreeDelegate::updateDisplay() {
2810  ccHObject* object = m_currentObject;
2811  if (!object) return;
2812 
2813  bool objectIsDisplayed = object->isDisplayed();
2814  if (!objectIsDisplayed) {
2815  // DGM: point clouds may be mesh vertices of meshes which may depend on
2816  // several of their parameters
2817  if (object->isKindOf(CV_TYPES::POINT_CLOUD)) {
2818  ccHObject* parent = object->getParent();
2819  if (parent && parent->isKindOf(CV_TYPES::MESH) &&
2820  parent->isDisplayed()) // specific case: vertices
2821  {
2822  object = parent;
2823  objectIsDisplayed = true;
2824  }
2825  }
2826  // Allows show name toggle on normally non-visible objects to update the
2827  // screen
2828  else if (object->isKindOf(CV_TYPES::HIERARCHY_OBJECT)) {
2829  objectIsDisplayed = true;
2830  }
2831  }
2832 
2833  if (objectIsDisplayed) {
2834  if (object->isGroup())
2836  else
2838  }
2839 }
2840 
2842  // simply re-fill model!
2844 }
2845 
2846 // Note: updateSelectionProperties has been removed. Selection properties
2847 // updates are now handled directly by cvFindDataDockWidget.
2848 
2850  const {
2851  if (!m_currentObject) {
2852  return QMap<QString, QString>();
2853  }
2855  QMap<QString, QString>());
2856 }
2857 
2859  if (mesh) {
2860  m_meshTexturePathMaps.remove(mesh);
2861  }
2862 }
2863 
2864 void ccPropertiesTreeDelegate::scalarFieldChanged(int pos) {
2865  if (!m_currentObject) return;
2866 
2868  if (cloud && cloud->getCurrentDisplayedScalarFieldIndex() + 1 != pos) {
2869  cloud->setCurrentDisplayedScalarField(pos - 1);
2870  cloud->showSF(pos > 0);
2871 
2872  updateCurrentEntity(pos > 0);
2873 
2874  // we must also reset the properties display!
2875  updateModel();
2876  }
2877 }
2878 
2879 void ccPropertiesTreeDelegate::spawnTextureFileEditor() {
2880  if (!m_currentObject) return;
2881 
2882  ecvTextureFileSelector* selector =
2883  dynamic_cast<ecvTextureFileSelector*>(QObject::sender());
2884  if (!selector) return;
2885 
2886  // get current material
2888  assert(mesh);
2889  const ccMaterialSet* materialSet = mesh ? mesh->getMaterialSet() : nullptr;
2890  if (materialSet) {
2891  // persistent settings
2892  QString currentPath =
2896  .toString();
2897  QString currentOpenDlgFilter =
2900  "*.png")
2901  .toString();
2902 
2903  QStringList fileFilters;
2904  // we grab the list of supported image file formats (reading)
2905  QList<QByteArray> formats = QImageReader::supportedImageFormats();
2906  if (formats.empty()) {
2907  fileFilters << "*.bmp"
2908  << "*.png"
2909  << "*.jpg"
2910  << "Image file (*.*)";
2911  } else {
2912  // we convert this list into a proper "filters" string
2913  for (int i = 0; i < formats.size(); ++i) {
2914  QString filter = QString("*.%1").arg(formats[i].data());
2915  fileFilters.append(filter);
2916  }
2917  fileFilters.append("Image file (*.*)");
2918  }
2919 
2920  // dialog options
2921  QFileDialog::Options dialogOptions = QFileDialog::Options();
2922  if (!ecvOptions::Instance().useNativeDialogs) {
2923  dialogOptions |= QFileDialog::DontUseNativeDialog;
2924  }
2925 
2926  // file choosing dialog
2927  QString selectedFiles = QFileDialog::getOpenFileName(
2928  MainWindow::TheInstance(), tr("Open Texture file(s)"),
2929  currentPath, fileFilters.join(";;"), &currentOpenDlgFilter,
2930  dialogOptions);
2931 
2932  if (selectedFiles.isEmpty()) return;
2933 
2934  // persistent save last loading parameters
2935  currentPath = QFileInfo(selectedFiles).absolutePath();
2937  currentPath);
2940  currentOpenDlgFilter);
2941 
2942  if (QFileInfo(selectedFiles).exists() && mesh) {
2943  // Add to current mesh's texture path map
2944  QMap<QString, QString>& texturePathMap =
2946  QString fileName = QFileInfo(selectedFiles).fileName();
2947  texturePathMap[fileName] = selectedFiles;
2948  selector->addItem(fileName, selectedFiles);
2949  selector->setSelectedTexturefile(selectedFiles);
2950  }
2951 
2952  updateModel();
2953  }
2954 }
2955 
2956 void ccPropertiesTreeDelegate::spawnColorRampEditor() {
2957  if (!m_currentObject) return;
2958 
2960  assert(cloud);
2961  ccScalarField* sf =
2962  (cloud ? static_cast<ccScalarField*>(
2964  : nullptr);
2965  if (sf) {
2970  editorDialog->setAssociatedScalarField(sf);
2971  if (editorDialog->exec()) {
2972  if (editorDialog->getActiveScale()) {
2973  sf->setColorScale(editorDialog->getActiveScale());
2974  updateCurrentEntity();
2975  }
2976 
2977  // save current scale manager state to persistent settings
2979 
2980  updateModel();
2981  }
2982  }
2983 }
2984 
2985 void ccPropertiesTreeDelegate::textureFileChanged(int pos) {
2986  if (!m_currentObject) return;
2987 
2988  if (pos < 0) {
2989  assert(false);
2990  return;
2991  }
2992 
2993  ecvTextureFileSelector* selector =
2994  dynamic_cast<ecvTextureFileSelector*>(QObject::sender());
2995  if (!selector) return;
2996 
2997  QString textureFilepath = selector->getTexturefilePath(pos);
2998  if (textureFilepath.isEmpty()) {
2999  return;
3000  }
3001 
3002  if (!QFileInfo(textureFilepath).exists()) {
3003  CVLog::Error(
3004  tr("Internal error: texture file : %1 doesn't exist anymore!")
3005  .arg(textureFilepath));
3006  return;
3007  }
3008 
3009  // get current material
3011  assert(mesh);
3012  const ccMaterialSet* materialSet = mesh ? mesh->getMaterialSet() : nullptr;
3013  if (materialSet && materialSet->findMaterialByName(
3014  QFileInfo(textureFilepath).fileName()) < 0) {
3015  if (!mesh->updateTextures(CVTools::FromQString(textureFilepath))) {
3017  "Update Textures failed, please toggle shown material "
3018  "first!");
3019  } else {
3021  }
3022 
3023  updateModel();
3024  }
3025 }
3026 
3027 void ccPropertiesTreeDelegate::colorScaleChanged(int pos) {
3028  if (!m_currentObject) return;
3029 
3030  if (pos < 0) {
3031  assert(false);
3032  return;
3033  }
3034 
3035  ccColorScaleSelector* selector =
3036  dynamic_cast<ccColorScaleSelector*>(QObject::sender());
3037  if (!selector) return;
3038 
3039  ccColorScale::Shared colorScale = selector->getScale(pos);
3040  if (!colorScale) {
3041  CVLog::Error(tr(
3042  "Internal error: color scale doesn't seem to exist anymore!"));
3043  return;
3044  }
3045 
3046  // get current SF
3048  assert(cloud);
3049  ccScalarField* sf = cloud ? static_cast<ccScalarField*>(
3051  : nullptr;
3052  if (sf && sf->getColorScale() != colorScale) {
3053  sf->setColorScale(colorScale);
3054 
3055  updateCurrentEntity();
3056  updateModel();
3057  }
3058 }
3059 
3060 void ccPropertiesTreeDelegate::colorRampStepsChanged(int pos) {
3061  if (!m_currentObject) return;
3062 
3064  assert(cloud);
3065  ccScalarField* sf = static_cast<ccScalarField*>(
3067  if (sf && sf->getColorRampSteps() != static_cast<unsigned>(pos)) {
3068  sf->setColorRampSteps(static_cast<unsigned>(pos));
3069  updateCurrentEntity();
3070  }
3071 }
3072 
3073 void ccPropertiesTreeDelegate::octreeDisplayModeChanged(int pos) {
3074  if (!m_currentObject) return;
3075  QComboBox* comboBox = dynamic_cast<QComboBox*>(QObject::sender());
3076  if (!comboBox) return;
3077 
3079  assert(octree);
3080 
3081  int mode = comboBox->itemData(pos, Qt::UserRole).toInt();
3082  if (octree->getDisplayMode() != mode) {
3083  octree->setDisplayMode(static_cast<ccOctree::DisplayMode>(mode));
3084 
3086  ccOctreeProxy* octreeProxy =
3088  octreeProxy->setRedrawFlagRecursive(true);
3089 
3090  updateDisplay();
3091  }
3092 }
3093 
3094 void ccPropertiesTreeDelegate::octreeDisplayedLevelChanged(int val) {
3095  if (!m_currentObject) return;
3096 
3098  assert(octree);
3099 
3100  if (octree->getDisplayedLevel() != val) // to avoid infinite loops!
3101  {
3102  octree->setDisplayedLevel(val);
3103 
3104  updateCurrentEntity();
3105 
3106  // we must also reset the properties display!
3107  updateModel();
3108  }
3109 }
3110 
3111 void ccPropertiesTreeDelegate::circleResolutionChanged(int val) {
3112  if (!m_currentObject) {
3113  return;
3114  }
3115 
3117  assert(circle);
3118  if (!circle) return;
3119 
3120  if (circle->getResolution() != static_cast<unsigned int>(val)) {
3121  bool wasVisible = circle->isVisible();
3122  circle->setResolution(val);
3123  circle->setVisible(wasVisible);
3124 
3125  updateCurrentEntity();
3126 
3127  // record item role to force the scroll focus (see 'createEditor').
3129 
3130  // we must also reset the properties display!
3131  updateModel();
3132  }
3133 }
3134 
3135 void ccPropertiesTreeDelegate::circleRadiusChanged(double val) {
3136  if (!m_currentObject) return;
3137 
3139  assert(circle);
3140  if (!circle) return;
3141 
3142  if (circle->getRadius() != val) {
3143  bool wasVisible = circle->isVisible();
3144  circle->setRadius(val);
3145  circle->setVisible(wasVisible);
3146 
3147  updateCurrentEntity();
3148 
3149  // record item role to force the scroll focus (see 'createEditor').
3151 
3152  // we must also reset the properties display!
3153  updateModel();
3154  }
3155 }
3156 
3157 void ccPropertiesTreeDelegate::discRadiusChanged(double val) {
3158  if (!m_currentObject) return;
3159 
3161  assert(disc);
3162  if (!disc) return;
3163 
3164  PointCoordinateType radius = static_cast<PointCoordinateType>(val);
3165  if (disc->getRadius() != radius) {
3166  disc->setRadius(radius);
3167 
3168  updateCurrentEntity();
3169 
3170  // record item role to force the scroll focus (see 'createEditor').
3172  updateModel();
3173  }
3174 }
3175 
3176 void ccPropertiesTreeDelegate::primitivePrecisionChanged(int val) {
3177  if (!m_currentObject) return;
3178 
3179  ccGenericPrimitive* primitive =
3181  assert(primitive);
3182 
3183  if (primitive->getDrawingPrecision() != static_cast<unsigned int>(val)) {
3184  bool wasVisible = primitive->isVisible();
3185  primitive->setDrawingPrecision(static_cast<unsigned>(val));
3186  primitive->setVisible(wasVisible);
3187 
3188  updateCurrentEntity();
3189 
3190  // we must also reset the properties display!
3191  updateModel();
3192  }
3193 }
3194 
3195 void ccPropertiesTreeDelegate::sphereRadiusChanged(double val) {
3196  if (!m_currentObject) return;
3197 
3199  assert(sphere);
3200 
3201  PointCoordinateType radius = static_cast<PointCoordinateType>(val);
3202  if (sphere->getRadius() != radius) {
3203  bool wasVisible = sphere->isVisible();
3204  sphere->setRadius(radius);
3205  sphere->setVisible(wasVisible);
3206 
3207  updateCurrentEntity();
3208 
3209  // we must also reset the properties display!
3210  updateModel();
3211  }
3212 }
3213 
3214 void ccPropertiesTreeDelegate::coneHeightChanged(double val) {
3215  if (!m_currentObject) return;
3216 
3218  assert(cone);
3219 
3220  PointCoordinateType height = static_cast<PointCoordinateType>(val);
3221  if (cone->getHeight() != height) {
3222  bool wasVisible = cone->isVisible();
3223  cone->setHeight(height);
3224  cone->setVisible(wasVisible);
3225 
3226  updateCurrentEntity();
3227 
3228  // we must also reset the properties display!
3229  updateModel();
3230  }
3231 }
3232 
3233 void ccPropertiesTreeDelegate::coneBottomRadiusChanged(double val) {
3234  if (!m_currentObject) return;
3235 
3237  assert(cone);
3238 
3239  PointCoordinateType radius = static_cast<PointCoordinateType>(val);
3240  if (cone->getBottomRadius() != radius) {
3241  bool wasVisible = cone->isVisible();
3242  cone->setBottomRadius(radius); // works for both the bottom and top
3243  // radii for cylinders!
3244  cone->setVisible(wasVisible);
3245 
3246  updateCurrentEntity();
3247 
3248  // we must also reset the properties display!
3249  updateModel();
3250  }
3251 }
3252 
3253 void ccPropertiesTreeDelegate::coneTopRadiusChanged(double val) {
3254  if (!m_currentObject) return;
3255 
3257  assert(cone);
3258 
3259  PointCoordinateType radius = static_cast<PointCoordinateType>(val);
3260  if (cone->getTopRadius() != radius) {
3261  bool wasVisible = cone->isVisible();
3262  cone->setTopRadius(radius); // works for both the bottom and top radii
3263  // for cylinders!
3264  cone->setVisible(wasVisible);
3265 
3266  updateCurrentEntity();
3267 
3268  // we must also reset the properties display!
3269  updateModel();
3270  }
3271 }
3272 
3273 void ccPropertiesTreeDelegate::imageAlphaChanged(int val) {
3275 
3276  float alpha = val / 255.0f;
3277  if (image && image->getAlpha() != alpha) {
3278  image->setAlpha(alpha);
3280  alpha, CVTools::FromQString(image->getViewId()));
3281  }
3282 }
3283 
3284 void ccPropertiesTreeDelegate::opacityChanged(int val) {
3285  if (!m_currentObject) return;
3286 
3287  // Convert slider value [0, 100] to opacity [0.0, 1.0]
3288  float opacity = val / 100.0f;
3289 
3290  // Check if this is a folder with children
3291  if (m_currentObject->getChildrenNumber() > 0) {
3292  // For folders, apply opacity to all renderable children recursively
3293  std::function<void(ccHObject*, float)> applyOpacityRecursive =
3294  [&applyOpacityRecursive](ccHObject* obj, float op) {
3295  if (!obj || !obj->isEnabled()) return;
3296 
3297  // Check if this is a renderable object
3298  bool isRenderable = (obj->isKindOf(CV_TYPES::POINT_CLOUD) ||
3299  obj->isKindOf(CV_TYPES::MESH) ||
3300  obj->isKindOf(CV_TYPES::PRIMITIVE) ||
3301  obj->isKindOf(CV_TYPES::POLY_LINE) ||
3302  obj->isKindOf(CV_TYPES::FACET));
3303 
3304  if (isRenderable) {
3305  // Check if opacity actually changed to avoid
3306  // unnecessary updates
3307  if (std::abs(obj->getOpacity() - op) >= 0.001f) {
3308  obj->setOpacity(op);
3309 
3310  // Determine entity type for proper property
3311  // application
3312  ENTITY_TYPE entityType =
3314  if (obj->isKindOf(CV_TYPES::POINT_CLOUD)) {
3315  entityType = ENTITY_TYPE::ECV_POINT_CLOUD;
3316  } else if (obj->isKindOf(CV_TYPES::MESH) ||
3317  obj->isKindOf(CV_TYPES::PRIMITIVE)) {
3318  entityType = ENTITY_TYPE::ECV_MESH;
3319  } else if (obj->isKindOf(CV_TYPES::POLY_LINE)) {
3320  entityType = ENTITY_TYPE::ECV_LINES_3D;
3321  } else if (obj->isKindOf(CV_TYPES::FACET)) {
3322  entityType = ENTITY_TYPE::ECV_MESH;
3323  }
3324 
3325  // Create property parameter and apply opacity
3326  // change
3327  PROPERTY_PARAM param(obj, static_cast<double>(op));
3328  param.entityType = entityType;
3329  param.viewId = obj->getViewId();
3330  param.viewport = 0;
3331 
3332  // Apply the opacity change via display tools
3334  true);
3335  }
3336  }
3337 
3338  // Recursively process children
3339  for (unsigned i = 0; i < obj->getChildrenNumber(); ++i) {
3340  applyOpacityRecursive(obj->getChild(i), op);
3341  }
3342  };
3343 
3344  applyOpacityRecursive(m_currentObject, opacity);
3345 
3347  QString("[ccPropertiesTreeDelegate::opacityChanged] "
3348  "Set opacity to %1 for folder '%2' and all renderable "
3349  "children")
3350  .arg(opacity)
3351  .arg(m_currentObject->getName()));
3352  } else {
3353  // Single object - original behavior
3354  // Check if opacity actually changed to avoid unnecessary updates
3355  if (std::abs(m_currentObject->getOpacity() - opacity) < 0.001f) {
3356  return;
3357  }
3358 
3359  // Store the new opacity in the object
3360  m_currentObject->setOpacity(opacity);
3361 
3362  // Determine entity type for proper property application
3363  ENTITY_TYPE entityType = ENTITY_TYPE::ECV_POINT_CLOUD; // Default
3364 
3366  entityType = ENTITY_TYPE::ECV_POINT_CLOUD;
3367  } else if (m_currentObject->isKindOf(CV_TYPES::MESH) ||
3369  entityType = ENTITY_TYPE::ECV_MESH;
3371  entityType = ENTITY_TYPE::ECV_LINES_3D;
3372  } else if (m_currentObject->isKindOf(CV_TYPES::FACET)) {
3373  entityType = ENTITY_TYPE::ECV_MESH;
3374  }
3375 
3376  // Create property parameter and apply opacity change
3377  PROPERTY_PARAM param(m_currentObject, static_cast<double>(opacity));
3378  param.entityType = entityType;
3379  param.viewId = m_currentObject->getViewId();
3380  param.viewport = 0;
3381 
3382  // Apply the opacity change via display tools
3384 
3386  QString("[ccPropertiesTreeDelegate::opacityChanged] "
3387  "Set opacity to %1 for object '%2'")
3388  .arg(opacity)
3389  .arg(m_currentObject->getName()));
3390  }
3391 }
3392 
3393 void ccPropertiesTreeDelegate::applyImageViewport() {
3394  if (!m_currentObject) return;
3395 
3397  assert(image);
3398 
3399  if (image->getAssociatedSensor() &&
3400  image->getAssociatedSensor()->applyViewport()) {
3401  CVLog::Print("[ApplyImageViewport] Viewport applied");
3402  }
3403 }
3404 
3405 void ccPropertiesTreeDelegate::applySensorViewport() {
3406  if (!m_currentObject) return;
3407 
3409  assert(sensor);
3410 
3411  if (sensor->applyViewport()) {
3412  CVLog::Print(tr("[ApplySensorViewport] Viewport applied"));
3413  }
3414 }
3415 
3416 void ccPropertiesTreeDelegate::applyLabelViewport() {
3417  if (!m_currentObject) return;
3418 
3419  cc2DViewportObject* viewport =
3421  assert(viewport);
3422 
3425 }
3426 
3427 void ccPropertiesTreeDelegate::updateLabelViewport() {
3428  if (!m_currentObject) return;
3429 
3430  cc2DViewportObject* viewport =
3432  assert(viewport);
3433 
3435  CVLog::Print(tr("Viewport '%1' has been updated").arg(viewport->getName()));
3436 }
3437 
3438 void ccPropertiesTreeDelegate::sensorScaleChanged(double val) {
3439  if (!m_currentObject) return;
3440 
3442  assert(sensor);
3443 
3444  if (sensor &&
3445  sensor->getGraphicScale() != static_cast<PointCoordinateType>(val)) {
3446  sensor->setGraphicScale(static_cast<PointCoordinateType>(val));
3447  updateCurrentEntity();
3448  }
3449 }
3450 
3451 void ccPropertiesTreeDelegate::coordinateSystemDisplayScaleChanged(double val) {
3452  if (!m_currentObject) {
3453  return;
3454  }
3455 
3456  ccCoordinateSystem* cs =
3458  assert(cs);
3459 
3460  if (cs && cs->getDisplayScale() != static_cast<PointCoordinateType>(val)) {
3461  cs->setDisplayScale(static_cast<PointCoordinateType>(val));
3462  updateDisplay();
3463  }
3464 }
3465 
3466 void ccPropertiesTreeDelegate::sensorUncertaintyChanged() {
3467  if (!m_currentObject) return;
3468 
3469  QLineEdit* lineEdit = qobject_cast<QLineEdit*>(QObject::sender());
3470  if (!lineEdit) {
3471  assert(false);
3472  return;
3473  }
3474 
3476  assert(sensor);
3477 
3478  PointCoordinateType uncertainty =
3479  static_cast<PointCoordinateType>(lineEdit->text().toDouble());
3480  if (sensor && sensor->getUncertainty() != uncertainty) {
3481  sensor->setUncertainty(uncertainty);
3482  }
3483 }
3484 
3485 void ccPropertiesTreeDelegate::sensorIndexChanged(double val) {
3486  if (!m_currentObject) return;
3487 
3489  assert(sensor);
3490 
3491  if (sensor && sensor->getActiveIndex() != val) {
3492  sensor->setActiveIndex(val);
3493  updateCurrentEntity();
3494  }
3495 }
3496 
3497 void ccPropertiesTreeDelegate::trihedronsScaleChanged(double val) {
3498  if (!m_currentObject) return;
3499 
3502  assert(buffer);
3503 
3504  if (buffer && buffer->triherdonsDisplayScale() != static_cast<float>(val)) {
3505  buffer->setTriherdonsDisplayScale(static_cast<float>(val));
3506  if (buffer->triherdonsShown()) {
3507  updateCurrentEntity();
3508  }
3509  }
3510 }
3511 
3512 void ccPropertiesTreeDelegate::cloudPointSizeChanged(int size) {
3513  if (!m_currentObject) return;
3514 
3515  ccGenericPointCloud* cloud =
3517  assert(cloud);
3518 
3519  if (cloud && cloud->getPointSize() != size) {
3520  cloud->setPointSize(static_cast<unsigned>(size));
3521  updateCurrentEntity(false);
3522  }
3523 }
3524 
3525 void ccPropertiesTreeDelegate::polyineWidthChanged(int size) {
3526  if (!m_currentObject) return;
3527 
3529  assert(polyline);
3530 
3531  if (polyline &&
3532  polyline->getWidth() != static_cast<PointCoordinateType>(size)) {
3533  polyline->setWidth(static_cast<PointCoordinateType>(size));
3534  updateCurrentEntity(false);
3535  }
3536 }
3537 
3538 void ccPropertiesTreeDelegate::coordinateSystemAxisWidthChanged(int size) {
3539  if (!m_currentObject) {
3540  return;
3541  }
3542 
3543  ccCoordinateSystem* cs =
3545  assert(cs);
3546 
3547  if (cs && cs->getAxisWidth() != static_cast<PointCoordinateType>(size)) {
3548  cs->setAxisWidth(static_cast<PointCoordinateType>(size));
3549  updateDisplay();
3550  }
3551 }
3552 
3553 void ccPropertiesTreeDelegate::objectDisplayChanged(
3554  const QString& newDisplayTitle) {
3555  if (!m_currentObject) return;
3556 
3557  QString actualDisplayTitle = Settings::APP_TITLE;
3558 
3559  if (actualDisplayTitle != newDisplayTitle) {
3560  // we first mark the "old displays" before removal,
3561  // to be sure that they will also be redrawn!
3562  // m_currentObject->prepareDisplayForRefresh_recursive();
3563 
3564  // ccGLWindow* win = MainWindow::GetGLWindow(newDisplayTitle);
3565  // m_currentObject->setDisplay_recursive(win);
3566  // if (win)
3567  //{
3568  // m_currentObject->prepareDisplayForRefresh_recursive();
3569  // win->zoomGlobal();
3570  // }
3571 
3572  // MainWindow::TheInstance()->refreshAll();
3573  }
3574 }
3575 
3576 void ccPropertiesTreeDelegate::colorSourceChanged(const QString& source) {
3577  if (!m_currentObject) return;
3578 
3579  bool appearanceChanged = false;
3580 
3582 
3583  if (source == s_noneString) {
3584  appearanceChanged =
3586  m_currentObject->showColors(false);
3587  m_currentObject->showSF(false);
3588  } else if (source == s_rgbColor) {
3589  appearanceChanged =
3591  m_currentObject->showColors(true);
3592  m_currentObject->showSF(false);
3593  if (m_currentObject->hasColors() &&
3596  }
3597  } else if (source == s_sfColor) {
3598  appearanceChanged =
3600  m_currentObject->showColors(false);
3601  m_currentObject->showSF(true);
3602  } else {
3603  // assert(false);
3604  CVLog::Warning(QString("unsupported source type [%1]").arg(source));
3605  }
3606 
3607  if (appearanceChanged) {
3608  updateDisplay();
3609  } else {
3611  }
3612 }
3613 
3614 void ccPropertiesTreeDelegate::updateCurrentEntity(bool redraw /* = true*/) {
3617  updateDisplay();
3618 }
3619 
3620 // ParaView-style View Properties implementation
3621 
3622 void ccPropertiesTreeDelegate::lightIntensityChanged(double intensity) {
3624  return;
3625  }
3626 
3627  // Apply light intensity to backend
3629 
3630  // Trigger screen update
3632 }
3633 
3634 void ccPropertiesTreeDelegate::dataAxesGridEditRequested() {
3635  // Get viewID from current object
3636  if (!m_currentObject) {
3637  return;
3638  }
3639 
3640  QString viewID = m_currentObject->getViewId();
3641  if (viewID.isEmpty()) {
3642  return;
3643  }
3644 
3645  // Check if we have a valid display tools instance
3647  return;
3648  }
3649 
3650  // Create and show dialog with current properties
3651  ecvAxesGridDialog dialog(tr("Data Axes Grid Properties"), m_view);
3652 
3653  // Get current properties from backend (using struct-based interface)
3654  AxesGridProperties props;
3655 
3656  try {
3658  props);
3659  } catch (const std::exception& e) {
3661  QString("[Data Axes Grid] Exception getting properties: %1")
3662  .arg(e.what()));
3663  props = AxesGridProperties();
3664  } catch (...) {
3665  CVLog::Warning("[Data Axes Grid] Unknown exception getting properties");
3666  props = AxesGridProperties();
3667  }
3668 
3669  // Set current values in dialog from backend
3670  try {
3671  // Clamp color values to valid range [0, 255]
3672  int r = std::max(0, std::min(255, static_cast<int>(props.color.x)));
3673  int g = std::max(0, std::min(255, static_cast<int>(props.color.y)));
3674  int b = std::max(0, std::min(255, static_cast<int>(props.color.z)));
3675  dialog.setColor(QColor::fromRgb(r, g, b));
3676 
3677  // Set all properties from backend
3678  dialog.setLineWidth(props.lineWidth);
3679  dialog.setOpacity(props.opacity);
3680  dialog.setShowLabels(props.showLabels);
3681  dialog.setShowGrid(props.showGrid);
3682  dialog.setXTitle(props.xTitle);
3683  dialog.setYTitle(props.yTitle);
3684  dialog.setZTitle(props.zTitle);
3685  dialog.setXAxisUseCustomLabels(props.xUseCustomLabels);
3686  dialog.setYAxisUseCustomLabels(props.yUseCustomLabels);
3687  dialog.setZAxisUseCustomLabels(props.zUseCustomLabels);
3688  dialog.setXAxisCustomLabels(props.xCustomLabels);
3689  dialog.setYAxisCustomLabels(props.yCustomLabels);
3690  dialog.setZAxisCustomLabels(props.zCustomLabels);
3691  dialog.setUseCustomBounds(props.useCustomBounds);
3692 
3693  // Set custom bounds values (FIX: These were missing!)
3694  dialog.setXMin(props.xMin);
3695  dialog.setXMax(props.xMax);
3696  dialog.setYMin(props.yMin);
3697  dialog.setYMax(props.yMax);
3698  dialog.setZMin(props.zMin);
3699  dialog.setZMax(props.zMax);
3700  } catch (const std::exception& e) {
3701  CVLog::Warning(QString("[Data Axes Grid] Exception setting dialog "
3702  "properties: %1")
3703  .arg(e.what()));
3704  } catch (...) {
3706  "[Data Axes Grid] Unknown exception setting dialog properties");
3707  }
3708 
3709  // Lambda for applying properties (used by both Apply and OK buttons)
3710  auto applyProperties = [&]() {
3711  // Use the new struct-based interface (cleaner API)
3712  AxesGridProperties props;
3713 
3714  // Get all values from dialog
3715  QColor dialogColor = dialog.getGridColor();
3716  props.visible = true; // Auto-enable when editing (ParaView-style)
3717  props.color = CCVector3(dialogColor.red(), dialogColor.green(),
3718  dialogColor.blue());
3719  props.lineWidth = dialog.getLineWidth();
3720  // Keep spacing and subdivisions from backend (not exposed in dialog
3721  // yet) props.spacing and props.subdivisions already set from
3722  // getDataAxesGridProperties
3723  props.showLabels = dialog.getShowLabels();
3724  props.opacity = dialog.getOpacity();
3725 
3726  // Extended properties
3727  props.showGrid = dialog.getShowGrid();
3728  props.xTitle = dialog.getXTitle();
3729  props.yTitle = dialog.getYTitle();
3730  props.zTitle = dialog.getZTitle();
3731  props.xUseCustomLabels = dialog.getXAxisUseCustomLabels();
3732  props.yUseCustomLabels = dialog.getYAxisUseCustomLabels();
3733  props.zUseCustomLabels = dialog.getZAxisUseCustomLabels();
3734  props.useCustomBounds = dialog.getUseCustomBounds();
3735 
3736  // Custom labels (ParaView-style)
3737  props.xCustomLabels = dialog.getXAxisCustomLabels();
3738  props.yCustomLabels = dialog.getYAxisCustomLabels();
3739  props.zCustomLabels = dialog.getZAxisCustomLabels();
3740 
3741  // Custom bounds values (FIX: These were missing!)
3742  props.xMin = dialog.getXMin();
3743  props.xMax = dialog.getXMax();
3744  props.yMin = dialog.getYMin();
3745  props.yMax = dialog.getYMax();
3746  props.zMin = dialog.getZMin();
3747  props.zMax = dialog.getZMax();
3748 
3749  // Apply using clean struct-based interface
3751  props);
3753  };
3754 
3755  // Connect Apply button for real-time preview (ParaView-style)
3756  connect(&dialog, &ecvAxesGridDialog::applyRequested, this, applyProperties);
3757 
3758  // Show non-modal dialog (allows moving and interacting with scene)
3759  dialog.show();
3760 
3761  // Wait for dialog to close
3762  int result = dialog.exec();
3763 
3764  // Apply on OK (final confirmation)
3765  if (result == QDialog::Accepted) {
3766  applyProperties();
3767  }
3768 }
constexpr float MIN_POINT_SIZE_F
Definition: CVConst.h:78
constexpr float MIN_LINE_WIDTH_F
Definition: CVConst.h:80
constexpr float MAX_LINE_WIDTH_F
Definition: CVConst.h:81
constexpr float MAX_POINT_SIZE_F
Definition: CVConst.h:79
Vector3Tpl< PointCoordinateType > CCVector3
Default 3D Vector.
Definition: CVGeom.h:798
float PointCoordinateType
Type of the coordinates of a (N-D) point.
Definition: CVTypes.h:16
std::shared_ptr< core::Tensor > image
int size
std::string name
int height
cmdLineReadable * params[]
core::Tensor result
Definition: VtkUtils.cpp:76
virtual unsigned getLinkCount() const
Returns the current link count.
Definition: CVShareable.h:40
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 PrintVerbose(const char *format,...)
Prints out a verbose formatted message in console.
Definition: CVLog.cpp:103
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
Array of RGB colors for each point.
const ccHObject::Container & getSelectedEntities() const override
Returns currently selected entities ("read only")
Definition: MainWindow.h:238
static MainWindow * TheInstance()
Returns the unique instance of this object.
Simple widget to display a 4x4 matrix in various formats.
void clear()
Clears widget.
void fillDialogWith(const ccGLMatrix &mat)
Updates dialog with a given (float) matrix.
Array of compressed 3D normals (single index)
Array of (uncompressed) 3D normals (Nx,Ny,Nz)
Array of 2D texture coordinates.
Type y
Definition: CVGeom.h:137
Type x
Definition: CVGeom.h:137
Type z
Definition: CVGeom.h:137
2D label (typically attached to points)
Definition: ecv2DLabel.h:22
void updateLabel()
bool isPointLegendDisplayed() const
Returns whether the point(s) legend is displayed.
Definition: ecv2DLabel.h:111
void setDisplayedIn2D(bool state)
Whether to display the label in 2D.
Definition: ecv2DLabel.h:114
QStringList getLabelContent(int precision) const
Gets label content (as it will be displayed)
void update2DLabelView(CC_DRAW_CONTEXT &context, bool updateScreen=true)
bool isDisplayedIn2D() const
Returns whether the label is displayed in 2D.
Definition: ecv2DLabel.h:117
void displayPointLegend(bool state)
Whether to display the point(s) legend (title only)
Definition: ecv2DLabel.h:108
2D viewport label
2D viewport object
const ecvViewportParameters & getParameters() const
Gets parameters.
void setParameters(const ecvViewportParameters &params)
Sets perspective view state.
Shareable array that can be properly inserted in the DB tree.
Definition: ecvArray.h:21
Bounding box structure.
Definition: ecvBBox.h:25
Camera (projective) sensor.
bool frustumIsDrawn() const
Returns whether the frustum should be displayed or not.
void drawFrustumPlanes(bool state)
Sets whether the frustum planes should be displayed or not.
bool frustumPlanesAreDrawn() const
Returns whether the frustum planes should be displayed or not.
const IntrinsicParameters & getIntrinsicParameters() const
Returns intrinsic parameters.
void drawFrustum(bool state)
Sets whether the frustum should be displayed or not.
Circle (as a polyline)
Definition: ecvCircle.h:16
double getRadius() const
Returns the radius of the circle.
Definition: ecvCircle.h:50
unsigned getResolution() const
Returns the resolution of the displayed circle.
Definition: ecvCircle.h:58
void setRadius(double radius)
Sets the radius of the circle.
void setResolution(unsigned resolution)
Sets the resolution of the displayed circle.
Dialog to edit/create color scales.
ccColorScale::Shared getActiveScale()
Returns active scale.
void setAssociatedScalarField(ccScalarField *sf)
Sets associated scalar field (optional)
Advanced editor for color scales.
void colorScaleSelected(int)
Signal emitted when a color scale is selected.
void init()
Inits selector with the Color Scales Manager.
void setSelectedScale(QString uuid)
Sets selected combo box item (scale) by UUID.
void colorScaleEditorSummoned()
ccColorScale::Shared getScale(int index) const
Returns a given color scale by index.
static const unsigned MIN_STEPS
Minimum number of steps.
Definition: ecvColorScale.h:99
QSharedPointer< ccColorScale > Shared
Shared pointer type.
Definition: ecvColorScale.h:74
static const unsigned MAX_STEPS
Maximum number of steps (internal representation)
void toPersistentSettings() const
Save custom color scales to persistent settings.
static ccColorScalesManager * GetUniqueInstance()
Returns unique instance.
Cone (primitive)
Definition: ecvCone.h:16
PointCoordinateType getTopRadius() const
Returns top radius.
Definition: ecvCone.h:70
PointCoordinateType getHeight() const
Returns height.
Definition: ecvCone.h:52
virtual void setTopRadius(PointCoordinateType radius)
Sets top radius.
PointCoordinateType getBottomRadius() const
Returns bottom radius.
Definition: ecvCone.h:60
void setHeight(PointCoordinateType height)
Sets height.
virtual void setBottomRadius(PointCoordinateType radius)
Sets bottom radius.
Coordinate System (primitive)
bool axisPlanesAreShown() const
CCVector3 getOrigin() const
static constexpr float MIN_AXIS_WIDTH_F
Minimum Axis line width.
void ShowAxisLines(bool show)
void ShowAxisPlanes(bool show)
virtual void hideShowDrawings(CC_DRAW_CONTEXT &context) override
static constexpr float MAX_AXIS_WIDTH_F
Maximum Axis line width.
void setDisplayScale(PointCoordinateType scale)
PointCoordinateType getDisplayScale() const
bool axisLinesAreShown() const
PointCoordinateType getAxisWidth() const
void setAxisWidth(PointCoordinateType width)
Disc (primitive)
Definition: ecvDisc.h:16
PointCoordinateType getRadius() const
Returns radius.
Definition: ecvDisc.h:41
void setRadius(PointCoordinateType radius)
Sets radius.
virtual bool colorsShown() const
Returns whether colors are shown or not.
virtual float getOpacity() const
virtual bool isVisible() const
Returns whether entity is visible or not.
virtual bool isVisibilityLocked() const
Returns whether visibility is locked or not.
virtual bool hasColors() const
Returns whether colors are enabled or not.
virtual void setVisible(bool state)
Sets entity visibility.
virtual bool sfShown() const
Returns whether active scalar field is visible.
virtual bool isGLTransEnabled() const
Returns whether a GL transformation is enabled or not.
virtual bool normalsShown() const
Returns whether normals are shown or not.
virtual const ccGLMatrix & getGLTransformation() const
Returns associated GL transformation.
virtual bool hasNormals() const
Returns whether normals are enabled or not.
virtual bool isColorOverridden() const
virtual bool isSelected() const
Returns whether entity is selected or not.
virtual void showNameIn3D(bool state)
Sets whether name should be displayed in 3D.
virtual bool nameShownIn3D() const
Returns whether name is displayed in 3D or not.
virtual void showNormals(bool state)
Sets normals visibility.
virtual void showColors(bool state)
Sets colors visibility.
virtual void showSF(bool state)
Sets active scalarfield visibility.
virtual void setOpacity(float opacity)
Set opacity activation state.
virtual bool hasScalarFields() const
Returns whether one or more scalar fields are instantiated.
Facet.
Definition: ecvFacet.h:25
ccMesh * getPolygon()
Returns polygon mesh (if any)
Definition: ecvFacet.h:81
double getSurface() const
Returns associated surface area.
Definition: ecvFacet.h:70
ccPolyline * getContour()
Returns contour polyline (if any)
Definition: ecvFacet.h:86
double getRMS() const
Returns associated RMS.
Definition: ecvFacet.h:68
const CCVector3 & getCenter() const
Returns the facet center.
Definition: ecvFacet.h:78
Ground-based Laser sensor.
Definition: ecvGBLSensor.h:26
PointCoordinateType getMinPitch() const
Returns the minimal pitch limit (in radians)
Definition: ecvGBLSensor.h:94
PointCoordinateType getMinYaw() const
Returns the minimal yaw limit (in radians)
Definition: ecvGBLSensor.h:119
void setUncertainty(PointCoordinateType u)
Sets the Z-buffer uncertainty on depth values.
Definition: ecvGBLSensor.h:153
PointCoordinateType getUncertainty() const
Returns the Z-buffer uncertainty on depth values.
Definition: ecvGBLSensor.h:147
PointCoordinateType getPitchStep() const
Returns the lateral pitch step (in radians)
Definition: ecvGBLSensor.h:105
PointCoordinateType getMaxYaw() const
Returns the maximal yaw limit (in radians)
Definition: ecvGBLSensor.h:122
PointCoordinateType getMaxPitch() const
Returns the maximal pitch limit (in radians)
Definition: ecvGBLSensor.h:97
PointCoordinateType getYawStep() const
Returns the yaw step (in radians)
Definition: ecvGBLSensor.h:130
Vector3Tpl< T > getTranslationAsVec3D() const
Returns a copy of the translation as a CCVector3.
Float version of ccGLMatrixTpl.
Definition: ecvGLMatrix.h:19
Generic mesh interface.
virtual void showPoints(bool state)
bool updateTextures(const std::string &texture_file)
virtual bool materialsShown() const
Sets whether textures/material should be displayed or not.
virtual void showWired(bool state)
Sets whether mesh should be displayed as a wire or with plain facets.
virtual bool isShownAsWire() const
Returns whether the mesh is displayed as wired or with plain facets.
virtual const ccMaterialSet * getMaterialSet() const =0
virtual ccGenericPointCloud * getAssociatedCloud() const =0
Returns the vertices cloud.
void enableStippling(bool state)
Enables polygon stippling.
virtual void showMaterials(bool state)
Sets whether textures should be displayed or not.
virtual bool isShownAsPoints() const
Returns whether the mesh is displayed as wired or with plain facets.
virtual bool hasMaterials() const =0
A 3D cloud interface with associated features (color, normals, octree, etc.)
unsigned char getPointSize() const
Returns current point size.
void setPointSize(unsigned size=0)
Sets point size.
Generic primitive interface.
virtual QString getTypeName() const =0
Returns type name (sphere, cylinder, etc.)
virtual bool setDrawingPrecision(unsigned steps)
Sets drawing precision.
virtual void hideShowDrawings(CC_DRAW_CONTEXT &context)
virtual unsigned getDrawingPrecision() const
Returns drawing precision (or 0 if feature is not supported)
virtual bool hasDrawingPrecision() const
Whether drawing is dependent on 'precision' parameter.
static ccOctree * ToOctree(ccHObject *obj)
Converts current object to ccOctree (if possible)
static ccDisc * ToDisc(ccHObject *obj)
Converts current object to ccDisc (if possible)
static ccPointCloud * ToPointCloud(ccHObject *obj, bool *isLockedVertices=nullptr)
Converts current object to 'equivalent' ccPointCloud.
static cc2DViewportLabel * To2DViewportLabel(ccHObject *obj)
Converts current object to cc2DViewportLabel (if possible)
static ccShiftedObject * ToShifted(ccHObject *obj, bool *isLockedVertices=nullptr)
Converts current object to 'equivalent' ccShiftedObject.
static ccCameraSensor * ToCameraSensor(ccHObject *obj)
static ccOctreeProxy * ToOctreeProxy(ccHObject *obj)
Converts current object to ccOctreeProxy (if possible)
static ccKdTree * ToKdTree(ccHObject *obj)
Converts current object to ccKdTree (if possible)
static ccGenericPrimitive * ToPrimitive(ccHObject *obj)
Converts current object to ccGenericPrimitive (if possible)
static ccPolyline * ToPolyline(ccHObject *obj)
Converts current object to ccPolyline (if possible)
static cc2DLabel * To2DLabel(ccHObject *obj)
Converts current object to cc2DLabel (if possible)
static ccGenericPointCloud * ToGenericPointCloud(ccHObject *obj, bool *isLockedVertices=nullptr)
Converts current object to 'equivalent' ccGenericPointCloud.
static ccSensor * ToSensor(ccHObject *obj)
Converts current object to ccSensor (if possible)
static cc2DViewportObject * To2DViewportObject(ccHObject *obj)
Converts current object to cc2DViewportObject (if possible)
static ccCoordinateSystem * ToCoordinateSystem(ccHObject *obj)
Converts current object to ccCoordinateSystem (if possible)
static ccPlanarEntityInterface * ToPlanarEntity(ccHObject *obj)
Converts current object to ccPlanarEntityInterface (if possible)
static ccImage * ToImage(ccHObject *obj)
static ccFacet * ToFacet(ccHObject *obj)
Converts current object to ccFacet (if possible)
static ccIndexedTransformationBuffer * ToTransBuffer(ccHObject *obj)
Converts current object to ccIndexedTransformationBuffer (if possible)
static ccSphere * ToSphere(ccHObject *obj)
Converts current object to ccSphere (if possible)
static ccCone * ToCone(ccHObject *obj)
Converts current object to ccCone (if possible)
static ccGenericMesh * ToGenericMesh(ccHObject *obj)
Converts current object to ccGenericMesh (if possible)
static ccGBLSensor * ToGBLSensor(ccHObject *obj)
static ccCircle * ToCircle(ccHObject *obj)
Converts current object to ccCircle (if possible)
Hierarchical CLOUDVIEWER Object.
Definition: ecvHObject.h:25
virtual SelectionBehavior getSelectionBehavior() const
Returns selection behavior.
Definition: ecvHObject.h:621
void hideBB(CC_DRAW_CONTEXT context)
virtual const ccGLMatrix & getGLTransformationHistory() const
Returns the transformation 'history' matrix.
Definition: ecvHObject.h:631
@ SELECTION_FIT_BBOX
Definition: ecvHObject.h:607
virtual bool isDisplayed() const
Returns whether the object is actually displayed (visible) or not.
virtual ccBBox getOwnFitBB(ccGLMatrix &trans)
Returns best-fit bounding-box (if available)
bool isAncestorOf(const ccHObject *anObject) const
Returns true if the current object is an ancestor of the specified one.
QString getViewId() const
Definition: ecvHObject.h:225
unsigned getChildrenNumber() const
Returns the number of children.
Definition: ecvHObject.h:312
void setRedrawFlagRecursive(bool redraw=false)
virtual ccBBox getBB_recursive(bool withGLFeatures=false, bool onlyEnabledChildren=true)
Returns the bounding-box of this entity and it's children.
ccHObject * getParent() const
Returns parent object.
Definition: ecvHObject.h:245
std::vector< ccHObject * > Container
Standard instances container (for children, etc.)
Definition: ecvHObject.h:337
void setForceRedrawRecursive(bool redraw=false)
void showBB(CC_DRAW_CONTEXT context)
ccHObject * getChild(unsigned childPos) const
Returns the ith child.
Definition: ecvHObject.h:325
bool isGroup() const
Returns whether the instance is a group.
Definition: ecvHObject.h:237
Generic image.
Definition: ecvImage.h:19
unsigned getW() const
Returns image width.
Definition: ecvImage.h:51
unsigned getH() const
Returns image height.
Definition: ecvImage.h:54
ccCameraSensor * getAssociatedSensor()
Returns associated sensor.
Definition: ecvImage.h:72
void setTriherdonsDisplayScale(float scale)
[Display option] Sets trihedron display size
float triherdonsDisplayScale()
[Display option] Returns trihedron display size
KD-tree structure.
Definition: ecvKdTree.h:25
Mesh (triangle) material.
int findMaterialByName(QString mtlName) const
Finds material by name.
QSharedPointer< const ccMaterial > CShared
Const + Shared type.
Definition: ecvMaterial.h:31
Triangular mesh.
Definition: ecvMesh.h:35
static void ConvertNormalToDipAndDipDir(const CCVector3 &N, PointCoordinateType &dip_deg, PointCoordinateType &dipDir_deg)
Converts a normal vector to geological 'dip direction & dip' parameters.
Generic "CLOUDVIEWER Object" template.
Definition: ecvObject.h:49
const QVariantMap & metaData() const
Returns meta-data map (const only)
Definition: ecvObject.h:184
virtual bool isLocked() const
Returns whether the object is locked or not.
Definition: ecvObject.h:112
virtual QString getName() const
Returns object name.
Definition: ecvObject.h:72
virtual unsigned getUniqueID() const
Returns object unique ID.
Definition: ecvObject.h:86
bool isA(CV_CLASS_ENUM type) const
Definition: ecvObject.h:131
virtual void setName(const QString &name)
Sets object name.
Definition: ecvObject.h:75
bool isHierarchy() const
Definition: ecvObject.h:124
virtual bool isEnabled() const
Returns whether the object is enabled or not.
Definition: ecvObject.h:97
bool isKindOf(CV_CLASS_ENUM type) const
Definition: ecvObject.h:128
Octree structure proxy.
Octree structure.
Definition: ecvOctree.h:27
DisplayMode
Octree displaying methods.
Definition: ecvOctree.h:77
@ MEAN_POINTS
Definition: ecvOctree.h:80
@ MEAN_CUBES
Definition: ecvOctree.h:83
int getDisplayedLevel() const
Returns the currently displayed octree level.
Definition: ecvOctree.h:67
Interface for a planar entity.
void showNormalVector(bool state)
Show normal vector.
bool normalVectorIsShown() const
Whether normal vector is shown or not.
virtual CCVector3 getNormal() const =0
Returns the entity normal.
Plane (primitive)
Definition: ecvPlane.h:18
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void setCurrentDisplayedScalarField(int index)
Sets the currently displayed scalar field.
bool sfColorScaleShown() const
Returns whether color scale should be displayed or not.
FWFDescriptorSet & fwfDescriptors()
Gives access to the FWF descriptors.
std::vector< ccWaveform > & waveforms()
Gives access to the associated FWF data.
void showSFColorsScale(bool state)
Sets whether color scale should be displayed or not.
bool hasFWF() const
Returns whether the cloud has associated Full WaveForm data.
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)
SharedFWFDataContainer & fwfData()
Gives access to the associated FWF data container.
Grid::Shared & grid(size_t gridIndex)
Returns an associated grid.
size_t gridCount() const
Returns the number of associated grids.
Colored polyline.
Definition: ecvPolyline.h:24
PointCoordinateType computeLength() const
Computes the polyline length.
bool is2DMode() const
Returns whether the polyline is considered as 2D or 3D.
Definition: ecvPolyline.h:63
PointCoordinateType getWidth() const
Returns the width of the line.
Definition: ecvPolyline.h:94
void setWidth(PointCoordinateType width)
Sets the width of the line.
GUI properties list dialog element.
void fillSFWithPointCloud(ccGenericPointCloud *)
void fillWithCoordinateSystem(const ccCoordinateSystem *)
void fillWithShifted(ccShiftedObject *)
void ccObjectAppearanceChanged(ccHObject *hObject, bool forceRedraw=true) const
void fillModel(ccHObject *hObject)
Fill property view with QItems corresponding to object's type.
virtual void setEditorData(QWidget *editor, const QModelIndex &index) const
void fillWithViewportObject(cc2DViewportObject *)
bool isWideEditor(int itemData) const
Returns whether the editor is wide (i.e. spans on two columns) or not.
ccPropertiesTreeDelegate(QStandardItemModel *_model, QAbstractItemView *_view, QObject *parent=0)
Default constructor.
CC_PROPERTY_ROLE
Delegate items roles.
QMap< QString, QString > getCurrentMeshTexturePathMap() const
Get texture path map for current mesh object.
ccHObject * getCurrentObject()
Returns currently bound object.
void clearMeshTexturePathMap(ccHObject *mesh)
Clear texture path map for a specific mesh object.
void updateModel()
Updates the current model (assuming object is the same)
void fillWithTransBuffer(ccIndexedTransformationBuffer *)
void appendWideRow(QStandardItem *item, bool openPersistentEditor=true)
virtual QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
void ccObjectPropertiesChanged(ccHObject *hObject) const
void clearModel()
Clear the model completely.
QMap< ccHObject *, QMap< QString, QString > > m_meshTexturePathMaps
void fillWithPointCloud(ccGenericPointCloud *)
void fillWithMaterialSet(ccMaterialSet *)
void fillWithCCArray(ccArray< Type, N, ComponentType > *)
CC_PROPERTY_ROLE m_lastFocusItemRole
Last focused item role (used to force scroll focus after model update)
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
void fillWithPrimitive(ccGenericPrimitive *)
void appendRow(QStandardItem *leftItem, QStandardItem *rightItem, bool openPersistentEditor=false)
virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
void ccObjectAndChildrenAppearanceChanged(ccHObject *hObject, bool forceRedraw=true) const
void fillWithCameraSensor(ccCameraSensor *)
virtual ~ccPropertiesTreeDelegate()
Default destructor.
void fillWithPlanarEntity(ccPlanarEntityInterface *)
A scalar field associated to display-related parameters.
const ccColorScale::Shared & getColorScale() const
Returns associated color scale.
void setColorRampSteps(unsigned steps)
Sets number of color ramp steps used for display.
unsigned getColorRampSteps() const
Returns number of color ramp steps.
void setColorScale(ccColorScale::Shared scale)
Sets associated color scale.
Generic sensor interface.
Definition: ecvSensor.h:27
ccIndexedTransformationBuffer * getPositions()
Returns associated positions.
Definition: ecvSensor.h:63
PointCoordinateType getGraphicScale() const
Returns the sensor graphic representation scale.
Definition: ecvSensor.h:128
virtual void hideShowDrawings(CC_DRAW_CONTEXT &context)
void getIndexBounds(double &minIndex, double &maxIndex) const
Gets index boundaries (shortcut)
bool getActiveAbsoluteTransformation(ccIndexedTransformation &trans) const
Gets currently active absolute transformation.
double getActiveIndex() const
Sets currently active index (displayed position, etc.)
Definition: ecvSensor.h:119
virtual bool applyViewport()
Apply sensor 'viewport' to a 3D view.
void setActiveIndex(double index)
Sets currently active index (displayed position, etc.)
Definition: ecvSensor.h:122
void setGraphicScale(PointCoordinateType scale)
Sets the sensor graphic representation scale.
Definition: ecvSensor.h:125
Shifted entity interface.
CCVector3d toGlobal3d(const Vector3Tpl< T > &Plocal) const
Returns the point back-projected into the original coordinates system.
virtual const CCVector3d & getGlobalShift() const
Returns the shift applied to original coordinates.
virtual double getGlobalScale() const
Returns the scale applied to original coordinates.
Sphere (primitive)
Definition: ecvSphere.h:16
void setRadius(PointCoordinateType radius)
Sets radius.
PointCoordinateType getRadius() const
Returns radius.
Definition: ecvSphere.h:45
Vector3Tpl< T > getDiagVec() const
Returns diagonal vector.
Definition: BoundingBox.h:169
Vector3Tpl< T > getCenter() const
Returns center.
Definition: BoundingBox.h:164
bool isValid() const
Returns whether bounding box is valid or not.
Definition: BoundingBox.h:203
static const int MAX_OCTREE_LEVEL
Max octree subdivision level.
Definition: DgmOctree.h:67
const PointCoordinateType & getCellSize(unsigned char level) const
Returns the octree cells length for a given level of subdivision.
Definition: DgmOctree.h:494
const unsigned & getCellNumber(unsigned char level) const
Returns the number of cells for a given level of subdivision.
Definition: DgmOctree.h:1038
virtual unsigned size() const =0
Returns the number of points.
virtual unsigned size() const =0
Returns the number of triangles.
unsigned getNumberOfScalarFields() const
Returns the number of associated (and active) scalar fields.
const char * getScalarFieldName(int index) const
Returns the name of a specific scalar field.
unsigned size() const override
Returns the number of points.
A simple scalar field (to be associated to a point cloud)
Definition: ScalarField.h:25
double getMaxError() const
Returns max error threshold used for planarity-based split strategy.
Definition: TrueKdTree.h:138
DistanceComputationTools::ERROR_MEASURES getMaxErrorType() const
Returns max error estimator used for planarity-based split strategy.
Definition: TrueKdTree.h:141
ParaView-style Axes Grid Properties Dialog.
static void ChangeEntityProperties(PROPERTY_PARAM &propertyParam, bool autoUpdate=true)
static const ecvViewportParameters & GetViewportParameters()
static void GetContext(CC_DRAW_CONTEXT &CONTEXT)
Returns context information.
static QMainWindow * GetMainWindow()
virtual void setDataAxesGridProperties(const QString &viewID, const AxesGridProperties &props, int viewport=0)
Set Data Axes Grid properties (Virtual interface for derived classes)
static void ChangeOpacity(double opacity, const std::string &viewID, int viewport=0)
static void ToggleCameraOrientationWidget(bool show)
virtual void getDataAxesGridProperties(const QString &viewID, AxesGridProperties &props, int viewport=0) const
Get Data Axes Grid properties (Virtual interface for derived classes)
static ecvDisplayTools * TheInstance()
static void SetViewportParameters(const ecvViewportParameters &params)
virtual double getLightIntensity() const
static void SetRedrawRecursive(bool redraw=false)
static void UpdateScreen()
static void RedrawDisplay(bool only2D=false, bool forceRedraw=true)
virtual void setLightIntensity(double intensity)
static const ParamStruct & Parameters()
Returns the stored values of each parameter.
static const ecvOptions & Instance()
Returns the stored values of each parameter.
Definition: ecvOptions.h:48
static const QString TextureFilePath()
static const QString SelectedImageInputFilter()
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)
Advanced editor for color scales.
QString getTexturefilePath(int index) const
void setSelectedTexturefile(QString textureFilepath)
Sets selected combo box item (scale) by UUID.
void textureFileSelected(int)
Signal emitted when a texture file item is selected.
void addItem(const QString &textureFilename, const QString &textureFilepath)
void init(const QMap< QString, QString > &texturePathMap)
Inits selector with the Empty texture file path.
GUI scalar field interactor for properties list dialog.
Definition: sfEditDlg.h:21
void entitySFHasChanged()
Signal emitted when the SF display parameters have changed.
void fillDialogWith(ccScalarField *sf)
Updates dialog with a given scalar field.
Definition: sfEditDlg.cpp:91
int min(int a, int b)
Definition: cutil_math.h:53
__host__ __device__ int2 abs(int2 v)
Definition: cutil_math.h:1267
int max(int a, int b)
Definition: cutil_math.h:48
ENTITY_TYPE
@ ECV_LINES_3D
@ ECV_MESH
@ ECV_POINT_CLOUD
QStandardItem * ITEM(QString name, Qt::ItemFlag additionalFlags=Qt::NoItemFlags, ccPropertiesTreeDelegate::CC_PROPERTY_ROLE role=ccPropertiesTreeDelegate::OBJECT_NO_PROPERTY)
void SetSpinBoxValue(QWidget *editor, int value, bool keyboardTracking=false)
QStandardItem * PERSISTENT_EDITOR(ccPropertiesTreeDelegate::CC_PROPERTY_ROLE role)
constexpr const char * SEPARATOR_STYLESHEET("QLabel { background-color : darkGray; color : white; }")
void SetComboBoxIndex(QWidget *editor, int index)
QStandardItem * CHECKABLE_ITEM(bool checkState, ccPropertiesTreeDelegate::CC_PROPERTY_ROLE role)
void SetDoubleSpinBoxValue(QWidget *editor, double value, bool keyboardTracking=false)
ImGuiContext * context
Definition: Window.cpp:76
@ SENSOR
Definition: CVTypes.h:116
@ HIERARCHY_OBJECT
Definition: CVTypes.h:103
@ VIEWPORT_2D_OBJECT
Definition: CVTypes.h:141
@ PRIMITIVE
Definition: CVTypes.h:119
@ MESH
Definition: CVTypes.h:105
@ GBL_SENSOR
Definition: CVTypes.h:117
@ NORMAL_INDEXES_ARRAY
Definition: CVTypes.h:135
@ RGB_COLOR_ARRAY
Definition: CVTypes.h:137
@ IMAGE
Definition: CVTypes.h:114
@ COORDINATESYSTEM
Definition: CVTypes.h:145
@ TRANS_BUFFER
Definition: CVTypes.h:144
@ CONE
Definition: CVTypes.h:123
@ POINT_CLOUD
Definition: CVTypes.h:104
@ TEX_COORDS_ARRAY
Definition: CVTypes.h:139
@ NORMALS_ARRAY
Definition: CVTypes.h:134
@ CIRCLE
Definition: CVTypes.h:113
@ LABEL_2D
Definition: CVTypes.h:140
@ POLY_LINE
Definition: CVTypes.h:112
@ POINT_KDTREE
Definition: CVTypes.h:111
@ FACET
Definition: CVTypes.h:109
@ SUB_MESH
Definition: CVTypes.h:106
@ POINT_OCTREE
Definition: CVTypes.h:110
@ SPHERE
Definition: CVTypes.h:121
@ MATERIAL_SET
Definition: CVTypes.h:132
@ CAMERA_SENSOR
Definition: CVTypes.h:118
@ PLANE
Definition: CVTypes.h:120
@ DISC
Definition: CVTypes.h:146
@ VIEWPORT_2D_LABEL
Definition: CVTypes.h:142
@ CYLINDER
Definition: CVTypes.h:126
static const QString APP_TITLE
float RadiansToDegrees(int radians)
Convert radians to degrees.
Definition: CVMath.h:71
std::string toString(T x)
Definition: Common.h:80
QString defaultDocPath()
Shortcut for getting the documents location path.
Definition: ecvFileUtils.h:30
cloudViewer::DgmOctree * octree
Data Axes Grid properties structure Encapsulates all properties for vtkCubeAxesActor configuration.
QList< QPair< double, QString > > xCustomLabels
QList< QPair< double, QString > > yCustomLabels
QList< QPair< double, QString > > zCustomLabels
Intrinsic parameters of the camera sensor.
Display context.
QSharedPointer< Grid > Shared
Shared type.
GUI parameters.
Definition: lsd.c:1170
double width
Definition: lsd.c:1172