ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
cvSelectionData.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 "cvSelectionData.h"
9 
10 // VTK
11 #include <vtkActor.h>
12 #include <vtkIdTypeArray.h>
13 #include <vtkPolyData.h>
14 
15 // STD
16 #include <algorithm>
17 
18 //-----------------------------------------------------------------------------
20  : m_vtkArray(nullptr), m_fieldAssociation(CELLS) {}
21 
22 //-----------------------------------------------------------------------------
23 cvSelectionData::cvSelectionData(vtkIdTypeArray* vtkArray, int association)
24  : m_vtkArray(nullptr),
25  m_fieldAssociation(static_cast<FieldAssociation>(association)) {
26  if (vtkArray) {
27  // CRITICAL FIX: Validate array before DeepCopy
28  try {
29  vtkIdType numTuples = vtkArray->GetNumberOfTuples();
30  if (numTuples < 0) {
31  // Invalid array
32  return;
33  }
34 
36  m_vtkArray->DeepCopy(vtkArray);
37  } catch (...) {
38  // DeepCopy failed - leave m_vtkArray as nullptr
39  m_vtkArray = nullptr;
40  }
41  }
42 }
43 
44 //-----------------------------------------------------------------------------
45 cvSelectionData::cvSelectionData(const QVector<qint64>& ids,
46  FieldAssociation association)
47  : m_vtkArray(nullptr), m_fieldAssociation(association) {
48  if (!ids.isEmpty()) {
50  m_vtkArray->SetNumberOfTuples(ids.size());
51  for (int i = 0; i < ids.size(); ++i) {
52  m_vtkArray->SetValue(i, ids[i]);
53  }
54  }
55 }
56 
57 //-----------------------------------------------------------------------------
59  : m_vtkArray(nullptr),
60  m_fieldAssociation(other.m_fieldAssociation),
61  m_actorInfos(other.m_actorInfos) {
62  if (other.m_vtkArray) {
63  // CRITICAL FIX: Validate array before DeepCopy
64  try {
65  vtkIdType numTuples = other.m_vtkArray->GetNumberOfTuples();
66  if (numTuples < 0) {
67  // Invalid array
68  return;
69  }
70 
72  m_vtkArray->DeepCopy(other.m_vtkArray);
73  } catch (...) {
74  // DeepCopy failed - leave m_vtkArray as nullptr
75  m_vtkArray = nullptr;
76  }
77  }
78 }
79 
80 //-----------------------------------------------------------------------------
82  if (this != &other) {
83  // Copy new data (smart pointer handles cleanup automatically)
84  m_fieldAssociation = other.m_fieldAssociation;
85  m_actorInfos = other.m_actorInfos;
86 
87  if (other.m_vtkArray) {
88  // CRITICAL FIX: Validate array before DeepCopy
89  try {
90  vtkIdType numTuples = other.m_vtkArray->GetNumberOfTuples();
91  if (numTuples >= 0) {
93  m_vtkArray->DeepCopy(other.m_vtkArray);
94  } else {
95  m_vtkArray = nullptr;
96  }
97  } catch (...) {
98  // DeepCopy failed - leave m_vtkArray as nullptr
99  m_vtkArray = nullptr;
100  }
101  } else {
102  m_vtkArray = nullptr;
103  }
104  }
105  return *this;
106 }
107 
108 //-----------------------------------------------------------------------------
110  // Smart pointer handles cleanup automatically
111 }
112 
113 //-----------------------------------------------------------------------------
115  return !m_vtkArray || m_vtkArray->GetNumberOfTuples() == 0;
116 }
117 
118 //-----------------------------------------------------------------------------
120  return m_vtkArray ? m_vtkArray->GetNumberOfTuples() : 0;
121 }
122 
123 //-----------------------------------------------------------------------------
124 QVector<qint64> cvSelectionData::ids() const {
125  QVector<qint64> result;
126  if (m_vtkArray) {
127  vtkIdType numTuples = m_vtkArray->GetNumberOfTuples();
128  result.reserve(numTuples);
129  for (vtkIdType i = 0; i < numTuples; ++i) {
130  result.append(m_vtkArray->GetValue(i));
131  }
132  }
133  return result;
134 }
135 
136 //-----------------------------------------------------------------------------
138  m_vtkArray = nullptr; // Smart pointer handles cleanup automatically
139  m_actorInfos.clear();
140 }
141 
142 //-----------------------------------------------------------------------------
144  return (m_fieldAssociation == CELLS) ? "cells" : "points";
145 }
146 
147 //-----------------------------------------------------------------------------
149  m_actorInfos.append(info);
150 
151  // Sort by Z-value (front to back: smaller Z = closer to camera)
152  std::sort(m_actorInfos.begin(), m_actorInfos.end(),
153  [](const cvActorSelectionInfo& a, const cvActorSelectionInfo& b) {
154  return a.zValue < b.zValue;
155  });
156 }
157 
158 //-----------------------------------------------------------------------------
159 void cvSelectionData::setActorInfo(vtkActor* actor,
160  vtkPolyData* polyData,
161  double zValue) {
162  m_actorInfos.clear();
163 
165  info.actor = actor;
166  info.polyData = polyData;
167  info.zValue = zValue;
168 
169  m_actorInfos.append(info);
170 }
171 
172 //-----------------------------------------------------------------------------
174  if (index >= 0 && index < m_actorInfos.size()) {
175  return m_actorInfos[index];
176  }
177  return cvActorSelectionInfo(); // Return empty struct
178 }
179 
180 //-----------------------------------------------------------------------------
181 vtkActor* cvSelectionData::primaryActor() const {
182  return m_actorInfos.isEmpty() ? nullptr : m_actorInfos[0].actor;
183 }
184 
185 //-----------------------------------------------------------------------------
186 vtkPolyData* cvSelectionData::primaryPolyData() const {
187  return m_actorInfos.isEmpty() ? nullptr : m_actorInfos[0].polyData;
188 }
189 
190 //-----------------------------------------------------------------------------
191 void cvSelectionData::clearActorInfo() { m_actorInfos.clear(); }
core::Tensor result
Definition: VtkUtils.cpp:76
Encapsulates selection data without exposing VTK types.
~cvSelectionData()
Destructor.
cvSelectionData()
Construct empty selection data.
vtkSmartPointer< vtkIdTypeArray > vtkArray() const
Get the underlying VTK array (for internal use only)
QString fieldTypeString() const
Get human-readable field type string.
void addActorInfo(const cvActorSelectionInfo &info)
Actor/Representation information (ParaView-style)
FieldAssociation
Field association for selection.
@ CELLS
Selection applies to cells.
bool isEmpty() const
Check if selection is empty.
void clearActorInfo()
Clear actor information.
QVector< qint64 > ids() const
Get selected IDs as a vector (copy)
cvSelectionData & operator=(const cvSelectionData &other)
Assignment operator.
int count() const
Get number of selected items.
cvActorSelectionInfo actorInfo(int index=0) const
Get actor info at index.
void clear()
Clear the selection.
vtkPolyData * primaryPolyData() const
Get the primary (front-most) polyData.
vtkActor * primaryActor() const
Get the primary (front-most) actor.
void setActorInfo(vtkActor *actor, vtkPolyData *polyData, double zValue=1.0)
Set actor information (single actor case)
a[190]
Information about a selected actor/representation.
double zValue
Z-buffer depth value (for front-to-back ordering)
vtkPolyData * polyData
The associated polyData (weak pointer)
vtkActor * actor
The selected actor (weak pointer)