ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
cvSelectionBase.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include "cvSelectionBase.h"
9 
10 #include "PclUtils/PCLVis.h"
11 #include "cvViewSelectionManager.h" // For singleton access
12 
13 // CV_CORE_LIB
14 #include <CVLog.h>
15 
16 // VTK
17 #include <vtkActor.h>
18 #include <vtkDataSet.h>
19 #include <vtkDataSetMapper.h>
20 #include <vtkMapper.h>
21 #include <vtkPolyData.h>
22 #include <vtkPolyDataMapper.h>
23 #include <vtkPropCollection.h>
24 #include <vtkRenderer.h>
25 
26 // Qt
27 #include <QList>
28 
29 // ECV
30 #include <CVLog.h>
31 
32 //-----------------------------------------------------------------------------
34  if (!m_viewer) {
35  return nullptr;
36  }
37  return reinterpret_cast<PclUtils::PCLVis*>(m_viewer);
38 }
39 
40 //-----------------------------------------------------------------------------
42  return m_viewer && getPCLVis() != nullptr;
43 }
44 
45 //-----------------------------------------------------------------------------
46 // ParaView-style helper methods
47 //-----------------------------------------------------------------------------
48 
49 vtkDataSet* cvSelectionBase::getDataFromActor(vtkActor* actor) {
50  if (!actor) {
51  return nullptr;
52  }
53 
54  vtkMapper* mapper = actor->GetMapper();
55  if (!mapper) {
56  return nullptr;
57  }
58 
59  vtkDataSet* data = mapper->GetInput();
60 
61  if (data) {
62  CVLog::PrintVerbose(QString("[cvSelectionBase::getDataFromActor] Got "
63  "data: %1 points, %2 cells")
64  .arg(data->GetNumberOfPoints())
65  .arg(data->GetNumberOfCells()));
66  }
67 
68  return data;
69 }
70 
71 //-----------------------------------------------------------------------------
73  const cvSelectionData* selectionData) {
74  vtkPolyData* polyData = nullptr;
75 
76  // Priority 1: From provided selection data's actor info (ParaView way!)
77  if (selectionData && selectionData->hasActorInfo()) {
78  polyData = selectionData->primaryPolyData();
79  if (polyData) {
81  "[cvSelectionBase] Using polyData from provided selection "
82  "actor info");
83  return polyData;
84  }
85  }
86 
87  // Priority 2: From selection manager singleton
88  // Note: Only call if this is NOT the manager itself to avoid circular calls
90  if (manager && dynamic_cast<cvViewSelectionManager*>(this) != manager) {
91  polyData = manager->getPolyData();
92  if (polyData) {
94  "[cvSelectionBase] Using polyData from selection manager "
95  "singleton");
96  return polyData;
97  }
98  }
99 
100  // Priority 3: Fallback to first data actor (for non-selection operations)
101  if (!polyData) {
102  QList<vtkActor*> actors = getDataActors();
103  if (!actors.isEmpty()) {
104  vtkDataSet* data = getDataFromActor(actors.first());
105  polyData = vtkPolyData::SafeDownCast(data);
106  if (polyData) {
108  "[cvSelectionBase] Fallback to first data actor");
109  }
110  }
111  }
112 
113  return polyData;
114 }
115 
116 //-----------------------------------------------------------------------------
117 QList<vtkActor*> cvSelectionBase::getDataActors() const {
118  QList<vtkActor*> actors;
119 
120  PclUtils::PCLVis* pclVis = getPCLVis();
121  if (!pclVis) {
123  "[cvSelectionBase::getDataActors] visualizer is nullptr");
124  return actors;
125  }
126 
127  vtkRenderer* renderer = pclVis->getCurrentRenderer();
128  if (!renderer) {
129  CVLog::Warning("[cvSelectionBase::getDataActors] renderer is nullptr");
130  return actors;
131  }
132 
133  // Collect all pickable actors with data
134  vtkPropCollection* props = renderer->GetViewProps();
135  props->InitTraversal();
136 
137  while (vtkProp* prop = props->GetNextProp()) {
138  vtkActor* actor = vtkActor::SafeDownCast(prop);
139 
140  if (actor && actor->GetVisibility() && actor->GetPickable() &&
141  actor->GetMapper() && actor->GetMapper()->GetInput()) {
142  actors.append(actor);
143  }
144  }
145 
147  QString("[cvSelectionBase::getDataActors] Found %1 data actors")
148  .arg(actors.size()));
149 
150  return actors;
151 }
152 
153 //-----------------------------------------------------------------------------
155  std::vector<vtkPolyData*> polyDataList;
156 
157  PclUtils::PCLVis* pclVis = getPCLVis();
158  if (!pclVis) {
160  "[cvSelectionBase::getAllPolyDataFromVisualizer] visualizer is "
161  "nullptr");
162  return polyDataList;
163  }
164 
165  vtkRenderer* renderer = pclVis->getCurrentRenderer();
166  if (!renderer) {
168  "[cvSelectionBase::getAllPolyDataFromVisualizer] renderer is "
169  "nullptr");
170  return polyDataList;
171  }
172 
173  // Collect all polydata from actors
174  vtkPropCollection* props = renderer->GetViewProps();
175  props->InitTraversal();
176 
177  int actorCount = 0;
178  int polyDataCount = 0;
179 
180  while (vtkProp* p = props->GetNextProp()) {
181  vtkActor* actor = vtkActor::SafeDownCast(p);
182  if (actor && actor->GetMapper() &&
183  actor->GetVisibility() && // Check visibility
184  actor->GetPickable()) { // Check if pickable (skip helper actors)
185  actorCount++;
186  vtkMapper* mapper = actor->GetMapper();
187 
188  vtkPolyData* polyData = nullptr;
189 
190  // Try vtkPolyDataMapper first (most common for textured meshes)
191  vtkPolyDataMapper* polyMapper =
192  vtkPolyDataMapper::SafeDownCast(mapper);
193  if (polyMapper) {
194  polyData = vtkPolyData::SafeDownCast(polyMapper->GetInput());
195  } else {
196  // Try vtkDataSetMapper (used for non-textured meshes)
197  vtkDataSetMapper* datasetMapper =
198  vtkDataSetMapper::SafeDownCast(mapper);
199  if (datasetMapper) {
200  vtkDataSet* dataset = datasetMapper->GetInput();
201  if (dataset) {
202  polyData = vtkPolyData::SafeDownCast(dataset);
203  }
204  }
205  }
206 
207  // Add valid polyData to list
208  if (polyData && polyData->GetNumberOfCells() > 0) {
209  polyDataList.push_back(polyData);
210  polyDataCount++;
212  QString("[cvSelectionBase::"
213  "getAllPolyDataFromVisualizer] Found "
214  "PolyData #%1: "
215  "%2 cells, %3 points")
216  .arg(polyDataCount)
217  .arg(polyData->GetNumberOfCells())
218  .arg(polyData->GetNumberOfPoints()));
219  }
220  }
221  }
222 
224  QString("[cvSelectionBase::getAllPolyDataFromVisualizer] "
225  "Found %1 polyData(s) "
226  "from %2 actor(s)")
227  .arg(polyDataCount)
228  .arg(actorCount));
229 
230  return polyDataList;
231 }
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
PclUtils::PCLVis * getPCLVis() const
Get PCLVis instance (for VTK-specific operations)
vtkDataSet * getDataFromActor(vtkActor *actor)
Get data object from a specific actor (ParaView-style)
QList< vtkActor * > getDataActors() const
Get all visible data actors from visualizer.
std::vector< vtkPolyData * > getAllPolyDataFromVisualizer()
Get all polyData from the visualizer.
virtual vtkPolyData * getPolyDataForSelection(const cvSelectionData *selectionData=nullptr)
Get polyData using ParaView-style priority (centralized method)
ecvGenericVisualizer3D * m_viewer
Visualizer instance (abstract interface)
bool hasValidPCLVis() const
Check if visualizer is valid and is PCLVis.
Encapsulates selection data without exposing VTK types.
bool hasActorInfo() const
Check if actor information is available.
vtkPolyData * primaryPolyData() const
Get the primary (front-most) polyData.
Central manager for all selection operations in the view.
vtkPolyData * getPolyData() const
Get the underlying polyData for selection operations.
static cvViewSelectionManager * instance()
Get the singleton instance.
GraphType data
Definition: graph_cut.cc:138