41 SmartPointer<Domain<T, D>> levelSet =
nullptr;
47 static constexpr T DEFAULT_MAX_VALUE = 0.5;
48 static constexpr T EPSILON = 1e-12;
49 static constexpr T FINITE_DIFF_FACTOR = 0.5;
57 T passedMaxValue = DEFAULT_MAX_VALUE,
60 : levelSet(passedLevelSet), maxValue(passedMaxValue),
61 method(passedMethod) {}
64 levelSet = passedLevelSet;
68 if (passedMaxValue <= 0) {
69 VIENNACORE_LOG_WARNING(
70 "CalculateNormalVectors: maxValue should be positive. "
71 "Using default value " +
72 std::to_string(DEFAULT_MAX_VALUE) +
".");
73 maxValue = DEFAULT_MAX_VALUE;
75 maxValue = passedMaxValue;
80 method = passedMethod;
83 SmartPointer<Domain<T, D>>
getLevelSet()
const {
return levelSet; }
89 if (levelSet ==
nullptr)
91 auto &pointData = levelSet->getPointData();
96 if (levelSet ==
nullptr) {
98 "No level set was passed to CalculateNormalVectors.");
104 calculateCentralDifferences();
107 calculateOneSidedMinMod();
113 void calculateCentralDifferences() {
114 if (levelSet->getLevelSetWidth() < (maxValue * 4) + 1) {
115 VIENNACORE_LOG_WARNING(
"CalculateNormalVectors: Level set width must be "
117 std::to_string((maxValue * 4) + 1) +
118 ". Expanding level set to " +
119 std::to_string((maxValue * 4) + 1) +
".");
123 std::vector<std::vector<Vec3D<T>>> normalVectorsVector(
124 levelSet->getNumberOfSegments());
127 double pointsPerSegment =
128 double(2 * levelSet->getDomain().getNumberOfPoints()) /
129 double(levelSet->getLevelSetWidth());
131 auto grid = levelSet->getGrid();
134#pragma omp parallel num_threads(levelSet->getNumberOfSegments())
138 p = omp_get_thread_num();
141 auto &normalVectors = normalVectorsVector[p];
142 normalVectors.reserve(pointsPerSegment);
144 viennahrle::Index<D>
const startVector =
145 (p == 0) ? grid.getMinGridPoint()
146 : levelSet->getDomain().getSegmentation()[p - 1];
148 viennahrle::Index<D>
const endVector =
149 (p !=
static_cast<int>(levelSet->getNumberOfSegments() - 1))
150 ? levelSet->getDomain().getSegmentation()[p]
151 : grid.incrementIndices(grid.getMaxGridPoint());
153 for (viennahrle::ConstSparseStarIterator<
155 neighborIt(levelSet->getDomain(), startVector);
156 neighborIt.getIndices() < endVector; neighborIt.next()) {
158 auto ¢er = neighborIt.getCenter();
159 if (!center.isDefined()) {
161 }
else if (std::abs(center.getValue()) > maxValue) {
164 normalVectors.push_back(tmp);
171 for (
int i = 0; i <
D; i++) {
172 viennahrle::Index<D> posIdx(0);
174 viennahrle::Index<D> negIdx(0);
176 T pos = neighborIt.getNeighbor(posIdx).getValue() - center.getValue();
177 T neg = center.getValue() - neighborIt.getNeighbor(negIdx).getValue();
178 n[i] = (pos + neg) * FINITE_DIFF_FACTOR;
179 denominator += n[i] * n[i];
182 denominator = std::sqrt(denominator);
183 if (std::abs(denominator) < EPSILON) {
184 VIENNACORE_LOG_WARNING(
185 "CalculateNormalVectors: Vector of length 0 at " +
186 neighborIt.getIndices().to_string());
187 for (
unsigned i = 0; i <
D; ++i)
190 for (
unsigned i = 0; i <
D; ++i) {
195 normalVectors.push_back(n);
198 insertIntoPointData(normalVectorsVector);
201 void calculateOneSidedMinMod() {
204 auto &domain = levelSet->getDomain();
205 auto &grid = levelSet->getGrid();
210 std::vector<Vec3D<T>> normalVectors(levelSet->getNumberOfPoints());
212#pragma omp parallel num_threads(levelSet->getNumberOfSegments())
216 p = omp_get_thread_num();
219 viennahrle::Index<D> startVector =
220 (p == 0) ? grid.getMinGridPoint()
221 : levelSet->getDomain().getSegmentation()[p - 1];
222 viennahrle::Index<D> endVector =
223 (p !=
static_cast<int>(levelSet->getNumberOfSegments() - 1))
224 ? levelSet->getDomain().getSegmentation()[p]
225 : grid.incrementIndices(grid.getMaxGridPoint());
227 viennahrle::SparseStarIterator<typename Domain<T, D>::DomainType, 1>
228 neighborIt(domain, startVector);
230 for (; neighborIt.getIndices() < endVector; neighborIt.next()) {
231 if (neighborIt.getCenter().isDefined()) {
233 for (
int i = 0; i <
D; ++i) {
234 viennahrle::Index<D> posIdx(0);
236 viennahrle::Index<D> negIdx(0);
238 bool negDefined = neighborIt.getNeighbor(negIdx).isDefined();
239 bool posDefined = neighborIt.getNeighbor(posIdx).isDefined();
241 if (negDefined && posDefined) {
242 T valNeg = neighborIt.getNeighbor(negIdx).getValue();
243 T valCenter = neighborIt.getCenter().getValue();
244 T valPos = neighborIt.getNeighbor(posIdx).getValue();
246 const bool centerSign = valCenter >= 0;
247 const bool negSign = valNeg > 0;
248 const bool posSign = valPos > 0;
250 const T d_neg = valCenter - valNeg;
251 const T d_pos = valPos - valCenter;
253 if (centerSign != negSign && centerSign != posSign) {
257 }
else if (centerSign != negSign) {
260 }
else if (centerSign != posSign) {
265 grad[i] = (std::abs(d_pos) < std::abs(d_neg)) ? d_pos : d_neg;
267 }
else if (negDefined) {
268 grad[i] = (neighborIt.getCenter().getValue() -
269 neighborIt.getNeighbor(negIdx).getValue());
270 }
else if (posDefined) {
271 grad[i] = (neighborIt.getNeighbor(posIdx).getValue() -
272 neighborIt.getCenter().getValue());
278 normalVectors[neighborIt.getCenter().getPointId()] = grad;
284 auto &pointData = levelSet->getPointData();
287 if (vectorDataPointer ==
nullptr) {
291 *vectorDataPointer = std::move(normalVectors);
296 insertIntoPointData(std::vector<std::vector<Vec3D<T>>> &normalVectorsVector) {
298 unsigned numberOfNormals = 0;
299 for (
unsigned i = 0; i < levelSet->getNumberOfSegments(); ++i) {
300 numberOfNormals += normalVectorsVector[i].size();
302 normalVectorsVector[0].reserve(numberOfNormals);
304 for (
unsigned i = 1; i < levelSet->getNumberOfSegments(); ++i) {
305 normalVectorsVector[0].insert(normalVectorsVector[0].end(),
306 normalVectorsVector[i].begin(),
307 normalVectorsVector[i].end());
311 auto &pointData = levelSet->getPointData();
314 if (vectorDataPointer ==
nullptr) {
315 pointData.insertNextVectorData(normalVectorsVector[0],
319 *vectorDataPointer = std::move(normalVectorsVector[0]);
Class containing all information about the level set, including the dimensions of the domain,...
Definition lsDomain.hpp:28
viennahrle::Domain< T, D > DomainType
Definition lsDomain.hpp:33