//============================================================================ // 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. //============================================================================ #ifndef vtk_m_exec_CellEdge_h #define vtk_m_exec_CellEdge_h #include #include #include #include #include namespace vtkm { namespace exec { namespace detail { class CellEdgeTables { public: static constexpr vtkm::Int32 MAX_NUM_EDGES = 12; public: VTKM_EXEC vtkm::Int32 NumEdges(vtkm::Int32 cellShapeId) const { VTKM_STATIC_CONSTEXPR_ARRAY vtkm::Int32 numEdges[vtkm::NUMBER_OF_CELL_SHAPES] = { // NumEdges 0, // 0: CELL_SHAPE_EMPTY 0, // 1: CELL_SHAPE_VERTEX 0, // 2: Unused 0, // 3: CELL_SHAPE_LINE 0, // 4: CELL_SHAPE_POLY_LINE 3, // 5: CELL_SHAPE_TRIANGLE 0, // 6: Unused -1, // 7: CELL_SHAPE_POLYGON ---special case--- 0, // 8: Unused 4, // 9: CELL_SHAPE_QUAD 6, // 10: CELL_SHAPE_TETRA 0, // 11: Unused 12, // 12: CELL_SHAPE_HEXAHEDRON 9, // 13: CELL_SHAPE_WEDGE 8 // 14: CELL_SHAPE_PYRAMID }; return numEdges[cellShapeId]; } VTKM_EXEC vtkm::Int32 PointsInEdge(vtkm::Int32 cellShapeId, vtkm::Int32 edgeIndex, vtkm::Int32 localPointIndex) const { VTKM_STATIC_CONSTEXPR_ARRAY vtkm::Int32 pointsInEdge[vtkm::NUMBER_OF_CELL_SHAPES][MAX_NUM_EDGES][2] = { // clang-format off // 0: CELL_SHAPE_EMPTY { { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, // 1: CELL_SHAPE_VERTEX { { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, // 2: Unused { { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, // 3: CELL_SHAPE_LINE { { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, // 4: CELL_SHAPE_POLY_LINE { { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, // 5: CELL_SHAPE_TRIANGLE { { 0, 1 }, { 1, 2 }, { 2, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, // 6: Unused { { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, // 7: CELL_SHAPE_POLYGON --- special case --- { { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, // 8: Unused { { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, // 9: CELL_SHAPE_QUAD { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, // 10: CELL_SHAPE_TETRA { { 0, 1 }, { 1, 2 }, { 2, 0 }, { 0, 3 }, { 1, 3 }, { 2, 3 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, // 11: Unused { { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, // 12: CELL_SHAPE_HEXAHEDRON { { 0, 1 }, { 1, 2 }, { 3, 2 }, { 0, 3 }, { 4, 5 }, { 5, 6 }, { 7, 6 }, { 4, 7 }, { 0, 4 }, { 1, 5 }, { 3, 7 }, { 2, 6 } }, // 13: CELL_SHAPE_WEDGE { { 0, 1 }, { 1, 2 }, { 2, 0 }, { 3, 4 }, { 4, 5 }, { 5, 3 }, { 0, 3 }, { 1, 4 }, { 2, 5 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }, // 14: CELL_SHAPE_PYRAMID { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 }, { 0, 4 }, { 1, 4 }, { 2, 4 }, { 3, 4 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 } } // clang-format on }; return pointsInEdge[cellShapeId][edgeIndex][localPointIndex]; } }; } // namespace detail template static inline VTKM_EXEC vtkm::ErrorCode CellEdgeNumberOfEdges(vtkm::IdComponent numPoints, CellShapeTag, vtkm::IdComponent& numEdges) { if (numPoints != vtkm::CellTraits::NUM_POINTS) { numEdges = -1; return vtkm::ErrorCode::InvalidNumberOfPoints; } numEdges = detail::CellEdgeTables{}.NumEdges(CellShapeTag::Id); return vtkm::ErrorCode::Success; } static inline VTKM_EXEC vtkm::ErrorCode CellEdgeNumberOfEdges(vtkm::IdComponent numPoints, vtkm::CellShapeTagPolygon, vtkm::IdComponent& numEdges) { if (numPoints <= 0) { numEdges = -1; return vtkm::ErrorCode::InvalidNumberOfPoints; } numEdges = numPoints; return vtkm::ErrorCode::Success; } static inline VTKM_EXEC vtkm::ErrorCode CellEdgeNumberOfEdges(vtkm::IdComponent numPoints, vtkm::CellShapeTagPolyLine, vtkm::IdComponent& numEdges) { if (numPoints <= 0) { numEdges = -1; return vtkm::ErrorCode::InvalidNumberOfPoints; } numEdges = detail::CellEdgeTables{}.NumEdges(vtkm::CELL_SHAPE_POLY_LINE); return vtkm::ErrorCode::Success; } /// @brief Get the number of edges in a cell. /// /// @param[in] numPoints The number of points in the cell. /// @param[in] shape A tag of type `CellShapeTag*` to identify the shape of the cell. /// This method is overloaded for different shape types. /// @param[out] numEdges A reference to return the number of edges. static inline VTKM_EXEC vtkm::ErrorCode CellEdgeNumberOfEdges(vtkm::IdComponent numPoints, vtkm::CellShapeTagGeneric shape, vtkm::IdComponent& numEdges) { if (shape.Id == vtkm::CELL_SHAPE_POLYGON) { return CellEdgeNumberOfEdges(numPoints, vtkm::CellShapeTagPolygon(), numEdges); } else if (shape.Id == vtkm::CELL_SHAPE_POLY_LINE) { return CellEdgeNumberOfEdges(numPoints, vtkm::CellShapeTagPolyLine(), numEdges); } else { numEdges = detail::CellEdgeTables{}.NumEdges(shape.Id); return vtkm::ErrorCode::Success; } } template static inline VTKM_EXEC vtkm::ErrorCode CellEdgeLocalIndex(vtkm::IdComponent numPoints, vtkm::IdComponent pointIndex, vtkm::IdComponent edgeIndex, CellShapeTag shape, vtkm::IdComponent& result) { if ((pointIndex < 0) || (pointIndex > 1)) { result = -1; return vtkm::ErrorCode::InvalidPointId; } if ((edgeIndex < 0) || (edgeIndex >= detail::CellEdgeTables::MAX_NUM_EDGES)) { result = -1; return vtkm::ErrorCode::InvalidEdgeId; } vtkm::IdComponent numEdges; VTKM_RETURN_ON_ERROR(vtkm::exec::CellEdgeNumberOfEdges(numPoints, shape, numEdges)); if (edgeIndex >= numEdges) { result = -1; return vtkm::ErrorCode::InvalidEdgeId; } detail::CellEdgeTables table; result = table.PointsInEdge(CellShapeTag::Id, edgeIndex, pointIndex); return vtkm::ErrorCode::Success; } static inline VTKM_EXEC vtkm::ErrorCode CellEdgeLocalIndex(vtkm::IdComponent numPoints, vtkm::IdComponent pointIndex, vtkm::IdComponent edgeIndex, vtkm::CellShapeTagPolygon, vtkm::IdComponent& result) { if (numPoints < 3) { result = -1; return vtkm::ErrorCode::InvalidNumberOfPoints; } if ((pointIndex < 0) || (pointIndex > 1)) { result = -1; return vtkm::ErrorCode::InvalidPointId; } if ((edgeIndex < 0) || (edgeIndex >= numPoints)) { result = -1; return vtkm::ErrorCode::InvalidEdgeId; } if (edgeIndex + pointIndex < numPoints) { result = edgeIndex + pointIndex; } else { result = 0; } return vtkm::ErrorCode::Success; } /// Given the index for an edge of a cell and one of the points on that edge, this /// function returns the point index for the cell. /// To get the point indices relative to the data set, the returned index should be used /// to reference a `PointIndices` list. /// /// @param[in] numPoints The number of points in the cell. /// @param[in] pointIndex The index of the edge within the cell. /// @param[in] edgeIndex The index of the point on the edge (either 0 or 1). /// @param[in] shape A tag of type `CellShapeTag*` to identify the shape of the cell. /// This method is overloaded for different shape types. /// @param[out] result Reference to put the index of the point relative to the cell /// (between 0 and the number of points in the cell). static inline VTKM_EXEC vtkm::ErrorCode CellEdgeLocalIndex(vtkm::IdComponent numPoints, vtkm::IdComponent pointIndex, vtkm::IdComponent edgeIndex, vtkm::CellShapeTagGeneric shape, vtkm::IdComponent& result) { if ((pointIndex < 0) || (pointIndex > 1)) { result = -1; return vtkm::ErrorCode::InvalidPointId; } if ((edgeIndex < 0) || (edgeIndex >= detail::CellEdgeTables::MAX_NUM_EDGES)) { result = -1; return vtkm::ErrorCode::InvalidEdgeId; } if (shape.Id == vtkm::CELL_SHAPE_POLYGON) { return CellEdgeLocalIndex( numPoints, pointIndex, edgeIndex, vtkm::CellShapeTagPolygon(), result); } else { detail::CellEdgeTables table; if (edgeIndex >= table.NumEdges(shape.Id)) { result = -1; return vtkm::ErrorCode::InvalidEdgeId; } result = table.PointsInEdge(shape.Id, edgeIndex, pointIndex); return vtkm::ErrorCode::Success; } } /// @brief Returns a canonical identifier for a cell edge /// /// Given information about a cell edge and the global point indices for that cell, returns a /// vtkm::Id2 that contains values that are unique to that edge. The values for two edges will be /// the same if and only if the edges contain the same points. /// template static inline VTKM_EXEC vtkm::ErrorCode CellEdgeCanonicalId( vtkm::IdComponent numPoints, vtkm::IdComponent edgeIndex, CellShapeTag shape, const GlobalPointIndicesVecType& globalPointIndicesVec, vtkm::Id2& result) { result = { -1, -1 }; vtkm::IdComponent localIndex0; VTKM_RETURN_ON_ERROR(vtkm::exec::CellEdgeLocalIndex(numPoints, 0, edgeIndex, shape, localIndex0)); vtkm::Id pointIndex0 = globalPointIndicesVec[localIndex0]; vtkm::IdComponent localIndex1; VTKM_RETURN_ON_ERROR(vtkm::exec::CellEdgeLocalIndex(numPoints, 1, edgeIndex, shape, localIndex1)); vtkm::Id pointIndex1 = globalPointIndicesVec[localIndex1]; if (pointIndex0 < pointIndex1) { result = vtkm::Id2(pointIndex0, pointIndex1); } else { result = vtkm::Id2(pointIndex1, pointIndex0); } return vtkm::ErrorCode::Success; } } } // namespace vtkm::exec #endif //vtk_m_exec_CellFaces_h