/*========================================================================= Program: Visualization Toolkit Module: vtkCellArrayIterator.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ /** * @class vtkCellArrayIterator * @brief Encapsulate traversal logic for vtkCellArray. * * This is iterator for thread-safe traversal of a vtkCellArray. It provides * random access and forward iteration. Typical usage for forward iteration * looks like: * * ``` * auto iter = vtk::TakeSmartPointer(cellArray->NewIterator()); * for (iter->GoToFirstCell(); !iter->IsDoneWithTraversal(); iter->GoToNextCell()) * { * // do work with iter * iter->GetCurrentCell(numCellPts, cellPts); * } * ``` * * Typical usage for random access looks like: * * ``` * auto iter = vtk::TakeSmartPointer(cellArray->NewIterator()); * iter->GetCellAtId(cellId, numCellPts, cellPts); * ``` * * Here @a cellId is the id of the ith cell in the vtkCellArray; * @a numCellPts is the number of points defining the cell represented * as vtkIdType; and @a cellPts is a pointer to the point ids defined * as vtkIdType const*&. * * Internally the iterator may copy data from the vtkCellArray, or reference * the internal vtkCellArray storage. This depends on the relationship of * vtkIdType to the type and structure of internal storage. If the type of * storage is the same as vtkIdType, and the storage is a single-component * AOS array (i.e., a 1D array), then shared access to the vtkCellArray * storage is provided. Otherwise, the data from storage is copied into an * internal iterator buffer. (Of course copying is slower and can result in * 3-4x reduction in traversal performance. On the other hand, the * vtkCellArray can use the appropriate storage to save memory, perform * zero-copy, and/or efficiently represent the cell connectivity * information.) Note that referencing internal vtkCellArray storage has * implications on the validity of the iterator. If the underlying * vtkCellArray storage changes while iterating, and the iterator is * referencing this storage, unpredictable and catastrophic results are * likely - hence do not modify the vtkCellArray while iterating. * * @sa * vtkCellArray */ #ifndef vtkCellArrayIterator_h #define vtkCellArrayIterator_h #include "vtkCommonDataModelModule.h" // For export macro #include "vtkObject.h" #include "vtkCellArray.h" // Needed for inline methods #include "vtkIdList.h" // Needed for inline methods #include "vtkSmartPointer.h" // For vtkSmartPointer #include // for assert #include // for std::enable_if class VTKCOMMONDATAMODEL_EXPORT vtkCellArrayIterator : public vtkObject { public: //@{ /** * Standard methods for instantiation, type information, and printing. */ vtkTypeMacro(vtkCellArrayIterator, vtkObject); void PrintSelf(ostream& os, vtkIndent indent) override; static vtkCellArrayIterator* New(); //@} /** * Return the vtkCellArray object over which iteration is occuring. */ vtkCellArray* GetCellArray() { return this->CellArray; } /** * Intialize the iterator to a specific cell. This will revalidate the * iterator if the underlying vtkCellArray has been modified. This method * can always be used to set the starting location for forward iteration, * and it is also used to support random access. */ void GoToCell(vtkIdType cellId) { this->CurrentCellId = cellId; this->NumberOfCells = this->CellArray->GetNumberOfCells(); assert(cellId <= this->NumberOfCells); } /** * The following are methods supporting random access iteration. */ //@{ /** * Initialize the iterator to a specific cell and return the cell. Note * that methods passing vtkIdLists always copy data from the vtkCellArray * storage buffer into the vtkIdList. Otherwise, a fastpath returning * (numCellPts,cellPts) which may return a pointer to internal vtkCellArray * storage is possible, if vtkIdType is the same as the vtkCellArray buffer * (which is typical). */ void GetCellAtId(vtkIdType cellId, vtkIdType& numCellPts, vtkIdType const*& cellPts) { this->GoToCell(cellId); this->GetCurrentCell(numCellPts, cellPts); } void GetCellAtId(vtkIdType cellId, vtkIdList* cellIds) { this->GoToCell(cellId); this->GetCurrentCell(cellIds); } vtkIdList* GetCellAtId(vtkIdType cellId) { this->GoToCell(cellId); return this->GetCurrentCell(); } //@} /** * The following are methods supporting forward iteration. */ /** * Initialize the iterator for forward iteration. This will revalidate the * iterator if the underlying vtkCellArray has been modified. */ void GoToFirstCell() { this->CurrentCellId = 0; this->NumberOfCells = this->CellArray->GetNumberOfCells(); } /** * Advance the forward iterator to the next cell. */ void GoToNextCell() { ++this->CurrentCellId; } /** * Returns true if the iterator has completed the traversal. */ bool IsDoneWithTraversal() { return this->CurrentCellId >= this->NumberOfCells; } /** * Returns the id of the current cell during forward iteration. */ vtkIdType GetCurrentCellId() const { return this->CurrentCellId; } //@} /** * Returns the definition of the current cell during forward * traversal. Note that methods passing vtkIdLists always copy data from * the vtkCellArray storage buffer into the vtkIdList. Otherwise, a * fastpath returning (numCellPts,cellPts) - which may return a pointer to * internal vtkCellArray storage - is possible, if vtkIdType is the same as * the vtkCellArray storage (which is typical). */ void GetCurrentCell(vtkIdType& cellSize, vtkIdType const*& cellPoints) { assert(this->CurrentCellId < this->NumberOfCells); // Either refer to vtkCellArray storage buffer, or copy into local buffer if (this->CellArray->IsStorageShareable()) { this->CellArray->GetCellAtId(this->CurrentCellId, cellSize, cellPoints); } else // or copy into local iterator buffer. { this->CellArray->GetCellAtId(this->CurrentCellId, this->TempCell); cellSize = this->TempCell->GetNumberOfIds(); cellPoints = this->TempCell->GetPointer(0); } } void GetCurrentCell(vtkIdList* ids) { assert(this->CurrentCellId < this->NumberOfCells); this->CellArray->GetCellAtId(this->CurrentCellId, ids); } vtkIdList* GetCurrentCell() { assert(this->CurrentCellId < this->NumberOfCells); this->CellArray->GetCellAtId(this->CurrentCellId, this->TempCell); return this->TempCell; } //@} /** * Specialized methods for performing operations on the vtkCellArray. */ /** * Replace the current cell with the ids in `list`. Note that this method * CANNOT change the number of points in the cell, it can only redefine the * ids (e.g. `list` must contain the same number of entries as the current * cell's points). */ void ReplaceCurrentCell(vtkIdList* list) { assert(this->CurrentCellId < this->NumberOfCells); this->CellArray->ReplaceCellAtId(this->CurrentCellId, list); } /** * Replace the current cell with the ids in `pts`. Note that this method * CANNOT change the number of points in the cell, it can only redefine the * ids (e.g. `npts` must equal the current cell's number of points). */ void ReplaceCurrentCell(vtkIdType npts, const vtkIdType* pts) { assert(this->CurrentCellId < this->NumberOfCells); this->CellArray->ReplaceCellAtId(this->CurrentCellId, npts, pts); } /** * Reverses the order of the point ids in the current cell. */ void ReverseCurrentCell() { assert(this->CurrentCellId < this->NumberOfCells); this->CellArray->ReverseCellAtId(this->CurrentCellId); } friend class vtkCellArray; protected: vtkCellArrayIterator() = default; ~vtkCellArrayIterator() override = default; vtkSetMacro(CellArray, vtkCellArray*); vtkSmartPointer CellArray; vtkNew TempCell; vtkIdType CurrentCellId; vtkIdType NumberOfCells; private: vtkCellArrayIterator(const vtkCellArrayIterator&) = delete; void operator=(const vtkCellArrayIterator&) = delete; }; #endif // vtkCellArrayIterator_h