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 for
135 for (
unsigned p = 0; p < levelSet->getNumberOfSegments(); ++p) {
137 auto &normalVectors = normalVectorsVector[p];
138 normalVectors.reserve(pointsPerSegment);
140 viennahrle::Index<D>
const startVector =
141 (p == 0) ? grid.getMinGridPoint()
142 : levelSet->getDomain().getSegmentation()[p - 1];
144 viennahrle::Index<D>
const endVector =
145 (p !=
static_cast<int>(levelSet->getNumberOfSegments() - 1))
146 ? levelSet->getDomain().getSegmentation()[p]
147 : grid.incrementIndices(grid.getMaxGridPoint());
149 for (viennahrle::ConstSparseStarIterator<
151 neighborIt(levelSet->getDomain(), startVector);
152 neighborIt.getIndices() < endVector; neighborIt.next()) {
154 auto ¢er = neighborIt.getCenter();
155 if (!center.isDefined()) {
157 }
else if (std::abs(center.getValue()) > maxValue) {
160 normalVectors.push_back(tmp);
167 for (
int i = 0; i <
D; i++) {
168 viennahrle::Index<D> posIdx(0);
170 viennahrle::Index<D> negIdx(0);
172 T pos = neighborIt.getNeighbor(posIdx).getValue() - center.getValue();
173 T neg = center.getValue() - neighborIt.getNeighbor(negIdx).getValue();
174 n[i] = (pos + neg) * FINITE_DIFF_FACTOR;
175 denominator += n[i] * n[i];
178 denominator = std::sqrt(denominator);
179 if (std::abs(denominator) < EPSILON) {
180 VIENNACORE_LOG_WARNING(
181 "CalculateNormalVectors: Vector of length 0 at " +
182 neighborIt.getIndices().to_string());
183 for (
unsigned i = 0; i <
D; ++i)
186 for (
unsigned i = 0; i <
D; ++i) {
191 normalVectors.push_back(n);
194 insertIntoPointData(normalVectorsVector);
197 void calculateOneSidedMinMod() {
200 auto &domain = levelSet->getDomain();
201 auto &grid = levelSet->getGrid();
206 std::vector<Vec3D<T>> normalVectors(levelSet->getNumberOfPoints());
208#pragma omp parallel for
209 for (
unsigned p = 0; p < levelSet->getNumberOfSegments(); ++p) {
211 viennahrle::Index<D> startVector =
212 (p == 0) ? grid.getMinGridPoint()
213 : levelSet->getDomain().getSegmentation()[p - 1];
214 viennahrle::Index<D> endVector =
215 (p !=
static_cast<int>(levelSet->getNumberOfSegments() - 1))
216 ? levelSet->getDomain().getSegmentation()[p]
217 : grid.incrementIndices(grid.getMaxGridPoint());
219 viennahrle::SparseStarIterator<typename Domain<T, D>::DomainType, 1>
220 neighborIt(domain, startVector);
222 for (; neighborIt.getIndices() < endVector; neighborIt.next()) {
223 if (neighborIt.getCenter().isDefined()) {
225 for (
int i = 0; i <
D; ++i) {
226 viennahrle::Index<D> posIdx(0);
228 viennahrle::Index<D> negIdx(0);
230 bool negDefined = neighborIt.getNeighbor(negIdx).isDefined();
231 bool posDefined = neighborIt.getNeighbor(posIdx).isDefined();
233 if (negDefined && posDefined) {
234 T valNeg = neighborIt.getNeighbor(negIdx).getValue();
235 T valCenter = neighborIt.getCenter().getValue();
236 T valPos = neighborIt.getNeighbor(posIdx).getValue();
238 const bool centerSign = valCenter >= 0;
239 const bool negSign = valNeg > 0;
240 const bool posSign = valPos > 0;
242 const T d_neg = valCenter - valNeg;
243 const T d_pos = valPos - valCenter;
245 if (centerSign != negSign && centerSign != posSign) {
249 }
else if (centerSign != negSign) {
252 }
else if (centerSign != posSign) {
257 grad[i] = (std::abs(d_pos) < std::abs(d_neg)) ? d_pos : d_neg;
259 }
else if (negDefined) {
260 grad[i] = (neighborIt.getCenter().getValue() -
261 neighborIt.getNeighbor(negIdx).getValue());
262 }
else if (posDefined) {
263 grad[i] = (neighborIt.getNeighbor(posIdx).getValue() -
264 neighborIt.getCenter().getValue());
270 normalVectors[neighborIt.getCenter().getPointId()] = grad;
276 auto &pointData = levelSet->getPointData();
279 if (vectorDataPointer ==
nullptr) {
283 *vectorDataPointer = std::move(normalVectors);
288 insertIntoPointData(std::vector<std::vector<Vec3D<T>>> &normalVectorsVector) {
290 unsigned numberOfNormals = 0;
291 for (
unsigned i = 0; i < levelSet->getNumberOfSegments(); ++i) {
292 numberOfNormals += normalVectorsVector[i].size();
294 normalVectorsVector[0].reserve(numberOfNormals);
296 for (
unsigned i = 1; i < levelSet->getNumberOfSegments(); ++i) {
297 normalVectorsVector[0].insert(normalVectorsVector[0].end(),
298 normalVectorsVector[i].begin(),
299 normalVectorsVector[i].end());
303 auto &pointData = levelSet->getPointData();
306 if (vectorDataPointer ==
nullptr) {
307 pointData.insertNextVectorData(normalVectorsVector[0],
311 *vectorDataPointer = std::move(normalVectorsVector[0]);
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