//============================================================================ // Copyright (c) Kitware, Inc. // All rights reserved. // See LICENSE.txt 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. // // Copyright 2014 Sandia Corporation. // Copyright 2014 UT-Battelle, LLC. // Copyright 2014. Los Alamos National Security // // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, // the U.S. Government retains certain rights in this software. // // Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National // Laboratory (LANL), the U.S. Government retains certain rights in // this software. //============================================================================ #ifndef vtk_m_Extent_h #define vtk_m_Extent_h #include namespace vtkm { /// Extent stores the values for the index ranges for a structured grid array. /// It does this through the minimum indices and the maximum indices for the /// points in the grid. /// template struct Extent { vtkm::Vec Min; vtkm::Vec Max; VTKM_EXEC_CONT_EXPORT Extent() : Min(0), Max(0) { } VTKM_EXEC_CONT_EXPORT Extent(const vtkm::Vec &min, const vtkm::Vec &max) : Min(min), Max(max) { } VTKM_EXEC_CONT_EXPORT Extent(const Extent &other) : Min(other.Min), Max(other.Max) { } VTKM_EXEC_CONT_EXPORT Extent &operator=(const Extent &rhs) { this->Min = rhs.Min; this->Max = rhs.Max; return *this; } }; /// This is the Extent to use for structured grids with 3 topological /// dimensions. /// typedef vtkm::Extent<3> Extent3; /// This is the Extent to use for structured grids with 2 topological /// dimensions. /// typedef vtkm::Extent<2> Extent2; /// Given an extent, returns the array dimensions for the points. /// template VTKM_EXEC_CONT_EXPORT vtkm::Vec ExtentPointDimensions(const vtkm::Extent &extent) { return extent.Max - extent.Min + vtkm::Vec(1); } VTKM_EXEC_CONT_EXPORT vtkm::Id3 ExtentPointDimensions(const vtkm::Extent3 &extent) { // Efficient implementation that uses no temporary Id3 to create dimensions. return vtkm::Id3(extent.Max[0] - extent.Min[0] + 1, extent.Max[1] - extent.Min[1] + 1, extent.Max[2] - extent.Min[2] + 1); } VTKM_EXEC_CONT_EXPORT vtkm::Id2 ExtentPointDimensions(const vtkm::Extent2 &extent) { // Efficient implementation that uses no temporary Id2 to create dimensions. return vtkm::Id2(extent.Max[0] - extent.Min[0] + 1, extent.Max[1] - extent.Min[1] + 1); } /// Given an extent, returns the array dimensions for the cells. /// template VTKM_EXEC_CONT_EXPORT vtkm::Vec ExtentCellDimensions(const vtkm::Extent &extent) { return extent.Max - extent.Min; } /// Given an extent, returns the number of points in the structured mesh. /// template VTKM_EXEC_CONT_EXPORT vtkm::Id ExtentNumberOfPoints(const vtkm::Extent &extent) { return internal::VecProduct()( vtkm::ExtentPointDimensions(extent)); } template<> VTKM_EXEC_CONT_EXPORT vtkm::Id ExtentNumberOfPoints(const vtkm::Extent3 &extent) { // Efficient implementation that uses no temporary Id3. return ( (extent.Max[0] - extent.Min[0] + 1) * (extent.Max[1] - extent.Min[1] + 1) * (extent.Max[2] - extent.Min[2] + 1)); } template<> VTKM_EXEC_CONT_EXPORT vtkm::Id ExtentNumberOfPoints(const vtkm::Extent2 &extent) { // Efficient implementation that uses no temporary Id2. return ( (extent.Max[0] - extent.Min[0] + 1) * (extent.Max[1] - extent.Min[1] + 1)); } /// Given an extent, returns the number of cells in the structured mesh. /// template VTKM_EXEC_CONT_EXPORT vtkm::Id ExtentNumberOfCells(const vtkm::Extent &extent) { return internal::VecProduct()( vtkm::ExtentCellDimensions(extent)); } template<> VTKM_EXEC_CONT_EXPORT vtkm::Id ExtentNumberOfCells(const vtkm::Extent3 &extent) { // Efficient implementation that uses no temporary Id3. return ( (extent.Max[0] - extent.Min[0]) * (extent.Max[1] - extent.Min[1]) * (extent.Max[2] - extent.Min[2])); } template<> VTKM_EXEC_CONT_EXPORT vtkm::Id ExtentNumberOfCells(const vtkm::Extent2 &extent) { // Efficient implementation that uses no temporary Id2. return ( (extent.Max[0] - extent.Min[0]) * (extent.Max[1] - extent.Min[1])); } /// Elements in structured grids have a single index with 0 being the entry at /// the minimum extent in every direction and then increasing first in the r /// then the s direction and so on. This method converts a flat index to the /// topological coordinates (e.g. r,s,t for 3d topologies). /// template VTKM_EXEC_CONT_EXPORT vtkm::Vec ExtentPointFlatIndexToTopologyIndex(vtkm::Id index, const vtkm::Extent &extent) { const vtkm::Vec dims = vtkm::ExtentPointDimensions(extent); vtkm::Vec ijkIndex; vtkm::Id indexOnDim = index; for (vtkm::IdComponent dimIndex = 0; dimIndex < Dimensions-1; dimIndex++) { ijkIndex[dimIndex] = indexOnDim % dims[dimIndex] + extent.Min[dimIndex]; indexOnDim /= dims[dimIndex]; } // Special case for last dimension to remove some unneeded operations ijkIndex[Dimensions-1] = indexOnDim + extent.Min[Dimensions-1]; return ijkIndex; } VTKM_EXEC_CONT_EXPORT vtkm::Id3 ExtentPointFlatIndexToTopologyIndex(vtkm::Id index, const vtkm::Extent3 &extent) { // Efficient implementation that tries to reduce the number of temporary // variables. const vtkm::Id3 dims = vtkm::ExtentPointDimensions(extent); return vtkm::Id3((index % dims[0]) + extent.Min[0], ((index / dims[0]) % dims[1]) + extent.Min[1], ((index / (dims[0]*dims[1]))) + extent.Min[2]); } VTKM_EXEC_CONT_EXPORT vtkm::Id2 ExtentPointFlatIndexToTopologyIndex(vtkm::Id index, const vtkm::Extent2 &extent) { // Efficient implementation that tries to reduce the number of temporary // variables. const vtkm::Id2 dims = vtkm::ExtentPointDimensions(extent); return vtkm::Id2((index % dims[0]) + extent.Min[0], (index / dims[0]) + extent.Min[1]); } /// Elements in structured grids have a single index with 0 being the entry at /// the minimum extent in every direction and then increasing first in the r /// then the s direction and so on. This method converts a flat index to the /// topological coordinates (e.g. r,s,t for 3d topologies). /// template VTKM_EXEC_CONT_EXPORT vtkm::Vec ExtentCellFlatIndexToTopologyIndex(vtkm::Id index, const vtkm::Extent &extent) { const vtkm::Vec dims = vtkm::ExtentCellDimensions(extent); vtkm::Vec ijkIndex; vtkm::Id indexOnDim = index; for (vtkm::IdComponent dimIndex = 0; dimIndex < Dimensions-1; dimIndex++) { ijkIndex[dimIndex] = indexOnDim % dims[dimIndex] + extent.Min[dimIndex]; indexOnDim /= dims[dimIndex]; } // Special case for last dimension to remove some unneeded operations ijkIndex[Dimensions-1] = indexOnDim + extent.Min[Dimensions-1]; return ijkIndex; } VTKM_EXEC_CONT_EXPORT vtkm::Id3 ExtentCellFlatIndexToTopologyIndex(vtkm::Id index, const vtkm::Extent3 &extent) { // Efficient implementation that tries to reduce the number of temporary // variables. const vtkm::Id3 dims = vtkm::ExtentCellDimensions(extent); return vtkm::Id3((index % dims[0]) + extent.Min[0], ((index / dims[0]) % dims[1]) + extent.Min[1], ((index / (dims[0]*dims[1]))) + extent.Min[2]); } VTKM_EXEC_CONT_EXPORT vtkm::Id2 ExtentCellFlatIndexToTopologyIndex(vtkm::Id index, const vtkm::Extent2 &extent) { // Efficient implementation that tries to reduce the number of temporary // variables. const vtkm::Id2 dims = vtkm::ExtentCellDimensions(extent); return vtkm::Id2((index % dims[0]) + extent.Min[0], (index / dims[0]) + extent.Min[1]); } /// Elements in structured grids have a single index with 0 being the entry at /// the minimum extent in every direction and then increasing first in the r /// then the s direction and so on. This method converts topological /// coordinates to a flat index. /// template VTKM_EXEC_CONT_EXPORT vtkm::Id ExtentPointTopologyIndexToFlatIndex(const vtkm::Vec &ijk, const vtkm::Extent &extent) { const vtkm::Vec dims = ExtentPointDimensions(extent); const vtkm::Vec deltas = ijk - extent.Min; vtkm::Id flatIndex = deltas[Dimensions-1]; for (vtkm::IdComponent dimIndex = Dimensions-2; dimIndex >= 0; dimIndex--) { flatIndex = flatIndex*dims[dimIndex] + deltas[dimIndex]; } return flatIndex; } /// Elements in structured grids have a single index with 0 being the entry at /// the minimum extent in every direction and then increasing first in the r /// then the s direction and so on. This method converts topological /// coordinates to a flat index. /// template VTKM_EXEC_CONT_EXPORT vtkm::Id ExtentCellTopologyIndexToFlatIndex(const vtkm::Vec &ijk, const vtkm::Extent &extent) { const vtkm::Vec dims = ExtentCellDimensions(extent); const vtkm::Vec deltas = ijk - extent.Min; vtkm::Id flatIndex = deltas[Dimensions-1]; for (vtkm::IdComponent dimIndex = Dimensions-2; dimIndex >= 0; dimIndex--) { flatIndex = flatIndex*dims[dimIndex] + deltas[dimIndex]; } return flatIndex; } /// Given a cell index, returns the index to the first point incident on that /// cell. /// template VTKM_EXEC_CONT_EXPORT vtkm::Id ExtentFirstPointOnCell(vtkm::Id cellIndex, const Extent &extent) { return ExtentPointTopologyIndexToFlatIndex( ExtentCellFlatIndexToTopologyIndex(cellIndex,extent), extent); } } // namespace vtkm #endif //vtk_m_Extent_h