// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkStructuredCellArray.h" #include "vtkIdList.h" #include "vtkImplicitArray.h" #include "vtkObjectFactory.h" #include "vtkStructuredData.h" #include VTK_ABI_NAMESPACE_BEGIN //------------------------------------------------------------------------------ struct vtkStructuredCellArray::vtkStructuredCellBackend { //------------------------------------------------------------------------------ vtkStructuredCellBackend() = default; //------------------------------------------------------------------------------ virtual ~vtkStructuredCellBackend() = default; //------------------------------------------------------------------------------ virtual int GetCellSize() const = 0; //------------------------------------------------------------------------------ virtual void mapStructuredTuple(int ijk[3], vtkIdType* values) const = 0; //------------------------------------------------------------------------------ virtual void mapTuple(vtkIdType tupleId, vtkIdType* values) const = 0; //------------------------------------------------------------------------------ virtual vtkIdType mapComponent(vtkIdType tupleId, int comp) const = 0; //------------------------------------------------------------------------------ virtual vtkIdType map(vtkIdType valueId) const = 0; }; //------------------------------------------------------------------------------ namespace vtkShiftLUT { constexpr std::array ShiftLUT0 = { { 0, 0, 0, 0, 0, 0, 0, 0 } }; constexpr std::array ShiftLUT3 = { { 0, 0, 0, 0, 1, 1, 1, 1 } }; // use for voxels/pixels constexpr std::array ShiftLUT1 = { { 0, 1, 0, 1, 0, 1, 0, 1 } }; constexpr std::array ShiftLUT2 = { { 0, 0, 1, 1, 0, 0, 1, 1 } }; // used for hexes/quads constexpr std::array ShiftLUTx = { { 0, 1, 1, 0, 0, 1, 1, 0 } }; constexpr std::array ShiftLUTy = { { 0, 0, 1, 1, 0, 0, 1, 1 } }; //------------------------------------------------------------------------------ template constexpr std::array, 3> GetShiftLUT(); //------------------------------------------------------------------------------ template <> constexpr std::array, 3> GetShiftLUT() { return { { ShiftLUT0, ShiftLUT0, ShiftLUT0 } }; } //------------------------------------------------------------------------------ template <> constexpr std::array, 3> GetShiftLUT() { return { { ShiftLUT0, ShiftLUT0, ShiftLUT0 } }; } //------------------------------------------------------------------------------ template <> constexpr std::array, 3> GetShiftLUT() { return { { ShiftLUT1, ShiftLUT0, ShiftLUT0 } }; } //------------------------------------------------------------------------------ template <> constexpr std::array, 3> GetShiftLUT() { return { { ShiftLUT0, ShiftLUT1, ShiftLUT0 } }; } //------------------------------------------------------------------------------ template <> constexpr std::array, 3> GetShiftLUT() { return { { ShiftLUT0, ShiftLUT0, ShiftLUT1 } }; } //------------------------------------------------------------------------------ template <> constexpr std::array, 3> GetShiftLUT() { return { { ShiftLUT1, ShiftLUT2, ShiftLUT0 } }; } //------------------------------------------------------------------------------ template <> constexpr std::array, 3> GetShiftLUT() { return { { ShiftLUT0, ShiftLUT1, ShiftLUT2 } }; } //------------------------------------------------------------------------------ template <> constexpr std::array, 3> GetShiftLUT() { return { { ShiftLUT1, ShiftLUT0, ShiftLUT2 } }; } //------------------------------------------------------------------------------ template <> constexpr std::array, 3> GetShiftLUT() { return { { ShiftLUT1, ShiftLUT2, ShiftLUT3 } }; } //------------------------------------------------------------------------------ template <> constexpr std::array, 3> GetShiftLUT() { return { { ShiftLUT0, ShiftLUT0, ShiftLUT0 } }; } //------------------------------------------------------------------------------ template <> constexpr std::array, 3> GetShiftLUT() { return { { ShiftLUT0, ShiftLUT0, ShiftLUT0 } }; } //------------------------------------------------------------------------------ template <> constexpr std::array, 3> GetShiftLUT() { return { { ShiftLUTx, ShiftLUT0, ShiftLUT0 } }; } //------------------------------------------------------------------------------ template <> constexpr std::array, 3> GetShiftLUT() { return { { ShiftLUT0, ShiftLUTx, ShiftLUT0 } }; } //------------------------------------------------------------------------------ template <> constexpr std::array, 3> GetShiftLUT() { return { { ShiftLUT0, ShiftLUT0, ShiftLUTx } }; } //------------------------------------------------------------------------------ template <> constexpr std::array, 3> GetShiftLUT() { return { { ShiftLUTx, ShiftLUTy, ShiftLUT0 } }; } //------------------------------------------------------------------------------ template <> constexpr std::array, 3> GetShiftLUT() { return { { ShiftLUT0, ShiftLUTx, ShiftLUTy } }; } //------------------------------------------------------------------------------ template <> constexpr std::array, 3> GetShiftLUT() { return { { ShiftLUTx, ShiftLUT0, ShiftLUTy } }; } //------------------------------------------------------------------------------ template <> constexpr std::array, 3> GetShiftLUT() { return { { ShiftLUTx, ShiftLUTy, ShiftLUT3 } }; } } //------------------------------------------------------------------------------ template struct vtkStructuredCellArray::vtkStructuredTCellBackend : public vtkStructuredCellBackend { // static constexpr members static constexpr int CellSize = DataDescription == vtkStructuredData::VTK_STRUCTURED_XYZ_GRID ? 8 // NOLINTNEXTLINE(readability-avoid-nested-conditional-operator) : DataDescription == vtkStructuredData::VTK_STRUCTURED_XY_PLANE || DataDescription == vtkStructuredData::VTK_STRUCTURED_YZ_PLANE || DataDescription == vtkStructuredData::VTK_STRUCTURED_XZ_PLANE ? 4 // NOLINTNEXTLINE(readability-avoid-nested-conditional-operator) : DataDescription == vtkStructuredData::VTK_STRUCTURED_X_LINE || DataDescription == vtkStructuredData::VTK_STRUCTURED_Y_LINE || DataDescription == vtkStructuredData::VTK_STRUCTURED_Z_LINE ? 2 // NOLINTNEXTLINE(readability-avoid-nested-conditional-operator) : DataDescription == vtkStructuredData::VTK_STRUCTURED_SINGLE_POINT ? 1 : 0; static constexpr vtkIdType ValidCellSize = vtkStructuredTCellBackend::CellSize > 0 ? vtkStructuredTCellBackend::CellSize : 1; static constexpr std::array, 3> ShiftLUT = vtkShiftLUT::GetShiftLUT(); // members std::array CellDimensions; const int PYStride; const int PZStride; //------------------------------------------------------------------------------ vtkStructuredTCellBackend() = default; //------------------------------------------------------------------------------ vtkStructuredTCellBackend(int dims[3]) : CellDimensions({ { dims[0] - 1, dims[1] - 1, dims[2] - 1 } }) , PYStride(dims[0]) , PZStride(dims[0] * dims[1]) { } //------------------------------------------------------------------------------ ~vtkStructuredTCellBackend() override = default; //------------------------------------------------------------------------------ int GetCellSize() const override { return CellSize; } //------------------------------------------------------------------------------ template typename std::enable_if<(Description == vtkStructuredData::VTK_STRUCTURED_EMPTY), void>::type VTK_ALWAYS_INLINE ComputeCellStructuredCoords(vtkIdType vtkNotUsed(cellId), int* ijk) const { ijk[0] = ijk[1] = ijk[2] = 0; } //------------------------------------------------------------------------------ template typename std::enable_if<(Description == vtkStructuredData::VTK_STRUCTURED_SINGLE_POINT), void>::type VTK_ALWAYS_INLINE ComputeCellStructuredCoords(vtkIdType vtkNotUsed(cellId), int* ijk) const { ijk[0] = ijk[1] = ijk[2] = 0; } //------------------------------------------------------------------------------ template typename std::enable_if<(Description == vtkStructuredData::VTK_STRUCTURED_X_LINE), void>::type VTK_ALWAYS_INLINE ComputeCellStructuredCoords(vtkIdType cellId, int* ijk) const { ijk[0] = cellId; ijk[1] = 0; ijk[2] = 0; } //------------------------------------------------------------------------------ template typename std::enable_if<(Description == vtkStructuredData::VTK_STRUCTURED_Y_LINE), void>::type VTK_ALWAYS_INLINE ComputeCellStructuredCoords(vtkIdType cellId, int* ijk) const { ijk[0] = 0; ijk[1] = cellId; ijk[2] = 0; } //------------------------------------------------------------------------------ template typename std::enable_if<(Description == vtkStructuredData::VTK_STRUCTURED_Z_LINE), void>::type VTK_ALWAYS_INLINE ComputeCellStructuredCoords(vtkIdType cellId, int* ijk) const { ijk[0] = 0; ijk[1] = 0; ijk[2] = cellId; } //------------------------------------------------------------------------------ template typename std::enable_if<(Description == vtkStructuredData::VTK_STRUCTURED_XY_PLANE), void>::type VTK_ALWAYS_INLINE ComputeCellStructuredCoords(vtkIdType cellId, int* ijk) const { const auto div = std::div(cellId, this->CellDimensions[0]); ijk[0] = div.rem; ijk[1] = div.quot; ijk[2] = 0; } //------------------------------------------------------------------------------ template typename std::enable_if<(Description == vtkStructuredData::VTK_STRUCTURED_YZ_PLANE), void>::type VTK_ALWAYS_INLINE ComputeCellStructuredCoords(vtkIdType cellId, int* ijk) const { const auto div = std::div(cellId, this->CellDimensions[1]); ijk[0] = 0; ijk[1] = div.rem; ijk[2] = div.quot; } //------------------------------------------------------------------------------ template typename std::enable_if<(Description == vtkStructuredData::VTK_STRUCTURED_XZ_PLANE), void>::type VTK_ALWAYS_INLINE ComputeCellStructuredCoords(vtkIdType cellId, int* ijk) const { const auto div = std::div(cellId, this->CellDimensions[0]); ijk[0] = div.rem; ijk[1] = 0; ijk[2] = div.quot; } //------------------------------------------------------------------------------ template typename std::enable_if<(Description == vtkStructuredData::VTK_STRUCTURED_XYZ_GRID), void>::type VTK_ALWAYS_INLINE ComputeCellStructuredCoords(vtkIdType cellId, int* ijk) const { const auto div1 = std::div(cellId, this->CellDimensions[0]); const auto div2 = std::div(div1.quot, this->CellDimensions[1]); ijk[0] = div1.rem; ijk[1] = div2.rem; ijk[2] = div2.quot; } //------------------------------------------------------------------------------ void mapStructuredTuple(int ijk[3], vtkIdType* values) const override { for (int comp = 0; comp < vtkStructuredTCellBackend::CellSize; ++comp) { values[comp] = (static_cast(ijk[0]) + vtkStructuredTCellBackend::ShiftLUT[0][comp]) + (static_cast(ijk[1]) + vtkStructuredTCellBackend::ShiftLUT[1][comp]) * this->PYStride + (static_cast(ijk[2]) + vtkStructuredTCellBackend::ShiftLUT[2][comp]) * this->PZStride; } } //------------------------------------------------------------------------------ void mapTuple(vtkIdType tupleId, vtkIdType* values) const override { int ijk[3]; this->ComputeCellStructuredCoords(tupleId, ijk); for (int comp = 0; comp < vtkStructuredTCellBackend::CellSize; ++comp) { values[comp] = (static_cast(ijk[0]) + vtkStructuredTCellBackend::ShiftLUT[0][comp]) + (static_cast(ijk[1]) + vtkStructuredTCellBackend::ShiftLUT[1][comp]) * this->PYStride + (static_cast(ijk[2]) + vtkStructuredTCellBackend::ShiftLUT[2][comp]) * this->PZStride; } } //------------------------------------------------------------------------------ vtkIdType mapComponent(vtkIdType tupleId, int comp) const override { int ijk[3]; this->ComputeCellStructuredCoords(tupleId, ijk); return (ijk[0] + vtkStructuredTCellBackend::ShiftLUT[0][comp]) + (ijk[1] + vtkStructuredTCellBackend::ShiftLUT[1][comp]) * this->PYStride + (ijk[2] + vtkStructuredTCellBackend::ShiftLUT[2][comp]) * this->PZStride; } //------------------------------------------------------------------------------ vtkIdType map(vtkIdType valueId) const override { const auto div = std::div(valueId, vtkStructuredTCellBackend::ValidCellSize); return this->mapComponent(div.quot, div.rem); } }; //------------------------------------------------------------------------------ // template instantiated for each data description template struct vtkStructuredCellArray::vtkStructuredTCellBackend< vtkStructuredData::VTK_STRUCTURED_SINGLE_POINT, true>; template struct vtkStructuredCellArray::vtkStructuredTCellBackend< vtkStructuredData::VTK_STRUCTURED_X_LINE, true>; template struct vtkStructuredCellArray::vtkStructuredTCellBackend< vtkStructuredData::VTK_STRUCTURED_Y_LINE, true>; template struct vtkStructuredCellArray::vtkStructuredTCellBackend< vtkStructuredData::VTK_STRUCTURED_Z_LINE, true>; template struct vtkStructuredCellArray::vtkStructuredTCellBackend< vtkStructuredData::VTK_STRUCTURED_XY_PLANE, true>; template struct vtkStructuredCellArray::vtkStructuredTCellBackend< vtkStructuredData::VTK_STRUCTURED_YZ_PLANE, true>; template struct vtkStructuredCellArray::vtkStructuredTCellBackend< vtkStructuredData::VTK_STRUCTURED_XZ_PLANE, true>; template struct vtkStructuredCellArray::vtkStructuredTCellBackend< vtkStructuredData::VTK_STRUCTURED_XYZ_GRID, true>; template struct vtkStructuredCellArray::vtkStructuredTCellBackend< vtkStructuredData::VTK_STRUCTURED_EMPTY, false>; template struct vtkStructuredCellArray::vtkStructuredTCellBackend< vtkStructuredData::VTK_STRUCTURED_SINGLE_POINT, false>; template struct vtkStructuredCellArray::vtkStructuredTCellBackend< vtkStructuredData::VTK_STRUCTURED_X_LINE, false>; template struct vtkStructuredCellArray::vtkStructuredTCellBackend< vtkStructuredData::VTK_STRUCTURED_Y_LINE, false>; template struct vtkStructuredCellArray::vtkStructuredTCellBackend< vtkStructuredData::VTK_STRUCTURED_Z_LINE, false>; template struct vtkStructuredCellArray::vtkStructuredTCellBackend< vtkStructuredData::VTK_STRUCTURED_XY_PLANE, false>; template struct vtkStructuredCellArray::vtkStructuredTCellBackend< vtkStructuredData::VTK_STRUCTURED_YZ_PLANE, false>; template struct vtkStructuredCellArray::vtkStructuredTCellBackend< vtkStructuredData::VTK_STRUCTURED_XZ_PLANE, false>; template struct vtkStructuredCellArray::vtkStructuredTCellBackend< vtkStructuredData::VTK_STRUCTURED_XYZ_GRID, false>; //------------------------------------------------------------------------------ vtkStandardNewMacro(vtkStructuredCellArray); //------------------------------------------------------------------------------ vtkStructuredCellArray::vtkStructuredCellArray() = default; //------------------------------------------------------------------------------ vtkStructuredCellArray::~vtkStructuredCellArray() = default; //------------------------------------------------------------------------------ void vtkStructuredCellArray::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); if (this->Connectivity) { this->Connectivity->PrintSelf(os, indent.GetNextIndent()); } else { os << indent << "Connectivity: (nullptr)\n"; } } //------------------------------------------------------------------------------ void vtkStructuredCellArray::Initialize() { this->Connectivity->Initialize(); } //------------------------------------------------------------------------------ vtkIdType vtkStructuredCellArray::GetNumberOfCells() const { return this->Connectivity->GetNumberOfTuples(); } //------------------------------------------------------------------------------ vtkIdType vtkStructuredCellArray::GetNumberOfOffsets() const { return this->Connectivity->GetNumberOfTuples() + 1; } //------------------------------------------------------------------------------ vtkIdType vtkStructuredCellArray::GetOffset(vtkIdType cellId) { return this->Connectivity->GetNumberOfComponents() * cellId; } //------------------------------------------------------------------------------ vtkIdType vtkStructuredCellArray::GetNumberOfConnectivityIds() const { return this->Connectivity->GetNumberOfTuples() * this->Connectivity->GetNumberOfComponents(); } //------------------------------------------------------------------------------ void vtkStructuredCellArray::SetData(int extent[6], bool usePixelVoxelOrientation) { this->Connectivity = vtkSmartPointer>::New(); int dims[3]; vtkStructuredData::GetDimensionsFromExtent(extent, dims); const auto description = vtkStructuredData::GetDataDescription(dims); std::shared_ptr backEnd; if (usePixelVoxelOrientation) { switch (description) { case vtkStructuredData::VTK_STRUCTURED_EMPTY: { using TBackend = vtkStructuredTCellBackend; backEnd = std::make_shared(dims); break; } case vtkStructuredData::VTK_STRUCTURED_SINGLE_POINT: { using TBackend = vtkStructuredTCellBackend; backEnd = std::make_shared(dims); break; } case vtkStructuredData::VTK_STRUCTURED_X_LINE: { using TBackend = vtkStructuredTCellBackend; backEnd = std::make_shared(dims); break; } case vtkStructuredData::VTK_STRUCTURED_Y_LINE: { using TBackend = vtkStructuredTCellBackend; backEnd = std::make_shared(dims); break; } case vtkStructuredData::VTK_STRUCTURED_Z_LINE: { using TBackend = vtkStructuredTCellBackend; backEnd = std::make_shared(dims); break; } case vtkStructuredData::VTK_STRUCTURED_XY_PLANE: { using TBackend = vtkStructuredTCellBackend; backEnd = std::make_shared(dims); break; } case vtkStructuredData::VTK_STRUCTURED_YZ_PLANE: { using TBackend = vtkStructuredTCellBackend; backEnd = std::make_shared(dims); break; } case vtkStructuredData::VTK_STRUCTURED_XZ_PLANE: { using TBackend = vtkStructuredTCellBackend; backEnd = std::make_shared(dims); break; } case vtkStructuredData::VTK_STRUCTURED_XYZ_GRID: { using TBackend = vtkStructuredTCellBackend; backEnd = std::make_shared(dims); break; } default: { vtkErrorMacro("Unsupported data description: " << description); return; } } } else { switch (description) { case vtkStructuredData::VTK_STRUCTURED_EMPTY: { using TBackend = vtkStructuredTCellBackend; backEnd = std::make_shared(dims); break; } case vtkStructuredData::VTK_STRUCTURED_SINGLE_POINT: { using TBackend = vtkStructuredTCellBackend; backEnd = std::make_shared(dims); break; } case vtkStructuredData::VTK_STRUCTURED_X_LINE: { using TBackend = vtkStructuredTCellBackend; backEnd = std::make_shared(dims); break; } case vtkStructuredData::VTK_STRUCTURED_Y_LINE: { using TBackend = vtkStructuredTCellBackend; backEnd = std::make_shared(dims); break; } case vtkStructuredData::VTK_STRUCTURED_Z_LINE: { using TBackend = vtkStructuredTCellBackend; backEnd = std::make_shared(dims); break; } case vtkStructuredData::VTK_STRUCTURED_XY_PLANE: { using TBackend = vtkStructuredTCellBackend; backEnd = std::make_shared(dims); break; } case vtkStructuredData::VTK_STRUCTURED_YZ_PLANE: { using TBackend = vtkStructuredTCellBackend; backEnd = std::make_shared(dims); break; } case vtkStructuredData::VTK_STRUCTURED_XZ_PLANE: { using TBackend = vtkStructuredTCellBackend; backEnd = std::make_shared(dims); break; } case vtkStructuredData::VTK_STRUCTURED_XYZ_GRID: { using TBackend = vtkStructuredTCellBackend; backEnd = std::make_shared(dims); break; } default: { vtkErrorMacro("Unsupported data description: " << description); return; } } } this->Connectivity->SetBackend(backEnd); this->Connectivity->SetNumberOfComponents(backEnd->GetCellSize()); this->Connectivity->SetNumberOfTuples(vtkStructuredData::GetNumberOfCells(extent)); this->Modified(); } //------------------------------------------------------------------------------ vtkIdType vtkStructuredCellArray::IsHomogeneous() const { return this->Connectivity ? this->Connectivity->GetNumberOfComponents() : 0; } //------------------------------------------------------------------------------ void vtkStructuredCellArray::GetCellAtId(vtkIdType cellId, vtkIdType& cellSize, vtkIdType const*& cellPoints, vtkIdList* ptIds) VTK_SIZEHINT(cellPoints, cellSize) { ptIds->SetNumberOfIds(this->Connectivity->GetNumberOfComponents()); this->Connectivity->GetTypedTuple(cellId, ptIds->GetPointer(0)); cellSize = this->Connectivity->GetNumberOfComponents(); cellPoints = ptIds->GetPointer(0); } //------------------------------------------------------------------------------ void vtkStructuredCellArray::GetCellAtId(vtkIdType cellId, vtkIdList* ptIds) { ptIds->SetNumberOfIds(this->Connectivity->GetNumberOfComponents()); this->Connectivity->GetTypedTuple(cellId, ptIds->GetPointer(0)); } //------------------------------------------------------------------------------ void vtkStructuredCellArray::GetCellAtId( vtkIdType cellId, vtkIdType& cellSize, vtkIdType* cellPoints) VTK_SIZEHINT(cellPoints, cellSize) VTK_EXPECTS(0 <= cellId && cellId < GetNumberOfCells()) { cellSize = this->Connectivity->GetNumberOfComponents(); this->Connectivity->GetTypedTuple(cellId, cellPoints); } //------------------------------------------------------------------------------ void vtkStructuredCellArray::GetCellAtId(int ijk[3], vtkIdList* ptIds) { ptIds->SetNumberOfIds(this->Connectivity->GetNumberOfComponents()); this->Connectivity->GetBackend()->mapStructuredTuple(ijk, ptIds->GetPointer(0)); } //------------------------------------------------------------------------------ void vtkStructuredCellArray::GetCellAtId(int ijk[3], vtkIdType& cellSize, vtkIdType* cellPoints) { cellSize = this->Connectivity->GetNumberOfComponents(); this->Connectivity->GetBackend()->mapStructuredTuple(ijk, cellPoints); } //------------------------------------------------------------------------------ vtkIdType vtkStructuredCellArray::GetCellSize(const vtkIdType vtkNotUsed(cellId)) const { return this->Connectivity->GetNumberOfComponents(); } //------------------------------------------------------------------------------ int vtkStructuredCellArray::GetMaxCellSize() { return this->Connectivity->GetNumberOfComponents(); } //------------------------------------------------------------------------------ void vtkStructuredCellArray::DeepCopy(vtkAbstractCellArray* ca) { auto other = vtkStructuredCellArray::SafeDownCast(ca); if (!other) { vtkErrorMacro("Cannot copy from a different type of cell array."); return; } this->Connectivity = vtkSmartPointer>::New(); this->Connectivity->ImplicitDeepCopy(other->Connectivity.Get()); this->Modified(); } //------------------------------------------------------------------------------ void vtkStructuredCellArray::ShallowCopy(vtkAbstractCellArray* ca) { auto other = vtkStructuredCellArray::SafeDownCast(ca); if (!other) { vtkErrorMacro("Cannot copy from a different type of cell array."); return; } this->Connectivity = other->Connectivity; this->Modified(); } VTK_ABI_NAMESPACE_END