ViennaLS
Loading...
Searching...
No Matches
lsCurvatureFormulas.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cmath>
4
5#include <lsDomain.hpp>
6
7#include <vcLogger.hpp>
8
9namespace lsInternal {
10
11using namespace viennacore;
12
13// Formulas for space curves and higher dimension can be found here:
14// https://doi.org/10.1016/j.cagd.2005.06.005
15
17template <class It> double squareSumSquare(It begin, It end) {
18 double result = 0.;
19 while (begin != end) {
20 result += *begin * *begin;
21 ++begin;
22 }
23 return result * result;
24}
25
28template <class It> double rootSumSquarePow3(It begin, It end) {
29 double result = 0.;
30 while (begin != end) {
31 result += *begin * *begin;
32 ++begin;
33 }
34 return std::pow(result, 1.5);
35}
36
40template <class T, std::size_t N>
41double meanCurvature2D(std::array<T, N> funcValues) {
42 double norm = rootSumSquarePow3(funcValues.begin(), funcValues.begin() + 2);
43 auto &d = funcValues;
44
45 return (d[3] * d[1] * d[1] - 2. * d[1] * d[0] * d[6] + d[4] * d[0] * d[0]) /
46 norm;
47}
48
52template <class T, std::size_t N>
53double meanCurvature3D(std::array<T, N> funcValues) {
54 double norm = rootSumSquarePow3(funcValues.begin(), funcValues.begin() + 3);
55 auto &d = funcValues;
56
57 return (d[0] * d[0] * (d[4] + d[5]) + d[1] * d[1] * (d[3] + d[5]) +
58 d[2] * d[2] * (d[3] + d[4]) +
59 -2. *
60 (d[0] * d[1] * d[6] + d[0] * d[2] * d[8] + d[1] * d[2] * d[7])) /
61 (2. * norm);
62}
63
67template <class T, std::size_t N>
68double gaussianCurvature3D(std::array<T, N> funcValues) {
69 double norm = squareSumSquare(funcValues.begin(), funcValues.begin() + 3);
70 auto &d = funcValues;
71
72 return -(d[0] * d[0] * (d[7] * d[7] - d[4] * d[5]) +
73 d[1] * d[1] * (d[8] * d[8] - d[3] * d[5]) +
74 d[2] * d[2] * (d[6] * d[6] - d[3] * d[4]) +
75 2. * (d[0] * d[1] * (d[5] * d[6] - d[8] * d[7]) +
76 d[0] * d[2] * (d[4] * d[8] - d[6] * d[7]) +
77 d[1] * d[2] * (d[3] * d[7] - d[6] * d[8]))) /
78 norm;
79}
80
84template <class It, class T = typename It::DomainType::hrleValueType>
85std::array<T, 9> smallStencilFromIterator(It &it, const double gridDelta) {
86 constexpr int D = It::DomainType::dimension;
87 std::array<T, 9> d;
88 for (int i = 0; i < D; i++) {
89 hrleVectorType<hrleIndexType, D> posUnit(0);
90 hrleVectorType<hrleIndexType, D> negUnit(0);
91 posUnit[i] = 1;
92 negUnit[i] = -1;
93 T phi_0 = it.getCenter().getValue();
94 T phi_px = it.getNeighbor(posUnit).getValue();
95 T phi_nx = it.getNeighbor(negUnit).getValue();
96 int second_pos = (i + 1) % D;
97 posUnit[second_pos] = 1;
98 negUnit[second_pos] = 1;
99 T phi_pp = it.getNeighbor(posUnit).getValue();
100 T phi_np = it.getNeighbor(negUnit).getValue();
101 posUnit[second_pos] = -1;
102 negUnit[second_pos] = -1;
103 T phi_pn = it.getNeighbor(posUnit).getValue();
104 T phi_nn = it.getNeighbor(negUnit).getValue();
105
106 // Calculate derivatives for Hessian
107 d[i] = (phi_px - phi_nx) / 2.;
108 d[i + 3] = (phi_px - 2. * phi_0 + phi_nx) / gridDelta;
109 d[i + 6] = (phi_pp - phi_pn - phi_np + phi_nn) / (4 * gridDelta);
110 }
111 return d;
112}
113
117template <class It, class T = typename It::DomainType::hrleValueType>
118std::array<T, 9> bigStencilFromIterator(It &it, const double gridDelta) {
119 constexpr int D = It::DomainType::dimension;
120 std::array<T, 9> d;
121 const double gridDelta2 = gridDelta * gridDelta;
122 for (int i = 0; i < D; i++) {
123 hrleVectorType<hrleIndexType, D> posUnit(0);
124 hrleVectorType<hrleIndexType, D> negUnit(0);
125 int first_axis = i;
126 int second_axis = (i + 1) % D;
127 posUnit[first_axis] = 1;
128 negUnit[first_axis] = -1;
129 T phi_0 = it.getCenter().getValue();
130 T phi_px = it.getNeighbor(posUnit).getValue();
131 T phi_nx = it.getNeighbor(negUnit).getValue();
132 posUnit[second_axis] = 1;
133 negUnit[second_axis] = 1;
134 T phi_pp = it.getNeighbor(posUnit).getValue();
135 T phi_np = it.getNeighbor(negUnit).getValue();
136 posUnit[second_axis] = -1;
137 negUnit[second_axis] = -1;
138 T phi_pn = it.getNeighbor(posUnit).getValue();
139 T phi_nn = it.getNeighbor(negUnit).getValue();
140 posUnit[first_axis] = 0;
141 negUnit[first_axis] = 0;
142 posUnit[second_axis] = 1;
143 negUnit[second_axis] = -1;
144 T phi_py = it.getNeighbor(posUnit).getValue();
145 T phi_ny = it.getNeighbor(negUnit).getValue();
146
147 d[i] = (phi_pp - phi_np + phi_pn - phi_nn) / (4 * gridDelta);
148 d[i + 3] = (phi_pp - 2. * phi_py + phi_np + phi_px - 2. * phi_0 + phi_nx +
149 phi_pn - 2. * phi_ny + phi_nn) /
150 (3 * gridDelta2);
151 d[i + 6] = (phi_pp - phi_pn - phi_np + phi_nn) / (4 * gridDelta2);
152 }
153 return d;
154}
155
160template <class It, class T = typename It::DomainType::hrleValueType>
161T meanCurvature(It &it, bool bigStencil = false) {
162 constexpr int D = It::DomainType::dimension;
163 auto gridDelta = it.getDomain().getGrid().getGridDelta();
164 std::array<T, 9> d;
165 if (bigStencil)
166 d = bigStencilFromIterator(it, gridDelta);
167 else
168 d = smallStencilFromIterator(it, gridDelta);
169 if constexpr (D == 2) {
170 return meanCurvature2D(d);
171 } else {
172 return meanCurvature3D(d);
173 }
174}
175
180template <class It, class T = typename It::DomainType::hrleValueType>
181T gaussianCurvature(It &it, bool bigStencil = false) {
182 constexpr int D = It::DomainType::dimension;
183 auto gridDelta = it.getDomain().getGrid().getGridDelta();
184 std::array<T, 9> d;
185 if (bigStencil)
186 d = bigStencilFromIterator(it, gridDelta);
187 else
188 d = smallStencilFromIterator(it, gridDelta);
189 if constexpr (D == 2) {
190 Logger::getInstance()
191 .addWarning(
192 "2D structures do not have a Gaussian Curvature, use "
193 "\"meanCurvature(IteratorType & neighborIterator)\" instead!")
194 .print();
195 return 0.;
196 } else {
197 return gaussianCurvature3D(d);
198 }
199}
200
201} // namespace lsInternal
Definition lsAdvect.hpp:37
double squareSumSquare(It begin, It end)
Returns the squared sum square for values in the range [start, end[.
Definition lsCurvatureFormulas.hpp:17
std::array< T, 9 > smallStencilFromIterator(It &it, const double gridDelta)
Fills an std::array with differential values calculated from neighbour values. This stencil only uses...
Definition lsCurvatureFormulas.hpp:85
double gaussianCurvature3D(std::array< T, N > funcValues)
Gaussian curvature formula for implicit surfaces in 3D, the passed array should contain the function ...
Definition lsCurvatureFormulas.hpp:68
double meanCurvature2D(std::array< T, N > funcValues)
Mean curvature formula for implicit surfaces in 2D, the passed array should contain the function valu...
Definition lsCurvatureFormulas.hpp:41
T gaussianCurvature(It &it, bool bigStencil=false)
Calculates the Gaussian Curvature of the level set function from a suitable hrle iterator....
Definition lsCurvatureFormulas.hpp:181
std::array< T, 9 > bigStencilFromIterator(It &it, const double gridDelta)
Fills an std::array with differential values calculated from neighbour values. This stencil also uses...
Definition lsCurvatureFormulas.hpp:118
T meanCurvature(It &it, bool bigStencil=false)
Calculates the Mean Curvature of the level set function from a suitable hrle iterator....
Definition lsCurvatureFormulas.hpp:161
double rootSumSquarePow3(It begin, It end)
Returns the root sum square to the 3rd power for values in the range [start, end[.
Definition lsCurvatureFormulas.hpp:28
double meanCurvature3D(std::array< T, N > funcValues)
Mean curvature formula for implicit surfaces in 3D, the passed array should contain the function valu...
Definition lsCurvatureFormulas.hpp:53
constexpr int D
Definition pyWrap.cpp:65
double T
Definition pyWrap.cpp:63