ViennaLS
Loading...
Searching...
No Matches
lsCalculateCurvatures.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <hrleCartesianPlaneIterator.hpp>
5#include <lsDomain.hpp>
6#include <lsExpand.hpp>
7
8#include <vcLogger.hpp>
9#include <vcSmartPointer.hpp>
10
11namespace viennals {
12
13using namespace viennacore;
14
20
21// Calculates the Mean Curvature and/or Gaussian Curvature (3D)
22// for the passed lsDomain for all points with level set values <= 0.5. The
23// result is saved in the lsDomain.
24template <class T, int D> class CalculateCurvatures {
25 SmartPointer<Domain<T, D>> levelSet = nullptr;
26 T maxValue = 0.5;
28
29public:
30 static constexpr char meanCurvatureLabel[] = "MeanCurvatures";
31 static constexpr char gaussianCurvatureLabel[] = "GaussianCurvatures";
32
34
35 CalculateCurvatures(SmartPointer<Domain<T, D>> passedLevelSet)
36 : levelSet(passedLevelSet) {}
37
38 CalculateCurvatures(SmartPointer<Domain<T, D>> passedLevelSet,
39 CurvatureEnum method)
40 : levelSet(passedLevelSet), type(method) {}
41
42 void setLevelSet(SmartPointer<Domain<T, D>> passedLevelSet) {
43 levelSet = passedLevelSet;
44 }
45
47 // in 2D there is only one option so ignore
48 if constexpr (D == 3) {
49 type = passedType;
50 } else {
51 if (passedType != type) {
52 Logger::getInstance().addWarning(
53 "CalculateCurvatures: Could not set curvature type because 2D "
54 "only supports mean curvature.");
55 }
56 }
57 }
58
59 void setMaxValue(const T passedMaxValue) { maxValue = passedMaxValue; }
60
61 void apply() {
62 if (levelSet == nullptr) {
63 Logger::getInstance()
64 .addError("No level set was passed to CalculateCurvatures.")
65 .print();
66 }
67
68 // need second neighbours
69 if (unsigned minWidth = std::ceil((maxValue * 8) + 1);
70 levelSet->getLevelSetWidth() < minWidth) {
71 Logger::getInstance()
72 .addWarning("CalculateCurvatures: Level set width must be "
73 "at least " +
74 std::to_string(minWidth) + ". Expanding level set to " +
75 std::to_string(minWidth) + ".")
76 .print();
77 Expand<T, D>(levelSet, minWidth).apply();
78 }
79
80 std::vector<std::vector<T>> meanCurvaturesVector(
81 levelSet->getNumberOfSegments());
82 std::vector<std::vector<T>> gaussCurvaturesVector(
83 levelSet->getNumberOfSegments());
84
85 auto grid = levelSet->getGrid();
86 const bool calculateMean =
89 const bool calculateGauss =
92
94#pragma omp parallel num_threads(levelSet->getNumberOfSegments())
95 {
96 int p = 0;
97#ifdef _OPENMP
98 p = omp_get_thread_num();
99#endif
100
101 auto &meanCurvatures = meanCurvaturesVector[p];
102 auto &gaussCurvatures = gaussCurvaturesVector[p];
103
104 if (calculateMean) {
105 meanCurvatures.reserve(
106 levelSet->getDomain().getDomainSegment(p).getNumberOfPoints());
107 }
108 if (calculateGauss) {
109 gaussCurvatures.reserve(
110 levelSet->getDomain().getDomainSegment(p).getNumberOfPoints());
111 }
112
113 viennahrle::Index<D> const startVector =
114 (p == 0) ? grid.getMinGridPoint()
115 : levelSet->getDomain().getSegmentation()[p - 1];
116
117 viennahrle::Index<D> const endVector =
118 (p != static_cast<int>(levelSet->getNumberOfSegments() - 1))
119 ? levelSet->getDomain().getSegmentation()[p]
120 : grid.incrementIndices(grid.getMaxGridPoint());
121
122 for (viennahrle::CartesianPlaneIterator<typename Domain<T, D>::DomainType>
123 neighborIt(levelSet->getDomain(), startVector);
124 neighborIt.getIndices() < endVector; neighborIt.next()) {
125
126 auto &center = neighborIt.getCenter();
127 if (!center.isDefined()) {
128 continue;
129 } else if (std::abs(center.getValue()) > maxValue) {
130 if (calculateMean)
131 meanCurvatures.push_back(0.);
132 if (calculateGauss)
133 gaussCurvatures.push_back(0.);
134 continue;
135 }
136
137 // calculate curvatures
138 if (calculateMean) {
139 meanCurvatures.push_back(lsInternal::meanCurvature(neighborIt));
140 }
141 if (calculateGauss) {
142 gaussCurvatures.push_back(lsInternal::gaussianCurvature(neighborIt));
143 }
144 }
145 }
146
147 // put all curvature values in the correct ordering
148 if (calculateMean) {
149 unsigned numberOfCurvatures = 0;
150 for (unsigned i = 0; i < levelSet->getNumberOfSegments(); ++i) {
151 numberOfCurvatures += meanCurvaturesVector[i].size();
152 }
153 meanCurvaturesVector[0].reserve(numberOfCurvatures);
154
155 for (unsigned i = 1; i < levelSet->getNumberOfSegments(); ++i) {
156 meanCurvaturesVector[0].insert(meanCurvaturesVector[0].end(),
157 meanCurvaturesVector[i].begin(),
158 meanCurvaturesVector[i].end());
159 }
160 }
161
162 if (calculateGauss) {
163 unsigned numberOfCurvatures = 0;
164 for (unsigned i = 0; i < levelSet->getNumberOfSegments(); ++i) {
165 numberOfCurvatures += gaussCurvaturesVector[i].size();
166 }
167 gaussCurvaturesVector[0].reserve(numberOfCurvatures);
168
169 for (unsigned i = 1; i < levelSet->getNumberOfSegments(); ++i) {
170 gaussCurvaturesVector[0].insert(gaussCurvaturesVector[0].end(),
171 gaussCurvaturesVector[i].begin(),
172 gaussCurvaturesVector[i].end());
173 }
174 }
175
176 // insert into pointData of levelSet
177 if (calculateMean) {
178 auto &pointData = levelSet->getPointData();
179 auto scalarDataPointer =
180 pointData.getScalarData(meanCurvatureLabel, true);
181 // if it does not exist, insert new normals vector
182 if (scalarDataPointer == nullptr) {
183 pointData.insertNextScalarData(meanCurvaturesVector[0],
185 } else {
186 // if it does exist, just swap the old with the new values
187 *scalarDataPointer = std::move(meanCurvaturesVector[0]);
188 }
189 }
190
191 if (calculateGauss) {
192 auto &pointData = levelSet->getPointData();
193 auto scalarDataPointer =
194 pointData.getScalarData(gaussianCurvatureLabel, true);
195 // if it does not exist, insert new normals vector
196 if (scalarDataPointer == nullptr) {
197 pointData.insertNextScalarData(gaussCurvaturesVector[0],
199 } else {
200 // if it does exist, just swap the old with the new values
201 *scalarDataPointer = std::move(gaussCurvaturesVector[0]);
202 }
203 }
204 }
205};
206
207} // namespace viennals
constexpr int D
Definition Epitaxy.cpp:9
double T
Definition Epitaxy.cpp:10
void setCurvatureType(CurvatureEnum passedType)
Definition lsCalculateCurvatures.hpp:46
void setMaxValue(const T passedMaxValue)
Definition lsCalculateCurvatures.hpp:59
static constexpr char meanCurvatureLabel[]
Definition lsCalculateCurvatures.hpp:30
CalculateCurvatures(SmartPointer< Domain< T, D > > passedLevelSet, CurvatureEnum method)
Definition lsCalculateCurvatures.hpp:38
void apply()
Definition lsCalculateCurvatures.hpp:61
static constexpr char gaussianCurvatureLabel[]
Definition lsCalculateCurvatures.hpp:31
CalculateCurvatures(SmartPointer< Domain< T, D > > passedLevelSet)
Definition lsCalculateCurvatures.hpp:35
void setLevelSet(SmartPointer< Domain< T, D > > passedLevelSet)
Definition lsCalculateCurvatures.hpp:42
Class containing all information about the level set, including the dimensions of the domain,...
Definition lsDomain.hpp:27
viennahrle::Domain< T, D > DomainType
Definition lsDomain.hpp:32
Expands the levelSet to the specified number of layers. The largest value in the levelset is thus wid...
Definition lsExpand.hpp:17
void apply()
Apply the expansion to the specified width.
Definition lsExpand.hpp:44
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
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
Definition lsAdvect.hpp:36
CurvatureEnum
Definition lsCalculateCurvatures.hpp:15
@ GAUSSIAN_CURVATURE
Definition lsCalculateCurvatures.hpp:17
@ MEAN_AND_GAUSSIAN_CURVATURE
Definition lsCalculateCurvatures.hpp:18
@ MEAN_CURVATURE
Definition lsCalculateCurvatures.hpp:16