TTK
Loading...
Searching...
No Matches
SignedDistanceField.h
Go to the documentation of this file.
1
36
37#pragma once
38#include <iostream>
39
40// base code includes
42#include <DataTypes.h>
43#include <Debug.h>
44#include <Geometry.h>
46#include <Triangulation.h>
47#include <VisitedMask.h>
48#include <queue>
49
50namespace ttk {
51
52 class SignedDistanceField : virtual public Debug {
53 public:
55
56 template <typename triangulationType, typename triangulationType2>
57 int execute(float *const outputScalars,
58 triangulationType *const triangulation,
59 triangulationType2 *const boundingTriangulation,
60 int *const edgeCrossing,
61 int *const isInterior) const;
62
63 inline int
65 if(triangulation) {
66 triangulation->preconditionVertexEdges();
67 triangulation->preconditionVertexStars();
68 }
69 return 0;
70 }
71
72 protected:
73 template <typename triangulationType>
74 void findOutsideVertices(const SimplexId vertexId,
75 triangulationType *const boundingTriangulation,
76 const std::vector<bool> &vertexIntersection,
77 int *const isInterior) const;
78
79 inline int
80 getNeighbor(unsigned int vertexId, unsigned int dim, int dir) const {
81 unsigned int res[3] = {xResolution_, yResolution_, zResolution_};
82 unsigned int coord[3]
83 = {vertexId % res[0], (vertexId % (res[0] * res[1])) / res[0],
84 vertexId / (res[0] * res[1])};
85
86 if(not(static_cast<int>(coord[dim]) + dir >= 0
87 and coord[dim] + dir < res[dim]))
88 return -1;
89 coord[dim] += dir;
90
91 return coord[0] + coord[1] * res[0] + coord[2] * res[0] * res[1];
92 }
93
95
96 template <typename dataType>
97 void fastMarching(std::vector<bool> &vertexIntersection,
98 dataType *const distances,
99 int *const isInterior) const;
100
101 template <typename dataType>
102 void fastMarchingIterativeNode(std::vector<VertexMarchingType> &vertexType,
103 dataType *const distances,
104 int *const isInterior) const;
105
106 template <typename dataType>
107 void fastMarchingIterativeBand(std::vector<VertexMarchingType> &vertexType,
108 dataType *const distances,
109 int *const isInterior) const;
110
111 template <typename dataType>
113 unsigned int vertexId,
114 dataType *const distances,
115 int *const isInterior,
116 std::vector<VertexMarchingType> &vertexType) const;
117
118 template <typename dataType>
120 unsigned int vertexId,
121 dataType *const distances,
122 int *const isInterior,
123 std::vector<VertexMarchingType> &vertexType) const;
124
125 template <typename dataType>
127 unsigned int vertexId,
128 dataType *const distances,
129 int *const isInterior,
130 std::vector<VertexMarchingType> &vertexType) const;
131
132 template <typename dataType>
133 bool fastMarchingSolveQuadratic(unsigned int vertexId,
134 dataType a,
135 dataType b,
136 dataType c,
137 int *const isInterior,
138 dataType &out) const;
139
140 unsigned int xResolution_{1}, yResolution_{1}, zResolution_{1};
141 std::array<double, 3> spacing_{1.0, 1.0, 1.0};
142 std::array<double, 3> invSpacingSquared_{1.0, 1.0, 1.0};
143 bool expandBox_ = true;
144 int backend_ = 0;
146 };
147
148} // namespace ttk
149
150template <typename dataType>
152 std::vector<bool> &vertexIntersection,
153 dataType *const distances,
154 int *const isInterior) const {
155 std::vector<VertexMarchingType> vertexType(
156 vertexIntersection.size(), VertexMarchingType::FAR);
157 for(unsigned int i = 0; i < vertexIntersection.size(); ++i)
158 if(vertexIntersection[i])
159 vertexType[i] = VertexMarchingType::FROZEN;
160
161#ifdef TTK_ENABLE_OPENMP
162#pragma omp parallel for num_threads(threadNumber_) schedule(dynamic)
163#endif
164 for(unsigned int i = 0; i < vertexType.size(); ++i) {
165 // Compute narrow band
166 if(vertexType[i] == VertexMarchingType::FAR) {
167 for(int dim = 0; dim < 3; ++dim) {
168 // each direction
169 for(int j = -1; j < 2; j += 2) {
170 int neighborId = getNeighbor(i, dim, j);
171 if(neighborId != -1
172 and vertexType[neighborId] == VertexMarchingType::FROZEN
173 and vertexType[i] == VertexMarchingType::FAR) {
174 vertexType[i] = VertexMarchingType::NARROW;
175 distances[i]
176 = fastMarchingUpdatePoint(i, distances, isInterior, vertexType);
177 }
178 }
179 }
180 }
181 }
182
183 if(backend_ == 2)
184 fastMarchingIterativeBand(vertexType, distances, isInterior);
185 else
186 fastMarchingIterativeNode(vertexType, distances, isInterior);
187}
188
189template <typename dataType>
191 std::vector<VertexMarchingType> &vertexType,
192 dataType *const distances,
193 int *const isInterior) const {
194 printMsg("Fast Marching");
195 auto abs = [](auto arg) {
196 using T = decltype(arg);
197 if constexpr(std::is_unsigned<T>::value) {
198 // If T is an unsigned type, simply return the argument
199 return arg;
200 } else {
201 // If T is not an unsigned type, return std::abs(arg)
202 return std::abs(arg);
203 }
204 };
205 struct Compare {
206 constexpr bool
207 operator()(std::pair<int, dataType> const &a,
208 std::pair<int, dataType> const &b) const noexcept {
209 return a.second > b.second;
210 }
211 };
212 std::priority_queue<std::pair<int, dataType>,
213 std::vector<std::pair<int, dataType>>, Compare>
214 heap;
215 for(unsigned int i = 0; i < vertexType.size(); ++i)
216 if(vertexType[i] == VertexMarchingType::NARROW)
217 heap.push(std::make_pair(i, abs(distances[i])));
218 std::vector<int> toFreeze;
219
220 while(!heap.empty()) {
221 toFreeze.clear();
222 std::pair<int, dataType> pair = heap.top();
223 auto vertexId = std::get<0>(pair);
224 auto value = std::get<1>(pair);
225 heap.pop();
226 if(not(value <= abs(distances[vertexId]) + 1e-6
227 and value >= abs(distances[vertexId]) - 1e-6))
228 continue;
229
230 vertexType[vertexId] = VertexMarchingType::FROZEN;
231 toFreeze.emplace_back(vertexId);
232
233 bool done = false;
234 while(!done) {
235 if(!heap.empty()) {
236 std::pair<int, dataType> l_pair = heap.top();
237 auto l_vertexId = std::get<0>(l_pair);
238 auto l_value = std::get<1>(l_pair);
239 if(value <= l_value + 1e-6 and value >= l_value - 1e-6) {
240 heap.pop();
241 vertexType[l_vertexId] = VertexMarchingType::FROZEN;
242 toFreeze.emplace_back(l_vertexId);
243 } else
244 done = true;
245 } else
246 done = true;
247 }
248
249 for(unsigned int k = 0; k < toFreeze.size(); ++k) {
250 int id = toFreeze[k];
251
252 for(unsigned int dim = 0; dim < 3; ++dim) {
253 // each direction
254 for(int j = -1; j < 2; j += 2) {
255 int neighborId = getNeighbor(id, dim, j);
256 if(neighborId != -1
257 and vertexType[neighborId] != VertexMarchingType::FROZEN
258 and (vertexType[neighborId] == VertexMarchingType::NARROW
259 or vertexType[neighborId] == VertexMarchingType::FAR)) {
260 dataType d = fastMarchingUpdatePoint(
261 neighborId, distances, isInterior, vertexType);
262 if(d) {
263 distances[neighborId] = d;
264 heap.push(std::make_pair(neighborId, abs(d)));
265 if(vertexType[neighborId] == VertexMarchingType::FAR)
266 vertexType[neighborId] = VertexMarchingType::NARROW;
267 } else
268 printWrn("not d");
269 }
270 // update the far point in the second order stencil
271 // "jump" over a Frozen point if needed
272 if(fastMarchingOrder_ == 2) {
273 if(neighborId != -1
274 and vertexType[neighborId] == VertexMarchingType::FROZEN) {
275 int neighbor2Id = getNeighbor(id, dim, j * 2);
276 if(neighbor2Id != -1
277 and vertexType[neighbor2Id] == VertexMarchingType::NARROW) {
278 dataType d = fastMarchingUpdatePointOrderTwo(
279 neighbor2Id, distances, isInterior, vertexType);
280 if(d) {
281 heap.push(std::make_pair(neighbor2Id, abs(d)));
282 distances[neighbor2Id] = d;
283 }
284 }
285 }
286 }
287 } // for each direction
288 } // for each dimension
289 }
290 } // main loop of Fast Marching Method
291}
292
293template <typename dataType>
295 std::vector<VertexMarchingType> &vertexType,
296 dataType *const distances,
297 int *const isInterior) const {
298 printMsg("Fast Marching Band");
299 std::vector<int> toProcess;
300 for(unsigned int i = 0; i < vertexType.size(); ++i)
301 if(vertexType[i] == VertexMarchingType::NARROW)
302 toProcess.emplace_back(i);
303
304 while(!toProcess.empty()) {
305#ifdef TTK_ENABLE_OPENMP
306#pragma omp parallel for num_threads(threadNumber_)
307#endif
308 for(unsigned int i = 0; i < toProcess.size(); ++i) {
309 auto vertexId = toProcess[i];
310 vertexType[vertexId] = VertexMarchingType::FROZEN;
311
312 for(unsigned int dim = 0; dim < 3; ++dim) {
313 for(int j = -1; j < 2; j += 2) {
314 int neighborId = getNeighbor(vertexId, dim, j);
315 if(neighborId != -1
316 and vertexType[neighborId] == VertexMarchingType::FAR)
317#pragma omp atomic write
318 vertexType[neighborId] = VertexMarchingType::NARROW;
319 }
320 }
321 }
322#ifdef TTK_ENABLE_OPENMP
323#pragma omp parallel for num_threads(threadNumber_) schedule(dynamic)
324#endif
325 for(unsigned int i = 0; i < toProcess.size(); ++i)
326 if(vertexType[i] == VertexMarchingType::NARROW)
327 distances[i]
328 = fastMarchingUpdatePoint(i, distances, isInterior, vertexType);
329 toProcess.clear();
330 for(unsigned int i = 0; i < vertexType.size(); ++i)
331 if(vertexType[i] == VertexMarchingType::NARROW)
332 toProcess.emplace_back(i);
333 }
334}
335
336template <typename dataType>
338 unsigned int vertexId,
339 dataType *const distances,
340 int *const isInterior,
341 std::vector<VertexMarchingType> &vertexType) const {
342 dataType d;
343 if(fastMarchingOrder_ == 2)
344 d = fastMarchingUpdatePointOrderTwo(
345 vertexId, distances, isInterior, vertexType);
346 else
347 d = fastMarchingUpdatePointOrderOne(
348 vertexId, distances, isInterior, vertexType);
349 return d;
350}
351
352template <typename dataType>
354 unsigned int vertexId,
355 dataType *const distances,
356 int *const isInterior,
357 std::vector<VertexMarchingType> &vertexType) const {
358 const dataType aa = 9.0 / 4.0;
359 const dataType oneThird = 1.0 / 3.0;
360 dataType a, b, c;
361 a = b = c = 0;
362 for(int dim = 0; dim < 3; dim++) {
363 dataType value1 = std::numeric_limits<dataType>::max();
364 dataType value2 = std::numeric_limits<dataType>::max();
365 bool found1 = false, found2 = false;
366 // each direction
367 for(int j = -1; j < 2; j += 2) {
368 int neighborId = getNeighbor(vertexId, dim, j);
369 if(neighborId != -1
370 and vertexType[neighborId] == VertexMarchingType::FROZEN
371 and std::abs((double)distances[neighborId])
372 < std::abs((double)value1)) {
373 value1 = distances[neighborId];
374 found1 = true;
375 int neighbor2Id = getNeighbor(vertexId, dim, j * 2);
376 if(neighbor2Id != -1
377 and vertexType[neighbor2Id] == VertexMarchingType::FROZEN
378 and ((distances[neighbor2Id] <= value1 && value1 >= 0)
379 || (distances[neighbor2Id] >= value1 && value1 <= 0))) {
380 value2 = distances[neighbor2Id];
381 found2 = true;
382 }
383 }
384 }
385 if(found2) {
386 dataType tp = oneThird * (4 * value1 - value2);
387 a += invSpacingSquared_[dim] * aa;
388 b -= invSpacingSquared_[dim] * 2 * aa * tp;
389 c += invSpacingSquared_[dim] * aa * pow(tp, 2);
390 } else if(found1) {
391 a += invSpacingSquared_[dim];
392 b -= invSpacingSquared_[dim] * 2 * value1;
393 c += invSpacingSquared_[dim] * pow(value1, 2);
394 }
395 }
396 dataType out;
397 if(not fastMarchingSolveQuadratic(vertexId, a, b, c, isInterior, out)) {
398 // if the second order method fails, try the first order method instead
399 return fastMarchingUpdatePointOrderOne(
400 vertexId, distances, isInterior, vertexType);
401 }
402 return out;
403}
404
405template <typename dataType>
407 unsigned int vertexId,
408 dataType *const distances,
409 int *const isInterior,
410 std::vector<VertexMarchingType> &vertexType) const {
411 dataType a, b, c;
412 a = b = c = 0;
413 for(unsigned int dim = 0; dim < 3; ++dim) {
414 dataType value = std::numeric_limits<dataType>::max();
415 bool found = false;
416 // each direction
417 for(int j = -1; j < 2; j += 2) {
418 int neighborId = getNeighbor(vertexId, dim, j);
419 if(neighborId != -1
420 and vertexType[neighborId] == VertexMarchingType::FROZEN
421 and std::abs((double)distances[neighborId])
422 < std::abs((double)value)) {
423 value = distances[neighborId];
424 found = true;
425 }
426 }
427 if(found) {
428 a += invSpacingSquared_[dim];
429 b -= invSpacingSquared_[dim] * 2 * value;
430 c += invSpacingSquared_[dim] * pow(value, 2);
431 }
432 }
433 dataType out;
434 if(not fastMarchingSolveQuadratic(vertexId, a, b, c, isInterior, out)) {
435 // if the quadratic equation can't be solved, use the
436 // position of the minimum as a more reasonable approximation
437 return -b / (2.0 * a);
438 }
439 return out;
440}
441
442template <typename dataType>
444 dataType a,
445 dataType b,
446 dataType c,
447 int *const isInterior,
448 dataType &out) const {
449 c -= 1;
450 dataType det = pow(b, 2) - 4 * a * c;
451 if(det >= 0) {
452 if(isInterior[vertexId] == 0) {
453 out = (-b + sqrt(det)) / 2.0 / a;
454 } else {
455 out = (-b - sqrt(det)) / 2.0 / a;
456 }
457 return true;
458 }
459 return false;
460}
461
462template <typename triangulationType>
464 const SimplexId startVertexId,
465 triangulationType *const boundingTriangulation,
466 const std::vector<bool> &vertexIntersection,
467 int *const isInterior) const {
468 std::stack<SimplexId> vertexStack;
469 std::vector<bool> outsideVertexSelected(
470 boundingTriangulation->getNumberOfVertices(), false);
471
472 vertexStack.push(startVertexId);
473 outsideVertexSelected[startVertexId] = true;
474 isInterior[startVertexId] = 0;
475
476 int cpt = 1;
477 while(!vertexStack.empty()) {
478 SimplexId vertexId = vertexStack.top();
479 vertexStack.pop();
480
481 if(vertexIntersection[vertexId])
482 continue;
483
484 std::vector<SimplexId> neighbors;
485 for(unsigned int dim = 0; dim < 3; ++dim) {
486 for(int j = -1; j < 2; j += 2) {
487 int neighborId = getNeighbor(vertexId, dim, j);
488 if(neighborId != -1)
489 neighbors.emplace_back(neighborId);
490 }
491 }
492 for(const auto &neighborId : neighbors) {
493 if(not outsideVertexSelected[neighborId]
494 and not vertexIntersection[vertexId]) {
495 vertexStack.push(neighborId);
496 outsideVertexSelected[neighborId] = true;
497 isInterior[neighborId] = 0;
498 cpt++;
499 }
500 }
501 }
502 std::stringstream ss;
503 ss << "Number of outside vertices = " << cpt;
504 printMsg(ss.str());
505}
506
507template <typename triangulationType, typename triangulationType2>
509 float *const outputScalars,
510 triangulationType *const triangulation,
511 triangulationType2 *const boundingTriangulation,
512 int *const edgeCrossing,
513 int *const isInterior) const {
514
515 Timer t;
516
517 auto noVertices = boundingTriangulation->getNumberOfVertices();
518#ifdef TTK_ENABLE_OPENMP
519#pragma omp parallel for num_threads(threadNumber_)
520#endif
521 for(int i = 0; i < noVertices; i++) {
522 isInterior[i] = 1;
523 edgeCrossing[i] = 0;
524 }
525
526 // ======================================================
527 // === BVH
528 // ======================================================
529 Timer t_bvh;
530 SimplexId vertexNumber = triangulation->getNumberOfVertices();
531 std::vector<float> bvhCoordinates(3 * vertexNumber);
532#ifdef TTK_ENABLE_OPENMP
533#pragma omp parallel for num_threads(threadNumber_)
534#endif
535 for(int vertexId = 0; vertexId < vertexNumber; vertexId++) {
536 float x = 0, y = 0, z = 0;
537 triangulation->getVertexPoint(vertexId, x, y, z);
538 bvhCoordinates[vertexId * 3 + 0] = x;
539 bvhCoordinates[vertexId * 3 + 1] = y;
540 bvhCoordinates[vertexId * 3 + 2] = z;
541 }
542
543 SimplexId triangleNumber = triangulation->getNumberOfTriangles();
544 std::vector<SimplexId> bvhConnectivityList(triangleNumber * 3);
545#ifdef TTK_ENABLE_OPENMP
546#pragma omp parallel for num_threads(threadNumber_)
547#endif
548 for(int triangleId = 0; triangleId < triangleNumber; triangleId++) {
549 SimplexId vertexTriangleIdA;
550 triangulation->getTriangleVertex(triangleId, 0, vertexTriangleIdA);
551 SimplexId vertexTriangleIdB;
552 triangulation->getTriangleVertex(triangleId, 1, vertexTriangleIdB);
553 SimplexId vertexTriangleIdC;
554 triangulation->getTriangleVertex(triangleId, 2, vertexTriangleIdC);
555 bvhConnectivityList[triangleId * 3 + 0] = vertexTriangleIdA;
556 bvhConnectivityList[triangleId * 3 + 1] = vertexTriangleIdB;
557 bvhConnectivityList[triangleId * 3 + 2] = vertexTriangleIdC;
558 }
559 BoundingVolumeHierarchy<SimplexId> bvh(bvhCoordinates.data(),
560 bvhConnectivityList.data(),
561 static_cast<size_t>(triangleNumber));
562 this->printMsg("Build BVH", 1.0, t_bvh.getElapsedTime(), this->threadNumber_);
563
564 // ===================================
565 // === Find Segments Intersecting Triangles
566 // ===================================
567 Timer t_intersect;
568
569 std::vector<bool> vertexIntersection(noVertices, false);
570 std::vector<std::vector<unsigned int>> verticesIntersected;
571
572 unsigned int noOrigins = yResolution_ * zResolution_
573 + xResolution_ * zResolution_
574 + xResolution_ * yResolution_;
575 verticesIntersected.resize(noOrigins);
576#ifdef TTK_ENABLE_OPENMP
577#pragma omp parallel for num_threads(threadNumber_) schedule(dynamic)
578#endif
579 for(unsigned int i = 0; i < noOrigins; ++i) {
580 // Get origin vertex id
581 int vertexId, dirDimension;
582 if(i < yResolution_ * zResolution_) {
583 // O_x = {a * r_x | a in N / r_y r_z N}
584 vertexId = i * xResolution_;
585 dirDimension = 0;
586 } else if(i < yResolution_ * zResolution_ + xResolution_ * zResolution_) {
587 // O_y = {a * r_x * r_y + b | a in N / r_z N, b in N / r_x N}
588 unsigned int ind = i - yResolution_ * zResolution_;
589 vertexId = (int)(ind / xResolution_) * xResolution_ * yResolution_
590 + ind % xResolution_;
591 dirDimension = 1;
592 } else {
593 // O_z = {a | a in N / r_x r_y N}
594 vertexId
595 = i - (yResolution_ * zResolution_ + xResolution_ * zResolution_);
596 dirDimension = 2;
597 }
598
599 // Use BVH to find triangles on this ray direction
600 float ray_origin[3];
601 boundingTriangulation->getVertexPoint(
602 vertexId, ray_origin[0], ray_origin[1], ray_origin[2]);
603
604 if(not expandBox_) {
605 int dirToShift[3] = {0, 0, 0};
606 int shiftCounter = 0;
607 for(int dim = 0; dim < 3; ++dim) {
608 for(int j = -1; j < 2; j += 2) {
609 int neighborId = getNeighbor(vertexId, dim, j);
610 if(neighborId == -1) {
611 dirToShift[dim] = j * -1;
612 ++shiftCounter;
613 }
614 }
615 }
616 if(shiftCounter >= 2) {
617 for(int dim = 0; dim < 3; ++dim) {
618 if(dim == dirDimension)
619 continue;
620 ray_origin[dim] += dirToShift[dim] * 1e-3 * spacing_[dim];
621 }
622 }
623 }
624
625 float ray_dir[3] = {0, 0, 0};
626 ray_dir[dirDimension] = spacing_[dirDimension];
627 Ray ray(ray_dir, ray_origin);
628 std::vector<int> triangles;
629 std::vector<float> distances;
630 bool wasHit = bvh.intersect(ray, bvhConnectivityList.data(),
631 bvhCoordinates.data(), triangles, distances);
632
633 // For each edge of this ray check if it is intersecting a triangle
634 if(wasHit) {
635 unsigned int rayNoVertices
636 = (dirDimension == 0
637 ? xResolution_
638 : (dirDimension == 1 ? yResolution_ : zResolution_));
639 std::vector<unsigned int> verticesList(rayNoVertices);
640 for(unsigned int j = 0; j < verticesList.size(); ++j) {
641 if(dirDimension == 0) {
642 verticesList[j] = vertexId + j;
643 } else if(dirDimension == 1) {
644 verticesList[j] = vertexId + j * xResolution_;
645 } else {
646 verticesList[j] = vertexId + j * xResolution_ * yResolution_;
647 }
648 }
649 for(auto &distance : distances) {
650 unsigned int ind = distance;
651 if(ind + 1 >= verticesList.size())
652 --ind;
653 auto vertexIdA = verticesList[ind];
654 auto vertexIdB = verticesList[ind + 1];
655 verticesIntersected[i].emplace_back(vertexIdA);
656 verticesIntersected[i].emplace_back(vertexIdB);
657 }
658 }
659 }
660 // Can not be parallelized because some vertices can appear more than once
661 for(unsigned int i = 0; i < verticesIntersected.size(); ++i) {
662 for(auto &vertexId : verticesIntersected[i]) {
663 vertexIntersection[vertexId] = true;
664 edgeCrossing[vertexId] = 1;
665 }
666 }
667 this->printMsg("Find intersection edges", 1.0, t_intersect.getElapsedTime(),
668 this->threadNumber_);
669
670 // ===================================
671 // === Find Outside vertices
672 // ===================================
673 Timer t_outside;
674 // We search for an outside vertex
675 SimplexId outsideVertex = std::numeric_limits<SimplexId>::max();
676 for(unsigned int i = 0; i < vertexIntersection.size(); i++) {
677 if(not vertexIntersection[i]) {
678 outsideVertex = i;
679 std::stringstream ss;
680 ss << "First outside vertex found : " << outsideVertex;
681 printMsg(ss.str());
682 break;
683 }
684 }
685 findOutsideVertices(
686 outsideVertex, boundingTriangulation, vertexIntersection, isInterior);
687 this->printMsg("Find outside vertices", 1.0, t_outside.getElapsedTime(),
688 this->threadNumber_);
689
690 // ======================================================
691 // === Signed Distance Field
692 // ======================================================
693 // Find the distance between each point of the grid and the nearest point in
694 // the domain
695 Timer t_distance;
696 printMsg("Start distance computation...");
697
698 std::vector<int> verticesCrossing;
699 if(backend_ != 0) {
700 for(unsigned int i = 0; i < vertexIntersection.size(); ++i)
701 if(vertexIntersection[i])
702 verticesCrossing.emplace_back(i);
703 noVertices = verticesCrossing.size();
704 }
705
706#ifdef TTK_ENABLE_OPENMP
707#pragma omp parallel for num_threads(threadNumber_)
708#endif
709 for(int i = 0; i < noVertices; i++) {
710 auto vertexId = i;
711 if(backend_ != 0)
712 vertexId = verticesCrossing[i];
713
714 float x = 0, y = 0, z = 0;
715 boundingTriangulation->getVertexPoint(vertexId, x, y, z);
716
717 std::array<float, 3> point;
718 point[0] = x;
719 point[1] = y;
720 point[2] = z;
721
722 std::vector<float> dists(triangulation->getNumberOfVertices());
723 Geometry::ProjectionInput projectionInput{
724 static_cast<size_t>(vertexId), point,
725 Geometry::getNearestSurfaceVertex(point.data(), dists, *triangulation)};
726
727 std::vector<SimplexId> visitedTriangles{};
728 std::vector<bool> trianglesTested(
729 triangulation->getNumberOfTriangles(), false);
730
731 ttk::VisitedMask vm{trianglesTested, visitedTriangles};
732 std::vector<float> dists2(triangulation->getNumberOfVertices());
733 std::stack<ttk::SimplexId> trianglesToTest;
734 bool reverseProjection = false;
735
737 projectionInput, vm, dists2, trianglesToTest, reverseProjection,
738 *boundingTriangulation, *triangulation);
739
740 // We calculate the distance
741 std::vector<double> p0({x, y, z});
742 std::vector<double> p1(
743 {projectionResult.pt[0], projectionResult.pt[1], projectionResult.pt[2]});
744 double distance = ttk::Geometry::distance(p0.data(), p1.data(), 3);
745
746 outputScalars[vertexId] = (isInterior[vertexId] ? -1.0 : 1.0) * distance;
747 }
748 this->printMsg(
749 "Distance", 1.0, t_distance.getElapsedTime(), this->threadNumber_);
750
751 if(backend_ != 0) {
752 Timer t_marching;
753 printMsg("Start fast marching...");
754 fastMarching(vertexIntersection, outputScalars, isInterior);
755 this->printMsg(
756 "Fast marching", 1.0, t_marching.getElapsedTime(), this->threadNumber_);
757 }
758
759 this->printMsg(
760 "Signed distance field", 1.0, t.getElapsedTime(), this->threadNumber_);
761
762 return 0;
763}
AbstractTriangulation is an interface class that defines an interface for efficient traversal methods...
Acceleration structure for native ray tracer. Based on implementation described in Physically Based R...
bool intersect(Ray &r, const IT *connectivityList, const float *vertexCoords, int *triangleIndex, float *distance, std::vector< int > &triangles, std::vector< float > &distances, bool segmentIntersection=false) const
Minimalist debugging class.
Definition Debug.h:88
Data structure for a ray.
Definition Ray.h:11
This filter computes a signed distance field given a surface in input.
dataType fastMarchingUpdatePoint(unsigned int vertexId, dataType *const distances, int *const isInterior, std::vector< VertexMarchingType > &vertexType) const
dataType fastMarchingUpdatePointOrderOne(unsigned int vertexId, dataType *const distances, int *const isInterior, std::vector< VertexMarchingType > &vertexType) const
void fastMarchingIterativeNode(std::vector< VertexMarchingType > &vertexType, dataType *const distances, int *const isInterior) const
bool fastMarchingSolveQuadratic(unsigned int vertexId, dataType a, dataType b, dataType c, int *const isInterior, dataType &out) const
std::array< double, 3 > invSpacingSquared_
std::array< double, 3 > spacing_
void fastMarchingIterativeBand(std::vector< VertexMarchingType > &vertexType, dataType *const distances, int *const isInterior) const
void findOutsideVertices(const SimplexId vertexId, triangulationType *const boundingTriangulation, const std::vector< bool > &vertexIntersection, int *const isInterior) const
int preconditionTriangulation(AbstractTriangulation *triangulation) const
void fastMarching(std::vector< bool > &vertexIntersection, dataType *const distances, int *const isInterior) const
dataType fastMarchingUpdatePointOrderTwo(unsigned int vertexId, dataType *const distances, int *const isInterior, std::vector< VertexMarchingType > &vertexType) const
int execute(float *const outputScalars, triangulationType *const triangulation, triangulationType2 *const boundingTriangulation, int *const edgeCrossing, int *const isInterior) const
int getNeighbor(unsigned int vertexId, unsigned int dim, int dir) const
double getElapsedTime()
Definition Timer.h:15
SimplexId getNearestSurfaceVertex(const T *pa, std::vector< T > &dists, const triangulationType &triangulation)
Find nearest vertex on the surface.
Definition Geometry.h:517
T distance(const T *p0, const T *p1, const int &dimension=3)
Definition Geometry.cpp:362
ProjectionResult findProjection(const ProjectionInput &pi, VisitedMask &trianglesTested, std::vector< float > &dists, std::stack< SimplexId > &trianglesToTest, const bool reverseProjection, const triangulationType0 &triangulationToSmooth, const triangulationType1 &triangulation)
Definition Geometry.h:891
The Topology ToolKit.
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
constexpr bool operator()(std::pair< int, double > const &a, std::pair< int, double > const &b) const noexcept
Stores the findProjection() input.
Definition Geometry.h:880
Stores the findProjection() result.
Definition Geometry.h:864
std::array< float, 3 > pt
Definition Geometry.h:866
Auto-cleaning re-usable graph propagations data structure.
Definition VisitedMask.h:27
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)