ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
cvViewSelectionManager.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 #include "cvSelectionData.h"
11 
12 // Selection utility modules
13 #include "cvSelectionAlgebra.h"
14 #include "cvSelectionAnnotation.h"
15 #include "cvSelectionHighlighter.h"
16 #include "cvSelectionPipeline.h"
17 
18 // LOCAL
19 #include "PclUtils/PCLVis.h"
20 
21 // CV_DB_LIB
22 #include <ecvMesh.h>
23 #include <ecvPointCloud.h>
24 
25 // CV_CORE_LIB
26 #include <CVLog.h>
27 
28 // VTK
29 #include <vtkHardwareSelector.h>
30 #include <vtkIdTypeArray.h>
31 #include <vtkIntArray.h>
32 #include <vtkPolyData.h>
33 
34 // QT
35 #include <QSet>
36 
37 //-----------------------------------------------------------------------------
39  static cvViewSelectionManager _instance;
40  return &_instance;
41 }
42 
43 //-----------------------------------------------------------------------------
44 cvViewSelectionManager::cvViewSelectionManager(QObject* parent)
45  : QObject(parent),
47  m_currentMode(static_cast<SelectionMode>(-1)),
48  m_currentModifier(SelectionModifier::SELECTION_DEFAULT),
49  m_isActive(false),
50  m_currentSelection(nullptr),
51  m_currentSelectionFieldAssociation(0),
52  m_algebra(nullptr),
53  m_pipeline(nullptr),
54  m_filter(nullptr),
55  m_annotations(nullptr),
56  m_highlighter(nullptr),
57  m_sourceObject(nullptr) {
58  // Initialize utility modules (ParaView-style architecture)
59  // Note: m_history and m_bookmarks removed - UI not implemented
60  m_algebra = new cvSelectionAlgebra(this);
61  m_pipeline = new cvSelectionPipeline(this);
62  m_filter = new cvSelectionFilter(this);
63  m_annotations = new cvSelectionAnnotationManager(this);
64  m_highlighter =
65  new cvSelectionHighlighter(); // Shared highlighter for all tools
66 
68  "[cvViewSelectionManager] Initialized with utility modules");
69 }
70 
71 //-----------------------------------------------------------------------------
72 cvViewSelectionManager::~cvViewSelectionManager() {
73  // Disable current selection if active
74  if (m_isActive) {
76  }
77 
78  // Clean up selection data
79  // Smart pointer handles cleanup automatically
80  m_currentSelection = nullptr;
81 
82  // Clean up highlighter (not a QObject, so manual cleanup)
83  delete m_highlighter;
84  m_highlighter = nullptr;
85 }
86 
87 //-----------------------------------------------------------------------------
88 // Override setVisualizer to handle utility module updates
90  if (getVisualizer() == viewer) {
91  return;
92  }
93 
94  // Disable current selection if active
95  if (m_isActive) {
97  }
98 
100 
101  // Update visualizer for utility modules
102  if (m_annotations && getPCLVis()) {
103  m_annotations->setVisualizer(getPCLVis());
104  }
105  if (m_pipeline && getPCLVis()) {
106  m_pipeline->setVisualizer(getPCLVis());
107 
108  // ParaView-style: Invalidate cached selection when visualizer changes
109  // Reference: pqRenderViewSelectionReaction connects to dataUpdated
110  // signal
111  m_pipeline->invalidateCachedSelection();
112  }
113 
114  // Update visualizer for shared highlighter
115  if (m_highlighter && getPCLVis()) {
116  m_highlighter->setVisualizer(getPCLVis());
117  }
118 }
119 
120 //-----------------------------------------------------------------------------
122  // NOTE: In the new architecture, cvRenderViewSelectionReaction handles
123  // all selection logic. This method only updates internal state.
124 
125  // Special handling for non-interactive modes
126  if (mode == SelectionMode::CLEAR_SELECTION) {
127  clearSelection();
128  return;
129  }
130  if (mode == SelectionMode::GROW_SELECTION) {
131  growSelection();
132  return;
133  }
134  if (mode == SelectionMode::SHRINK_SELECTION) {
135  shrinkSelection();
136  return;
137  }
138 
139  // Update internal state
140  m_currentMode = mode;
141  m_isActive = true;
142 
143  emit modeChanged(mode);
144 }
145 
146 //-----------------------------------------------------------------------------
148  // NOTE: In the new architecture, cvRenderViewSelectionReaction handles
149  // all selection logic. This method only updates internal state.
150 
151  if (!m_isActive) {
152  return;
153  }
154 
155  m_isActive = false;
156  m_currentMode = static_cast<SelectionMode>(-1);
157 
158  emit modeChanged(m_currentMode);
159 }
160 
161 //-----------------------------------------------------------------------------
162 bool cvViewSelectionManager::isSelectionActive() const { return m_isActive; }
163 
164 //-----------------------------------------------------------------------------
166  if (m_currentModifier == modifier) {
167  return;
168  }
169 
170  m_currentModifier = modifier;
171  emit modifierChanged(modifier);
172 }
173 
174 //-----------------------------------------------------------------------------
176  // Clear current selection
177  setCurrentSelection(nullptr, 0);
178 
179  // Reset number of layers and original selection when clearing
180  // Reference: ParaView's selection source resets NumberOfLayers when cleared
181  m_numberOfLayers = 0;
182  m_originalSelection = cvSelectionData(); // Clear original selection
183 
184  emit selectionChanged();
185 }
186 
187 //-----------------------------------------------------------------------------
189  // ParaView-style: Use expand with +1 layer
190  expandSelection(1, m_growRemoveSeed, m_growRemoveIntermediateLayers);
191 }
192 
193 //-----------------------------------------------------------------------------
195  // ParaView-style: Use expand with -1 layer
196  expandSelection(-1, false, false);
197 }
198 
199 //-----------------------------------------------------------------------------
201  bool removeSeed,
202  bool removeIntermediateLayers) {
203  // ParaView-compatible expand selection
204  // Reference: vtkSMSelectionHelper::ExpandSelection()
205  // ParaView ALWAYS expands/shrinks from the ORIGINAL selection, not the
206  // current one This is the key difference that makes grow/shrink reversible
207 
208  if (!m_algebra) {
209  CVLog::Warning("[cvViewSelectionManager] No algebra module available");
210  return;
211  }
212 
213  if (!hasSelection()) {
215  "[cvViewSelectionManager] No selection to expand (grow/shrink "
216  "requires an existing selection)");
217  return;
218  }
219 
220  // Get polyData with enhanced fallback
221  vtkPolyData* polyData = getPolyData();
222 
223  if (!polyData) {
225  "[cvViewSelectionManager] No polyData available for expand "
226  "operation. Make sure you have data loaded in the viewer.");
227  return;
228  }
229 
230  // ParaView-style: Calculate the NEW total number of layers
231  int newNumberOfLayers = m_numberOfLayers + layers;
232 
233  // Ensure it doesn't go negative
234  if (newNumberOfLayers < 0) {
235  newNumberOfLayers = 0;
236  }
237 
238  // ParaView-style: ALWAYS expand from the original selection
239  // Use the stored original selection as the base
240  cvSelectionData baseSelection = m_originalSelection.isEmpty()
241  ? currentSelection()
242  : m_originalSelection;
243 
244  // Expand from the original selection with the NEW total number of layers
246  if (newNumberOfLayers == 0) {
247  // No layers = return to original selection
248  result = baseSelection;
249  // CVLog::Print("[cvViewSelectionManager] Returning to original
250  // selection");
251  } else {
252  // Expand the original selection by newNumberOfLayers
253  result = m_algebra->expandSelection(polyData, baseSelection,
254  newNumberOfLayers, removeSeed,
255  removeIntermediateLayers);
256  }
257 
258  if (!result.isEmpty() || newNumberOfLayers == 0) {
259  // Don't reset layers since this is a grow/shrink operation
260  setCurrentSelection(result, false);
261 
262  // Update number of layers
263  m_numberOfLayers = newNumberOfLayers;
264 
266  QString("[cvViewSelectionManager] Updated NumberOfLayers: %1")
267  .arg(m_numberOfLayers));
268 
269  // History removed - UI not implemented
270 
271  // Update highlight
272  if (m_highlighter) {
273  if (!result.isEmpty()) {
274  m_highlighter->highlightSelection(
275  polyData, result.vtkArray(),
276  static_cast<int>(result.fieldAssociation()),
278  } else {
279  m_highlighter->clearHighlights();
280  }
281  }
282 
283  QString operationName =
284  layers > 0 ? "Grow Selection" : "Shrink Selection";
285  CVLog::Print(
286  QString("[cvViewSelectionManager] %1: %2 -> %3 %4 (layers=%5)")
287  .arg(operationName)
288  .arg(baseSelection.count())
289  .arg(result.count())
290  .arg(result.fieldTypeString())
291  .arg(m_numberOfLayers));
292  emit selectionChanged();
293  } else {
295  "[cvViewSelectionManager] Expand resulted in empty selection");
296  }
297 }
298 
299 //-----------------------------------------------------------------------------
301  m_growRemoveSeed = remove;
302 }
303 
304 //-----------------------------------------------------------------------------
306  bool remove) {
307  m_growRemoveIntermediateLayers = remove;
308  CVLog::PrintVerbose(QString("[cvViewSelectionManager] "
309  "GrowSelectionRemoveIntermediateLayers = %1")
310  .arg(remove));
311 }
312 
313 //-----------------------------------------------------------------------------
315  SelectionMode mode2) const {
316  // Same mode is always compatible
317  if (mode1 == mode2) {
318  return true;
319  }
320 
321  // Cell selection modes are compatible with each other
322  // Reference: pqRenderViewSelectionReaction.cxx, line 1037-1060
323  QSet<SelectionMode> cellModes = {
328 
329  if (cellModes.contains(mode1) && cellModes.contains(mode2)) {
330  return true;
331  }
332 
333  // Point selection modes are compatible with each other
334  QSet<SelectionMode> pointModes = {
339 
340  if (pointModes.contains(mode1) && pointModes.contains(mode2)) {
341  return true;
342  }
343 
344  // Block selection modes are compatible
345  QSet<SelectionMode> blockModes = {SelectionMode::SELECT_BLOCKS,
347 
348  if (blockModes.contains(mode1) && blockModes.contains(mode2)) {
349  return true;
350  }
351 
352  return false;
353 }
354 
355 //-----------------------------------------------------------------------------
357  static cvSelectionData emptySelection;
358  if (!m_currentSelection) {
359  return emptySelection;
360  }
361 
362  // Create a temporary cvSelectionData from current VTK array
363  static thread_local cvSelectionData cachedSelection;
364  cachedSelection = cvSelectionData(m_currentSelection,
365  m_currentSelectionFieldAssociation);
366  return cachedSelection;
367 }
368 
369 //-----------------------------------------------------------------------------
371  const cvSelectionData& selectionData, bool resetLayers) {
372  // Convert cvSelectionData to VTK array for internal storage
373  setCurrentSelection(selectionData.vtkArray(),
374  static_cast<int>(selectionData.fieldAssociation()),
375  resetLayers);
376 
377  // Store as original selection if this is a new selection (resetLayers=true)
378  // ParaView-style: Original selection is the base for all grow/shrink
379  // operations
380  if (resetLayers) {
381  m_originalSelection = selectionData;
382  m_numberOfLayers = 0;
383  CVLog::PrintVerbose(QString("[cvViewSelectionManager] Stored original "
384  "selection: %1 %2")
385  .arg(selectionData.count())
386  .arg(selectionData.fieldTypeString()));
387  }
388 }
389 
390 //-----------------------------------------------------------------------------
392  const vtkSmartPointer<vtkIdTypeArray>& selection,
393  int fieldAssociation,
394  bool resetLayers) {
395  // CRITICAL FIX: Validate selection pointer before use
396  if (selection && selection.GetPointer() == nullptr) {
397  CVLog::Error(
398  "[cvViewSelectionManager] Selection SmartPointer contains null "
399  "pointer!");
400  return;
401  }
402 
403  // Additional validation: check if the object is valid
404  vtkIdType newCount = 0;
405  if (selection) {
406  try {
407  // Test if we can safely access the array
408  newCount = selection->GetNumberOfTuples();
409  if (newCount < 0) {
410  CVLog::Error(
411  "[cvViewSelectionManager] Selection array has invalid "
412  "tuple count!");
413  return;
414  }
415  } catch (...) {
416  CVLog::Error(
417  "[cvViewSelectionManager] Selection array access failed - "
418  "invalid pointer!");
419  return;
420  }
421  }
422 
423  // CRITICAL FIX: Check if selection actually changed to prevent infinite
424  // recursion Compare with current selection
425  bool hasChanged = false;
426  if (!m_currentSelection && newCount == 0) {
427  // Both empty - no change
429  "[cvViewSelectionManager] Selection unchanged (both empty)");
430  return;
431  } else if (!m_currentSelection && newCount > 0) {
432  // Was empty, now has content
433  hasChanged = true;
434  } else if (m_currentSelection && newCount == 0) {
435  // Had content, now empty
436  hasChanged = true;
437  } else if (m_currentSelection) {
438  // Both have content - check if they're identical
439  vtkIdType oldCount = m_currentSelection->GetNumberOfTuples();
440  if (oldCount != newCount ||
441  m_currentSelectionFieldAssociation != fieldAssociation) {
442  hasChanged = true;
443  } else {
444  // Same count and field association - check if IDs are identical
445  bool idsMatch = true;
446  for (vtkIdType i = 0; i < newCount; ++i) {
447  if (m_currentSelection->GetValue(i) != selection->GetValue(i)) {
448  idsMatch = false;
449  break;
450  }
451  }
452  hasChanged = !idsMatch;
453  }
454  }
455 
456  if (!hasChanged) {
458  "[cvViewSelectionManager] Selection unchanged, skipping "
459  "update");
460  return;
461  }
462 
463  // Clean up old selection
464  // Smart pointer handles cleanup automatically
465  m_currentSelection = nullptr;
466 
467  // Store new selection
468  if (selection && newCount > 0) {
469  m_currentSelection = vtkSmartPointer<vtkIdTypeArray>::New();
470 
471  try {
472  m_currentSelection->DeepCopy(selection);
473  m_currentSelectionFieldAssociation = fieldAssociation;
474 
476  QString("[cvViewSelectionManager] Selection updated: %1 "
477  "%2 selected")
478  .arg(newCount)
479  .arg(fieldAssociation == 0 ? "cells" : "points"));
480  } catch (const std::exception& e) {
481  CVLog::Error(QString("[cvViewSelectionManager] DeepCopy failed: %1")
482  .arg(e.what()));
483  m_currentSelection = nullptr;
484  m_currentSelectionFieldAssociation = 0;
485  return;
486  } catch (...) {
487  CVLog::Error(
488  "[cvViewSelectionManager] DeepCopy failed with unknown "
489  "exception!");
490  m_currentSelection = nullptr;
491  m_currentSelectionFieldAssociation = 0;
492  return;
493  }
494  } else {
495  m_currentSelectionFieldAssociation = 0;
496  }
497 
498  // Create selection data object
499  cvSelectionData selectionData(m_currentSelection,
500  m_currentSelectionFieldAssociation);
501 
502  // History removed - UI not implemented
503 
504  // Emit both new and legacy signals
505  emit selectionChanged(selectionData);
506  emit selectionChanged(); // Legacy signal
507 }
508 
509 //-----------------------------------------------------------------------------
511  return m_currentSelection && m_currentSelection->GetNumberOfTuples() > 0;
512 }
513 
514 //-----------------------------------------------------------------------------
515 // Algebra operations (using cvSelectionAlgebra)
516 //-----------------------------------------------------------------------------
518  int op,
519  const cvSelectionData& selectionA,
520  const cvSelectionData& selectionB) {
521  if (!m_algebra) {
522  CVLog::Warning("[cvViewSelectionManager] Algebra module not available");
523  return cvSelectionData();
524  }
525 
526  vtkPolyData* polyData = getPolyData();
527 
529  static_cast<cvSelectionAlgebra::Operation>(op), selectionA,
530  selectionB, polyData);
531 
532  // History removed - UI not implemented
533 
534  return result;
535 }
536 
537 //-----------------------------------------------------------------------------
539  // ParaView-style: Try to get from last selection result first (from
540  // pipeline)
541  if (m_pipeline && m_pipeline->getLastSelection()) {
543  m_pipeline->getLastSelection());
544  if (data) {
545  vtkPolyData* polyData = vtkPolyData::SafeDownCast(data);
546  if (polyData) {
548  "[cvViewSelectionManager::getPolyData] Got polyData "
549  "from last selection");
550  return polyData;
551  }
552  }
553  }
554 
555  // Fallback: Get from visualizer's data actors
556  // Note: Cast away const to call non-const methods
557  cvViewSelectionManager* mutableThis =
558  const_cast<cvViewSelectionManager*>(this);
559  QList<vtkActor*> actors = mutableThis->getDataActors();
560  if (!actors.isEmpty()) {
561  vtkDataSet* data = mutableThis->getDataFromActor(actors.first());
562  if (data) {
563  vtkPolyData* polyData = vtkPolyData::SafeDownCast(data);
564  if (polyData) {
566  "[cvViewSelectionManager::getPolyData] Got polyData "
567  "from first data actor");
568  return polyData;
569  }
570  }
571  }
572 
573  return nullptr;
574 }
575 
576 //-----------------------------------------------------------------------------
578  // ParaView-style: Invalidate cached selection when data changes
579  // Reference: pqRenderViewSelectionReaction::clearSelectionCache()
580  if (m_pipeline) {
581  m_pipeline->invalidateCachedSelection();
582  }
583 }
584 
585 //-----------------------------------------------------------------------------
587  if (m_pipeline) {
588  m_pipeline->setPointPickingRadius(radius);
589  }
590 }
591 
592 //-----------------------------------------------------------------------------
594  if (m_pipeline) {
595  return m_pipeline->getPointPickingRadius();
596  }
597  return 5; // Default value
598 }
599 
600 //-----------------------------------------------------------------------------
602  // CRITICAL FIX: Clear current selection to prevent crashes from dangling
603  // pointers This is called when objects might have been deleted
604 
605  CVLog::Print(
606  "[cvViewSelectionManager] Clearing current selection (preventing "
607  "stale references)");
608 
609  // Clear the stored selection data
610  if (m_currentSelection) {
611  m_currentSelection = nullptr;
612  }
613 
614  m_currentSelectionFieldAssociation = -1;
615 
616  // Clear source object reference
617  m_sourceObject = nullptr;
618 
619  // Clear pipeline cache
620  if (m_pipeline) {
621  m_pipeline->invalidateCachedSelection();
622  }
623 
624  // Emit signal to notify listeners
625  cvSelectionData emptySelection;
626  emit selectionChanged(emptySelection);
627  emit selectionChanged(); // Legacy signal
628 }
629 
630 //-----------------------------------------------------------------------------
632  m_sourceObject = obj;
633 }
634 
635 //-----------------------------------------------------------------------------
637  return m_sourceObject;
638 }
639 
640 //-----------------------------------------------------------------------------
642  ccHObject* obj = getSourceObject();
643  if (!obj) {
644  CVLog::Print(
645  "[cvViewSelectionManager::getSourcePointCloud] No source "
646  "object");
647  return nullptr;
648  }
649 
650  // Note: We can't reliably detect if obj has been deleted in C++ without
651  // causing undefined behavior. The caller must ensure the object is still
652  // valid. We rely on the application to clear m_sourceObject when objects
653  // are deleted (e.g., via clearCurrentSelection()).
654 
655  // Check if it's a point cloud
656  if (obj->isA(CV_TYPES::POINT_CLOUD)) {
657  ccPointCloud* cloud = static_cast<ccPointCloud*>(obj);
659  QString("[cvViewSelectionManager::getSourcePointCloud] "
660  "Returning point cloud '%1' with %2 points")
661  .arg(cloud->getName())
662  .arg(cloud->size()));
663  return cloud;
664  }
665 
667  QString("[cvViewSelectionManager::getSourcePointCloud] "
668  "Source object '%1' is not a point cloud (type=%2)")
669  .arg(obj->getName())
670  .arg(obj->getClassID()));
671  return nullptr;
672 }
673 
674 //-----------------------------------------------------------------------------
676  ccHObject* obj = getSourceObject();
677  if (!obj) {
679  "[cvViewSelectionManager::getSourceMesh] No source object");
680  return nullptr;
681  }
682 
683  // Note: We can't reliably detect if obj has been deleted in C++ without
684  // causing undefined behavior. The caller must ensure the object is still
685  // valid. We rely on the application to clear m_sourceObject when objects
686  // are deleted (e.g., via clearCurrentSelection()).
687 
688  // Check if it's a mesh
689  if (obj->isKindOf(CV_TYPES::MESH)) {
690  ccMesh* mesh = static_cast<ccMesh*>(obj);
691  CVLog::PrintVerbose(QString("[cvViewSelectionManager::getSourceMesh] "
692  "Returning mesh '%1' with %2 triangles")
693  .arg(mesh->getName())
694  .arg(mesh->size()));
695  return mesh;
696  }
697 
698  CVLog::Warning(QString("[cvViewSelectionManager::getSourceMesh] "
699  "Source object '%1' is not a mesh (type=%2)")
700  .arg(obj->getName())
701  .arg(obj->getClassID()));
702  return nullptr;
703 }
704 
705 //-----------------------------------------------------------------------------
707  // Note: In C++, there's no reliable way to detect if a raw pointer points
708  // to a deleted object without causing undefined behavior. We rely on the
709  // application to clear m_sourceObject when objects are deleted.
710  // The actual safety check happens in getSourcePointCloud/getSourceMesh
711  // where we verify the object is still accessible before using it.
712  bool isValid = (m_sourceObject != nullptr);
713  return isValid;
714 }
core::Tensor result
Definition: VtkUtils.cpp:76
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
Hierarchical CLOUDVIEWER Object.
Definition: ecvHObject.h:25
CV_CLASS_ENUM getClassID() const override
Returns class ID.
Definition: ecvHObject.h:232
Triangular mesh.
Definition: ecvMesh.h:35
virtual unsigned size() const override
Returns the number of triangles.
Definition: ecvMesh.cpp:2143
virtual QString getName() const
Returns object name.
Definition: ecvObject.h:72
bool isA(CV_CLASS_ENUM type) const
Definition: ecvObject.h:131
bool isKindOf(CV_CLASS_ENUM type) const
Definition: ecvObject.h:128
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
unsigned size() const override
Definition: PointCloudTpl.h:38
Base class for selection tools with picking capabilities.
::SelectionMode SelectionMode
Selection mode Now using global SelectionMode enum from cvSelectionTypes.h.
::SelectionModifier SelectionModifier
Selection modifier (for multi-selection) Now using global SelectionModifier enum from cvSelectionType...
Selection algebra operations.
Operation
Algebra operations Using enum class to avoid macro conflicts (e.g., DIFFERENCE may be defined as a ma...
static cvSelectionData expandSelection(vtkPolyData *polyData, const cvSelectionData &input, int layers, bool removeSeed=false, bool removeIntermediateLayers=false)
Expand selection (ParaView-compatible)
static cvSelectionData performOperation(Operation op, const cvSelectionData &a, const cvSelectionData &b, vtkPolyData *polyData=nullptr)
Perform algebra operation on two selections.
Selection annotation manager.
void setVisualizer(PclUtils::PCLVis *viewer)
Set the visualizer.
PclUtils::PCLVis * getPCLVis() const
Get PCLVis instance (for VTK-specific operations)
vtkDataSet * getDataFromActor(vtkActor *actor)
Get data object from a specific actor (ParaView-style)
virtual void setVisualizer(ecvGenericVisualizer3D *viewer)
Set the visualizer instance.
QList< vtkActor * > getDataActors() const
Get all visible data actors from visualizer.
ecvGenericVisualizer3D * getVisualizer() const
Get the visualizer instance.
Encapsulates selection data without exposing VTK types.
FieldAssociation fieldAssociation() const
Get field association.
vtkSmartPointer< vtkIdTypeArray > vtkArray() const
Get the underlying VTK array (for internal use only)
QString fieldTypeString() const
Get human-readable field type string.
bool isEmpty() const
Check if selection is empty.
int count() const
Get number of selected items.
Advanced selection filtering system.
Helper class for highlighting selected elements in the visualizer.
bool highlightSelection(const vtkSmartPointer< vtkIdTypeArray > &selection, int fieldAssociation, HighlightMode mode=SELECTED)
Highlight selected elements (automatically gets polyData from visualizer)
void clearHighlights()
Clear all highlights.
Selection pipeline abstraction layer.
void setPointPickingRadius(unsigned int radius)
Point Picking Radius support (ParaView-aligned)
void invalidateCachedSelection()
Clear selection cache and invalidate cached buffers.
void setVisualizer(PclUtils::PCLVis *viewer)
Set the visualizer for selection operations.
static vtkDataSet * getPrimaryDataFromSelection(vtkSelection *selection)
Get the primary data object from selection.
vtkSmartPointer< vtkSelection > getLastSelection() const
Get the last selection result.
unsigned int getPointPickingRadius() const
Get the current point picking radius.
Central manager for all selection operations in the view.
void setGrowSelectionRemoveSeed(bool remove)
Grow/Shrink Selection Settings (ParaView-aligned)
ccPointCloud * getSourcePointCloud() const
Get the source object as ccPointCloud.
void setCurrentSelection(const cvSelectionData &selectionData, bool resetLayers=true)
Set the current selection data.
bool isSourceObjectValid() const
Check if the source object is still valid.
void setSelectionModifier(SelectionModifier modifier)
Set the selection modifier.
bool isCompatible(SelectionMode mode1, SelectionMode mode2) const
Check if a selection mode is compatible with the current mode.
void disableSelection()
Disable the current selection mode (legacy - state tracking only)
void notifyDataUpdated()
Notify that scene data has been updated.
vtkPolyData * getPolyData() const
Get the underlying polyData for selection operations.
bool isSelectionActive() const
Check if any selection mode is currently active.
cvSelectionData performAlgebraOperation(int op, const cvSelectionData &selectionA, const cvSelectionData &selectionB=cvSelectionData())
Perform algebra operation on selections.
void clearCurrentSelection()
Clear the current selection data (prevents crashes from stale references)
void shrinkSelection()
Shrink the current selection by one layer.
void modeChanged(SelectionMode mode)
Emitted when the selection mode changes.
void modifierChanged(SelectionModifier modifier)
Emitted when selection modifier changes.
bool hasSelection() const
Check if there is a current selection.
ccHObject * getSourceObject() const
Get the source object for the current selection.
void setPointPickingRadius(unsigned int radius)
Set the point picking radius for single-point selection.
void clearSelection()
Clear all selections.
static cvViewSelectionManager * instance()
Get the singleton instance.
void setVisualizer(ecvGenericVisualizer3D *viewer) override
Set the visualizer for all selection operations.
void setGrowSelectionRemoveIntermediateLayers(bool remove)
Set whether to remove intermediate layers when growing selection.
void growSelection()
Grow the current selection by one layer.
unsigned int getPointPickingRadius() const
Get the current point picking radius.
ccMesh * getSourceMesh() const
Get the source object as ccMesh.
void enableSelection(SelectionMode mode)
Enable a selection mode (legacy - state tracking only)
const cvSelectionData & currentSelection() const
Get the current selection data (VTK-independent)
void expandSelection(int layers, bool removeSeed=false, bool removeIntermediateLayers=false)
Expand selection by given number of layers.
void setSourceObject(ccHObject *obj)
Set the source object for selection operations.
void selectionChanged()
Emitted when the selection has changed (legacy - for backward compatibility)
Generic visualizer 3D interface.
SelectionMode
Selection modes matching ParaView's SelectionMode enum.
@ SELECT_BLOCKS
Select blocks (rectangle)
@ SELECT_FRUSTUM_BLOCKS
Select blocks in frustum.
@ SELECT_FRUSTUM_POINTS
Select points in frustum.
@ SELECT_SURFACE_POINTS
Select points on surface (rectangle)
@ SELECT_SURFACE_POINTS_POLYGON
Select points on surface (polygon)
@ GROW_SELECTION
Expand selection by one layer.
@ SHRINK_SELECTION
Shrink selection by one layer.
@ SELECT_SURFACE_POINTS_INTERACTIVELY
@ SELECT_SURFACE_CELLS
Select cells on surface (rectangle)
@ SELECT_SURFACE_CELLS_INTERACTIVELY
@ SELECT_SURFACE_CELLS_POLYGON
Select cells on surface (polygon)
@ SELECT_FRUSTUM_CELLS
Select cells in frustum.
@ CLEAR_SELECTION
Clear current selection.
SelectionModifier
Selection modifiers for combining selections.
@ SELECTION_DEFAULT
Replace selection (default)
const double * e
GraphType data
Definition: graph_cut.cc:138
@ MESH
Definition: CVTypes.h:105
@ POINT_CLOUD
Definition: CVTypes.h:104