| 132 | */ |
| 133 | template <class ArrayT> |
| 134 | void operator()(ArrayT* p, int numPts, const vtkIdType* pts, double* n) |
| 135 | { |
| 136 | auto points = vtk::DataArrayTupleRange<3>(p); |
| 137 | using PointType = typename decltype(points)::ConstTupleReferenceType; |
| 138 | double v1[3], v2[3]; |
| 139 | vtkIdType pointId; |
| 140 | vtkIdType commonPointId = -1; |
| 141 | for (pointId = 0; pointId < (numPts - 2); ++pointId) |
| 142 | { |
| 143 | PointType p0 = points[::GetPointId<PointIdRedirection>(pts, pointId)]; |
| 144 | vtkMath::Subtract(points[::GetPointId<PointIdRedirection>(pts, pointId + 1)], p0, v1); |
| 145 | if (vtkMath::SquaredNorm(v1) > 0) |
| 146 | { |
| 147 | commonPointId = pointId; |
| 148 | pointId += 2; // consume the two points we just used to obtain a non-zero v1 |
| 149 | break; |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | if (pointId >= numPts || commonPointId < 0) |
| 154 | { |
| 155 | // Either all the points in the loop were coincident or we used |
| 156 | // all the points to obtain v1 and have nothing left for v2. |
| 157 | n[0] = 0; |
| 158 | n[1] = 0; |
| 159 | n[2] = 0; |
| 160 | return; |
| 161 | } |
| 162 | |
| 163 | PointType p0 = points[::GetPointId<PointIdRedirection>(pts, commonPointId)]; |
| 164 | for (; pointId < numPts; ++pointId) |
| 165 | { |
| 166 | vtkMath::Subtract(points[::GetPointId<PointIdRedirection>(pts, pointId)], p0, v2); |
| 167 | vtkMath::Cross(v1, v2, v1); |
| 168 | vtkMath::Add(n, v1, n); |
| 169 | std::swap(v1, v2); |
| 170 | } |
| 171 | } |
| 172 | }; |
| 173 | |
| 174 | //------------------------------------------------------------------------------ |
nothing calls this directly
no test coverage detected