191 std::vector<VertexMarchingType> &vertexType,
192 dataType *
const distances,
193 int *
const isInterior)
const {
195 auto abs = [](
auto arg) {
196 using T =
decltype(arg);
197 if constexpr(std::is_unsigned<T>::value) {
202 return std::abs(arg);
208 std::pair<int, dataType>
const &b)
const noexcept {
209 return a.second > b.second;
212 std::priority_queue<std::pair<int, dataType>,
213 std::vector<std::pair<int, dataType>>,
Compare>
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;
220 while(!heap.empty()) {
222 std::pair<int, dataType> pair = heap.top();
223 auto vertexId = std::get<0>(pair);
224 auto value = std::get<1>(pair);
226 if(not(value <= abs(distances[vertexId]) + 1e-6
227 and value >= abs(distances[vertexId]) - 1e-6))
230 vertexType[vertexId] = VertexMarchingType::FROZEN;
231 toFreeze.emplace_back(vertexId);
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) {
241 vertexType[l_vertexId] = VertexMarchingType::FROZEN;
242 toFreeze.emplace_back(l_vertexId);
249 for(
unsigned int k = 0; k < toFreeze.size(); ++k) {
250 int id = toFreeze[k];
252 for(
unsigned int dim = 0; dim < 3; ++dim) {
254 for(
int j = -1; j < 2; j += 2) {
255 int neighborId = getNeighbor(
id, dim, j);
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);
263 distances[neighborId] = d;
264 heap.push(std::make_pair(neighborId, abs(d)));
265 if(vertexType[neighborId] == VertexMarchingType::FAR)
266 vertexType[neighborId] = VertexMarchingType::NARROW;
272 if(fastMarchingOrder_ == 2) {
274 and vertexType[neighborId] == VertexMarchingType::FROZEN) {
275 int neighbor2Id = getNeighbor(
id, dim, j * 2);
277 and vertexType[neighbor2Id] == VertexMarchingType::NARROW) {
278 dataType d = fastMarchingUpdatePointOrderTwo(
279 neighbor2Id, distances, isInterior, vertexType);
281 heap.push(std::make_pair(neighbor2Id, abs(d)));
282 distances[neighbor2Id] = d;
295 std::vector<VertexMarchingType> &vertexType,
296 dataType *
const distances,
297 int *
const isInterior)
const {
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);
304 while(!toProcess.empty()) {
305#ifdef TTK_ENABLE_OPENMP
306#pragma omp parallel for num_threads(threadNumber_)
308 for(
unsigned int i = 0; i < toProcess.size(); ++i) {
309 auto vertexId = toProcess[i];
310 vertexType[vertexId] = VertexMarchingType::FROZEN;
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);
316 and vertexType[neighborId] == VertexMarchingType::FAR)
317#pragma omp atomic write
318 vertexType[neighborId] = VertexMarchingType::NARROW;
322#ifdef TTK_ENABLE_OPENMP
323#pragma omp parallel for num_threads(threadNumber_) schedule(dynamic)
325 for(
unsigned int i = 0; i < toProcess.size(); ++i)
326 if(vertexType[i] == VertexMarchingType::NARROW)
328 = fastMarchingUpdatePoint(i, distances, isInterior, vertexType);
330 for(
unsigned int i = 0; i < vertexType.size(); ++i)
331 if(vertexType[i] == VertexMarchingType::NARROW)
332 toProcess.emplace_back(i);
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;
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;
367 for(
int j = -1; j < 2; j += 2) {
368 int neighborId = getNeighbor(vertexId, dim, j);
370 and vertexType[neighborId] == VertexMarchingType::FROZEN
371 and std::abs((
double)distances[neighborId])
372 < std::abs((
double)value1)) {
373 value1 = distances[neighborId];
375 int neighbor2Id = getNeighbor(vertexId, dim, j * 2);
377 and vertexType[neighbor2Id] == VertexMarchingType::FROZEN
378 and ((distances[neighbor2Id] <= value1 && value1 >= 0)
379 || (distances[neighbor2Id] >= value1 && value1 <= 0))) {
380 value2 = distances[neighbor2Id];
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);
391 a += invSpacingSquared_[dim];
392 b -= invSpacingSquared_[dim] * 2 * value1;
393 c += invSpacingSquared_[dim] * pow(value1, 2);
397 if(not fastMarchingSolveQuadratic(vertexId, a, b, c, isInterior, out)) {
399 return fastMarchingUpdatePointOrderOne(
400 vertexId, distances, isInterior, vertexType);
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);
472 vertexStack.push(startVertexId);
473 outsideVertexSelected[startVertexId] =
true;
474 isInterior[startVertexId] = 0;
477 while(!vertexStack.empty()) {
481 if(vertexIntersection[vertexId])
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);
489 neighbors.emplace_back(neighborId);
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;
502 std::stringstream ss;
503 ss <<
"Number of outside vertices = " << cpt;
509 float *
const outputScalars,
510 triangulationType *
const triangulation,
511 triangulationType2 *
const boundingTriangulation,
512 int *
const edgeCrossing,
513 int *
const isInterior)
const {
517 auto noVertices = boundingTriangulation->getNumberOfVertices();
518#ifdef TTK_ENABLE_OPENMP
519#pragma omp parallel for num_threads(threadNumber_)
521 for(
int i = 0; i < noVertices; i++) {
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_)
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;
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_)
548 for(
int triangleId = 0; triangleId < triangleNumber; triangleId++) {
550 triangulation->getTriangleVertex(triangleId, 0, vertexTriangleIdA);
552 triangulation->getTriangleVertex(triangleId, 1, vertexTriangleIdB);
554 triangulation->getTriangleVertex(triangleId, 2, vertexTriangleIdC);
555 bvhConnectivityList[triangleId * 3 + 0] = vertexTriangleIdA;
556 bvhConnectivityList[triangleId * 3 + 1] = vertexTriangleIdB;
557 bvhConnectivityList[triangleId * 3 + 2] = vertexTriangleIdC;
560 bvhConnectivityList.data(),
561 static_cast<size_t>(triangleNumber));
569 std::vector<bool> vertexIntersection(noVertices,
false);
570 std::vector<std::vector<unsigned int>> verticesIntersected;
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)
579 for(
unsigned int i = 0; i < noOrigins; ++i) {
581 int vertexId, dirDimension;
582 if(i < yResolution_ * zResolution_) {
584 vertexId = i * xResolution_;
586 }
else if(i < yResolution_ * zResolution_ + xResolution_ * zResolution_) {
588 unsigned int ind = i - yResolution_ * zResolution_;
589 vertexId = (int)(ind / xResolution_) * xResolution_ * yResolution_
590 + ind % xResolution_;
595 = i - (yResolution_ * zResolution_ + xResolution_ * zResolution_);
601 boundingTriangulation->getVertexPoint(
602 vertexId, ray_origin[0], ray_origin[1], ray_origin[2]);
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;
616 if(shiftCounter >= 2) {
617 for(
int dim = 0; dim < 3; ++dim) {
618 if(dim == dirDimension)
620 ray_origin[dim] += dirToShift[dim] * 1e-3 * spacing_[dim];
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);
635 unsigned int rayNoVertices
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_;
646 verticesList[j] = vertexId + j * xResolution_ * yResolution_;
649 for(
auto &distance : distances) {
650 unsigned int ind = distance;
651 if(ind + 1 >= verticesList.size())
653 auto vertexIdA = verticesList[ind];
654 auto vertexIdB = verticesList[ind + 1];
655 verticesIntersected[i].emplace_back(vertexIdA);
656 verticesIntersected[i].emplace_back(vertexIdB);
661 for(
unsigned int i = 0; i < verticesIntersected.size(); ++i) {
662 for(
auto &vertexId : verticesIntersected[i]) {
663 vertexIntersection[vertexId] =
true;
664 edgeCrossing[vertexId] = 1;
668 this->threadNumber_);
675 SimplexId outsideVertex = std::numeric_limits<SimplexId>::max();
676 for(
unsigned int i = 0; i < vertexIntersection.size(); i++) {
677 if(not vertexIntersection[i]) {
679 std::stringstream ss;
680 ss <<
"First outside vertex found : " << outsideVertex;
686 outsideVertex, boundingTriangulation, vertexIntersection, isInterior);
688 this->threadNumber_);
696 printMsg(
"Start distance computation...");
698 std::vector<int> verticesCrossing;
700 for(
unsigned int i = 0; i < vertexIntersection.size(); ++i)
701 if(vertexIntersection[i])
702 verticesCrossing.emplace_back(i);
703 noVertices = verticesCrossing.size();
706#ifdef TTK_ENABLE_OPENMP
707#pragma omp parallel for num_threads(threadNumber_)
709 for(
int i = 0; i < noVertices; i++) {
712 vertexId = verticesCrossing[i];
714 float x = 0, y = 0, z = 0;
715 boundingTriangulation->getVertexPoint(vertexId, x, y, z);
717 std::array<float, 3> point;
722 std::vector<float> dists(triangulation->getNumberOfVertices());
724 static_cast<size_t>(vertexId), point,
727 std::vector<SimplexId> visitedTriangles{};
728 std::vector<bool> trianglesTested(
729 triangulation->getNumberOfTriangles(),
false);
732 std::vector<float> dists2(triangulation->getNumberOfVertices());
733 std::stack<ttk::SimplexId> trianglesToTest;
734 bool reverseProjection =
false;
737 projectionInput, vm, dists2, trianglesToTest, reverseProjection,
738 *boundingTriangulation, *triangulation);
741 std::vector<double> p0({x, y, z});
742 std::vector<double> p1(
743 {projectionResult.
pt[0], projectionResult.
pt[1], projectionResult.
pt[2]});
746 outputScalars[vertexId] = (isInterior[vertexId] ? -1.0 : 1.0) * distance;
749 "Distance", 1.0, t_distance.
getElapsedTime(), this->threadNumber_);
754 fastMarching(vertexIntersection, outputScalars, isInterior);
756 "Fast marching", 1.0, t_marching.
getElapsedTime(), this->threadNumber_);
760 "Signed distance field", 1.0, t.
getElapsedTime(), this->threadNumber_);