25#include "levelSetSegmentationObject.hpp"
27#include "bitpit_CG.hpp"
28#include "levelSetObject.hpp"
59 : m_surface(other.m_surface),
60 m_featureAngle(other.m_featureAngle),
61 m_surfaceSmoothing(other.m_surfaceSmoothing),
62 m_segmentVertexOffset(other.m_segmentVertexOffset),
63 m_segmentNormalsValid(other.m_segmentNormalsValid),
64 m_segmentNormalsStorage(other.m_segmentNormalsStorage),
65 m_unlimitedVertexNormalsValid(other.m_unlimitedVertexNormalsValid),
66 m_unlimitedVertexNormalsStorage(other.m_unlimitedVertexNormalsStorage),
67 m_limitedSegmentVertexNormalValid(other.m_limitedSegmentVertexNormalValid),
68 m_limitedSegmentVertexNormalStorage(other.m_limitedSegmentVertexNormalStorage)
70 if (other.m_ownedSurface) {
71 m_ownedSurface = std::unique_ptr<SurfUnstructured>(
new SurfUnstructured(*(other.m_ownedSurface)));
73 m_ownedSurface =
nullptr;
76 if (other.m_searchTree) {
77 m_searchTree = std::unique_ptr<SurfaceSkdTree>(
new SurfaceSkdTree(m_surface));
78 m_searchTree->build();
80 m_searchTree =
nullptr;
92 m_surfaceSmoothing(surfaceSmoothing)
104 : m_surfaceSmoothing(surfaceSmoothing)
118 setSurface(surface, featureAngle, surfaceSmoothing);
136 m_ownedSurface = std::move(surface);
137 setSurface(m_ownedSurface.get(), featureAngle);
150 throw std::runtime_error (
"Segmentation needs adjacencies!") ;
155 m_featureAngle = featureAngle;
156 m_surfaceSmoothing = surfaceSmoothing;
162 std::size_t nTotalSegmentVertices = 0;
163 for (
auto itr = m_segmentVertexOffset.
begin(); itr != m_segmentVertexOffset.
end(); ++itr) {
164 *itr = nTotalSegmentVertices;
165 nTotalSegmentVertices += m_surface->
getCells().rawAt(itr.getRawIndex()).getVertexCount();
171 m_segmentNormalsValid.
fill(
false);
177 m_unlimitedVertexNormalsValid.
fill(
false);
181 m_limitedSegmentVertexNormalValid.assign(nTotalSegmentVertices,
false);
184 m_searchTree = std::unique_ptr<SurfaceSkdTree>(
new SurfaceSkdTree(surface));
185 m_searchTree->build();
202 return *m_searchTree;
210 return m_featureAngle;
219 return m_surfaceSmoothing;
234 std::array<double, 3> *distanceVector)
const
237 int nSegmentVertices = segmentItr->getVertexCount();
239 std::array<double, 3> pointProjection =
evalProjection(point, segmentItr, lambda);
240 (*distanceVector) = point - pointProjection;
243 double unsignedDistance =
norm2(*distanceVector);
244 if (!signedDistance) {
245 return unsignedDistance;
253 std::array<double, 3> pseudoNormal = computePseudoNormal(segmentItr, lambda);
254 double pointProjectionNormalComponent =
dotProduct(*distanceVector, pseudoNormal);
256 double distanceTolerance = m_surface->
getTol();
259 if (!pointOnSegmentation) {
260 throw std::runtime_error(
"Unable to evaluate point sign: the point lies on the normal plane!");
264 return sign(pointProjectionNormalComponent) * unsignedDistance;
277 bool signedDistance)
const
279 std::array<double, 3> distanceVector;
280 return evalDistance(point, segmentItr, signedDistance, &distanceVector);
293 int nSegmentVertices = segmentItr->getVertexCount();
295 std::array<double, 3> pointProjection =
evalProjection(point, segmentItr, lambda);
297 return (point - pointProjection);
311 std::array<double, 3> projectionPoint;
312 std::array<double, 3> projectionNormal;
313 evalProjection(point, segmentItr, &projectionPoint, &projectionNormal);
315 return projectionNormal;
326 const double *lambda )
const
328 return computePseudoNormal(segmentItr, lambda);
345void LevelSetSegmentationSurfaceInfo::evalProjectionOnVertex(
const std::array<double,3> &point,
346 const SegmentConstIterator &segmentItr,
347 std::array<double, 3> *projectionPoint,
348 std::array<double, 3> *projectionNormal)
const
353 const Cell &segment = *segmentItr;
354 assert(segment.
getType() == ElementType::VERTEX);
358 long id = segmentVertexIds[0];
362 (*projectionNormal) = {0., 0., 0.};
415void LevelSetSegmentationSurfaceInfo::evalHighOrderProjectionOnLine(
const std::array<double,3> &point,
416 const SegmentConstIterator &segmentItr,
417 std::array<double, 3> *projectionPoint,
418 std::array<double, 3> *projectionNormal)
const
421 const Cell &segment = *segmentItr;
422 assert(segment.getType() == ElementType::LINE);
425 ConstProxyVector<long> segmentVertexIds = segment.getVertexIds();
427 const std::array<double,3> &point0 = m_surface->
getVertexCoords(segmentVertexIds[0]);
428 const std::array<double,3> &point1 = m_surface->
getVertexCoords(segmentVertexIds[1]);
431 std::array<double,2> t;
435 double distanceTolerance = m_surface->
getTol();
436 for (
int i = 0; i < 2; ++i) {
437 if (utils::DoubleFloatingEqual()(t[i], 1., distanceTolerance, distanceTolerance)) {
439 (*projectionNormal) = computeSegmentVertexNormal(segmentItr, i,
true);
445 std::array<double, 3> facetNormal = computeSegmentNormal(segmentItr);
446 std::array<double, 3> normal_s = point - point_s;
448 double distance =
norm2(normal_s);
449 if (utils::DoubleFloatingEqual()(distance, 0., distanceTolerance, distanceTolerance)) {
450 normal_s = facetNormal;
452 normal_s /= distance;
453 if (
dotProduct(normal_s, facetNormal) < 0.0) {
459 std::array<double, 3> normal0 = computeSegmentVertexNormal(segmentItr, 0,
true);
460 std::array<double, 3> normal1 = computeSegmentVertexNormal(segmentItr, 1,
true);
463 std::array<double, 3> edge = point1 - point0;
468 double product1 = t[0] * t[1];
469 double product2 = lambda01 * t[0] + lambda10 * t[1];
470 double f = product1 * product2;
471 double df = product1 * (lambda01 - lambda10) + product2 * (t[1] - t[0]);
474 (*projectionPoint) = point_s + f * normal_s;
477 double length =
norm2(edge);
478 (*projectionNormal) = df * edge + length * length * normal_s;
479 (*projectionNormal) /=
norm2((*projectionNormal));
481 if (
dotProduct(normal_s, (*projectionNormal)) < 0.0) {
482 (*projectionNormal) *= -1.0;
616void LevelSetSegmentationSurfaceInfo::evalHighOrderProjectionOnTriangle(
const std::array<double,3> &point,
617 const SegmentConstIterator &segmentItr,
618 std::array<double, 3> *projectionPoint,
619 std::array<double, 3> *projectionNormal)
const
622 const Cell &segment = *segmentItr;
623 assert(segment.getType() == ElementType::TRIANGLE);
626 ConstProxyVector<long> segmentVertexIds = segment.getVertexIds();
628 const std::array<double,3> &point0 = m_surface->
getVertexCoords(segmentVertexIds[0]);
629 const std::array<double,3> &point1 = m_surface->
getVertexCoords(segmentVertexIds[1]);
630 const std::array<double,3> &point2 = m_surface->
getVertexCoords(segmentVertexIds[2]);
633 std::array<double,3> tau;
635 std::array<double, 3> d0_point_s = point0 - point2;
636 std::array<double, 3> d1_point_s = point1 - point2;
639 double distanceTolerance = m_surface->
getTol();
640 for (
int i = 0; i < 3; ++i) {
641 if (utils::DoubleFloatingEqual()(tau[i], 1., distanceTolerance, distanceTolerance)) {
643 (*projectionNormal) = computeSegmentVertexNormal(segmentItr, i,
true);
649 std::array<double, 3> facetNormal = computeSegmentNormal(segmentItr);
650 std::array<double, 3> normal_s = point - point_s;
652 double distance =
norm2(normal_s);
653 if (utils::DoubleFloatingEqual()(distance, 0., distanceTolerance, distanceTolerance)) {
654 normal_s = facetNormal;
656 normal_s /= distance;
657 if (
dotProduct(normal_s, facetNormal) < 0.0) {
663 std::array<std::array<double, 3>,3 > edgePoint_s;
664 std::array< std::array<double, 3>, 3 > d0_edgePoint_s;
665 std::array< std::array<double, 3>, 3 > d1_edgePoint_s;
666 std::array< std::array<double, 3>, 3 > edgePoint_p;
667 std::array< std::array<double, 3>, 3 > d0_edgePoint_p;
668 std::array< std::array<double, 3>, 3 > d1_edgePoint_p;
669 std::array< std::array<double, 3>, 3 > edgeNormal_p;
670 std::array< std::array<double, 3>, 3 > d0_edgeNormal_p;
671 std::array< std::array<double, 3>, 3 > d1_edgeNormal_p;
672 for (
int e = 0; e < 3; ++e) {
674 const Cell &segment = *segmentItr;
677 ConstProxyVector<int> edgeLocalVertexIds = segment.getFaceLocalVertexIds(e);
678 int localId0 = edgeLocalVertexIds[0];
679 int localId1 = edgeLocalVertexIds[1];
680 int id0 = segment.getVertexId(localId0);
681 int id1 = segment.getVertexId(localId1);
687 std::array<double, 3> normal0 = computeSegmentVertexNormal(segmentItr, localId0,
true);
688 std::array<double, 3> normal1 = computeSegmentVertexNormal(segmentItr, localId1,
true);
691 std::array<double, 3> edgeNormal_s = computeSegmentEdgeNormal(segmentItr, e,
true);
694 std::array<double, 3> edge = node1 - node0;
702 }
else if (p01 < 0.0) {
710 double p10 = 1.0 - p01;
711 double d0_p10 = - d0_p01;
712 double d1_p10 = - d1_p01;
719 double product1 = p10 * p01;
720 double d_product1 = p01 - p10;
722 double product2 = lambda01 * p10 + lambda10 * p01;
723 double d_product2 = lambda01 - lambda10;
725 double f01 = product1 * product2;
726 double d_f01 = d_product1 * product2 + product1 * d_product2;
727 double d_d_f01 = 2.0 * (d_product1 * d_product2 - product2);
729 edgePoint_s[e] = p10 * node0 + p01 * node1;
730 std::array<double, 3> d_edgePoint_s = node0 - node1;
732 d0_edgePoint_s[e] = d_edgePoint_s * d0_p10;
733 d1_edgePoint_s[e] = d_edgePoint_s * d1_p10;
735 edgePoint_p[e] = edgePoint_s[e] + f01 * edgeNormal_s;
736 std::array<double, 3> d_edgePoint_p = d_edgePoint_s + d_f01 * edgeNormal_s;
738 d0_edgePoint_p[e] = d_edgePoint_p * d0_p10;
739 d1_edgePoint_p[e] = d_edgePoint_p * d1_p10;
742 double length =
norm2(edge);
743 edgeNormal_p[e] = d_f01 * edge + length * length * edgeNormal_s;
744 std::array<double, 3> d_edgeNormal_p = d_d_f01 * edge;
747 double d_norm =
dotProduct(edgeNormal_p[e], d_edgeNormal_p) /
norm;
748 edgeNormal_p[e] /=
norm;
749 d_edgeNormal_p = (d_edgeNormal_p - edgeNormal_p[e] * d_norm) /
norm;
751 d0_edgeNormal_p[e] = d_edgeNormal_p * d0_p10;
752 d1_edgeNormal_p[e] = d_edgeNormal_p * d1_p10;
757 double d0_sum_t = 0.0;
758 double d1_sum_t = 0.0;
759 std::array<double, 3> t;
760 std::array<double, 3> d0_t;
761 std::array<double, 3> d1_t;
762 for (
int i = 0; i < 3; i ++) {
765 std::array<double, 3> v1 = edgePoint_s[j] - point_s;
766 std::array<double, 3> d0_v1 = d0_edgePoint_s[j]- d0_point_s;
767 std::array<double, 3> d1_v1 = d1_edgePoint_s[j]- d1_point_s;
769 std::array<double, 3> v2 = edgePoint_s[k] - point_s;
770 std::array<double, 3> d0_v2 = d0_edgePoint_s[k]- d0_point_s;
771 std::array<double, 3> d1_v2 = d1_edgePoint_s[k]- d1_point_s;
777 t[i] =
norm2(normal);
778 d0_t[i] =
dotProduct(normal, d0_normal) / t[i];
779 d1_t[i] =
dotProduct(normal, d1_normal) / t[i];
785 std::array<double, 3> point_m = {0.0, 0.0, 0.0};
786 std::array<double, 3> d0_point_m = {0.0, 0.0, 0.0};
787 std::array<double, 3> d1_point_m = {0.0, 0.0, 0.0};
788 for (
int i = 0; i < 3; i ++) {
790 d0_t[i] = (d0_t[i] - t[i] * d0_sum_t) / sum_t;
791 d1_t[i] = (d1_t[i] - t[i] * d1_sum_t) / sum_t;
792 point_m += t[i] * edgePoint_p[i];
793 d0_point_m += d0_t[i] * edgePoint_p[i] + t[i] * d0_edgePoint_p[i];
794 d1_point_m += d1_t[i] * edgePoint_p[i] + t[i] * d1_edgePoint_p[i];
799 for (
int i = 0; i < 3; ++i) {
800 if (utils::DoubleFloatingEqual()(t[i], 1., distanceTolerance, distanceTolerance)) {
801 (*projectionPoint) = edgePoint_p[i];
802 (*projectionNormal) = edgeNormal_p[i];
811 for (
int e = 0; e < 3; ++e) {
816 std::array<double,3> &node_i = edgePoint_p[i];
817 std::array<double,3> &d0_node_i = d0_edgePoint_p[i];
818 std::array<double,3> &d1_node_i = d1_edgePoint_p[i];
820 std::array<double,3> &node_j = edgePoint_p[j];
821 std::array<double, 3> &d0_node_j = d0_edgeNormal_p[j];
822 std::array<double, 3> &d1_node_j = d1_edgeNormal_p[j];
824 std::array<double, 3> &normal_i = edgeNormal_p[i];
825 std::array<double, 3> &d0_normal_i = d0_edgeNormal_p[i];
826 std::array<double, 3> &d1_normal_i = d1_edgeNormal_p[i];
828 std::array<double, 3> &normal_j = edgeNormal_p[j];
829 std::array<double, 3> &d0_normal_j = d0_edgeNormal_p[j];
830 std::array<double, 3> &d1_normal_j = d1_edgeNormal_p[j];
833 std::array<double, 3> edge = node_j - node_i;
834 std::array<double, 3> d0_edge = d0_node_j - d0_node_i;
835 std::array<double, 3> d1_edge = d1_node_j - d1_node_i;
846 f += t[i] * t[j] * (lambda_ij * t[i] + lambda_ji * t[j]);
847 d0_f += (d0_t[i] * t[j] + t[i] * d0_t[j]) * (lambda_ij * t[i] + lambda_ji * t[j])
848 + t[i] * t[j] * (d0_lambda_ij * t[i] + lambda_ij * d0_t[i] + d0_lambda_ji * t[j] + lambda_ji * d0_t[j]);
849 d1_f += (d1_t[i] * t[j] + t[i] * d1_t[j]) * (lambda_ij * t[i] + lambda_ji * t[j])
850 + t[i] * t[j] * (d1_lambda_ij * t[i] + lambda_ij * d1_t[i] + d1_lambda_ji * t[j] + lambda_ji * d1_t[j]);
854 (*projectionPoint) = point_m + f * normal_s;
857 std::array<double, 3> d0_point_p = d0_point_m + d0_f * normal_s;
858 std::array<double, 3> d1_point_p = d1_point_m + d1_f * normal_s;
860 (*projectionNormal) =
crossProduct(d0_point_p, d1_point_p);
861 (*projectionNormal) /=
norm2((*projectionNormal));
863 if (
dotProduct(normal_s, (*projectionNormal)) < 0.0) {
864 (*projectionNormal) *= -1.0;
889void LevelSetSegmentationSurfaceInfo::evalHighOrderProjectionOnPolygon(
const std::array<double,3> &point,
890 const SegmentConstIterator &segmentItr,
891 std::array<double, 3> *projectionPoint,
892 std::array<double, 3> *projectionNormal)
const
895 const Cell &segment = *segmentItr;
900 std::size_t nSegmentVertices = segmentVertexIds.size();
901 BITPIT_CREATE_WORKSPACE(segmentVertexCoords, std::array<double BITPIT_COMMA 3>, nSegmentVertices, ReferenceElementInfo::MAX_ELEM_VERTICES);
902 m_surface->
getVertexCoords(segmentVertexIds.size(), segmentVertexIds.data(), segmentVertexCoords);
907 std::array<double, 3> lowOrderProjectionNormal = tau[0] * computeSegmentVertexNormal(segmentItr, 0,
true);
908 for (std::size_t i = 1; i < nSegmentVertices; ++i) {
909 lowOrderProjectionNormal += tau[i] * computeSegmentVertexNormal(segmentItr, i,
true);
913 double distanceTolerance = m_surface->
getTol();
914 for (std::size_t i = 0; i < nSegmentVertices; ++i) {
915 if (utils::DoubleFloatingEqual()(tau[i], 1., distanceTolerance, distanceTolerance)) {
916 (*projectionPoint) = segmentVertexCoords[i];
917 (*projectionNormal) = computeSegmentVertexNormal(segmentItr, i,
true);
922 std::array<double, 3> d0_point_s;
923 std::array<double, 3> d1_point_s;
929 double cosMin = std::numeric_limits<double>::max();
930 for (std::size_t i = 0; i < nSegmentVertices; ++i) {
932 int i_c = (i + 1) % nSegmentVertices;
933 int i_n = (i + 2) % nSegmentVertices;
935 const std::array<double,3> &point_p = m_surface->
getVertexCoords(segmentVertexIds[i_p]);
936 const std::array<double,3> &point_c = m_surface->
getVertexCoords(segmentVertexIds[i_c]);
937 const std::array<double,3> &point_n = m_surface->
getVertexCoords(segmentVertexIds[i_n]);
939 std::array<double,3> x_p = point_p - point_c;
940 std::array<double,3> x_n = point_n - point_c;
951 std::array<double, 3> facetNormal = computeSegmentNormal(segmentItr);
952 std::array<double, 3> normal_s = point - point_s;
953 double distance =
norm2(normal_s);
954 if (utils::DoubleFloatingEqual()(distance, 0., distanceTolerance, distanceTolerance)) {
955 normal_s = facetNormal;
957 normal_s /= distance;
958 if (
dotProduct(normal_s, facetNormal) < 0.0) {
964 int nSegmentEdges = nSegmentVertices;
965 BITPIT_CREATE_WORKSPACE(edgePoint_s, std::array<double BITPIT_COMMA 3>, nSegmentEdges, ReferenceElementInfo::MAX_ELEM_EDGES);
966 BITPIT_CREATE_WORKSPACE(d0_edgePoint_s, std::array<double BITPIT_COMMA 3>, nSegmentEdges, ReferenceElementInfo::MAX_ELEM_EDGES);
967 BITPIT_CREATE_WORKSPACE(d1_edgePoint_s, std::array<double BITPIT_COMMA 3>, nSegmentEdges, ReferenceElementInfo::MAX_ELEM_EDGES);
968 BITPIT_CREATE_WORKSPACE(edgePoint_p, std::array<double BITPIT_COMMA 3>, nSegmentEdges, ReferenceElementInfo::MAX_ELEM_EDGES);
969 BITPIT_CREATE_WORKSPACE(d0_edgePoint_p, std::array<double BITPIT_COMMA 3>, nSegmentEdges, ReferenceElementInfo::MAX_ELEM_EDGES);
970 BITPIT_CREATE_WORKSPACE(d1_edgePoint_p, std::array<double BITPIT_COMMA 3>, nSegmentEdges, ReferenceElementInfo::MAX_ELEM_EDGES);
971 BITPIT_CREATE_WORKSPACE(edgeNormal_p, std::array<double BITPIT_COMMA 3>, nSegmentEdges, ReferenceElementInfo::MAX_ELEM_EDGES);
972 BITPIT_CREATE_WORKSPACE(d0_edgeNormal_p, std::array<double BITPIT_COMMA 3>, nSegmentEdges, ReferenceElementInfo::MAX_ELEM_EDGES);
973 BITPIT_CREATE_WORKSPACE(d1_edgeNormal_p, std::array<double BITPIT_COMMA 3>, nSegmentEdges, ReferenceElementInfo::MAX_ELEM_EDGES);
974 for (
int e = 0; e < nSegmentEdges; ++e) {
976 ConstProxyVector<int> edgeLocalVertexIds = segment.getFaceLocalVertexIds(e);
977 int localId0 = edgeLocalVertexIds[0];
978 int localId1 = edgeLocalVertexIds[1];
979 int id0 = segment.getVertexId(localId0);
980 int id1 = segment.getVertexId(localId1);
986 std::array<double, 3> normal0 = computeSegmentVertexNormal(segmentItr, localId0,
true);
987 std::array<double, 3> normal1 = computeSegmentVertexNormal(segmentItr, localId1,
true);
990 std::array<double, 3> edgeNormal_s = computeSegmentEdgeNormal(segmentItr, e,
true);
993 std::array<double, 3> edge = node1 - node0;
1001 }
else if (p01 < 0.0) {
1009 double p10 = 1.0 - p01;
1010 double d0_p10 = - d0_p01;
1011 double d1_p10 = - d1_p01;
1018 double product1 = p10 * p01;
1019 double d_product1 = p01 - p10;
1021 double product2 = lambda01 * p10 + lambda10 * p01;
1022 double d_product2 = lambda01 - lambda10;
1024 double f01 = product1 * product2;
1025 double d_f01 = d_product1 * product2 + product1 * d_product2;
1026 double d_d_f01 = 2.0 * (d_product1 * d_product2 - product2);
1028 edgePoint_s[e] = p10 * node0 + p01 * node1;
1029 std::array<double, 3> d_edgePoint_s = node0 - node1;
1031 d0_edgePoint_s[e] = d_edgePoint_s * d0_p10;
1032 d1_edgePoint_s[e] = d_edgePoint_s * d1_p10;
1034 edgePoint_p[e] = edgePoint_s[e] + f01 * edgeNormal_s;
1035 std::array<double, 3> d_edgePoint_p = d_edgePoint_s + d_f01 * edgeNormal_s;
1037 d0_edgePoint_p[e] = d_edgePoint_p * d0_p10;
1038 d1_edgePoint_p[e] = d_edgePoint_p * d1_p10;
1041 double length =
norm2(edge);
1042 edgeNormal_p[e] = d_f01 * edge + length * length * edgeNormal_s;
1043 std::array<double, 3> d_edgeNormal_p = d_d_f01 * edge;
1046 double d_norm =
dotProduct(edgeNormal_p[e], d_edgeNormal_p) /
norm;
1047 edgeNormal_p[e] /=
norm;
1048 d_edgeNormal_p = (d_edgeNormal_p - edgeNormal_p[e] * d_norm) /
norm;
1050 d0_edgeNormal_p[e] = d_edgeNormal_p * d0_p10;
1051 d1_edgeNormal_p[e] = d_edgeNormal_p * d1_p10;
1056 for (
int e = 0; e < nSegmentEdges; ++e) {
1057 double distance =
norm2(edgePoint_s[e] - point_s);
1058 if (utils::DoubleFloatingEqual()(distance, 0.0, distanceTolerance, distanceTolerance)) {
1059 (*projectionPoint) = edgePoint_p[e];
1060 (*projectionNormal) = edgeNormal_p[e];
1076 for (std::size_t i = 0; i < nSegmentVertices; ++i) {
1077 d[i] = (edgePoint_s[i][0] - point_s[0]) * (edgePoint_s[i][0] - point_s[0])
1078 + (edgePoint_s[i][1] - point_s[1]) * (edgePoint_s[i][1] - point_s[1])
1079 + (edgePoint_s[i][2] - point_s[2]) * (edgePoint_s[i][2] - point_s[2]);
1083 d0_d[i] = 4.0 * d[i] *
dotProduct((edgePoint_s[i] - point_s), (d0_edgePoint_s[i] - d0_point_s));
1084 d1_d[i] = 4.0 * d[i] *
dotProduct((edgePoint_s[i] - point_s), (d1_edgePoint_s[i] - d1_point_s));
1091 double d0_sum = 0.0;
1092 double d1_sum = 0.0;
1093 for (std::size_t i = 0; i < nSegmentVertices; ++i) {
1097 for (std::size_t j = 0; j < nSegmentVertices; ++j) {
1101 double product = 1.0;
1102 for (std::size_t k = 0; k < nSegmentVertices; ++k) {
1107 d0_t[i] += d0_d[j] * product;
1108 d1_t[i] += d1_d[j] * product;
1115 for (std::size_t i = 0; i < nSegmentVertices; ++i) {
1117 d0_t[i] = (d0_t[i] - t[i] * d0_sum) /
sum;
1118 d1_t[i] = (d1_t[i] - t[i] * d1_sum) /
sum;
1121 std::array<double, 3> point_m = {0.0, 0.0, 0.0};
1122 std::array<double, 3> d0_point_m = {0.0, 0.0, 0.0};
1123 std::array<double, 3> d1_point_m = {0.0, 0.0, 0.0};
1124 for (std::size_t i = 0; i < nSegmentVertices; ++i) {
1125 point_m += (edgePoint_p[i] - edgePoint_s[i]) * t[i];
1126 d0_point_m += d0_t[i] * (edgePoint_p[i]- edgePoint_s[i]) + t[i] * (d0_edgePoint_p[i] - d0_edgePoint_s[i]);
1127 d1_point_m += d1_t[i] * (edgePoint_p[i]- edgePoint_s[i]) + t[i] * (d1_edgePoint_p[i] - d1_edgePoint_s[i]);
1130 d0_point_m += d0_point_s;
1131 d1_point_m += d1_point_s;
1137 for (
int e = 0; e < nSegmentEdges; ++e) {
1139 int j = (e + 1) % nSegmentEdges;
1142 std::array<double,3> &node_i = edgePoint_p[i];
1143 std::array<double,3> &d0_node_i = d0_edgePoint_p[i];
1144 std::array<double,3> &d1_node_i = d1_edgePoint_p[i];
1146 std::array<double, 3> &node_j = edgePoint_p[j];
1147 std::array<double, 3> &d0_node_j = d0_edgeNormal_p[j];
1148 std::array<double, 3> &d1_node_j = d1_edgeNormal_p[j];
1150 std::array<double, 3> &normal_i = edgeNormal_p[i];
1151 std::array<double, 3> &d0_normal_i = d0_edgeNormal_p[i];
1152 std::array<double, 3> &d1_normal_i = d1_edgeNormal_p[i];
1154 std::array<double, 3> &normal_j = edgeNormal_p[j];
1155 std::array<double, 3> &d0_normal_j = d0_edgeNormal_p[j];
1156 std::array<double, 3> &d1_normal_j = d1_edgeNormal_p[j];
1159 std::array<double, 3> edge = node_j - node_i;
1160 std::array<double, 3> d0_edge = d0_node_j - d0_node_i;
1161 std::array<double, 3> d1_edge = d1_node_j - d1_node_i;
1172 f += t[i] * t[j] * (lambda_ij * t[i] + lambda_ji * t[j]);
1173 d0_f += (d0_t[i] * t[j] + t[i] * d0_t[j]) * (lambda_ij * t[i] + lambda_ji * t[j])
1174 + t[i] * t[j] * (d0_lambda_ij * t[i] + lambda_ij * d0_t[i] + d0_lambda_ji * t[j] + lambda_ji * d0_t[j]);
1175 d1_f += (d1_t[i] * t[j] + t[i] * d1_t[j]) * (lambda_ij * t[i] + lambda_ji * t[j])
1176 + t[i] * t[j] * (d1_lambda_ij * t[i] + lambda_ij * d1_t[i] + d1_lambda_ji * t[j] + lambda_ji * d1_t[j]);
1180 (*projectionPoint) = point_m + f * normal_s;
1183 std::array<double, 3> d0_point_p = d0_point_m + d0_f * normal_s;
1184 std::array<double, 3> d1_point_p = d1_point_m + d1_f * normal_s;
1186 (*projectionNormal) =
crossProduct(d0_point_p, d1_point_p);
1187 (*projectionNormal) /=
norm2((*projectionNormal));
1189 if (
dotProduct(normal_s, (*projectionNormal)) < 0.0) {
1190 (*projectionNormal) *= -1.0;
1213void LevelSetSegmentationSurfaceInfo::evalHighOrderProjection(
const std::array<double,3> &point,
1214 const SegmentConstIterator &segmentItr,
1215 std::array<double, 3> *projectionPoint,
1216 std::array<double, 3> *projectionNormal)
const
1219 const Cell &segment = *segmentItr;
1221 switch (segmentType) {
1223 case ElementType::VERTEX:
1225 evalProjectionOnVertex(point, segmentItr, projectionPoint, projectionNormal);
1229 case ElementType::LINE:
1231 evalHighOrderProjectionOnLine(point, segmentItr, projectionPoint, projectionNormal);
1235 case ElementType::TRIANGLE:
1237 evalHighOrderProjectionOnTriangle(point, segmentItr, projectionPoint, projectionNormal);
1243 evalHighOrderProjectionOnPolygon(point, segmentItr, projectionPoint, projectionNormal);
1258void LevelSetSegmentationSurfaceInfo::evalLowOrderProjectionOnLine(
const std::array<double, 3> &point,
1259 const SegmentConstIterator &segmentItr,
1260 std::array<double, 3> *projectionPoint,
1261 std::array<double, 3> *projectionNormal)
const
1263 const Cell &segment = *segmentItr;
1264 assert(segment.getType() == ElementType::LINE);
1266 ConstProxyVector<long> segmentVertexIds = segment.getVertexIds();
1268 const std::array<double,3> &point0 = m_surface->
getVertexCoords(segmentVertexIds[0]);
1269 const std::array<double,3> &point1 = m_surface->
getVertexCoords(segmentVertexIds[1]);
1271 int nSegmentVertices = segment.getVertexCount();
1275 std::array<double, 3> normal0 = computeSegmentVertexNormal(segmentItr, 0,
true);
1276 std::array<double, 3> normal1 = computeSegmentVertexNormal(segmentItr, 1,
true);
1278 (*projectionNormal) = lambda[0] * normal0 + lambda[1] * normal1;
1279 (*projectionNormal) /=
norm2((*projectionNormal));
1290void LevelSetSegmentationSurfaceInfo::evalLowOrderProjectionOnTriangle(
const std::array<double, 3> &point,
1291 const SegmentConstIterator &segmentItr,
1292 std::array<double, 3> *projectionPoint,
1293 std::array<double, 3> *projectionNormal)
const
1295 const Cell &segment = *segmentItr;
1296 assert(segment.getType() == ElementType::TRIANGLE);
1298 ConstProxyVector<long> segmentVertexIds = segment.getVertexIds();
1300 const std::array<double,3> &point0 = m_surface->
getVertexCoords(segmentVertexIds[0]);
1301 const std::array<double,3> &point1 = m_surface->
getVertexCoords(segmentVertexIds[1]);
1302 const std::array<double,3> &point2 = m_surface->
getVertexCoords(segmentVertexIds[2]);
1304 int nSegmentVertices = segment.getVertexCount();
1308 std::array<double, 3> normal0 = computeSegmentVertexNormal(segmentItr, 0,
true);
1309 std::array<double, 3> normal1 = computeSegmentVertexNormal(segmentItr, 1,
true);
1310 std::array<double, 3> normal2 = computeSegmentVertexNormal(segmentItr, 2,
true);
1312 (*projectionNormal) = lambda[0] * normal0 + lambda[1] * normal1 + lambda[2] * normal2;
1313 (*projectionNormal) /=
norm2((*projectionNormal));
1324void LevelSetSegmentationSurfaceInfo::evalLowOrderProjectionOnPolygon(
const std::array<double, 3> &point,
1325 const SegmentConstIterator &segmentItr,
1326 std::array<double, 3> *projectionPoint,
1327 std::array<double, 3> *projectionNormal)
const
1329 const Cell &segment = *segmentItr;
1333 std::size_t nSegmentVertices = segmentVertexIds.size();
1334 BITPIT_CREATE_WORKSPACE(segmentVertexCoords, std::array<double BITPIT_COMMA 3>, nSegmentVertices, ReferenceElementInfo::MAX_ELEM_VERTICES);
1335 m_surface->
getVertexCoords(segmentVertexIds.size(), segmentVertexIds.data(), segmentVertexCoords);
1340 (*projectionNormal) = lambda[0] * computeSegmentVertexNormal(segmentItr, 0,
true);
1341 for (std::size_t i = 1; i < nSegmentVertices; ++i) {
1342 (*projectionNormal) += lambda[i] * computeSegmentVertexNormal(segmentItr, i,
true);
1344 (*projectionNormal) /=
norm2(*projectionNormal);
1355void LevelSetSegmentationSurfaceInfo::evalLowOrderProjection(
const std::array<double, 3> &point,
1356 const SegmentConstIterator &segmentItr,
1357 std::array<double, 3> *projectionPoint,
1358 std::array<double, 3> *projectionNormal)
const
1360 const Cell &segment = *segmentItr;
1362 switch (segmentType) {
1364 case ElementType::VERTEX:
1366 evalProjectionOnVertex(point, segmentItr, projectionPoint, projectionNormal);
1370 case ElementType::LINE:
1372 evalLowOrderProjectionOnLine(point, segmentItr, projectionPoint, projectionNormal);
1376 case ElementType::TRIANGLE:
1378 evalLowOrderProjectionOnTriangle(point, segmentItr, projectionPoint, projectionNormal);
1384 evalLowOrderProjectionOnPolygon(point, segmentItr, projectionPoint, projectionNormal);
1401 std::array<double, 3> *projectionPoint,
1402 std::array<double, 3> *projectionNormal)
const
1405 evalHighOrderProjection(point, segmentItr, projectionPoint, projectionNormal);
1407 evalLowOrderProjection(point, segmentItr, projectionPoint, projectionNormal);
1420 std::array<double, 3> *projectionPoint)
const
1422 std::array<double, 3> projectionNormal;
1423 evalProjection(point, segmentItr, projectionPoint, &projectionNormal);
1438 double *lambda)
const
1440 std::array<double, 3> projectionPoint;
1443 const Cell &segment = *segmentItr;
1445 return projectionPoint;
1470std::array<double,3> LevelSetSegmentationSurfaceInfo::computePseudoNormal(
const SegmentConstIterator &segmentItr,
1471 const double *lambda )
const
1474 const Cell &segment = *segmentItr;
1476 if (segmentType == ElementType::VERTEX) {
1477 return {{0., 0., 0.}};
1482 if (segmentType == ElementType::LINE) {
1487 if (positionFlag > 0) {
1488 int polygonVertex = positionFlag - 1;
1491 positionFlag = elementVertex + 1;
1492 }
else if (positionFlag < 0) {
1493 int polygonEdge = (- positionFlag) - 1;
1496 positionFlag = - (elementEdge + 1);
1500 std::array<double,3> pseudoNormal;
1501 if (positionFlag == 0) {
1502 pseudoNormal = computeSegmentNormal(segmentItr);
1503 }
else if (positionFlag > 0) {
1504 int vertex = positionFlag - 1;
1505 pseudoNormal = computeSegmentVertexNormal(segmentItr, vertex,
false);
1507 int edge = (- positionFlag) - 1;
1508 pseudoNormal = computeSegmentEdgeNormal(segmentItr, edge,
false);
1511 return pseudoNormal;
1526std::array<double,3> LevelSetSegmentationSurfaceInfo::computeSurfaceNormal(
const SegmentConstIterator &segmentItr,
1527 const double *lambda )
const
1530 const Cell &segment = *segmentItr;
1532 if (segmentType == ElementType::VERTEX) {
1533 return {{0., 0., 0.}};
1537 std::size_t nSegmentVertices = segment.getVertexCount();
1538 std::array<double,3> surfaceNormal = lambda[0] * computeSegmentVertexNormal(segmentItr, 0,
true);
1539 for (std::size_t i = 1; i < nSegmentVertices; ++i) {
1540 surfaceNormal += lambda[i] * computeSegmentVertexNormal(segmentItr, i,
true);
1542 surfaceNormal /=
norm2(surfaceNormal);
1544 return surfaceNormal;
1555std::array<double,3> LevelSetSegmentationSurfaceInfo::computeSegmentNormal(
const SegmentConstIterator &segmentItr )
const {
1557 std::size_t segmentRawId = segmentItr.getRawIndex();
1558 std::array<double, 3> *segmentNormal = m_segmentNormalsStorage.
rawData(segmentRawId);
1559 if (!m_segmentNormalsValid.
rawAt(segmentRawId)) {
1561 m_segmentNormalsValid.
rawAt(segmentRawId) =
true;
1564 return *segmentNormal;
1576std::array<double,3> LevelSetSegmentationSurfaceInfo::computeSegmentEdgeNormal(
const SegmentConstIterator &segmentItr,
int edge,
bool limited )
const {
1578 long segmentId = segmentItr.getId();
1580 std::array<double, 3> limitedEdgeNormal;
1581 std::array<double, 3> unlimitedEdgeNormal;
1582 m_surface->
evalEdgeNormals(segmentId, edge, m_featureAngle, &unlimitedEdgeNormal, &limitedEdgeNormal) ;
1585 return limitedEdgeNormal;
1588 return unlimitedEdgeNormal;
1602std::array<double,3> LevelSetSegmentationSurfaceInfo::computeSegmentVertexNormal(
const SegmentConstIterator &segmentItr,
int vertex,
bool limited )
const {
1605 long segmentId = segmentItr.getId();
1606 long segmentRawId = segmentItr.getRawIndex();
1607 const Cell &segment = *segmentItr;
1612 long vertexId = segment.getVertexId(vertex);
1613 std::size_t vertexRawId = m_surface->
getVertices().getRawIndex(vertexId);
1614 bool hasUnlimitedNormal = m_unlimitedVertexNormalsValid.
rawAt(vertexRawId);
1616 bool hasLimitedNormal = m_limitedSegmentVertexNormalValid[m_segmentVertexOffset.
rawAt(segmentRawId) + vertex];
1618 if (!hasUnlimitedNormal || !hasLimitedNormal) {
1619 static std::vector<long> vertexNeighbours;
1620 vertexNeighbours.clear();
1623 std::array<double, 3> limitedVertexNormal;
1624 std::array<double, 3> unlimitedVertexNormal;
1625 if (hasUnlimitedNormal) {
1626 limitedVertexNormal = m_surface->
evalLimitedVertexNormal(segmentId, vertex, vertexNeighbours.size(), vertexNeighbours.data(), m_featureAngle) ;
1627 unlimitedVertexNormal = m_unlimitedVertexNormalsStorage.
rawAt(vertexRawId);
1629 m_surface->
evalVertexNormals(segmentId, vertex, vertexNeighbours.size(), vertexNeighbours.data(), m_featureAngle, &unlimitedVertexNormal, &limitedVertexNormal) ;
1637 if (!hasLimitedNormal) {
1638 double misalignment =
norm2(unlimitedVertexNormal - limitedVertexNormal) ;
1639 if (misalignment >= m_surface->
getTol()) {
1640 std::pair<long, int> segmentVertexKey = std::make_pair(segmentId, vertex);
1641 m_limitedSegmentVertexNormalStorage.insert({segmentVertexKey, std::move(limitedVertexNormal)}) ;
1643 m_limitedSegmentVertexNormalValid[m_segmentVertexOffset.
rawAt(segmentRawId) + vertex] =
true;
1647 if (!hasUnlimitedNormal ) {
1648 m_unlimitedVertexNormalsStorage.
rawAt(vertexRawId) = std::move(unlimitedVertexNormal);
1649 m_unlimitedVertexNormalsValid.
rawAt(vertexRawId) = true ;
1655 std::pair<long, int> segmentVertexKey = std::make_pair(segmentId, vertex);
1656 auto limitedSegmentVertexNormal = m_limitedSegmentVertexNormalStorage.find(segmentVertexKey);
1657 if (limitedSegmentVertexNormal != m_limitedSegmentVertexNormalStorage.end()) {
1658 return limitedSegmentVertexNormal->second;
1662 return m_unlimitedVertexNormalsStorage.
rawAt(vertexRawId);
1692 return createFieldCellCache<long>(field, cacheId);
1711 return supportedFields;
1742 return _evalCellSurface(
id);
1753 auto evaluator = [
this] (
long id)
1758 auto fallback = [] (
long id)
1766 int part = evalCellFieldCached<int>(field,
id, evaluator, fallback);
1812 if (surface.
empty()) {
1832 auto evaluator = [
this] (
long id)
1834 return _evalCellNormal(
id,
false);
1837 auto fallback = [] (
long id)
1845 std::array<double, 3> normal = evalCellFieldCached<std::array<double, 3>>(field, id, evaluator, fallback);
1851 if (signedLevelSet) {
1853 if (cellSign <= 0) {
1854 normal *=
static_cast<double>(cellSign);;
1881 auto evaluator = [
this, searchRadius] (
long id)
1895 double supportSearchRadius;
1901 supportSearchRadius =
m_kernel->computeCellBoundingRadius(
id);
1904 supportSearchRadius = std::numeric_limits<double>::max();
1905 auto neighProcessor = [
this, &supportSearchRadius](
long neighId,
int layer) {
1915 supportSearchRadius = std::min(2 *
m_kernel->computeCellBoundingRadius(neighId), supportSearchRadius);
1925 supportSearchRadius +=
m_kernel->computeCellBoundingRadius(
id);
1927 supportSearchRadius = std::numeric_limits<double>::max();
1930 supportSearchRadius = searchRadius;
1934 return _evalCellSupport(
id, supportSearchRadius);
1937 auto fallback = [] (
long id)
1949 support = evalCellField<long>(field,
id, evaluator, fallback);
1957 support = evalCellFieldCached<long>(field,
id, evaluator, fallback);
1971 return _evalSurface(point);
1995 std::array<double, 3> projectionPoint;
1996 std::array<double, 3> projectionNormal;
1997 evalProjection(point, signedLevelSet, &projectionPoint, &projectionNormal);
1999 return projectionNormal;
2010 return _evalSupport(point);
2023 return _evalSupport(point, searchRadius);
2038 bool signedLevelSet,
2039 std::array<double, 3> *projectionPoint,
2040 std::array<double, 3> *projectionNormal)
const
2042 _evalProjection(point, signedLevelSet, projectionPoint, projectionNormal);
2089 vtkWriter.
addData<
long>( name, VTKFieldType::SCALAR, VTKLocation::CELL,
this);
2093 vtkWriter.
addData<
int>( name, VTKFieldType::SCALAR, VTKLocation::CELL,
this);
2097 vtkWriter.
addData<
double>( name, VTKFieldType::VECTOR, VTKLocation::CELL,
this);
2150 flushVTKOutputData<double>(stream, format, field, evaluator, fallback);
2156 auto evaluator = [
this] (
long id) {
return evalCellPart(
id); };
2158 flushVTKOutputData<double>(stream, format, field, evaluator, fallback);
2164 auto evaluator = [
this] (
long id) {
return evalCellNormal(
id,
true); };
2166 flushVTKOutputData<double>(stream, format, field, evaluator, fallback);
2247 return evalNormal(point, m_defaultSignedLevelSet);
2291 m_surfaceInfo(nullptr)
2304 setSurface(std::move(surface), featureAngle);
2329 setSurface(surface, featureAngle, surfaceSmoothing);
2340 if (other.m_surfaceInfo) {
2343 m_surfaceInfo =
nullptr;
2370 return m_surfaceInfo->getSurface();
2405 if (m_surfaceInfo) {
2408 throw std::runtime_error (
"The surface can only be set once.");
2412 m_surfaceInfo->setSurface(std::move(surface), featureAngle);
2454 if (m_surfaceInfo) {
2457 throw std::runtime_error (
"The surface can only be set once.");
2461 m_surfaceInfo->setSurface(surface, featureAngle);
2486 if (m_surfaceInfo) {
2489 throw std::runtime_error (
"The surface can only be set once.");
2493 m_surfaceInfo->setSurface(surface, featureAngle, surfaceSmoothing);
2508 return m_surfaceInfo->getSearchTree();
2516 return m_surfaceInfo->getFeatureAngle();
2525 return m_surfaceInfo->getSurfaceSmoothing();
2542 fillCartesianCellZoneCache();
2569 fillCartesianCellZoneCache();
2588void LevelSetSegmentationObject::fillCartesianCellZoneCache()
2593 throw std::runtime_error(
"The function needs a Cartesian kernels.");
2597 const VolCartesian &mesh = *(cartesianKernel->
getMesh() ) ;
2598 int meshDimension = mesh.getDimension();
2599 long nCells = mesh.getCellCount();
2601 std::array<double,3> meshMinPoint;
2602 std::array<double,3> meshMaxPoint;
2603 mesh.getBoundingBox(meshMinPoint, meshMaxPoint) ;
2606 const SurfUnstructured &surface =
getSurface();
2614 std::unordered_set<long> processList;
2616 std::vector<std::array<double,3>> intersectionPoints;
2617 std::vector<std::array<double,3>> segmentVertexCoords;
2618 for (
const Cell &segment : surface.getCells()) {
2623 ConstProxyVector<long> segmentVertexIds = surface.getFacetOrderedVertexIds(segment);
2624 std::size_t nSegmentVertices = segmentVertexIds.size();
2627 segmentVertexCoords.resize(nSegmentVertices);
2628 surface.getVertexCoords(nSegmentVertices, segmentVertexIds.data(), segmentVertexCoords.data());
2633 int nInnerVertices = 0;
2634 for (
const std::array<double,3> &vertexPoint : segmentVertexCoords) {
2635 long cellId = mesh.locatePoint(vertexPoint);
2640 processList.insert(cellId);
2644 if (nInnerVertices == 0) {
2645 if (
CGElem::intersectBoxPolygon(meshMinPoint, meshMaxPoint, segmentVertexCoords,
false,
true,
true, intersectionPoints, meshDimension)) {
2646 for (
const std::array<double,3> &intersectionPoint : intersectionPoints){
2647 long cellId = mesh.locateClosestCell(intersectionPoint);
2648 processList.insert(cellId);
2658 for (
long cellId = 0; cellId < nCells; ++cellId) {
2666 std::vector<long> intersectedCellIds;
2667 std::vector<bool> alreadyProcessed(nCells,
false);
2668 while (!processList.empty()) {
2670 long cellId = *(processList.begin());
2671 processList.erase(processList.begin());
2674 if (alreadyProcessed[cellId]) {
2677 alreadyProcessed[cellId] =
true;
2684 intersectedCellIds.push_back(cellId);
2689 auto neighProcessor = [&processList, &alreadyProcessed](
long neighId,
int layer) {
2693 if (alreadyProcessed[neighId]) {
2698 processList.insert(neighId);
2704 mesh.processCellFaceNeighbours(cellId, 1, neighProcessor);
2709 for (std::size_t cellId : intersectedCellIds) {
2711 auto neighProcessor = [
this, &locationCache](
long neighId,
int layer) {
2726 mesh.processCellFaceNeighbours(cellId, 1, neighProcessor);
2730 for (
long cellId = 0; cellId < nCells; ++cellId) {
2731 CellCacheCollection::ValueCache<char>::Entry locationCacheEntry = locationCache->findEntry(cellId);
2737#if BITPIT_ENABLE_MPI==1
2739 if (mesh.isPartitioned()) {
2766 if (cellSupport < 0) {
2771 std::array<double,3> cellCentroid =
m_kernel->computeCellCentroid(
id);
2774 double cellUnsigendValue = std::abs(cellCacheValue);
2796 locationCache->insertEntry(
id,
static_cast<char>(cellLocation));
2807 return cellLocation;
2832 std::array<double,3> centroid =
m_kernel->computeCellCentroid(
id);
2847 std::array<double,3> centroid =
m_kernel->computeCellCentroid(
id);
2849 return _evalValue(centroid, support, signedLevelSet);
2862 std::array<double,3> centroid =
m_kernel->computeCellCentroid(
id);
2881 std::array<double,3> centroid =
m_kernel->computeCellCentroid(
id);
2896 std::array<double,3> centroid =
m_kernel->computeCellCentroid(
id);
2898 std::array<double, 3> projectionPoint;
2899 std::array<double, 3> projectionNormal;
2900 _evalProjection(centroid, support, signedLevelSet, &projectionPoint, &projectionNormal);
2902 return projectionNormal;
2942 return _evalValue(point, support, signedLevelSet);
2971 bool signedLevelSet,
2972 std::array<double, 3> *projectionPoint,
2973 std::array<double, 3> *projectionNormal)
const
2978 return _evalProjection(point, support, signedLevelSet, projectionPoint, projectionNormal);
2996 throw std::runtime_error(
"Unable to evaluate the sign: the support is not valid.");
3001 return evalValueSign(m_surfaceInfo->evalDistance(point, supportItr,
true));
3013 bool signedLevelSet)
const
3019 if (!signedLevelSet ||
empty()) {
3023 throw std::runtime_error(
"With an invalid support, only the unsigend levelset can be evaluated.");
3028 double distance = m_surfaceInfo->evalDistance(point, supportItr, signedLevelSet);
3037 if (signedLevelSet) {
3040 value = std::abs(distance);
3055 bool signedLevelSet)
const
3061 if (!signedLevelSet ||
empty()) {
3065 throw std::runtime_error(
"With an invalid support, only the unsigend levelset can be evaluated.");
3070 std::array<double,3> distanceVector;
3071 double distance = m_surfaceInfo->evalDistance(point, supportItr, signedLevelSet, &distanceVector);
3075 if (signedLevelSet) {
3076 return m_surfaceInfo->evalNormal(point, supportItr);
3078 return {{0., 0., 0.}};
3083 std::array<double,3> gradient = distanceVector / distance;
3096 return _evalSupport(point, std::numeric_limits<double>::max());
3109 long closestSegmentId;
3110 double closestDistance;
3111 m_surfaceInfo->getSearchTree().findPointClosestCell(point, searchRadius, &closestSegmentId, &closestDistance);
3113 return closestSegmentId;
3130 bool signedLevelSet,
3131 std::array<double, 3> *projectionPoint,
3132 std::array<double, 3> *projectionNormal)
const
3138 if (!signedLevelSet ||
empty()) {
3143 throw std::runtime_error(
"With an invalid support, only the unsigend levelset can be evaluated.");
3150 m_surfaceInfo->evalProjection(point, segmentItr, projectionPoint, projectionNormal);
3154 if (!signedLevelSet) {
3155 (*projectionNormal) *=
static_cast<double>(
evalSign(point));
3169 bool minimumValid =
false;
3172 double segmentSize = surface.
evalCellSize(cell.getId());
3173 if (segmentSize < 0) {
3177 minimumValid =
true;
3178 minimumSize = std::min(segmentSize, minimumSize);
3181 if (!minimumValid) {
3200 double segmentSize = surface.
evalCellSize(cell.getId());
3201 maximumSize = std::max(segmentSize, maximumSize);
3245 return getCellReferenceObject(
id)->evalCellSurface(
id);
3256 return getCellReferenceObject(
id)->evalCellSupport(
id, searchRadius);
3267 return getCellReferenceObject(
id)->evalCellPart(
id);
3282 if ( !resultObject ) {
3286 std::array<double,3> normal = resultObject->
evalCellNormal(
id, signedLevelSet);
3287 if (signedLevelSet) {
3288 normal *=
static_cast<double>(result.getObjectSign());
3303 return getReferenceObject(point)->evalSurface(point);
3314 return getReferenceObject(point)->evalSupport(point);
3327 return getReferenceObject(point)->evalSupport(point, searchRadius);
3342 bool signedLevelSet,
3343 std::array<double, 3> *projectionPoint,
3344 std::array<double, 3> *projectionNormal)
const
3349 if ( !resultObject ) {
3354 resultObject->
evalProjection(point, signedLevelSet, projectionPoint, projectionNormal);
3355 if (signedLevelSet) {
3356 (*projectionNormal) *=
static_cast<double>(result.
getObjectSign());
3369 return getReferenceObject(point)->evalPart(point);
3399 return getSourceObject()->evalCellSurface(
id);
3416 return getSourceObject()->evalCellSupport(
id, searchRadius);
3427 return getCellReferenceObject(
id)->evalCellPart(
id);
3439 std::array<double,3> normal = getSourceObject()->evalCellNormal(
id, signedLevelSet);
3440 if (signedLevelSet) {
3455 return getSourceObject()->evalSurface(point);
3466 return getSourceObject()->evalSupport(point);
3479 return getSourceObject()->evalSupport(point, searchRadius);
3490 return getSourceObject()->evalPart(point);
3505 bool signedLevelSet,
3506 std::array<double, 3> *projectionPoint,
3507 std::array<double, 3> *projectionNormal)
const
3509 getSourceObject()->evalProjection(point, signedLevelSet, projectionPoint, projectionNormal);
3510 if (signedLevelSet) {
3511 (*projectionNormal) *= -1.;
The Cell class defines the cells.
ElementType getType() const
static ConstProxyVector< long > getVertexIds(ElementType type, const long *connectivity)
int getVertexCount() const
Base class which deals with boolean operation between two LevelSetObjects.
Class which deals with boolean operation between two LevelSetObjects.
Allow to evaluate the result of a boolean operation between two LevelSetObjects.
const SourceLevelSetObject * getObject() const
int getObjectSign() const
Implements LevelSetKernel for cartesian meshes.
VolCartesian * getMesh() const override
Base class that allows to evaluate the complement of a LevelSetObjects.
Class that allows to evaluate the complement of a LevelSetObjects.
virtual VolumeKernel * getMesh() const
std::unique_ptr< DataCommunicator > createDataCommunicator() const
static const LevelSetIntersectionMode CELL_LOCATION_INTERSECTION_MODE
void fillFieldCellCache(LevelSetField field, const std::vector< long > &cellIds)
short evalValueSign(double value) const
LevelSetKernel * m_kernel
void completeCellCacheExchange(const std::unordered_map< int, std::vector< long > > &sendCellIds, std::size_t cacheIds, DataCommunicator *)
virtual void addVTKOutputData(LevelSetField field, const std::string &objectName)
static const bool CELL_CACHE_IS_SIGNED
double m_narrowBandSize
Size of narrow band.
virtual std::string getVTKOutputFieldName(LevelSetField field) const
virtual short evalSign(const std::array< double, 3 > &point) const
virtual LevelSetIntersectionStatus _intersectSurface(long, double distance, LevelSetIntersectionMode=LevelSetIntersectionMode::FAST_FUZZY) const
virtual LevelSetFieldset getSupportedFields() const
virtual void fillCellLocationCache()
virtual short evalCellSign(long id) const
LevelSetCellLocation getCellLocation(long id) const
std::size_t m_cellLocationCacheId
Id of the cache that will keep track if cell zones.
virtual void flushVTKOutputData(std::fstream &stream, VTKFormat format, LevelSetField field) const
virtual std::size_t createFieldCellCache(LevelSetField field, std::size_t cacheId=CellCacheCollection::NULL_CACHE_ID)
std::string getVTKOutputDataName(LevelSetField field, const std::string &objectName) const
void startCellCacheExchange(const std::unordered_map< int, std::vector< long > > &recvCellIds, std::size_t cacheIds, DataCommunicator *) const
Implements visitor pattern fo segmentated geometries.
void evalProjection(const std::array< double, 3 > &point, bool signedLevelSet, std::array< double, 3 > *projectionPoint, std::array< double, 3 > *projectionNormal) const
void fillFieldCellCache(LevelSetField field, long id) override
void flushVTKOutputData(std::fstream &stream, VTKFormat format, LevelSetField field) const override
std::array< double, 3 > evalNormal(const std::array< double, 3 > &point, bool signedLevelSet) const
long getSupport(long cellId) const
const SurfUnstructured & evalSurface(const std::array< double, 3 > &point) const
LevelSetFieldset getSupportedFields() const override
std::array< double BITPIT_COMMA 3 > getNormal(long cellId) const
LevelSetIntersectionStatus _intersectSurface(long, double distance, LevelSetIntersectionMode=LevelSetIntersectionMode::FAST_FUZZY) const override
virtual int _evalPart(const std::array< double, 3 > &point) const
void addVTKOutputData(LevelSetField field, const std::string &objectName) override
int getPart(long cellId) const
std::array< double, 3 > evalCellNormal(long id, bool signedLevelSet) const
double getSurfaceFeatureSize(long cellId) const
virtual int _evalCellPart(long id) const
std::size_t createFieldCellCache(LevelSetField field, std::size_t cacheId=CellCacheCollection::NULL_CACHE_ID) override
int evalPart(const std::array< double, 3 > &point) const
long evalCellSupport(long id, double searchRadius=AUTOMATIC_SEARCH_RADIUS) const
int evalCellPart(long id) const
static BITPIT_PUBLIC_API const double AUTOMATIC_SEARCH_RADIUS
long evalSupport(const std::array< double, 3 > &point) const
const SurfUnstructured & evalCellSurface(long id) const
std::string getVTKOutputFieldName(LevelSetField field) const override
Implements visitor pattern fo segmentated geometries.
const SurfUnstructured & _evalSurface(const std::array< double, 3 > &point) const override
double getMaxSurfaceFeatureSize() const
LevelSetSegmentationObject * clone() const override
long _evalCellSupport(long id, double searchRadius=AUTOMATIC_SEARCH_RADIUS) const override
LevelSetCellLocation fillCellGeometricNarrowBandLocationCache(long id) override
long _evalSupport(const std::array< double, 3 > &point) const override
short _evalSign(const std::array< double, 3 > &point) const override
std::array< double, 3 > _evalGradient(const std::array< double, 3 > &point, bool signedLevelSet) const override
double _evalCellValue(long id, bool signedLevelSet) const override
bool empty() const override
std::array< double, 3 > _evalCellGradient(long id, bool signedLevelSet) const override
void fillCellLocationCache() override
LevelSetSurfaceSmoothing getSurfaceSmoothing() const
LevelSetSegmentationObject(int)
short _evalCellSign(long id) const override
double _evalValue(const std::array< double, 3 > &point, bool signedLevelSet) const override
void setSurface(std::unique_ptr< const SurfUnstructured > &&surface, bool force=false)
double getMinSurfaceFeatureSize() const
const SurfUnstructured & getSurface() const
std::array< double, 3 > _evalCellNormal(long id, bool signedLevelSet) const override
const SurfUnstructured & _evalCellSurface(long id) const override
double getFeatureAngle() const
void _evalProjection(const std::array< double, 3 > &point, bool signedLevelSet, std::array< double, 3 > *projectionPoint, std::array< double, 3 > *projectionNormal) const override
const SurfaceSkdTree & getSearchTree() const
void evalProjection(const std::array< double, 3 > &point, const SegmentConstIterator &segmentItr, std::array< double, 3 > *projectionPoint, std::array< double, 3 > *projectionNormal) const
double evalDistance(const std::array< double, 3 > &point, const SegmentConstIterator &segmentItr, bool signedDistance, std::array< double, 3 > *distanceVector) const
const SurfaceSkdTree & getSearchTree() const
const SurfUnstructured & getSurface() const
std::array< double, 3 > evalDistanceVector(const std::array< double, 3 > &point, const SegmentConstIterator &segmentItr) const
void setSurface(std::unique_ptr< const SurfUnstructured > &&surface, double featureAngle=DEFAULT_FEATURE_ANGLE)
std::array< double, 3 > evalNormal(const std::array< double, 3 > &point, const SegmentConstIterator &segmentItr) const
double getFeatureAngle() const
static BITPIT_PUBLIC_API const double DEFAULT_FEATURE_ANGLE
LevelSetSurfaceSmoothing getSurfaceSmoothing() const
std::array< double, 3 > evalPseudoNormal(const SurfUnstructured::CellConstIterator &segmentIterator, const double *lambda) const
LevelSetSegmentationSurfaceInfo()
The class LevelSetCache is the base class for defining caches that store values.
AdjacenciesBuildStrategy getAdjacenciesBuildStrategy() const
PiercedVector< Cell > & getCells()
bool empty(bool global=true) const
VTKUnstructuredGrid & getVTK()
PiercedVector< Vertex > & getVertices()
void processCellFaceNeighbours(long seedId, int nLayers, Function function) const
std::vector< long > findCellVertexNeighs(long id, bool complete=true) const
const std::array< double, 3 > & getVertexCoords(long id) const
CellConstIterator getCellConstIterator(long id) const
Iterator for the class PiercedStorage.
void setStaticKernel(const PiercedKernel< id_t > *kernel)
void unsetKernel(bool release=true)
__PS_REFERENCE__ rawAt(std::size_t pos, std::size_t offset=0)
__PS_POINTER__ rawData(std::size_t pos, std::size_t offset=0)
void fill(const value_t &value)
iterator begin() noexcept
Metafunction for generating a list of elements that can be either stored in an external vectror or,...
The SurfUnstructured class defines an unstructured surface triangulation.
int getFacetOrderedLocalEdge(const Cell &facet, std::size_t n) const
virtual void evalVertexNormals(long id, int vertex, std::size_t nVertexNeighs, const long *vertexNeighs, double limit, std::array< double, 3 > *unlimitedNormal, std::array< double, 3 > *limitedNormal) const
virtual std::array< double, 3 > evalFacetNormal(long, const std::array< double, 3 > &orientation={{0., 0., 1.}}) const
int getFacetOrderedLocalVertex(const Cell &facet, std::size_t n) const
ConstProxyVector< long > getFacetOrderedVertexIds(const Cell &facet) const
std::array< double, 3 > evalLimitedVertexNormal(long, int, double) const
void evalBarycentricCoordinates(long id, const std::array< double, 3 > &point, double *lambda) const
virtual void evalEdgeNormals(long id, int edge, double limit, std::array< double, 3 > *unlimitedNormal, std::array< double, 3 > *limitedNormal) const
double evalCellSize(long id) const override
The SurfaceSkdTree implements a Bounding Volume Hierarchy tree for surface patches.
A base class for VTK input output.
VTKField & addData(VTKField &&field)
The VolumeKernel class provides an interface for defining volume patches.
array3D projectPointTriangle(array3D const &, array3D const &, array3D const &, array3D const &)
array3D projectPointSegment(array3D const &, array3D const &, array3D const &)
int convertBarycentricToFlagSegment(std::array< double, 2 > const &, double tolerance=DEFAULT_DISTANCE_TOLERANCE)
int convertBarycentricToFlagPolygon(std::vector< double > const &, double tolerance=DEFAULT_DISTANCE_TOLERANCE)
bool intersectBoxPolygon(array3D const &, array3D const &, std::vector< array3D > const &, int dim=3, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
array3D projectPointPolygon(array3D const &, std::vector< array3D > const &)
void sum(const std::array< T, d > &x, T1 &s)
double norm(const std::array< T, d > &x, int p)
std::array< T, 3 > crossProduct(const std::array< T, 3 > &x, const std::array< T, 3 > &y)
T dotProduct(const std::array< T, d > &x, const std::array< T, d > &y)
double norm2(const std::array< T, d > &x)
#define BITPIT_UNUSED(variable)
#define BITPIT_CREATE_WORKSPACE(workspace, item_type, size, stack_size)
LevelSetIntersectionStatus
@ UNKNOWN
Unknown location.
@ NARROW_BAND_INTERSECTED
Narrow band zone, the cell intersects the surface.
const std::array< double, 3 > GRADIENT
const std::array< double, 3 > POINT
const std::array< double, 3 > NORMAL