VTK-m  2.0
CellMaxAngleMetric.h
Go to the documentation of this file.
1 //============================================================================
2 // Copyright (c) Kitware, Inc.
3 // All rights reserved.
4 // See LICENSE.txt for details.
5 // This software is distributed WITHOUT ANY WARRANTY; without even
6 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
7 // PURPOSE. See the above copyright notice for more information.
8 //
9 // Copyright 2018 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
10 // Copyright 2018 UT-Battelle, LLC.
11 // Copyright 2018 Los Alamos National Security.
12 //
13 // Under the terms of Contract DE-NA0003525 with NTESS,
14 // the U.S. Government retains certain rights in this software.
15 //
16 // Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
17 // Laboratory (LANL), the U.S. Government retains certain rights in
18 // this software.
19 //============================================================================
20 #ifndef vtk_m_worklet_cellmetrics_CellMaxAngleMetric_h
21 #define vtk_m_worklet_cellmetrics_CellMaxAngleMetric_h
22 
23 /*
24 * Mesh quality metric functions that compute the maximum angle of cell in a mesh.
25 ** These metric computations are adapted from the VTK implementation of the Verdict library,
26 * which provides a set of mesh/cell metrics for evaluating the geometric qualities of regions
27 * of mesh spaces.
28 ** See: The Verdict Library Reference Manual (for per-cell-type metric formulae)
29 * See: vtk/ThirdParty/verdict/vtkverdict (for VTK code implementation of this metric)
30 */
31 
32 #include "TypeOfCellHexahedral.h"
34 #include "TypeOfCellTetrahedral.h"
35 #include "TypeOfCellTriangle.h"
36 #include <vtkm/CellShape.h>
37 #include <vtkm/CellTraits.h>
38 #include <vtkm/ErrorCode.h>
39 #include <vtkm/VecTraits.h>
40 #include <vtkm/VectorAnalysis.h>
41 
42 #define UNUSED(expr) (void)(expr);
43 
44 namespace vtkm
45 {
46 namespace worklet
47 {
48 namespace cellmetrics
49 {
50 
51 // ========================= Unsupported cells ==================================
52 // By default, cells have zero shape unless the shape type template is specialized below.
53 template <typename OutType, typename PointCoordVecType, typename CellShapeType>
55  const PointCoordVecType& pts,
56  CellShapeType shape,
58 {
59  UNUSED(numPts);
60  UNUSED(pts);
61  UNUSED(shape);
62  return OutType(-1.0);
63 }
64 // ========================= 2D cells ==================================
65 // Compute the maximum angle of a triangle.
66 // Formula: q = max( arccos((Ln dot Ln+1)/(||Ln|| * ||Ln+1||))(180º/π) for n 0,1, and 2 )
67 // - L3 = L0
68 // - if any edge has length 0, return q = 360º
69 // - All angle measurements are in degrees
70 // q equals 60 for a unit triangle
71 // Acceptable range: [30º, 60º]
72 // Normal Range: [0º, 360º]
73 // Full range: [0º, 360º]
74 template <typename OutType, typename PointCoordVecType>
76  const PointCoordVecType& pts,
77  vtkm::CellShapeTagTriangle,
78  vtkm::ErrorCode& ec)
79 {
80  if (numPts != 3)
81  {
83  return OutType(0.0);
84  }
85 
86  using Scalar = OutType;
87  using CollectionOfPoints = PointCoordVecType;
88  using Vector = typename PointCoordVecType::ComponentType;
89 
90  const Scalar l0 = GetTriangleL0Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
91  const Scalar l1 = GetTriangleL1Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
92  const Scalar l2 = GetTriangleL2Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
93 
94  if (l0 <= Scalar(0.0) || l1 <= Scalar(0.0) || l2 <= Scalar(0.0))
95  {
96  return Scalar(0.0);
97  }
98 
99  const Scalar oneEightyOverPi = (Scalar)57.2957795131;
100  const Scalar two(2.0);
101  const Scalar q0 = vtkm::ACos(((l1 * l1) + (l2 * l2) - (l0 * l0)) / (two * l1 * l2));
102  const Scalar q1 = vtkm::ACos(((l2 * l2) + (l0 * l0) - (l1 * l1)) / (two * l2 * l0));
103  const Scalar q2 = vtkm::ACos(((l0 * l0) + (l1 * l1) - (l2 * l2)) / (two * l0 * l1));
104 
105  const Scalar q = vtkm::Max(q0, vtkm::Max(q1, q2));
106 
107  const Scalar qInDegrees = q * oneEightyOverPi;
108 
109  return qInDegrees;
110 }
111 // Compute the max angle of a quadrilateral.
112 // Formula: q = max( Ai for i 0,1,2, and 3 )
113 // - L4 = L0
114 // - Ai = -1^Si arccos(-1(Li dot Li+1)/(||Li||||Li+1||) )(180/π) + 360º*Si
115 // - if ||Li|| <= FLOAT_MIN or ||Li+1|| <= FLOAT_MIN, return q = 360º
116 // q = 90º for a unit square
117 // Acceptable range: [45º, 90º]
118 // Normal Range: [0º, 90º]
119 // Full range: [0º, 360º]
120 template <typename OutType, typename PointCoordVecType>
122  const PointCoordVecType& pts,
123  vtkm::CellShapeTagQuad,
124  vtkm::ErrorCode& ec)
125 {
126  if (numPts != 4)
127  {
129  return OutType(0.0);
130  }
131 
132  using Scalar = OutType;
133  using CollectionOfPoints = PointCoordVecType;
134  using Vector = typename PointCoordVecType::ComponentType;
135 
136  const Scalar l0 = GetQuadL0Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
137  const Scalar l1 = GetQuadL1Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
138  const Scalar l2 = GetQuadL2Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
139  const Scalar l3 = GetQuadL3Magnitude<Scalar, Vector, CollectionOfPoints>(pts);
140 
141  if (l0 <= Scalar(0.0) || l1 <= Scalar(0.0) || l2 <= Scalar(0.0) || l3 <= Scalar(0.0))
142  {
143  return Scalar(0.0);
144  }
145 
146  const Scalar alpha0 = GetQuadAlpha0<Scalar, Vector, CollectionOfPoints>(pts);
147  const Scalar alpha1 = GetQuadAlpha1<Scalar, Vector, CollectionOfPoints>(pts);
148  const Scalar alpha2 = GetQuadAlpha2<Scalar, Vector, CollectionOfPoints>(pts);
149  const Scalar alpha3 = GetQuadAlpha3<Scalar, Vector, CollectionOfPoints>(pts);
150 
151  const Scalar s0 = alpha0 < Scalar(0.0) ? Scalar(1.0) : Scalar(0.0);
152  const Scalar s1 = alpha1 < Scalar(0.0) ? Scalar(1.0) : Scalar(0.0);
153  const Scalar s2 = alpha2 < Scalar(0.0) ? Scalar(1.0) : Scalar(0.0);
154  const Scalar s3 = alpha3 < Scalar(0.0) ? Scalar(1.0) : Scalar(0.0);
155 
156  const Vector L0 = GetQuadL0<Scalar, Vector, CollectionOfPoints>(pts);
157  const Vector L1 = GetQuadL1<Scalar, Vector, CollectionOfPoints>(pts);
158  const Vector L2 = GetQuadL2<Scalar, Vector, CollectionOfPoints>(pts);
159  const Vector L3 = GetQuadL3<Scalar, Vector, CollectionOfPoints>(pts);
160 
161  // This angle is given in degrees, not radians. The verdict definition (1) converts to degrees, (2) gives co(terminal) angles, and (3) takes the min/max.
162  // Further, it combines steps 1 & 2 into a single expression using clever (-1)^power flags.
163  const Scalar neg1(-1.0);
164  const Scalar oneEightyOverPi = (Scalar)57.2957795131; // ~ 180/pi
165  const Scalar threeSixty(360.0);
166  const Scalar q0 =
167  (vtkm::Pow(neg1, s0) * vtkm::ACos(neg1 * (static_cast<Scalar>(vtkm::Dot(L0, L1)) / (l0 * l1))) *
168  oneEightyOverPi) +
169  (threeSixty * s0);
170  const Scalar q1 =
171  (vtkm::Pow(neg1, s1) * vtkm::ACos(neg1 * (static_cast<Scalar>(vtkm::Dot(L1, L2)) / (l1 * l2))) *
172  oneEightyOverPi) +
173  (threeSixty * s1);
174  const Scalar q2 =
175  (vtkm::Pow(neg1, s2) * vtkm::ACos(neg1 * (static_cast<Scalar>(vtkm::Dot(L2, L3)) / (l2 * l3))) *
176  oneEightyOverPi) +
177  (threeSixty * s2);
178  const Scalar q3 =
179  (vtkm::Pow(neg1, s3) * vtkm::ACos(neg1 * (static_cast<Scalar>(vtkm::Dot(L3, L0)) / (l3 * l0))) *
180  oneEightyOverPi) +
181  (threeSixty * s3);
182 
183  const Scalar q = vtkm::Max(q0, vtkm::Max(q1, vtkm::Max(q2, q3)));
184  return q;
185 }
186 } // namespace cellmetrics
187 } // namespace worklet
188 } // namespace vtkm
189 #endif // vtk_m_worklet_cellmetrics_CellMaxAngleMetric_h
vtkm::ErrorCode
ErrorCode
Definition: ErrorCode.h:19
VTKM_EXEC
#define VTKM_EXEC
Definition: ExportMacros.h:51
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
vtkm::IdComponent
vtkm::Int32 IdComponent
Represents a component ID (index of component in a vector).
Definition: Types.h:168
CellShape.h
ErrorCode.h
VectorAnalysis.h
vtkm::worklet::cellmetrics::CellMaxAngleMetric
VTKM_EXEC OutType CellMaxAngleMetric(const vtkm::IdComponent &numPts, const PointCoordVecType &pts, CellShapeType shape, vtkm::ErrorCode &)
Definition: CellMaxAngleMetric.h:54
TypeOfCellTetrahedral.h
TypeOfCellTriangle.h
TypeOfCellHexahedral.h
UNUSED
#define UNUSED(expr)
Definition: CellMaxAngleMetric.h:42
TypeOfCellQuadrilateral.h
CellTraits.h
vtkm::ACos
VTKM_EXEC_CONT vtkm::Float32 ACos(vtkm::Float32 x)
Compute the arc cosine of x.
Definition: Math.h:446
VecTraits.h
vtkm::ErrorCode::InvalidNumberOfPoints
@ InvalidNumberOfPoints