ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
cvGenericSelectionTool.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 "PclUtils/PCLVis.h"
11 #include "cvSelectionBase.h"
12 #include "cvSelectionPipeline.h"
13 // cvSelectionTypes.h merged into cvSelectionData.h // For SelectionMode and
14 // SelectionModifier enums
15 #include "cvViewSelectionManager.h"
16 
17 // Qt5/Qt6 Compatibility
18 #include <QtCompat.h>
19 
20 // VTK
21 #include <vtkActor.h>
22 #include <vtkCellPicker.h>
23 #include <vtkDataObject.h>
24 #include <vtkDataSetMapper.h>
25 #include <vtkHardwareSelector.h>
26 #include <vtkIdTypeArray.h>
27 #include <vtkInformation.h> // For vtkInformation
28 #include <vtkMapper.h>
29 #include <vtkPointPicker.h>
30 #include <vtkPolyData.h>
31 #include <vtkPolyDataMapper.h>
32 #include <vtkProp.h>
33 #include <vtkPropCollection.h>
34 #include <vtkRenderWindow.h>
35 #include <vtkRenderWindowInteractor.h>
36 #include <vtkRenderer.h>
37 #include <vtkSelection.h>
38 #include <vtkSelectionNode.h>
39 #include <vtkSmartPointer.h>
40 
41 // Qt
42 #include <QSet> // For QSet
43 
44 // ECV
45 #include <CVLog.h>
46 
47 // STD
48 #include <algorithm>
49 #include <map>
50 #include <set>
51 
52 //=============================================================================
53 // Manager and Pipeline Access
54 //=============================================================================
55 
57  if (!m_manager) {
58  return nullptr;
59  }
60  return m_manager->getPipeline();
61 }
62 
63 //-----------------------------------------------------------------------------
65  const cvSelectionData* selectionData) {
66  // Priority 1: From provided selection data's actor info (ParaView way!)
67  if (selectionData && selectionData->hasActorInfo()) {
68  vtkPolyData* polyData = selectionData->primaryPolyData();
69  if (polyData) {
71  "[cvGenericSelectionTool] Using polyData from provided "
72  "selection actor info");
73  return polyData;
74  }
75  }
76 
77  // Priority 2: From current selection's actor info (tool-specific)
79  vtkPolyData* polyData = m_currentSelection.primaryPolyData();
80  if (polyData) {
82  "[cvGenericSelectionTool] Using polyData from current "
83  "selection actor info");
84  return polyData;
85  }
86  }
87 
88  // Priority 3-4: Delegate to base class (manager singleton, then fallback)
89  return cvSelectionBase::getPolyDataForSelection(selectionData);
90 }
91 
92 //=============================================================================
93 // Hardware Selection Implementation (ParaView-Aligned)
94 //=============================================================================
95 
96 //-----------------------------------------------------------------------------
98  int x, int y, SelectionMode mode, SelectionModifier modifier) {
99  int region[4] = {x, y, x, y};
100  return hardwareSelectInRegion(region, mode, modifier);
101 }
102 
103 //-----------------------------------------------------------------------------
105  const int region[4], SelectionMode mode, SelectionModifier modifier) {
106  if (!hasValidPCLVis()) {
107  CVLog::Warning("[hardwareSelectInRegion] No valid visualizer");
108  return cvSelectionData();
109  }
110 
111  // Try to use pipeline if available (Phase 1: Pipeline Integration)
113  if (pipeline) {
115  "[hardwareSelectInRegion] Using cvSelectionPipeline");
116 
117  // Map SelectionMode to Pipeline SelectionType
119  switch (mode) {
121  pipelineType = cvSelectionPipeline::SURFACE_CELLS;
122  break;
125  break;
127  pipelineType = cvSelectionPipeline::FRUSTUM_CELLS;
128  break;
131  break;
132  default:
133  pipelineType = cvSelectionPipeline::SURFACE_CELLS;
134  break;
135  }
136 
137  // Execute selection through pipeline (with caching!)
138  // ParaView-style: Get vtkSelection first, then convert to
139  // cvSelectionData WITH actor info
141  pipeline->executeRectangleSelection(const_cast<int*>(region),
142  pipelineType);
143 
144  cvSelectionData newSelection;
145  if (vtkSel) {
146  int fieldAssoc =
151 
152  // Convert to cvSelectionData WITH actor information (ParaView way!)
154  vtkSel, static_cast<cvSelectionPipeline::FieldAssociation>(
155  fieldAssoc));
156  }
157 
158  // Apply modifier using pipeline's combineSelections
159  if (modifier != SelectionModifier::SELECTION_DEFAULT &&
162  switch (modifier) {
165  break;
168  break;
171  break;
172  default:
174  break;
175  }
177  m_currentSelection, newSelection, operation);
178  }
179 
180  // Store as current selection
182  m_currentSelection = newSelection;
183  }
184 
185  return newSelection;
186  }
187 
188  // Fallback: Direct VTK implementation (original code)
190  "[hardwareSelectInRegion] Pipeline not available, using direct "
191  "VTK");
192 
193  // Determine field association
194  int fieldAssociation = vtkDataObject::FIELD_ASSOCIATION_CELLS;
195  switch (mode) {
198  fieldAssociation = vtkDataObject::FIELD_ASSOCIATION_POINTS;
199  break;
200  default:
201  break;
202  }
203 
204  // Configure hardware selector (reused for performance)
205  vtkHardwareSelector* selector =
206  configureHardwareSelector(region, fieldAssociation);
207  if (!selector) {
209  "[hardwareSelectInRegion] Failed to configure hardware "
210  "selector");
211  return cvSelectionData();
212  }
213 
214  // Perform selection
215  vtkSmartPointer<vtkSelection> vtkSel = selector->Select();
216  if (!vtkSel) {
217  CVLog::Warning("[hardwareSelectInRegion] Selection failed");
218  return cvSelectionData();
219  }
220 
221  // Extract actor information
222  QVector<cvActorSelectionInfo> actorInfos =
223  extractActorInfo(selector, vtkSel);
224 
225  // Convert to our selection format
226  cvSelectionData newSelection = convertSelection(vtkSel, actorInfos);
227 
228  // Smart pointer handles cleanup automatically
229 
230  // Apply modifier if needed
231  if (modifier != SelectionModifier::SELECTION_DEFAULT &&
233  return applyModifier(newSelection, m_currentSelection, modifier);
234  }
235 
236  // Store as current selection
238  m_currentSelection = newSelection;
239  }
240 
241  return newSelection;
242 }
243 
244 //-----------------------------------------------------------------------------
245 QVector<cvActorSelectionInfo> cvGenericSelectionTool::getActorsAtPoint(int x,
246  int y) {
247  if (!hasValidPCLVis()) {
248  return QVector<cvActorSelectionInfo>();
249  }
250 
251  int region[4] = {x, y, x, y};
252  vtkHardwareSelector* selector = configureHardwareSelector(
253  region, vtkDataObject::FIELD_ASSOCIATION_CELLS);
254 
255  if (!selector) {
256  return QVector<cvActorSelectionInfo>();
257  }
258 
259  vtkSmartPointer<vtkSelection> vtkSel = selector->Select();
260  QVector<cvActorSelectionInfo> actorInfos;
261 
262  if (vtkSel) {
263  actorInfos = extractActorInfo(selector, vtkSel);
264  // Smart pointer handles cleanup automatically
265  }
266 
267  // Selector is reused, no need to delete
268  return actorInfos;
269 }
270 
271 //-----------------------------------------------------------------------------
272 vtkHardwareSelector* cvGenericSelectionTool::getHardwareSelector() {
273  if (!m_hardwareSelector) {
276  "[getHardwareSelector] Created new hardware selector instance");
277  }
278  return m_hardwareSelector;
279 }
280 
281 //-----------------------------------------------------------------------------
282 vtkHardwareSelector* cvGenericSelectionTool::configureHardwareSelector(
283  const int region[4], int fieldAssociation) {
284  vtkRenderer* renderer = getRenderer();
285  if (!renderer) {
286  CVLog::Warning("[configureHardwareSelector] No renderer available");
287  return nullptr;
288  }
289 
290  // Get or create hardware selector (reused for performance)
291  vtkHardwareSelector* selector = getHardwareSelector();
292  if (!selector) {
294  "[configureHardwareSelector] Failed to get hardware selector");
295  return nullptr;
296  }
297 
298  // Configure for this selection
299  selector->SetRenderer(renderer);
300  selector->SetArea(region[0], region[1], region[2], region[3]);
301  selector->SetFieldAssociation(fieldAssociation);
302 
303  // Capture Z-buffer values for depth sorting
304  selector->SetCaptureZValues(m_captureZValues);
305 
306  CVLog::PrintVerbose(QString("[configureHardwareSelector] Configured: "
307  "region=[%1,%2,%3,%4], "
308  "fieldAssoc=%5, captureZ=%6")
309  .arg(region[0])
310  .arg(region[1])
311  .arg(region[2])
312  .arg(region[3])
313  .arg(fieldAssociation)
314  .arg(m_captureZValues));
315 
316  return selector;
317 }
318 
319 //-----------------------------------------------------------------------------
320 QVector<cvActorSelectionInfo> cvGenericSelectionTool::extractActorInfo(
321  vtkHardwareSelector* selector, vtkSelection* vtkSel) {
322  QVector<cvActorSelectionInfo> actorInfos;
323 
324  if (!selector || !vtkSel) {
325  return actorInfos;
326  }
327 
328  // Get renderer for actor lookup
329  vtkRenderer* renderer = getRenderer();
330  if (!renderer) {
331  return actorInfos;
332  }
333 
334  // Map to store prop information
335  std::map<int, cvActorSelectionInfo> propInfoMap;
336 
337  // Iterate through selection nodes
338  for (unsigned int i = 0; i < vtkSel->GetNumberOfNodes(); ++i) {
339  vtkSelectionNode* node = vtkSel->GetNode(i);
340  if (!node) continue;
341 
342  // Get prop ID
343  int propId = -1;
344  if (node->GetProperties()->Has(vtkSelectionNode::PROP_ID())) {
345  propId = node->GetProperties()->Get(vtkSelectionNode::PROP_ID());
346  }
347 
348  if (propId < 0) continue;
349 
350  // Get the prop/actor
351  vtkProp* prop = selector->GetPropFromID(propId);
352  vtkActor* actor = vtkActor::SafeDownCast(prop);
353 
354  if (!actor) continue;
355 
356  // Create actor info
358  info.actor = actor;
359  info.propId = propId;
360 
361  // Get Z-value if available (for depth sorting)
362  if (m_captureZValues) {
363  unsigned int centerPos[2] = {
364  (selector->GetArea()[0] + selector->GetArea()[2]) / 2,
365  (selector->GetArea()[1] + selector->GetArea()[3]) / 2};
366  vtkHardwareSelector::PixelInformation pixelInfo =
367  selector->GetPixelInformation(centerPos, 0);
368 
369  if (pixelInfo.Valid && pixelInfo.PropID == propId) {
370  // Normalize Z value to [0, 1], smaller = closer to camera
371  info.zValue =
372  pixelInfo.AttributeID >= 0
373  ? static_cast<double>(pixelInfo.AttributeID) /
374  1000000.0
375  : 1.0;
376  }
377  }
378 
379  // Get polyData from actor
380  vtkMapper* mapper = actor->GetMapper();
381  if (mapper) {
382  // Try vtkPolyDataMapper first
383  if (vtkPolyDataMapper* pdMapper =
384  vtkPolyDataMapper::SafeDownCast(mapper)) {
385  info.polyData = vtkPolyData::SafeDownCast(pdMapper->GetInput());
386  }
387  // Try vtkDataSetMapper
388  else if (vtkDataSetMapper* dsMapper =
389  vtkDataSetMapper::SafeDownCast(mapper)) {
390  vtkDataSet* dataset = dsMapper->GetInput();
391  if (dataset) {
392  info.polyData = vtkPolyData::SafeDownCast(dataset);
393  }
394  }
395  }
396 
397  // Get composite index if available
398  if (node->GetProperties()->Has(vtkSelectionNode::COMPOSITE_INDEX())) {
399  info.blockIndex = node->GetProperties()->Get(
400  vtkSelectionNode::COMPOSITE_INDEX());
401  }
402 
403  // Store in map
404  propInfoMap[propId] = info;
405  }
406 
407  // Convert map to vector and sort by Z-value
408  actorInfos.reserve(propInfoMap.size());
409  for (const auto& pair : propInfoMap) {
410  actorInfos.append(pair.second);
411  }
412 
413  // Sort by Z-value (front to back)
414  std::sort(actorInfos.begin(), actorInfos.end(),
415  [](const cvActorSelectionInfo& a, const cvActorSelectionInfo& b) {
416  return a.zValue < b.zValue;
417  });
418 
419  CVLog::PrintVerbose(QString("[extractActorInfo] Found %1 actor(s)")
420  .arg(actorInfos.size()));
421 
422  return actorInfos;
423 }
424 
425 //-----------------------------------------------------------------------------
426 cvSelectionData cvGenericSelectionTool::convertSelection(
427  vtkSelection* vtkSel, const QVector<cvActorSelectionInfo>& actorInfos) {
428  cvSelectionData selection;
429 
430  if (!vtkSel || vtkSel->GetNumberOfNodes() == 0) {
431  return selection;
432  }
433 
434  // Get the first selection node
435  vtkSelectionNode* node = vtkSel->GetNode(0);
436  if (!node) {
437  return selection;
438  }
439 
440  // Get selection IDs
441  vtkIdTypeArray* selectionIds =
442  vtkIdTypeArray::SafeDownCast(node->GetSelectionList());
443 
444  if (!selectionIds) {
445  return selection;
446  }
447 
448  // Determine field association
449  int fieldAssociation = node->GetFieldType();
450 
451  // Create selection data
452  selection = cvSelectionData(selectionIds, fieldAssociation);
453 
454  // Attach actor information
455  for (const cvActorSelectionInfo& info : actorInfos) {
456  selection.addActorInfo(info);
457  }
458 
460  QString("[convertSelection] Selection: %1 items, %2 actors")
461  .arg(selection.count())
462  .arg(selection.actorCount()));
463 
464  return selection;
465 }
466 
467 //-----------------------------------------------------------------------------
468 cvSelectionData cvGenericSelectionTool::applyModifier(
469  const cvSelectionData& newSelection,
470  const cvSelectionData& currentSelection,
471  SelectionModifier modifier) {
472  if (newSelection.isEmpty()) {
473  return currentSelection;
474  }
475 
476  if (currentSelection.isEmpty() ||
478  return newSelection;
479  }
480 
481  // Get ID sets
482  QVector<qint64> newIds = newSelection.ids();
483  QVector<qint64> currentIds = currentSelection.ids();
484  QSet<qint64> resultSet = qSetFromVector(currentIds);
485 
486  switch (modifier) {
488  // Add new IDs to current selection
489  for (qint64 id : newIds) {
490  resultSet.insert(id);
491  }
492  break;
493  }
494 
496  // Remove new IDs from current selection
497  for (qint64 id : newIds) {
498  resultSet.remove(id);
499  }
500  break;
501  }
502 
504  // Toggle: add if not present, remove if present
505  for (qint64 id : newIds) {
506  if (resultSet.contains(id)) {
507  resultSet.remove(id);
508  } else {
509  resultSet.insert(id);
510  }
511  }
512  break;
513  }
514 
515  default:
516  break;
517  }
518 
519  // Convert back to vector
520  QVector<qint64> resultIds = qVectorFromSet(resultSet);
521 
522  // Create result selection
523  cvSelectionData result(resultIds, newSelection.fieldAssociation());
524 
525  // Merge actor information
526  if (modifier == SelectionModifier::SELECTION_ADDITION ||
528  for (int i = 0; i < currentSelection.actorCount(); ++i) {
529  result.addActorInfo(currentSelection.actorInfo(i));
530  }
531  }
532  for (int i = 0; i < newSelection.actorCount(); ++i) {
533  result.addActorInfo(newSelection.actorInfo(i));
534  }
535 
536  return result;
537 }
538 
539 //-----------------------------------------------------------------------------
540 vtkRenderer* cvGenericSelectionTool::getRenderer() {
541  PclUtils::PCLVis* pclVis = getPCLVis();
542  if (!pclVis) {
543  return nullptr;
544  }
545  return pclVis->getCurrentRenderer();
546 }
547 
548 //=============================================================================
549 // Software Picking Implementation (Unified from Subclasses)
550 //=============================================================================
551 
552 //-----------------------------------------------------------------------------
554  if (!m_cellPicker) {
556  m_cellPicker->SetTolerance(0.005); // Default tolerance for cells
557  }
558 
559  if (!m_pointPicker) {
561  m_pointPicker->SetTolerance(0.01); // Default tolerance for points
562  }
563 
564  CVLog::PrintVerbose("[initializePickers] Pickers initialized");
565 }
566 
567 //-----------------------------------------------------------------------------
569  int y,
570  bool selectCells) {
571  // Ensure pickers are initialized
573 
574  // Get renderer (try from member variable first, then from visualizer)
575  vtkRenderer* renderer = m_renderer;
576  if (!renderer) {
577  renderer = getRenderer();
578  }
579 
580  if (!renderer) {
581  CVLog::Warning("[pickAtPosition] No renderer available");
582  return -1;
583  }
584 
585  vtkIdType pickedId = -1;
586 
587  if (selectCells) {
588  // Pick cells
589  if (m_cellPicker->Pick(x, y, 0, renderer)) {
590  pickedId = m_cellPicker->GetCellId();
591 
592  // Get the picked actor for multi-actor support
593  vtkActor* pickedActor = m_cellPicker->GetActor();
594 
596  QString("[pickAtPosition] Picked cell ID: %1 from actor %2")
597  .arg(pickedId)
598  .arg((quintptr)pickedActor, 0, 16));
599  }
600  } else {
601  // Pick points
602  if (m_pointPicker->Pick(x, y, 0, renderer)) {
603  pickedId = m_pointPicker->GetPointId();
604 
605  // Get the picked actor for multi-actor support
606  vtkActor* pickedActor = m_pointPicker->GetActor();
607 
608  CVLog::PrintVerbose(QString("[pickAtPosition] Picked point ID: %1 "
609  "from actor %2")
610  .arg(pickedId)
611  .arg((quintptr)pickedActor, 0, 16));
612  }
613  }
614 
615  return pickedId;
616 }
617 
618 //-----------------------------------------------------------------------------
619 vtkIdType cvGenericSelectionTool::pickAtCursor(bool selectCells) {
620  if (!m_interactor) {
621  CVLog::Warning("[pickAtCursor] No interactor set");
622  return -1;
623  }
624 
625  // Get cursor position from interactor
626  int* cursorPos = m_interactor->GetEventPosition();
627  return pickAtPosition(cursorPos[0], cursorPos[1], selectCells);
628 }
629 
630 //-----------------------------------------------------------------------------
632  double pointTolerance) {
634 
635  if (m_cellPicker) {
636  m_cellPicker->SetTolerance(cellTolerance);
637  }
638 
639  if (m_pointPicker) {
640  m_pointPicker->SetTolerance(pointTolerance);
641  }
642 
643  CVLog::PrintVerbose(QString("[setPickerTolerance] Cell: %1, Point: %2")
644  .arg(cellTolerance)
645  .arg(pointTolerance));
646 }
647 
648 //-----------------------------------------------------------------------------
649 vtkActor* cvGenericSelectionTool::getPickedActor(bool selectCells) {
650  if (selectCells && m_cellPicker) {
651  return m_cellPicker->GetActor();
652  } else if (!selectCells && m_pointPicker) {
653  return m_pointPicker->GetActor();
654  }
655  return nullptr;
656 }
657 
658 //-----------------------------------------------------------------------------
659 vtkPolyData* cvGenericSelectionTool::getPickedPolyData(bool selectCells) {
660  vtkActor* actor = getPickedActor(selectCells);
661  if (!actor) {
662  return nullptr;
663  }
664 
665  vtkMapper* mapper = actor->GetMapper();
666  if (!mapper) {
667  return nullptr;
668  }
669 
670  // Try vtkPolyDataMapper
671  vtkPolyDataMapper* pdMapper = vtkPolyDataMapper::SafeDownCast(mapper);
672  if (pdMapper) {
673  return vtkPolyData::SafeDownCast(pdMapper->GetInput());
674  }
675 
676  // Try vtkDataSetMapper
677  vtkDataSetMapper* dsMapper = vtkDataSetMapper::SafeDownCast(mapper);
678  if (dsMapper) {
679  vtkDataSet* dataset = dsMapper->GetInput();
680  return vtkPolyData::SafeDownCast(dataset);
681  }
682 
683  return nullptr;
684 }
685 
686 //-----------------------------------------------------------------------------
688  double position[3]) {
689  if (selectCells && m_cellPicker) {
690  m_cellPicker->GetPickPosition(position);
691  return true;
692  } else if (!selectCells && m_pointPicker) {
693  m_pointPicker->GetPickPosition(position);
694  return true;
695  }
696  return false;
697 }
698 
699 //-----------------------------------------------------------------------------
701  vtkIdType pickedId, bool selectCells) {
702  cvSelectionData selection;
703 
704  if (pickedId < 0) {
705  return selection; // Empty selection
706  }
707 
708  // Create selection with single ID
709  QVector<qint64> ids;
710  ids.append(pickedId);
711 
714 
715  selection = cvSelectionData(ids, association);
716 
717  // Attach actor information
718  vtkActor* actor = getPickedActor(selectCells);
719  vtkPolyData* polyData = getPickedPolyData(selectCells);
720 
721  if (actor && polyData) {
722  double worldPos[3];
723  getPickedPosition(selectCells, worldPos);
724 
725  // Create actor info
727  info.actor = actor;
728  info.polyData = polyData;
729 
730  // Estimate Z value from world position (not as accurate as hardware
731  // selector) This is a simplified approximation
732  info.zValue = worldPos[2]; // Use world Z as approximation
733 
734  selection.addActorInfo(info);
735 
736  CVLog::PrintVerbose(QString("[createSelectionFromPick] Created "
737  "selection: ID=%1, actor=%2")
738  .arg(pickedId)
739  .arg((quintptr)actor, 0, 16));
740  }
741 
742  return selection;
743 }
744 
745 //-----------------------------------------------------------------------------
747  const cvSelectionData& newSelection,
748  const cvSelectionData& currentSelection,
749  int modifier,
750  int fieldAssociation) {
751  // ParaView-aligned: Use cvSelectionPipeline::combineSelections()
752  // This eliminates code duplication between tools
753 
754  CVLog::PrintVerbose(QString("[cvGenericSelectionTool] "
755  "applySelectionModifierUnified: modifier=%1")
756  .arg(modifier));
757 
758  // Map view manager modifier to pipeline operation
760  switch (modifier) {
761  case 0: // SELECTION_DEFAULT
763  break;
764  case 1: // SELECTION_ADDITION
766  break;
767  case 2: // SELECTION_SUBTRACTION
769  break;
770  case 3: // SELECTION_TOGGLE
772  break;
773  default:
775  QString("[cvGenericSelectionTool] Unknown modifier: %1")
776  .arg(modifier));
777  return newSelection;
778  }
779 
780  // Use Pipeline's unified combination logic
781  return cvSelectionPipeline::combineSelections(currentSelection,
782  newSelection, operation);
783 }
math::float3 position
QSet< T > qSetFromVector(const QVector< T > &vec)
Definition: QtCompat.h:1073
QVector< T > qVectorFromSet(const QSet< T > &set)
Definition: QtCompat.h:1078
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 PrintVerbose(const char *format,...)
Prints out a verbose formatted message in console.
Definition: CVLog.cpp:103
vtkRenderer * getCurrentRenderer(int viewport=0)
Definition: PCLVis.cpp:2924
vtkSmartPointer< vtkCellPicker > m_cellPicker
Software picking components (unified from subclasses)
cvSelectionPipeline * getSelectionPipeline() const
Get the selection pipeline from manager.
cvSelectionData hardwareSelectInRegion(const int region[4], SelectionMode mode=SelectionMode::SELECT_SURFACE_CELLS, SelectionModifier modifier=SelectionModifier::SELECTION_DEFAULT)
Perform hardware selection in a region.
bool getPickedPosition(bool selectCells, double position[3])
Get pick position in world coordinates.
bool m_captureZValues
Capture Z-buffer values.
vtkPolyData * getPolyDataForSelection(const cvSelectionData *selectionData=nullptr) override
Get polyData for a selection using ParaView-style priority (override)
void setPickerTolerance(double cellTolerance, double pointTolerance)
Set picker tolerance.
cvSelectionData applySelectionModifierUnified(const cvSelectionData &newSelection, const cvSelectionData &currentSelection, int modifier, int fieldAssociation)
Apply selection modifier to combine selections.
vtkPolyData * getPickedPolyData(bool selectCells)
Get the last picked polyData.
cvSelectionData hardwareSelectAtPoint(int x, int y, SelectionMode mode=SelectionMode::SELECT_SURFACE_CELLS, SelectionModifier modifier=SelectionModifier::SELECTION_DEFAULT)
Hardware-accelerated selection (ParaView-aligned)
vtkRenderWindowInteractor * m_interactor
Interactor (weak pointer)
vtkSmartPointer< vtkPointPicker > m_pointPicker
Point picker.
cvViewSelectionManager * m_manager
Manager reference (for pipeline access)
vtkIdType pickAtPosition(int x, int y, bool selectCells)
Pick element at screen position.
void initializePickers()
Software picking methods (unified from subclasses)
vtkIdType pickAtCursor(bool selectCells)
Pick element at current cursor position.
::SelectionMode SelectionMode
Selection mode Now using global SelectionMode enum from cvSelectionTypes.h.
cvSelectionData createSelectionFromPick(vtkIdType pickedId, bool selectCells)
Create cvSelectionData from software picking result.
vtkActor * getPickedActor(bool selectCells)
Get the last picked actor.
QVector< cvActorSelectionInfo > getActorsAtPoint(int x, int y)
Get all actors at a screen location (without full selection)
bool m_multipleSelectionMode
Allow multiple selections.
vtkSmartPointer< vtkHardwareSelector > m_hardwareSelector
Hardware selector (reused)
::SelectionModifier SelectionModifier
Selection modifier (for multi-selection) Now using global SelectionModifier enum from cvSelectionType...
cvSelectionData m_currentSelection
Current selection (for modifiers)
vtkRenderer * m_renderer
Renderer (weak pointer)
PclUtils::PCLVis * getPCLVis() const
Get PCLVis instance (for VTK-specific operations)
virtual vtkPolyData * getPolyDataForSelection(const cvSelectionData *selectionData=nullptr)
Get polyData using ParaView-style priority (centralized method)
bool hasValidPCLVis() const
Check if visualizer is valid and is PCLVis.
Encapsulates selection data without exposing VTK types.
FieldAssociation fieldAssociation() const
Get field association.
void addActorInfo(const cvActorSelectionInfo &info)
Actor/Representation information (ParaView-style)
FieldAssociation
Field association for selection.
@ CELLS
Selection applies to cells.
@ POINTS
Selection applies to points.
bool isEmpty() const
Check if selection is empty.
QVector< qint64 > ids() const
Get selected IDs as a vector (copy)
bool hasActorInfo() const
Check if actor information is available.
int actorCount() const
Get number of actors in this selection.
int count() const
Get number of selected items.
cvActorSelectionInfo actorInfo(int index=0) const
Get actor info at index.
vtkPolyData * primaryPolyData() const
Get the primary (front-most) polyData.
Selection pipeline abstraction layer.
static cvSelectionData convertToCvSelectionData(vtkSelection *selection, FieldAssociation fieldAssociation)
Convert vtkSelection to cvSelectionData with actor info (ParaView-style)
vtkSmartPointer< vtkSelection > executeRectangleSelection(int region[4], SelectionType type)
Execute a rectangular selection.
FieldAssociation
Field association type.
static cvSelectionData combineSelections(const cvSelectionData &sel1, const cvSelectionData &sel2, CombineOperation operation)
Combine two selections.
SelectionType
Selection type.
@ FRUSTUM_POINTS
Frustum points.
@ FRUSTUM_CELLS
Frustum cells.
@ SURFACE_CELLS
Surface cells (rectangle)
@ SURFACE_POINTS
Surface points (rectangle)
CombineOperation
Selection combination methods (ParaView-style)
@ OPERATION_TOGGLE
XOR (sel1 ^ sel2)
@ OPERATION_ADDITION
Union (sel1 | sel2)
@ OPERATION_DEFAULT
Replace (sel2 only)
@ OPERATION_SUBTRACTION
Difference (sel1 & !sel2)
cvSelectionPipeline * getPipeline()
Get the selection pipeline.
@ SELECT_FRUSTUM_POINTS
Select points in frustum.
@ SELECT_SURFACE_POINTS
Select points on surface (rectangle)
@ SELECT_SURFACE_CELLS
Select cells on surface (rectangle)
@ SELECT_FRUSTUM_CELLS
Select cells in frustum.
SelectionModifier
Selection modifiers for combining selections.
@ SELECTION_TOGGLE
Toggle selection (Ctrl+Shift)
@ SELECTION_DEFAULT
Replace selection (default)
@ SELECTION_ADDITION
Add to selection (Ctrl)
@ SELECTION_SUBTRACTION
Subtract from selection (Shift)
a[190]
normal_z y
normal_z x
Information about a selected actor/representation.
double zValue
Z-buffer depth value (for front-to-back ordering)
unsigned int blockIndex
Block index for composite datasets.
int propId
Unique prop ID (from hardware selector)
vtkPolyData * polyData
The associated polyData (weak pointer)
vtkActor * actor
The selected actor (weak pointer)