ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
cvGenericMeasurementTool.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 
11 
12 #ifdef _MSC_VER
13 #pragma warning(disable : 4996) // Use of [[deprecated]] feature
14 #endif
15 
16 // LOCAL
17 #include "PclUtils/PCLVis.h"
18 #include "VtkUtils/vtkutils.h"
19 
20 // CV_CORE_LIB
21 #include <CVLog.h>
22 
23 // CV_DB_LIB
24 #include <ecvDisplayTools.h>
25 #include <ecvHObject.h>
26 #include <ecvMesh.h>
27 #include <ecvPointCloud.h>
28 
29 // QT
30 #include <QApplication>
31 #include <QSizePolicy>
32 
33 // VTK
34 #include <vtkAbstractWidget.h>
35 #include <vtkActor.h>
36 #include <vtkProp.h>
37 #include <vtkRenderWindowInteractor.h>
38 #include <vtkRenderer.h>
39 #include <vtkSmartPointer.h>
40 
42  : QWidget(parent), m_ui(new Ui::GenericMeasurementToolDlg) {
43  setWindowTitle(tr("Generic Measurement Tool"));
44 
45  // CRITICAL: Set size policy to Minimum (horizontal) to prevent unnecessary
46  // expansion This ensures each tool adapts to its content width without
47  // extra whitespace ParaView-style: use Minimum to prevent horizontal
48  // expansion beyond content
49  setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
50 
51  // CRITICAL: Remove any fixed size constraints to allow Qt's layout system
52  // to work This prevents UI size interference between different tool types
53  setMinimumSize(0, 0);
54  setMaximumSize(16777215, 16777215); // QWIDGETSIZE_MAX equivalent
55 }
56 
58  // Disable all picking helpers before deletion to prevent shortcuts from
59  // triggering after tool is destroyed
60  for (cvPointPickingHelper* helper : m_pickingHelpers) {
61  if (helper) {
62  helper->setEnabled(false, false);
63  }
64  }
65 
66  // Clean up picking helpers
67  qDeleteAll(m_pickingHelpers);
68  m_pickingHelpers.clear();
69 
70  clearAllActor();
71  delete m_ui;
72 }
73 
76  // create UI first (must be done before initTool)
77  createUi();
78 
79  // call child function
80  modelReady();
81 
82  // update data
83  dataChanged();
84 
85  // according to data type
86  initTool();
87 
88  // Clear selection cache when starting tool (new session)
90 
91  // update screen
92  update();
93 }
94 
96  if (!win) {
98  "[cvGenericMeasurementTool] Widget is null, shortcuts not "
99  "setup");
100  return;
101  }
102 
103  // Save the widget reference for later use (e.g., when unlocking after being
104  // locked)
105  m_vtkWidget = win;
106 
107  // Only create shortcuts if they don't already exist
108  if (m_pickingHelpers.isEmpty()) {
109  CVLog::PrintDebug(QString("[cvGenericMeasurementTool::setupShortcuts] "
110  "Tool=%1, creating shortcuts...")
111  .arg((quintptr)this, 0, 16));
112 
113  // Setup keyboard shortcuts for point picking
115 
116  // Update picking helpers with current interactor/renderer
118 
119  CVLog::PrintDebug(QString("[cvGenericMeasurementTool::setupShortcuts] "
120  "Tool=%1, created %2 shortcuts")
121  .arg((quintptr)this, 0, 16)
122  .arg(m_pickingHelpers.size()));
123  } else {
125  QString("[cvGenericMeasurementTool::setupShortcuts] Tool=%1, "
126  "shortcuts already exist (%2), updating only")
127  .arg((quintptr)this, 0, 16)
128  .arg(m_pickingHelpers.size()));
129 
130  // Just update the interactor/renderer
132  }
133 
134  // Enable all shortcuts and set focus to the widget
135  for (cvPointPickingHelper* helper : m_pickingHelpers) {
136  if (helper) {
137  helper->setEnabled(true, true); // Enable and set focus
138  }
139  }
140 }
141 
143  m_entity = obj;
144  if (!m_entity) {
145  return false;
146  }
147  m_id = m_entity->getViewId().toStdString();
148 
149  if (!initModel()) {
150  return false;
151  }
152 
153  return true;
154 }
155 
157  if (!m_entity || !m_viewer) {
158  return false;
159  }
160 
161  // Get renderer from viewer
163  if (!m_renderer) {
164  CVLog::Error("[cvGenericMeasurementTool] Failed to get renderer!");
165  return false;
166  }
167 
168  return true;
169 }
170 
172  // Override in derived classes if needed
173 }
174 
176  if (m_viewer && m_renderer) {
177  if (m_viewer->getRenderWindow()) {
178  m_viewer->getRenderWindow()->Render();
179  // Clear picking cache after render as scene may have changed
181  }
182  }
183 }
184 
186  // Override in derived classes if needed
187 }
188 
190  // Override in derived classes if needed
191  return nullptr;
192 }
193 
195  m_viewer = viewer;
196  if (m_viewer) {
198  if (m_viewer->getRenderWindow()) {
199  m_interactor = m_viewer->getRenderWindow()->GetInteractor();
200  }
201  }
202 }
203 
205  vtkRenderWindowInteractor* interactor) {
206  m_interactor = interactor;
207 }
208 
210  if (m_renderer && actor) {
211  m_renderer->AddActor(actor);
212  }
213 }
214 
216  const vtkSmartPointer<vtkProp> actor) {
217  if (m_renderer && actor) {
218  m_renderer->RemoveActor(actor);
219  }
220 }
221 
223  if (m_renderer) {
224  if (m_modelActor) {
225  m_renderer->RemoveActor(m_modelActor);
226  }
227  }
228 }
229 
230 void cvGenericMeasurementTool::safeOff(vtkAbstractWidget* widget) {
231  if (widget) {
232  widget->Off();
233  }
234 }
235 
237  for (cvPointPickingHelper* helper : m_pickingHelpers) {
238  if (helper) {
239  helper->setInteractor(m_interactor);
240  helper->setRenderer(m_renderer);
241  }
242  }
243 }
244 
246  CVLog::PrintDebug(QString("[cvGenericMeasurementTool::disableShortcuts] "
247  "Tool=%1, disabling %2 shortcuts")
248  .arg((quintptr)this, 0, 16)
249  .arg(m_pickingHelpers.size()));
250 
251  // Disable all picking helpers to prevent shortcuts from triggering
252  for (cvPointPickingHelper* helper : m_pickingHelpers) {
253  if (helper) {
254  helper->setEnabled(false, false);
255  }
256  }
257 }
258 
260  // Clear selection cache in all picking helpers
261  // Call this when scene changes, camera moves significantly, or data updates
262  for (cvPointPickingHelper* helper : m_pickingHelpers) {
263  if (helper) {
264  helper->clearSelectionCache();
265  }
266  }
267 }
268 
269 void cvGenericMeasurementTool::setFontFamily(const QString& family) {
270  m_fontFamily = family;
272 }
273 
275  m_fontSize = size;
277 }
278 
280  m_fontBold = bold;
282 }
283 
285  m_fontItalic = italic;
287 }
288 
290  m_fontShadow = shadow;
292 }
293 
295  m_fontOpacity = opacity;
297 }
298 
299 void cvGenericMeasurementTool::setFontColor(double r, double g, double b) {
300  m_fontColor[0] = r;
301  m_fontColor[1] = g;
302  m_fontColor[2] = b;
304 }
305 
307  const QString& justification) {
308  m_horizontalJustification = justification;
310 }
311 
313  const QString& justification) {
314  m_verticalJustification = justification;
316 }
int size
static bool PrintDebug(const char *format,...)
Same as Print, but works only in Debug mode.
Definition: CVLog.cpp:153
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
Definition: CVLog.cpp:133
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Definition: CVLog.cpp:143
vtkRenderer * getCurrentRenderer(int viewport=0)
Definition: PCLVis.cpp:2924
Hierarchical CLOUDVIEWER Object.
Definition: ecvHObject.h:25
QString getViewId() const
Definition: ecvHObject.h:225
QWidget * m_vtkWidget
VTK widget reference for creating shortcuts (saved from linkWith)
virtual void applyFontProperties()=0
virtual void setItalic(bool italic)
Set font italic state for measurement labels.
void addActor(const vtkSmartPointer< vtkProp > actor)
vtkRenderWindowInteractor * m_interactor
QList< cvPointPickingHelper * > m_pickingHelpers
List of point picking helpers for keyboard shortcuts.
void removeActor(const vtkSmartPointer< vtkProp > actor)
virtual void setVerticalJustification(const QString &justification)
void setUpViewer(PclUtils::PCLVis *viewer)
QString m_fontFamily
Font properties for measurement labels (shared by all tools)
cvGenericMeasurementTool(QWidget *parent=nullptr)
void disableShortcuts()
Disable all keyboard shortcuts (call before tool destruction)
virtual void setHorizontalJustification(const QString &justification)
virtual void setBold(bool bold)
Set font bold state for measurement labels.
void setupShortcuts(QWidget *vtkWidget)
virtual void setShadow(bool shadow)
Set font shadow state for measurement labels.
virtual void setupPointPickingShortcuts(QWidget *vtkWidget)
void safeOff(vtkAbstractWidget *widget)
void setInteractor(vtkRenderWindowInteractor *interactor)
void updatePickingHelpers()
Update point picking helpers with current interactor/renderer.
virtual bool setInput(ccHObject *obj)
virtual void setFontSize(int size)
Set font size for measurement labels.
vtkSmartPointer< vtkActor > m_modelActor
virtual void setFontFamily(const QString &family)
virtual void setFontColor(double r, double g, double b)
Set font color for measurement labels (RGB values 0.0-1.0)
Ui::GenericMeasurementToolDlg * m_ui
virtual void setFontOpacity(double opacity)
Set font opacity for measurement labels (0.0 to 1.0)
cvPointPickingHelper is a helper class for supporting keyboard shortcut-based point picking in measur...
Definition: sfEditDlg.h:16
Tensor Minimum(const Tensor &input, const Tensor &other)
Computes the element-wise minimum of input and other. The tensors must have same data type and device...