/*========================================================================= Program: Visualization Toolkit Module: vtkStructuredGrid.cxx 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. =========================================================================*/ #include "vtkStructuredGrid.h" #include "vtkCellData.h" #include "vtkEmptyCell.h" #include "vtkGenericCell.h" #include "vtkHexahedron.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkLine.h" #include "vtkMath.h" #include "vtkObjectFactory.h" #include "vtkPointData.h" #include "vtkQuad.h" #include "vtkUnsignedCharArray.h" #include "vtkVertex.h" vtkStandardNewMacro(vtkStructuredGrid); vtkStandardExtendedNewMacro(vtkStructuredGrid); #define vtkAdjustBoundsMacro(A, B) \ A[0] = (B[0] < A[0] ? B[0] : A[0]); \ A[1] = (B[0] > A[1] ? B[0] : A[1]); \ A[2] = (B[1] < A[2] ? B[1] : A[2]); \ A[3] = (B[1] > A[3] ? B[1] : A[3]); \ A[4] = (B[2] < A[4] ? B[2] : A[4]); \ A[5] = (B[2] > A[5] ? B[2] : A[5]) vtkStructuredGrid::vtkStructuredGrid() { this->Vertex = vtkVertex::New(); this->Line = vtkLine::New(); this->Quad = vtkQuad::New(); this->Hexahedron = vtkHexahedron::New(); this->EmptyCell = vtkEmptyCell::New(); this->Dimensions[0] = 0; this->Dimensions[1] = 0; this->Dimensions[2] = 0; this->DataDescription = VTK_EMPTY; int extent[6] = { 0, -1, 0, -1, 0, -1 }; memcpy(this->Extent, extent, 6 * sizeof(int)); this->Information->Set(vtkDataObject::DATA_EXTENT_TYPE(), VTK_3D_EXTENT); this->Information->Set(vtkDataObject::DATA_EXTENT(), this->Extent, 6); } //------------------------------------------------------------------------------ vtkStructuredGrid::~vtkStructuredGrid() { this->Vertex->Delete(); this->Line->Delete(); this->Quad->Delete(); this->Hexahedron->Delete(); this->EmptyCell->Delete(); } //------------------------------------------------------------------------------ // Copy the geometric and topological structure of an input structured grid. void vtkStructuredGrid::CopyStructure(vtkDataSet* ds) { vtkStructuredGrid* sg = static_cast(ds); Superclass::CopyStructure(ds); int i; for (i = 0; i < 3; i++) { this->Dimensions[i] = sg->Dimensions[i]; } this->SetExtent(sg->GetExtent()); this->DataDescription = sg->DataDescription; if (ds->HasAnyBlankPoints()) { // there is blanking this->GetPointData()->AddArray(ds->GetPointGhostArray()); this->PointGhostArray = nullptr; } if (ds->HasAnyBlankCells()) { // there is blanking this->GetCellData()->AddArray(ds->GetCellGhostArray()); this->CellGhostArray = nullptr; } } //------------------------------------------------------------------------------ void vtkStructuredGrid::Initialize() { this->Superclass::Initialize(); if (this->Information) { this->SetDimensions(0, 0, 0); } } //------------------------------------------------------------------------------ int vtkStructuredGrid::GetCellType(vtkIdType cellId) { // see whether the cell is blanked if (!this->IsCellVisible(cellId)) { return VTK_EMPTY_CELL; } switch (this->DataDescription) { case VTK_EMPTY: return VTK_EMPTY_CELL; case VTK_SINGLE_POINT: return VTK_VERTEX; case VTK_X_LINE: case VTK_Y_LINE: case VTK_Z_LINE: return VTK_LINE; case VTK_XY_PLANE: case VTK_YZ_PLANE: case VTK_XZ_PLANE: return VTK_QUAD; case VTK_XYZ_GRID: return VTK_HEXAHEDRON; default: vtkErrorMacro(<< "Bad data description!"); return VTK_EMPTY_CELL; } } //------------------------------------------------------------------------------ vtkIdType vtkStructuredGrid::GetCellSize(vtkIdType cellId) { // see whether the cell is blanked if (!this->IsCellVisible(cellId)) { return 0; } switch (this->DataDescription) { case VTK_EMPTY: return 0; case VTK_SINGLE_POINT: return 1; case VTK_X_LINE: case VTK_Y_LINE: case VTK_Z_LINE: return 2; case VTK_XY_PLANE: case VTK_YZ_PLANE: case VTK_XZ_PLANE: return 4; case VTK_XYZ_GRID: return 8; default: vtkErrorMacro(<< "Bad data description!"); return 0; } } //------------------------------------------------------------------------------ vtkCell* vtkStructuredGrid::GetCell(vtkIdType cellId) { vtkCell* cell = nullptr; vtkIdType idx; int i, j, k; int d01, offset1, offset2; // Make sure data is defined if (!this->Points) { vtkErrorMacro(<< "No data"); return nullptr; } // see whether the cell is blanked if (!this->IsCellVisible(cellId)) { return this->EmptyCell; } // Update dimensions this->GetDimensions(); switch (this->DataDescription) { case VTK_EMPTY: return this->EmptyCell; case VTK_SINGLE_POINT: // cellId can only be = 0 cell = this->Vertex; cell->PointIds->SetId(0, 0); break; case VTK_X_LINE: cell = this->Line; cell->PointIds->SetId(0, cellId); cell->PointIds->SetId(1, cellId + 1); break; case VTK_Y_LINE: cell = this->Line; cell->PointIds->SetId(0, cellId); cell->PointIds->SetId(1, cellId + 1); break; case VTK_Z_LINE: cell = this->Line; cell->PointIds->SetId(0, cellId); cell->PointIds->SetId(1, cellId + 1); break; case VTK_XY_PLANE: cell = this->Quad; i = cellId % (this->Dimensions[0] - 1); j = cellId / (this->Dimensions[0] - 1); idx = i + j * this->Dimensions[0]; offset1 = 1; offset2 = this->Dimensions[0]; cell->PointIds->SetId(0, idx); cell->PointIds->SetId(1, idx + offset1); cell->PointIds->SetId(2, idx + offset1 + offset2); cell->PointIds->SetId(3, idx + offset2); break; case VTK_YZ_PLANE: cell = this->Quad; j = cellId % (this->Dimensions[1] - 1); k = cellId / (this->Dimensions[1] - 1); idx = j + k * this->Dimensions[1]; offset1 = 1; offset2 = this->Dimensions[1]; cell->PointIds->SetId(0, idx); cell->PointIds->SetId(1, idx + offset1); cell->PointIds->SetId(2, idx + offset1 + offset2); cell->PointIds->SetId(3, idx + offset2); break; case VTK_XZ_PLANE: cell = this->Quad; i = cellId % (this->Dimensions[0] - 1); k = cellId / (this->Dimensions[0] - 1); idx = i + k * this->Dimensions[0]; offset1 = 1; offset2 = this->Dimensions[0]; cell->PointIds->SetId(0, idx); cell->PointIds->SetId(1, idx + offset1); cell->PointIds->SetId(2, idx + offset1 + offset2); cell->PointIds->SetId(3, idx + offset2); break; case VTK_XYZ_GRID: cell = this->Hexahedron; d01 = this->Dimensions[0] * this->Dimensions[1]; i = cellId % (this->Dimensions[0] - 1); j = (cellId / (this->Dimensions[0] - 1)) % (this->Dimensions[1] - 1); k = cellId / ((this->Dimensions[0] - 1) * (this->Dimensions[1] - 1)); idx = i + j * this->Dimensions[0] + k * d01; offset1 = 1; offset2 = this->Dimensions[0]; cell->PointIds->SetId(0, idx); cell->PointIds->SetId(1, idx + offset1); cell->PointIds->SetId(2, idx + offset1 + offset2); cell->PointIds->SetId(3, idx + offset2); idx += d01; cell->PointIds->SetId(4, idx); cell->PointIds->SetId(5, idx + offset1); cell->PointIds->SetId(6, idx + offset1 + offset2); cell->PointIds->SetId(7, idx + offset2); break; default: vtkErrorMacro(<< "Invalid DataDescription."); return nullptr; } // Extract point coordinates and point ids. NOTE: the ordering of the vtkQuad // and vtkHexahedron cells are tricky. int NumberOfIds = cell->PointIds->GetNumberOfIds(); for (i = 0; i < NumberOfIds; i++) { idx = cell->PointIds->GetId(i); cell->Points->SetPoint(i, this->Points->GetPoint(idx)); } return cell; } //------------------------------------------------------------------------------ vtkCell* vtkStructuredGrid::GetCell(int i, int j, int k) { vtkIdType cellId = i + (j + (k * (this->Dimensions[1] - 1))) * (this->Dimensions[0] - 1); vtkCell* cell = nullptr; vtkIdType idx; int d01, offset1, offset2; // Make sure data is defined if (!this->Points) { vtkErrorMacro(<< "No data"); return nullptr; } // see whether the cell is blanked if (!this->IsCellVisible(cellId)) { return this->EmptyCell; } // Update dimensions this->GetDimensions(); switch (this->DataDescription) { case VTK_EMPTY: return this->EmptyCell; case VTK_SINGLE_POINT: // cellId can only be = 0 cell = this->Vertex; cell->PointIds->SetId(0, 0); break; case VTK_X_LINE: cell = this->Line; cell->PointIds->SetId(0, cellId); cell->PointIds->SetId(1, cellId + 1); break; case VTK_Y_LINE: cell = this->Line; cell->PointIds->SetId(0, cellId); cell->PointIds->SetId(1, cellId + 1); break; case VTK_Z_LINE: cell = this->Line; cell->PointIds->SetId(0, cellId); cell->PointIds->SetId(1, cellId + 1); break; case VTK_XY_PLANE: cell = this->Quad; idx = i + j * this->Dimensions[0]; offset1 = 1; offset2 = this->Dimensions[0]; cell->PointIds->SetId(0, idx); cell->PointIds->SetId(1, idx + offset1); cell->PointIds->SetId(2, idx + offset1 + offset2); cell->PointIds->SetId(3, idx + offset2); break; case VTK_YZ_PLANE: cell = this->Quad; idx = j + k * this->Dimensions[1]; offset1 = 1; offset2 = this->Dimensions[1]; cell->PointIds->SetId(0, idx); cell->PointIds->SetId(1, idx + offset1); cell->PointIds->SetId(2, idx + offset1 + offset2); cell->PointIds->SetId(3, idx + offset2); break; case VTK_XZ_PLANE: cell = this->Quad; idx = i + k * this->Dimensions[0]; offset1 = 1; offset2 = this->Dimensions[0]; cell->PointIds->SetId(0, idx); cell->PointIds->SetId(1, idx + offset1); cell->PointIds->SetId(2, idx + offset1 + offset2); cell->PointIds->SetId(3, idx + offset2); break; case VTK_XYZ_GRID: cell = this->Hexahedron; d01 = this->Dimensions[0] * this->Dimensions[1]; idx = i + j * this->Dimensions[0] + k * d01; offset1 = 1; offset2 = this->Dimensions[0]; cell->PointIds->SetId(0, idx); cell->PointIds->SetId(1, idx + offset1); cell->PointIds->SetId(2, idx + offset1 + offset2); cell->PointIds->SetId(3, idx + offset2); idx += d01; cell->PointIds->SetId(4, idx); cell->PointIds->SetId(5, idx + offset1); cell->PointIds->SetId(6, idx + offset1 + offset2); cell->PointIds->SetId(7, idx + offset2); break; default: vtkErrorMacro(<< "Invalid DataDescription."); return nullptr; } // Extract point coordinates and point ids. NOTE: the ordering of the vtkQuad // and vtkHexahedron cells are tricky. int NumberOfIds = cell->PointIds->GetNumberOfIds(); for (i = 0; i < NumberOfIds; i++) { idx = cell->PointIds->GetId(i); cell->Points->SetPoint(i, this->Points->GetPoint(idx)); } return cell; } //------------------------------------------------------------------------------ void vtkStructuredGrid::GetCell(vtkIdType cellId, vtkGenericCell* cell) { vtkIdType idx; int i, j, k; int d01, offset1, offset2; double x[3]; // Make sure data is defined if (!this->Points) { vtkErrorMacro(<< "No data"); } // see whether the cell is blanked if (!this->IsCellVisible(cellId)) { cell->SetCellTypeToEmptyCell(); return; } // Update dimensions this->GetDimensions(); switch (this->DataDescription) { case VTK_EMPTY: cell->SetCellTypeToEmptyCell(); return; case VTK_SINGLE_POINT: // cellId can only be = 0 cell->SetCellTypeToVertex(); cell->PointIds->SetId(0, 0); break; case VTK_X_LINE: cell->SetCellTypeToLine(); cell->PointIds->SetId(0, cellId); cell->PointIds->SetId(1, cellId + 1); break; case VTK_Y_LINE: cell->SetCellTypeToLine(); cell->PointIds->SetId(0, cellId); cell->PointIds->SetId(1, cellId + 1); break; case VTK_Z_LINE: cell->SetCellTypeToLine(); cell->PointIds->SetId(0, cellId); cell->PointIds->SetId(1, cellId + 1); break; case VTK_XY_PLANE: cell->SetCellTypeToQuad(); i = cellId % (this->Dimensions[0] - 1); j = cellId / (this->Dimensions[0] - 1); idx = i + j * this->Dimensions[0]; offset1 = 1; offset2 = this->Dimensions[0]; cell->PointIds->SetId(0, idx); cell->PointIds->SetId(1, idx + offset1); cell->PointIds->SetId(2, idx + offset1 + offset2); cell->PointIds->SetId(3, idx + offset2); break; case VTK_YZ_PLANE: cell->SetCellTypeToQuad(); j = cellId % (this->Dimensions[1] - 1); k = cellId / (this->Dimensions[1] - 1); idx = j + k * this->Dimensions[1]; offset1 = 1; offset2 = this->Dimensions[1]; cell->PointIds->SetId(0, idx); cell->PointIds->SetId(1, idx + offset1); cell->PointIds->SetId(2, idx + offset1 + offset2); cell->PointIds->SetId(3, idx + offset2); break; case VTK_XZ_PLANE: cell->SetCellTypeToQuad(); i = cellId % (this->Dimensions[0] - 1); k = cellId / (this->Dimensions[0] - 1); idx = i + k * this->Dimensions[0]; offset1 = 1; offset2 = this->Dimensions[0]; cell->PointIds->SetId(0, idx); cell->PointIds->SetId(1, idx + offset1); cell->PointIds->SetId(2, idx + offset1 + offset2); cell->PointIds->SetId(3, idx + offset2); break; case VTK_XYZ_GRID: cell->SetCellTypeToHexahedron(); d01 = this->Dimensions[0] * this->Dimensions[1]; i = cellId % (this->Dimensions[0] - 1); j = (cellId / (this->Dimensions[0] - 1)) % (this->Dimensions[1] - 1); k = cellId / ((this->Dimensions[0] - 1) * (this->Dimensions[1] - 1)); idx = i + j * this->Dimensions[0] + k * d01; offset1 = 1; offset2 = this->Dimensions[0]; cell->PointIds->SetId(0, idx); cell->PointIds->SetId(1, idx + offset1); cell->PointIds->SetId(2, idx + offset1 + offset2); cell->PointIds->SetId(3, idx + offset2); idx += d01; cell->PointIds->SetId(4, idx); cell->PointIds->SetId(5, idx + offset1); cell->PointIds->SetId(6, idx + offset1 + offset2); cell->PointIds->SetId(7, idx + offset2); break; } // Extract point coordinates and point ids. NOTE: the ordering of the vtkQuad // and vtkHexahedron cells are tricky. int NumberOfIds = cell->PointIds->GetNumberOfIds(); for (i = 0; i < NumberOfIds; i++) { idx = cell->PointIds->GetId(i); this->Points->GetPoint(idx, x); cell->Points->SetPoint(i, x); } } //------------------------------------------------------------------------------ // Fast implementation of GetCellBounds(). Bounds are calculated without // constructing a cell. void vtkStructuredGrid::GetCellBounds(vtkIdType cellId, double bounds[6]) { vtkIdType idx = 0; int i, j, k; vtkIdType d01; int offset1 = 0; int offset2 = 0; double x[3]; // Make sure data is defined if (!this->Points) { vtkErrorMacro(<< "No data"); return; } vtkMath::UninitializeBounds(bounds); // Update dimensions this->GetDimensions(); switch (this->DataDescription) { case VTK_EMPTY: return; case VTK_SINGLE_POINT: // cellId can only be = 0 this->Points->GetPoint(0, x); bounds[0] = bounds[1] = x[0]; bounds[2] = bounds[3] = x[1]; bounds[4] = bounds[5] = x[2]; break; case VTK_X_LINE: case VTK_Y_LINE: case VTK_Z_LINE: this->Points->GetPoint(cellId, x); bounds[0] = bounds[1] = x[0]; bounds[2] = bounds[3] = x[1]; bounds[4] = bounds[5] = x[2]; this->Points->GetPoint(cellId + 1, x); vtkAdjustBoundsMacro(bounds, x); break; case VTK_XY_PLANE: case VTK_YZ_PLANE: case VTK_XZ_PLANE: if (this->DataDescription == VTK_XY_PLANE) { i = cellId % (this->Dimensions[0] - 1); j = cellId / (this->Dimensions[0] - 1); idx = i + j * this->Dimensions[0]; offset1 = 1; offset2 = this->Dimensions[0]; } else if (this->DataDescription == VTK_YZ_PLANE) { j = cellId % (this->Dimensions[1] - 1); k = cellId / (this->Dimensions[1] - 1); idx = j + k * this->Dimensions[1]; offset1 = 1; offset2 = this->Dimensions[1]; } else if (this->DataDescription == VTK_XZ_PLANE) { i = cellId % (this->Dimensions[0] - 1); k = cellId / (this->Dimensions[0] - 1); idx = i + k * this->Dimensions[0]; offset1 = 1; offset2 = this->Dimensions[0]; } this->Points->GetPoint(idx, x); bounds[0] = bounds[1] = x[0]; bounds[2] = bounds[3] = x[1]; bounds[4] = bounds[5] = x[2]; this->Points->GetPoint(idx + offset1, x); vtkAdjustBoundsMacro(bounds, x); this->Points->GetPoint(idx + offset1 + offset2, x); vtkAdjustBoundsMacro(bounds, x); this->Points->GetPoint(idx + offset2, x); vtkAdjustBoundsMacro(bounds, x); break; case VTK_XYZ_GRID: d01 = this->Dimensions[0] * this->Dimensions[1]; i = cellId % (this->Dimensions[0] - 1); j = (cellId / (this->Dimensions[0] - 1)) % (this->Dimensions[1] - 1); k = cellId / ((this->Dimensions[0] - 1) * (this->Dimensions[1] - 1)); idx = i + j * this->Dimensions[0] + k * d01; offset1 = 1; offset2 = this->Dimensions[0]; this->Points->GetPoint(idx, x); bounds[0] = bounds[1] = x[0]; bounds[2] = bounds[3] = x[1]; bounds[4] = bounds[5] = x[2]; this->Points->GetPoint(idx + offset1, x); vtkAdjustBoundsMacro(bounds, x); this->Points->GetPoint(idx + offset1 + offset2, x); vtkAdjustBoundsMacro(bounds, x); this->Points->GetPoint(idx + offset2, x); vtkAdjustBoundsMacro(bounds, x); idx += d01; this->Points->GetPoint(idx, x); vtkAdjustBoundsMacro(bounds, x); this->Points->GetPoint(idx + offset1, x); vtkAdjustBoundsMacro(bounds, x); this->Points->GetPoint(idx + offset1 + offset2, x); vtkAdjustBoundsMacro(bounds, x); this->Points->GetPoint(idx + offset2, x); vtkAdjustBoundsMacro(bounds, x); break; } } //------------------------------------------------------------------------------ // Turn off a particular data point. void vtkStructuredGrid::BlankPoint(vtkIdType ptId) { vtkUnsignedCharArray* ghosts = this->GetPointGhostArray(); if (!ghosts) { ghosts = this->AllocatePointGhostArray(); } ghosts->SetValue(ptId, ghosts->GetValue(ptId) | vtkDataSetAttributes::HIDDENPOINT); assert(!this->IsPointVisible(ptId)); } //------------------------------------------------------------------------------ // Turn on a particular data point. void vtkStructuredGrid::UnBlankPoint(vtkIdType ptId) { vtkUnsignedCharArray* ghosts = this->GetPointGhostArray(); if (ghosts) { ghosts->SetValue(ptId, ghosts->GetValue(ptId) & ~vtkDataSetAttributes::HIDDENPOINT); } assert(this->IsPointVisible(ptId)); } //------------------------------------------------------------------------------ // Turn off a particular data cell. void vtkStructuredGrid::BlankCell(vtkIdType cellId) { vtkUnsignedCharArray* ghosts = this->GetCellGhostArray(); if (!ghosts) { ghosts = this->AllocateCellGhostArray(); } ghosts->SetValue(cellId, ghosts->GetValue(cellId) | vtkDataSetAttributes::HIDDENCELL); assert(!this->IsCellVisible(cellId)); } //------------------------------------------------------------------------------ // Turn on a particular data cell. void vtkStructuredGrid::UnBlankCell(vtkIdType cellId) { vtkUnsignedCharArray* ghosts = this->GetCellGhostArray(); if (ghosts) { ghosts->SetValue(cellId, ghosts->GetValue(cellId) & ~vtkDataSetAttributes::HIDDENCELL); } } //------------------------------------------------------------------------------ unsigned char vtkStructuredGrid::IsPointVisible(vtkIdType pointId) { return vtkStructuredData::IsPointVisible(pointId, this->GetPointGhostArray()); } //------------------------------------------------------------------------------ void vtkStructuredGrid::GetCellDims(int cellDims[3]) { for (int i = 0; i < 3; ++i) { cellDims[i] = ((this->Dimensions[i] - 1) < 1) ? 1 : this->Dimensions[i] - 1; } } //------------------------------------------------------------------------------ // Return non-zero if the specified cell is visible (i.e., not blanked) unsigned char vtkStructuredGrid::IsCellVisible(vtkIdType cellId) { return vtkStructuredData::IsCellVisible(cellId, this->Dimensions, this->DataDescription, this->GetCellGhostArray(), this->GetPointGhostArray()); } //------------------------------------------------------------------------------ // Set dimensions of structured grid dataset. void vtkStructuredGrid::SetDimensions(int i, int j, int k) { this->SetExtent(0, i - 1, 0, j - 1, 0, k - 1); } //------------------------------------------------------------------------------ // Set dimensions of structured grid dataset. void vtkStructuredGrid::SetDimensions(const int dim[3]) { this->SetExtent(0, dim[0] - 1, 0, dim[1] - 1, 0, dim[2] - 1); } //------------------------------------------------------------------------------ // Get the points defining a cell. (See vtkDataSet for more info.) void vtkStructuredGrid::GetCellPoints(vtkIdType cellId, vtkIdList* ptIds) { // Update dimensions this->GetDimensions(); int iMin, iMax, jMin, jMax, kMin, kMax; vtkIdType d01 = this->Dimensions[0] * this->Dimensions[1]; ptIds->Reset(); iMin = iMax = jMin = jMax = kMin = kMax = 0; switch (this->DataDescription) { case VTK_EMPTY: return; case VTK_SINGLE_POINT: // cellId can only be = 0 ptIds->SetNumberOfIds(1); ptIds->SetId(0, iMin + jMin * this->Dimensions[0] + kMin * d01); break; case VTK_X_LINE: iMin = cellId; iMax = cellId + 1; ptIds->SetNumberOfIds(2); ptIds->SetId(0, iMin + jMin * this->Dimensions[0] + kMin * d01); ptIds->SetId(1, iMax + jMin * this->Dimensions[0] + kMin * d01); break; case VTK_Y_LINE: jMin = cellId; jMax = cellId + 1; ptIds->SetNumberOfIds(2); ptIds->SetId(0, iMin + jMin * this->Dimensions[0] + kMin * d01); ptIds->SetId(1, iMin + jMax * this->Dimensions[0] + kMin * d01); break; case VTK_Z_LINE: kMin = cellId; kMax = cellId + 1; ptIds->SetNumberOfIds(2); ptIds->SetId(0, iMin + jMin * this->Dimensions[0] + kMin * d01); ptIds->SetId(1, iMin + jMin * this->Dimensions[0] + kMax * d01); break; case VTK_XY_PLANE: iMin = cellId % (this->Dimensions[0] - 1); iMax = iMin + 1; jMin = cellId / (this->Dimensions[0] - 1); jMax = jMin + 1; ptIds->SetNumberOfIds(4); ptIds->SetId(0, iMin + jMin * this->Dimensions[0] + kMin * d01); ptIds->SetId(1, iMax + jMin * this->Dimensions[0] + kMin * d01); ptIds->SetId(2, iMax + jMax * this->Dimensions[0] + kMin * d01); ptIds->SetId(3, iMin + jMax * this->Dimensions[0] + kMin * d01); break; case VTK_YZ_PLANE: jMin = cellId % (this->Dimensions[1] - 1); jMax = jMin + 1; kMin = cellId / (this->Dimensions[1] - 1); kMax = kMin + 1; ptIds->SetNumberOfIds(4); ptIds->SetId(0, iMin + jMin * this->Dimensions[0] + kMin * d01); ptIds->SetId(1, iMin + jMax * this->Dimensions[0] + kMin * d01); ptIds->SetId(2, iMin + jMax * this->Dimensions[0] + kMax * d01); ptIds->SetId(3, iMin + jMin * this->Dimensions[0] + kMax * d01); break; case VTK_XZ_PLANE: iMin = cellId % (this->Dimensions[0] - 1); iMax = iMin + 1; kMin = cellId / (this->Dimensions[0] - 1); kMax = kMin + 1; ptIds->SetNumberOfIds(4); ptIds->SetId(0, iMin + jMin * this->Dimensions[0] + kMin * d01); ptIds->SetId(1, iMax + jMin * this->Dimensions[0] + kMin * d01); ptIds->SetId(2, iMax + jMin * this->Dimensions[0] + kMax * d01); ptIds->SetId(3, iMin + jMin * this->Dimensions[0] + kMax * d01); break; case VTK_XYZ_GRID: iMin = cellId % (this->Dimensions[0] - 1); iMax = iMin + 1; jMin = (cellId / (this->Dimensions[0] - 1)) % (this->Dimensions[1] - 1); jMax = jMin + 1; kMin = cellId / ((this->Dimensions[0] - 1) * (this->Dimensions[1] - 1)); kMax = kMin + 1; ptIds->SetNumberOfIds(8); ptIds->SetId(0, iMin + jMin * this->Dimensions[0] + kMin * d01); ptIds->SetId(1, iMax + jMin * this->Dimensions[0] + kMin * d01); ptIds->SetId(2, iMax + jMax * this->Dimensions[0] + kMin * d01); ptIds->SetId(3, iMin + jMax * this->Dimensions[0] + kMin * d01); ptIds->SetId(4, iMin + jMin * this->Dimensions[0] + kMax * d01); ptIds->SetId(5, iMax + jMin * this->Dimensions[0] + kMax * d01); ptIds->SetId(6, iMax + jMax * this->Dimensions[0] + kMax * d01); ptIds->SetId(7, iMin + jMax * this->Dimensions[0] + kMax * d01); break; } } //------------------------------------------------------------------------------ void vtkStructuredGrid::SetExtent(int extent[6]) { int description; description = vtkStructuredData::SetExtent(extent, this->Extent); if (description < 0) // improperly specified { vtkErrorMacro(<< "Bad Extent, retaining previous values"); } if (description == VTK_UNCHANGED) { return; } this->DataDescription = description; this->Modified(); vtkStructuredData::GetDimensionsFromExtent(extent, this->Dimensions); } //------------------------------------------------------------------------------ void vtkStructuredGrid::SetExtent(int xMin, int xMax, int yMin, int yMax, int zMin, int zMax) { int extent[6]; extent[0] = xMin; extent[1] = xMax; extent[2] = yMin; extent[3] = yMax; extent[4] = zMin; extent[5] = zMax; this->SetExtent(extent); } int* vtkStructuredGrid::GetDimensions() { this->GetDimensions(this->Dimensions); return this->Dimensions; } void vtkStructuredGrid::GetDimensions(int dim[3]) { const int* extent = this->Extent; dim[0] = extent[1] - extent[0] + 1; dim[1] = extent[3] - extent[2] + 1; dim[2] = extent[5] - extent[4] + 1; } namespace { class CellVisibility { public: CellVisibility(vtkStructuredGrid* input) : Input(input) { } bool operator()(const vtkIdType id) { return !Input->IsCellVisible(id); } private: vtkStructuredGrid* Input; }; } // anonymous namespace //------------------------------------------------------------------------------ void vtkStructuredGrid::GetCellNeighbors(vtkIdType cellId, vtkIdList* ptIds, vtkIdList* cellIds) { int numPtIds = ptIds->GetNumberOfIds(); // Use special methods for speed switch (numPtIds) { case 0: cellIds->Reset(); return; case 1: case 2: case 4: // vertex, edge, face neighbors vtkStructuredData::GetCellNeighbors(cellId, ptIds, cellIds, this->GetDimensions()); break; default: this->Superclass::GetCellNeighbors(cellId, ptIds, cellIds); } // If blanking, remove blanked cells. if (this->GetPointGhostArray() || this->GetCellGhostArray()) { vtkIdType* pCellIds = cellIds->GetPointer(0); vtkIdType* end = std::remove_if(pCellIds, pCellIds + cellIds->GetNumberOfIds(), CellVisibility(this)); cellIds->Resize(std::distance(pCellIds, end)); } } //------------------------------------------------------------------------------ void vtkStructuredGrid::GetCellNeighbors( vtkIdType cellId, vtkIdList* ptIds, vtkIdList* cellIds, int* seedLoc) { int numPtIds = ptIds->GetNumberOfIds(); // Use special methods for speed switch (numPtIds) { case 0: cellIds->Reset(); return; case 1: case 2: case 4: // vertex, edge, face neighbors vtkStructuredData::GetCellNeighbors(cellId, ptIds, cellIds, this->GetDimensions(), seedLoc); break; default: this->Superclass::GetCellNeighbors(cellId, ptIds, cellIds); } // If blanking, remove blanked cells. if (this->GetPointGhostArray() || this->GetCellGhostArray()) { vtkIdType* pCellIds = cellIds->GetPointer(0); vtkIdType* end = std::remove_if(pCellIds, pCellIds + cellIds->GetNumberOfIds(), CellVisibility(this)); cellIds->Resize(std::distance(pCellIds, end)); } } //------------------------------------------------------------------------------ unsigned long vtkStructuredGrid::GetActualMemorySize() { return this->Superclass::GetActualMemorySize(); } //------------------------------------------------------------------------------ void vtkStructuredGrid::ShallowCopy(vtkDataObject* dataObject) { vtkStructuredGrid* grid = vtkStructuredGrid::SafeDownCast(dataObject); if (grid != nullptr) { this->InternalStructuredGridCopy(grid); } this->Superclass::ShallowCopy(dataObject); } //------------------------------------------------------------------------------ void vtkStructuredGrid::DeepCopy(vtkDataObject* dataObject) { auto mkhold = vtkMemkindRAII(this->GetIsInMemkind()); vtkStructuredGrid* grid = vtkStructuredGrid::SafeDownCast(dataObject); if (grid != nullptr) { this->InternalStructuredGridCopy(grid); } this->Superclass::DeepCopy(dataObject); } //------------------------------------------------------------------------------ // This copies all the local variables (but not objects). void vtkStructuredGrid::InternalStructuredGridCopy(vtkStructuredGrid* src) { int idx; this->DataDescription = src->DataDescription; // Update dimensions this->GetDimensions(); for (idx = 0; idx < 3; ++idx) { this->Dimensions[idx] = src->Dimensions[idx]; } memcpy(this->Extent, src->GetExtent(), 6 * sizeof(int)); } //------------------------------------------------------------------------------ // Override this method because of blanking void vtkStructuredGrid::ComputeScalarRange() { if (this->GetMTime() > this->ScalarRangeComputeTime) { vtkDataArray* ptScalars = this->PointData->GetScalars(); vtkDataArray* cellScalars = this->CellData->GetScalars(); double ptRange[2]; double cellRange[2]; double s; ptRange[0] = VTK_DOUBLE_MAX; ptRange[1] = VTK_DOUBLE_MIN; if (ptScalars) { vtkIdType num = this->GetNumberOfPoints(); for (vtkIdType id = 0; id < num; ++id) { if (this->IsPointVisible(id)) { s = ptScalars->GetComponent(id, 0); if (s < ptRange[0]) { ptRange[0] = s; } if (s > ptRange[1]) { ptRange[1] = s; } } } } cellRange[0] = ptRange[0]; cellRange[1] = ptRange[1]; if (cellScalars) { vtkIdType num = this->GetNumberOfCells(); for (vtkIdType id = 0; id < num; ++id) { if (this->IsCellVisible(id)) { s = cellScalars->GetComponent(id, 0); if (s < cellRange[0]) { cellRange[0] = s; } if (s > cellRange[1]) { cellRange[1] = s; } } } } this->ScalarRange[0] = (cellRange[0] >= VTK_DOUBLE_MAX ? 0.0 : cellRange[0]); this->ScalarRange[1] = (cellRange[1] <= VTK_DOUBLE_MIN ? 1.0 : cellRange[1]); this->ScalarRangeComputeTime.Modified(); } } //------------------------------------------------------------------------------ void vtkStructuredGrid::Crop(const int* updateExtent) { // Do nothing for empty datasets: for (int dim = 0; dim < 3; ++dim) { if (this->Extent[2 * dim] > this->Extent[2 * dim + 1]) { vtkDebugMacro(<< "Refusing to crop empty dataset."); return; } } int i, j, k; int uExt[6]; const int* extent = this->Extent; // If the update extent is larger than the extent, // we cannot do anything about it here. for (i = 0; i < 3; ++i) { uExt[i * 2] = updateExtent[i * 2]; if (uExt[i * 2] < extent[i * 2]) { uExt[i * 2] = extent[i * 2]; } uExt[i * 2 + 1] = updateExtent[i * 2 + 1]; if (uExt[i * 2 + 1] > extent[i * 2 + 1]) { uExt[i * 2 + 1] = extent[i * 2 + 1]; } } // If extents already match, then we need to do nothing. if (extent[0] == uExt[0] && extent[1] == uExt[1] && extent[2] == uExt[2] && extent[3] == uExt[3] && extent[4] == uExt[4] && extent[5] == uExt[5]) { return; } else { vtkStructuredGrid* newGrid; vtkPointData *inPD, *outPD; vtkCellData *inCD, *outCD; int outSize, jOffset, kOffset; vtkIdType idx, newId; vtkPoints *newPts, *inPts; int inInc1, inInc2; // Get the points. Protect against empty data objects. inPts = this->GetPoints(); if (inPts == nullptr) { return; } vtkDebugMacro(<< "Cropping Grid"); newGrid = vtkStructuredGrid::New(); inPD = this->GetPointData(); inCD = this->GetCellData(); outPD = newGrid->GetPointData(); outCD = newGrid->GetCellData(); // Allocate necessary objects // newGrid->SetExtent(uExt); outSize = (uExt[1] - uExt[0] + 1) * (uExt[3] - uExt[2] + 1) * (uExt[5] - uExt[4] + 1); newPts = inPts->NewInstance(); newPts->SetDataType(inPts->GetDataType()); newPts->SetNumberOfPoints(outSize); outPD->CopyAllocate(inPD, outSize, outSize); outCD->CopyAllocate(inCD, outSize, outSize); // Traverse this data and copy point attributes to output newId = 0; inInc1 = (extent[1] - extent[0] + 1); inInc2 = inInc1 * (extent[3] - extent[2] + 1); for (k = uExt[4]; k <= uExt[5]; ++k) { kOffset = (k - extent[4]) * inInc2; for (j = uExt[2]; j <= uExt[3]; ++j) { jOffset = (j - extent[2]) * inInc1; for (i = uExt[0]; i <= uExt[1]; ++i) { idx = (i - extent[0]) + jOffset + kOffset; newPts->SetPoint(newId, inPts->GetPoint(idx)); outPD->CopyData(inPD, idx, newId++); } } } // Traverse input data and copy cell attributes to output newId = 0; inInc1 = (extent[1] - extent[0]); inInc2 = inInc1 * (extent[3] - extent[2]); for (k = uExt[4]; k < uExt[5]; ++k) { kOffset = (k - extent[4]) * inInc2; for (j = uExt[2]; j < uExt[3]; ++j) { jOffset = (j - extent[2]) * inInc1; for (i = uExt[0]; i < uExt[1]; ++i) { idx = (i - extent[0]) + jOffset + kOffset; outCD->CopyData(inCD, idx, newId++); } } } this->SetExtent(uExt); this->SetPoints(newPts); newPts->Delete(); inPD->ShallowCopy(outPD); inCD->ShallowCopy(outCD); newGrid->Delete(); } } //------------------------------------------------------------------------------ void vtkStructuredGrid::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); int dim[3]; this->GetDimensions(dim); os << indent << "Dimensions: (" << dim[0] << ", " << dim[1] << ", " << dim[2] << ")\n"; const int* extent = this->Extent; os << indent << "Extent: " << extent[0] << ", " << extent[1] << ", " << extent[2] << ", " << extent[3] << ", " << extent[4] << ", " << extent[5] << endl; os << ")\n"; } //------------------------------------------------------------------------------ vtkStructuredGrid* vtkStructuredGrid::GetData(vtkInformation* info) { return info ? vtkStructuredGrid::SafeDownCast(info->Get(DATA_OBJECT())) : nullptr; } //------------------------------------------------------------------------------ vtkStructuredGrid* vtkStructuredGrid::GetData(vtkInformationVector* v, int i) { return vtkStructuredGrid::GetData(v->GetInformationObject(i)); } //------------------------------------------------------------------------------ void vtkStructuredGrid::GetPoint(int i, int j, int k, double p[3], bool adjustForExtent) { int extent[6]; this->GetExtent(extent); if (i < extent[0] || i > extent[1] || j < extent[2] || j > extent[3] || k < extent[4] || k > extent[5]) { vtkErrorMacro("ERROR: IJK coordinates are outside of grid extent!"); return; // out of bounds! } int pos[3]; pos[0] = i; pos[1] = j; pos[2] = k; vtkIdType id; if (adjustForExtent) { id = vtkStructuredData::ComputePointIdForExtent(extent, pos); } else { int dim[3]; this->GetDimensions(dim); id = vtkStructuredData::ComputePointId(dim, pos); } this->GetPoint(id, p); } //------------------------------------------------------------------------------ bool vtkStructuredGrid::HasAnyBlankPoints() { return this->IsAnyBitSet(this->GetPointGhostArray(), vtkDataSetAttributes::HIDDENPOINT); } //------------------------------------------------------------------------------ bool vtkStructuredGrid::HasAnyBlankCells() { int cellBlanking = this->IsAnyBitSet(this->GetCellGhostArray(), vtkDataSetAttributes::HIDDENCELL); return cellBlanking || this->HasAnyBlankPoints(); }