1 /*========================================================================= 2 3 Program: Visualization Toolkit 4 Module: vtkCellArrayIterator.h 5 6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 7 All rights reserved. 8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 9 10 This software is distributed WITHOUT ANY WARRANTY; without even 11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 12 PURPOSE. See the above copyright notice for more information. 13 14 =========================================================================*/ 15 16 /** 17 * @class vtkCellArrayIterator 18 * @brief Encapsulate traversal logic for vtkCellArray. 19 * 20 * This is iterator for thread-safe traversal of a vtkCellArray. It provides 21 * random access and forward iteration. Typical usage for forward iteration 22 * looks like: 23 * 24 * ``` 25 * auto iter = vtk::TakeSmartPointer(cellArray->NewIterator()); 26 * for (iter->GoToFirstCell(); !iter->IsDoneWithTraversal(); iter->GoToNextCell()) 27 * { 28 * // do work with iter 29 * iter->GetCurrentCell(numCellPts, cellPts); 30 * } 31 * ``` 32 * 33 * Typical usage for random access looks like: 34 * 35 * ``` 36 * auto iter = vtk::TakeSmartPointer(cellArray->NewIterator()); 37 * iter->GetCellAtId(cellId, numCellPts, cellPts); 38 * ``` 39 * 40 * Here @a cellId is the id of the ith cell in the vtkCellArray; 41 * @a numCellPts is the number of points defining the cell represented 42 * as vtkIdType; and @a cellPts is a pointer to the point ids defined 43 * as vtkIdType const*&. 44 * 45 * Internally the iterator may copy data from the vtkCellArray, or reference 46 * the internal vtkCellArray storage. This depends on the relationship of 47 * vtkIdType to the type and structure of internal storage. If the type of 48 * storage is the same as vtkIdType, and the storage is a single-component 49 * AOS array (i.e., a 1D array), then shared access to the vtkCellArray 50 * storage is provided. Otherwise, the data from storage is copied into an 51 * internal iterator buffer. (Of course copying is slower and can result in 52 * 3-4x reduction in traversal performance. On the other hand, the 53 * vtkCellArray can use the appropriate storage to save memory, perform 54 * zero-copy, and/or efficiently represent the cell connectivity 55 * information.) Note that referencing internal vtkCellArray storage has 56 * implications on the validity of the iterator. If the underlying 57 * vtkCellArray storage changes while iterating, and the iterator is 58 * referencing this storage, unpredictable and catastrophic results are 59 * likely - hence do not modify the vtkCellArray while iterating. 60 * 61 * @sa 62 * vtkCellArray 63 */ 64 65 #ifndef vtkCellArrayIterator_h 66 #define vtkCellArrayIterator_h 67 68 #include "vtkCommonDataModelModule.h" // For export macro 69 #include "vtkObject.h" 70 71 #include "vtkCellArray.h" // Needed for inline methods 72 #include "vtkIdList.h" // Needed for inline methods 73 #include "vtkSmartPointer.h" // For vtkSmartPointer 74 75 #include <cassert> // for assert 76 #include <type_traits> // for std::enable_if 77 78 class VTKCOMMONDATAMODEL_EXPORT vtkCellArrayIterator : public vtkObject 79 { 80 public: 81 ///@{ 82 /** 83 * Standard methods for instantiation, type information, and printing. 84 */ 85 vtkTypeMacro(vtkCellArrayIterator, vtkObject); 86 void PrintSelf(ostream& os, vtkIndent indent) override; 87 static vtkCellArrayIterator* New(); 88 ///@} 89 90 /** 91 * Return the vtkCellArray object over which iteration is occuring. 92 */ GetCellArray()93 vtkCellArray* GetCellArray() { return this->CellArray; } 94 95 /** 96 * Intialize the iterator to a specific cell. This will revalidate the 97 * iterator if the underlying vtkCellArray has been modified. This method 98 * can always be used to set the starting location for forward iteration, 99 * and it is also used to support random access. 100 */ GoToCell(vtkIdType cellId)101 void GoToCell(vtkIdType cellId) 102 { 103 this->CurrentCellId = cellId; 104 this->NumberOfCells = this->CellArray->GetNumberOfCells(); 105 assert(cellId <= this->NumberOfCells); 106 } 107 108 /** 109 * The following are methods supporting random access iteration. 110 */ 111 112 ///@{ 113 /** 114 * Initialize the iterator to a specific cell and return the cell. Note 115 * that methods passing vtkIdLists always copy data from the vtkCellArray 116 * storage buffer into the vtkIdList. Otherwise, a fastpath returning 117 * (numCellPts,cellPts) which may return a pointer to internal vtkCellArray 118 * storage is possible, if vtkIdType is the same as the vtkCellArray buffer 119 * (which is typical). 120 */ GetCellAtId(vtkIdType cellId,vtkIdType & numCellPts,vtkIdType const * & cellPts)121 void GetCellAtId(vtkIdType cellId, vtkIdType& numCellPts, vtkIdType const*& cellPts) 122 { 123 this->GoToCell(cellId); 124 this->GetCurrentCell(numCellPts, cellPts); 125 } GetCellAtId(vtkIdType cellId,vtkIdList * cellIds)126 void GetCellAtId(vtkIdType cellId, vtkIdList* cellIds) 127 { 128 this->GoToCell(cellId); 129 this->GetCurrentCell(cellIds); 130 } GetCellAtId(vtkIdType cellId)131 vtkIdList* GetCellAtId(vtkIdType cellId) 132 { 133 this->GoToCell(cellId); 134 return this->GetCurrentCell(); 135 } 136 ///@} 137 138 /** 139 * The following are methods supporting forward iteration. 140 */ 141 142 /** 143 * Initialize the iterator for forward iteration. This will revalidate the 144 * iterator if the underlying vtkCellArray has been modified. 145 */ GoToFirstCell()146 void GoToFirstCell() 147 { 148 this->CurrentCellId = 0; 149 this->NumberOfCells = this->CellArray->GetNumberOfCells(); 150 } 151 152 /** 153 * Advance the forward iterator to the next cell. 154 */ GoToNextCell()155 void GoToNextCell() { ++this->CurrentCellId; } 156 157 /** 158 * Returns true if the iterator has completed the traversal. 159 */ IsDoneWithTraversal()160 bool IsDoneWithTraversal() { return this->CurrentCellId >= this->NumberOfCells; } 161 162 /** 163 * Returns the id of the current cell during forward iteration. 164 */ GetCurrentCellId()165 vtkIdType GetCurrentCellId() const { return this->CurrentCellId; } 166 167 ///@{ 168 /** 169 * Returns the definition of the current cell during forward 170 * traversal. Note that methods passing vtkIdLists always copy data from 171 * the vtkCellArray storage buffer into the vtkIdList. Otherwise, a 172 * fastpath returning (numCellPts,cellPts) - which may return a pointer to 173 * internal vtkCellArray storage - is possible, if vtkIdType is the same as 174 * the vtkCellArray storage (which is typical). 175 */ GetCurrentCell(vtkIdType & cellSize,vtkIdType const * & cellPoints)176 void GetCurrentCell(vtkIdType& cellSize, vtkIdType const*& cellPoints) 177 { 178 assert(this->CurrentCellId < this->NumberOfCells); 179 // Either refer to vtkCellArray storage buffer, or copy into local buffer 180 if (this->CellArray->IsStorageShareable()) 181 { 182 this->CellArray->GetCellAtId(this->CurrentCellId, cellSize, cellPoints); 183 } 184 else // or copy into local iterator buffer. 185 { 186 this->CellArray->GetCellAtId(this->CurrentCellId, this->TempCell); 187 cellSize = this->TempCell->GetNumberOfIds(); 188 cellPoints = this->TempCell->GetPointer(0); 189 } 190 } GetCurrentCell(vtkIdList * ids)191 void GetCurrentCell(vtkIdList* ids) 192 { 193 assert(this->CurrentCellId < this->NumberOfCells); 194 this->CellArray->GetCellAtId(this->CurrentCellId, ids); 195 } GetCurrentCell()196 vtkIdList* GetCurrentCell() 197 { 198 assert(this->CurrentCellId < this->NumberOfCells); 199 this->CellArray->GetCellAtId(this->CurrentCellId, this->TempCell); 200 return this->TempCell; 201 } 202 ///@} 203 204 /** 205 * Specialized methods for performing operations on the vtkCellArray. 206 */ 207 208 /** 209 * Replace the current cell with the ids in `list`. Note that this method 210 * CANNOT change the number of points in the cell, it can only redefine the 211 * ids (e.g. `list` must contain the same number of entries as the current 212 * cell's points). 213 */ ReplaceCurrentCell(vtkIdList * list)214 void ReplaceCurrentCell(vtkIdList* list) 215 { 216 assert(this->CurrentCellId < this->NumberOfCells); 217 this->CellArray->ReplaceCellAtId(this->CurrentCellId, list); 218 } 219 220 /** 221 * Replace the current cell with the ids in `pts`. Note that this method 222 * CANNOT change the number of points in the cell, it can only redefine the 223 * ids (e.g. `npts` must equal the current cell's number of points). 224 */ ReplaceCurrentCell(vtkIdType npts,const vtkIdType * pts)225 void ReplaceCurrentCell(vtkIdType npts, const vtkIdType* pts) 226 { 227 assert(this->CurrentCellId < this->NumberOfCells); 228 this->CellArray->ReplaceCellAtId(this->CurrentCellId, npts, pts); 229 } 230 231 /** 232 * Reverses the order of the point ids in the current cell. 233 */ ReverseCurrentCell()234 void ReverseCurrentCell() 235 { 236 assert(this->CurrentCellId < this->NumberOfCells); 237 this->CellArray->ReverseCellAtId(this->CurrentCellId); 238 } 239 240 friend class vtkCellArray; 241 242 protected: 243 vtkCellArrayIterator() = default; 244 ~vtkCellArrayIterator() override = default; 245 246 vtkSetMacro(CellArray, vtkCellArray*); 247 248 vtkSmartPointer<vtkCellArray> CellArray; 249 vtkNew<vtkIdList> TempCell; 250 vtkIdType CurrentCellId; 251 vtkIdType NumberOfCells; 252 253 private: 254 vtkCellArrayIterator(const vtkCellArrayIterator&) = delete; 255 void operator=(const vtkCellArrayIterator&) = delete; 256 }; 257 258 #endif // vtkCellArrayIterator_h 259