You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

259 lines
8.5 KiB
C++

/*=========================================================================
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 <cassert> // for assert
#include <type_traits> // 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<vtkCellArray> CellArray;
vtkNew<vtkIdList> TempCell;
vtkIdType CurrentCellId;
vtkIdType NumberOfCells;
private:
vtkCellArrayIterator(const vtkCellArrayIterator&) = delete;
void operator=(const vtkCellArrayIterator&) = delete;
};
#endif // vtkCellArrayIterator_h