42#include <vtkSmartPointer.h>
43#include <vtkUnstructuredGrid.h>
45#include <vtkCellArray.h>
46#include <vtkFloatArray.h>
47#include <vtkPointData.h>
48#include <vtkTriangle.h>
49#include <vtkXMLUnstructuredGridWriter.h>
62 T bb = 0., bc = 0., cc = 0.;
64 for (
int i = 0; i < 3; i++) {
72 normal[0] = b[1] * c[2] - b[2] * c[1];
73 normal[1] = b[2] * c[0] - b[0] * c[2];
74 normal[2] = b[0] * c[1] - b[1] * c[0];
82 T D = 1.0 / (cc * bb - bc * bc);
91 for (
int i = 0; i < 3; i++) {
92 uBeta[i] = b[i] * ccD - c[i] * bcD;
93 uGamma[i] = c[i] * bbD - b[i] * bcD;
94 kBeta -= A[i] * uBeta[i];
95 kGamma -= A[i] * uGamma[i];
96 d += A[i] * normal[i];
105 center[0] = (point[0][0] + point[1][0]
107 center[1] = (point[0][1] + point[1][1]
109 center[2] = (point[0][2] + point[1][2]
119 vec[0] = point[0][0] - point[1][0];
120 vec[1] = point[0][1] - point[1][1];
121 vec[2] = point[0][2] - point[1][2];
129 vec[0] = point[0][0] - point[2][0];
130 vec[1] = point[0][1] - point[2][1];
131 vec[2] = point[0][2] - point[2][2];
139 const T epsilon = std::numeric_limits<BaseType<T>>::epsilon()*T(10);
141 const T beta = pt * uBeta + kBeta;
142 const T gamma = pt * uGamma + kGamma;
145 if (
util::nearZero(
norm(pt - (point[0] + beta*(point[1]-point[0]) + gamma*(point[2]-point[0]))), epsilon) ) {
146 const T alpha = T(1) - beta - gamma;
173 for (
int i = 0; i < 3; i++) {
174 rn += dir[i] * normal[i];
179 std::cout <<
"Pt: " << pt[0] <<
" " << pt[1] <<
" " << pt[2] << std::endl;
182 std::cout <<
"testPt: " << testPt[0] <<
" " << testPt[1] <<
" " << testPt[2]
185 std::cout <<
"PosNeg: "
186 << normal[0] * testPt[0] + normal[1] * testPt[1] + normal[2] * testPt[2]
189 std::cout <<
"Normal: " << normal[0] <<
" " << normal[1] <<
" " << normal[2]
194 if (
util::fabs(rn) < std::numeric_limits<T>::epsilon()) {
197 std::cout <<
"FALSE 1" << std::endl;
202 alpha = d - testPt[0] * normal[0] - testPt[1] * normal[1] - testPt[2] * normal[2];
207 if (alpha < -std::numeric_limits<T>::epsilon()) {
210 std::cout <<
"FALSE 2" << std::endl;
215 for (
int i = 0; i < 3; i++) {
216 q[i] = testPt[i] + alpha * dir[i];
219 for (
int i = 0; i < 3; i++) {
220 beta += uBeta[i] * q[i];
229 if (beta < -std::numeric_limits<T>::epsilon()) {
233 std::cout <<
"FALSE 3 BETA " << beta <<
" DIST " << dist << std::endl;
239 for (
int i = 0; i < 3; i++) {
240 gamma += uGamma[i] * q[i];
242 if (gamma < -std::numeric_limits<T>::epsilon()) {
245 std::cout <<
"FALSE 4 GAMMA " << gamma <<
" DIST " << dist << std::endl;
250 if (1. - beta - gamma < -std::numeric_limits<T>::epsilon()) {
253 std::cout <<
"FALSE 5 VAL " << 1 - beta - gamma <<
" DIST " << dist
260 std::cout <<
"TRUE" <<
" GAMMA " << gamma <<
" BETA " << beta << std::endl;
275 const T nEps = -std::numeric_limits<T>::epsilon();
276 const T Eps = std::numeric_limits<T>::epsilon();
282 T snom = (pt - point[0])*ab;
283 T sdenom = (pt - point[1])*(point[0] - point[1]);
285 T tnom = (pt - point[0])*ac;
286 T tdenom = (pt - point[2])*(point[0] - point[2]);
288 if (snom < nEps && tnom < nEps) {
292 T unom = (pt - point[1])*bc;
293 T udenom = (pt - point[2])*(point[1] - point[2]);
295 if (sdenom < nEps && unom < nEps) {
298 if (tdenom < nEps && udenom < nEps) {
304 if (vc < nEps && snom > Eps && sdenom > Eps) {
305 return point[0] + snom / (snom + sdenom) * ab;
310 if (va < nEps && unom > Eps && udenom > Eps) {
311 return point[1] + unom / (unom + udenom) * bc;
316 if (vb < nEps && tnom > Eps && tdenom > Eps) {
317 return point[0] + tnom / (tnom + tdenom) * ac;
320 T u = va / (va + vb + vc);
321 T v = vb / (va + vb + vc);
324 return u * point[0] + v * point[1] + w * point[2];
346 if(input[0] < sensitivity && input[1] >= sensitivity && input[2] >= sensitivity )
353 if(input[0] >= sensitivity && input[1] < sensitivity && input[2] >= sensitivity )
360 if(input[0] >= sensitivity && input[1] >= sensitivity && input[2] < sensitivity )
375 if (input[0] < sensitivity && input[1] < sensitivity && input[2] < sensitivity )
377 cout <<
"Error isVortexPoint! Possible reduce sensitivity!" << std::endl;
380 if(input[0] < sensitivity && input[1] < sensitivity)
386 if(input[0] < sensitivity && input[2] < sensitivity)
392 if(input[1] < sensitivity && input[2] < sensitivity)
403 const auto AB = point[1] - point[0];
404 const auto AC = point[2] - point[0];
405 const auto AP = physR - point[0];
407 const auto d1 = AB * AP;
408 const auto d2 = AC * AP;
409 if (d1 <= T{0} && d2 <= T{0}) {
413 auto BP = physR - point[1];
416 if (d3 >= T{0} && d4 <= d3) {
420 auto vc = d1 * d4 - d3 * d2;
421 if (vc <= T{0} && d1 >= T{0} && d3 <= T{0}) {
422 auto v = d1 / (d1 - d3);
423 return point[0] + v * AB;
426 auto CP = physR - point[2];
429 if (d6 >= T{0} && d5 <= d6) {
433 auto vb = d5 * d2 - d1 * d6;
434 if (vb <= T{0} && d2 >= T{0} && d6 <= T{0}) {
435 auto w = d2 / (d2 - d6);
436 return point[0] + w * AC;
439 auto va = d3 * d6 - d5 * d4;
440 if (va <= T{0} && (d4 - d3) >= T{0} && (d5 - d6) >= T{0}) {
441 auto w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
442 return point[1] + w * (point[2] - point[1]);
445 auto denom = 1.0 / (va + vb + vc);
448 return point[0] + AB * v + AC * w;
457 clout(std::cout,
"STLmesh")
459 std::ifstream f(fName.c_str(), std::ios::in);
460 _triangles.reserve(10000);
462 throw std::runtime_error(
"STL File not valid.");
467 const std::string asciiHeader =
"solid";
468 if (std::string(buf) == asciiHeader) {
469 f.seekg(0, std::ios::beg);
487 for (
int k = 0; k < 3; k++) {
488 tri.
point[0][k] *= stlSize;
489 tri.
point[1][k] *= stlSize;
490 tri.
point[2][k] *= stlSize;
496 _min[0] = tri.
point[0][0];
497 _min[1] = tri.
point[0][1];
498 _min[2] = tri.
point[0][2];
500 _max[0] = tri.
point[0][0];
501 _max[1] = tri.
point[0][1];
502 _max[2] = tri.
point[0][2];
549 _triangles.push_back(tri);
558 else if (s0 ==
"endsolid") {
566 f.open(fName.c_str(), std::ios::in | std::ios::binary);
571 throw std::runtime_error(
"STL File not valid.");
576 f.read(
reinterpret_cast<char *
>(&nFacets),
sizeof(int32_t));
579 throw std::runtime_error(
"STL File not valid.");
583 std::uint16_t uint16;
584 for (int32_t i = 0; i < nFacets; ++i) {
585 for (
unsigned int j = 0; j < 12; ++j) {
586 f.read(
reinterpret_cast<char *
>(&v[j]),
sizeof(
float));
588 f.read(
reinterpret_cast<char *
>(&uint16),
sizeof(std::uint16_t));
593 tri.
point[0][0] = v[3];
594 tri.
point[0][1] = v[4];
595 tri.
point[0][2] = v[5];
596 tri.
point[1][0] = v[6];
597 tri.
point[1][1] = v[7];
598 tri.
point[1][2] = v[8];
599 tri.
point[2][0] = v[9];
600 tri.
point[2][1] = v[10];
601 tri.
point[2][2] = v[11];
603 for (
int k = 0; k < 3; k++) {
604 tri.
point[0][k] *= stlSize;
605 tri.
point[1][k] *= stlSize;
606 tri.
point[2][k] *= stlSize;
609 _min[0] = tri.
point[0][0];
610 _min[1] = tri.
point[0][1];
611 _min[2] = tri.
point[0][2];
613 _max[0] = tri.
point[0][0];
614 _max[1] = tri.
point[0][1];
615 _max[2] = tri.
point[0][2];
660 _triangles.push_back(tri);
672 : _fName(
"meshPoints.stl"),
676 clout(std::cout,
"STLmesh")
678 _triangles.reserve(10000);
679 for (
size_t i = 0; i < meshPoints.size() / 3; i++) {
681 tri.
point[0][0] = meshPoints[i*3 + 0][0];
682 tri.
point[0][1] = meshPoints[i*3 + 0][1];
683 tri.
point[0][2] = meshPoints[i*3 + 0][2];
685 tri.
point[1][0] = meshPoints[i*3 + 1][0];
686 tri.
point[1][1] = meshPoints[i*3 + 1][1];
687 tri.
point[1][2] = meshPoints[i*3 + 1][2];
689 tri.
point[2][0] = meshPoints[i*3 + 2][0];
690 tri.
point[2][1] = meshPoints[i*3 + 2][1];
691 tri.
point[2][2] = meshPoints[i*3 + 2][2];
692 for (
int k = 0; k < 3; k++) {
693 tri.
point[0][k] *= stlSize;
694 tri.
point[1][k] *= stlSize;
695 tri.
point[2][k] *= stlSize;
701 _min[0] = tri.
point[0][0];
702 _min[1] = tri.
point[0][1];
703 _min[2] = tri.
point[0][2];
705 _max[0] = tri.
point[0][0];
706 _max[1] = tri.
point[0][1];
707 _max[2] = tri.
point[0][2];
753 _triangles.push_back(tri);
777 clout <<
"Triangles: " << std::endl;
778 typename std::vector<STLtriangle<T> >::iterator it = _triangles.begin();
780 for (; it != _triangles.end(); ++it) {
781 clout << i++ <<
": " << it->point[0][0] <<
" " << it->point[0][1]
782 <<
" " << it->point[0][2] <<
" | " << it->point[1][0] <<
" "
783 << it->point[1][1] <<
" " << it->point[1][2] <<
" | "
784 << it->point[2][0] <<
" " << it->point[2][1] <<
" "
785 << it->point[2][2] << std::endl;
788 clout <<
"nTriangles=" << _triangles.size() <<
"; maxDist2=" << _maxDist2
790 clout <<
"minPhysR(StlMesh)=(" << getMin()[0] <<
"," << getMin()[1] <<
","
791 << getMin()[2] <<
")";
792 clout <<
"; maxPhysR(StlMesh)=(" << getMax()[0] <<
"," << getMax()[1] <<
","
793 << getMax()[2] <<
")" << std::endl;
800#ifdef PARALLEL_MODE_MPI
806 std::ofstream f(fullName.c_str());
807 f <<
"solid ascii " << fullName <<
"\n";
809 for (
unsigned int i = 0; i < _triangles.size(); i++) {
810 f <<
"facet normal " << _triangles[i].normal[0] <<
" "
811 << _triangles[i].normal[1] <<
" " << _triangles[i].normal[2] <<
"\n";
812 f <<
" outer loop\n";
813 f <<
" vertex " << _triangles[i].point[0][0] <<
" "
814 << _triangles[i].point[0][1] <<
" " << _triangles[i].point[0][2]
816 f <<
" vertex " << _triangles[i].point[1][0] <<
" "
817 << _triangles[i].point[1][1] <<
" " << _triangles[i].point[1][2]
819 f <<
" vertex " << _triangles[i].point[2][0] <<
" "
820 << _triangles[i].point[2][1] <<
" " << _triangles[i].point[2][2]
828 clout <<
"Write ... OK" << std::endl;
834 std::set<unsigned int>::iterator it = tris.begin();
835 for (; it != tris.end(); ++it) {
836 if (_triangles[*it].testRayIntersect(pt, dir, q, alpha) && alpha < 1) {
849 RayMode method,
bool verbose, T overlap, T max)
850 : _voxelSize(voxelSize),
854 _mesh(fName, stlSize),
856 clout(std::cout,
"STLreader")
861 clout <<
"Voxelizing ..." << std::endl;
864 Vector<T,3> extension = _mesh.getMax() - _mesh.getMin();
872 T radius = _voxelSize *
util::pow(2, j - 1);
875 for (
unsigned i = 0; i < 3; i++) {
876 center[i] = (_mesh.getMin()[i] + _mesh.getMax()[i]) / 2. - _voxelSize / 4.;
880 _tree =
new Octree<T>(center, radius, &_mesh, j, _overlap);
883 for (
int i = 0; i < 3; i++) {
884 this->
_myMin[i] = center[i] + _voxelSize / 2.;
885 this->
_myMax[i] = center[i] - _voxelSize / 2.;
887 for (
int i = 0; i < 3; i++) {
888 while (this->
_myMin[i] > _mesh.getMin()[i]) {
889 this->
_myMin[i] -= _voxelSize;
891 while (this->
_myMax[i] < _mesh.getMax()[i]) {
892 this->
_myMax[i] += _voxelSize;
894 this->
_myMax[i] -= _voxelSize;
895 this->
_myMin[i] += _voxelSize;
921 clout <<
"Voxelizing ... OK" << std::endl;
930 RayMode method,
bool verbose, T overlap, T max)
931 : _voxelSize(voxelSize),
934 _fName(
"meshPoints.stl"),
935 _mesh(meshPoints, stlSize),
937 clout(std::cout,
"STLreader")
942 clout <<
"Voxelizing ..." << std::endl;
945 Vector<T,3> extension = _mesh.getMax() - _mesh.getMin();
953 T radius = _voxelSize *
util::pow(2, j - 1);
956 for (
unsigned i = 0; i < 3; i++) {
957 center[i] = (_mesh.getMin()[i] + _mesh.getMax()[i]) / 2. - _voxelSize / 4.;
962 _tree =
new Octree<T>(center, radius, &_mesh, j, _overlap);
965 for (
int i = 0; i < 3; i++) {
966 this->
_myMin[i] = center[i] + _voxelSize / 2.;
967 this->
_myMax[i] = center[i] - _voxelSize / 2.;
969 for (
int i = 0; i < 3; i++) {
970 while (this->
_myMin[i] > _mesh.getMin()[i]) {
971 this->
_myMin[i] -= _voxelSize;
973 while (this->
_myMax[i] < _mesh.getMax()[i]) {
974 this->
_myMax[i] += _voxelSize;
976 this->
_myMax[i] -= _voxelSize;
977 this->
_myMin[i] += _voxelSize;
1018 clout <<
"Voxelizing ... OK" << std::endl;
1037 std::vector<Octree<T>*> leafs;
1038 _tree->getLeafs(leafs);
1039 typename std::vector<Octree<T>*>::iterator it = leafs.begin();
1042 int intersections = 0;
1045 T step = 1. / 1000. * _voxelSize;
1046 for (; it != leafs.end(); ++it) {
1049 pt = (*it)->getCenter();
1057 while (s[0] < _mesh.getMax()[0] + std::numeric_limits<T>::epsilon()) {
1058 node = _tree->
find(s, (*it)->getMaxdepth());
1063 inside += (intersections % 2);
1071 while (s[1] < _mesh.getMax()[1] + std::numeric_limits<T>::epsilon()) {
1072 node = _tree->
find(s, (*it)->getMaxdepth());
1077 inside += (intersections % 2);
1085 while (s[2] < _mesh.getMax()[2] + std::numeric_limits<T>::epsilon()) {
1086 node = _tree->
find(s, (*it)->getMaxdepth());
1091 inside += (intersections % 2);
1092 (*it)->setInside(inside > 1);
1101void STLreader<T>::indicate2()
1104 Vector<T,3> rayPt = _tree->getCenter() - rad + .5 * _voxelSize;
1105 Vector<T,3> pt = rayPt;
1112 T step = 1. / 1000. * _voxelSize;
1114 Octree<T>* node =
nullptr;
1115 unsigned short rayInside = 0;
1116 Vector<T,3> nodeInters;
1117 while (pt[0] < _mesh.getMax()[0] + std::numeric_limits<T>::epsilon()) {
1118 node = _tree->find(pt);
1120 nodeInters[2] = node->getCenter()[2] - node->getRadius();
1122 while (pt[1] < _mesh.getMax()[1] + std::numeric_limits<T>::epsilon()) {
1123 node = _tree->find(pt);
1125 nodeInters[2] = node->getCenter()[2] - node->getRadius();
1127 while (pt[2] < _mesh.getMax()[2] + std::numeric_limits<T>::epsilon()) {
1128 node = _tree->find(pt);
1129 node->checkRay(nodeInters, rayDir, rayInside);
1130 node->intersectRayNode(pt, rayDir, nodeInters);
1131 pt = nodeInters + step * rayDir;
1134 pt[1] += _voxelSize;
1137 pt[0] += _voxelSize;
1148void STLreader<T>::indicate2_Xray()
1151 Vector<T,3> rayPt = _tree->getCenter() - rad + .5 * _voxelSize;
1152 Vector<T,3> pt = rayPt;
1159 T step = 1. / 1000. * _voxelSize;
1161 Octree<T>* node =
nullptr;
1162 unsigned short rayInside = 0;
1163 Vector<T,3> nodeInters;
1164 while (pt[2] < _mesh.getMax()[2] + std::numeric_limits<T>::epsilon()) {
1165 node = _tree->find(pt);
1167 nodeInters[0] = node->getCenter()[0] - node->getRadius();
1169 while (pt[1] < _mesh.getMax()[1] + std::numeric_limits<T>::epsilon()) {
1170 node = _tree->find(pt);
1172 nodeInters[0] = node->getCenter()[0] - node->getRadius();
1174 while (pt[0] < _mesh.getMax()[0] + std::numeric_limits<T>::epsilon()) {
1175 node = _tree->find(pt);
1176 node->checkRay(nodeInters, rayDir, rayInside);
1177 node->intersectRayNode(pt, rayDir, nodeInters);
1178 pt = nodeInters + step * rayDir;
1181 pt[1] += _voxelSize;
1184 pt[2] += _voxelSize;
1194void STLreader<T>::indicate2_Yray()
1196 T rad = _tree->getRadius();
1197 Vector<T,3> rayPt = _tree->getCenter() - rad + .5 * _voxelSize;
1198 Vector<T,3> pt = rayPt;
1205 T step = 1. / 1000. * _voxelSize;
1207 Octree<T>* node =
nullptr;
1208 unsigned short rayInside = 0;
1209 Vector<T,3> nodeInters;
1210 while (pt[2] < _mesh.getMax()[2] + std::numeric_limits<T>::epsilon()) {
1211 node = _tree->find(pt);
1213 nodeInters[1] = node->getCenter()[1] - node->getRadius();
1215 while (pt[0] < _mesh.getMax()[0] + std::numeric_limits<T>::epsilon()) {
1216 node = _tree->find(pt);
1218 nodeInters[1] = node->getCenter()[1] - node->getRadius();
1220 while (pt[1] < _mesh.getMax()[1] + std::numeric_limits<T>::epsilon()) {
1221 node = _tree->find(pt);
1222 node->checkRay(nodeInters, rayDir, rayInside);
1223 node->intersectRayNode(pt, rayDir, nodeInters);
1224 pt = nodeInters + step * rayDir;
1227 pt[0] += _voxelSize;
1230 pt[2] += _voxelSize;
1239void STLreader<T>::indicate3()
1241 std::vector<Octree<T>*> leafs;
1242 _tree->getLeafs(leafs);
1243 typename std::vector<Octree<T>*>::iterator it = leafs.begin();
1245 Vector<T,3> dir, pt,
s;
1246 Octree<T>* node =
nullptr;
1247 T step = 1. / 1000. * _voxelSize;
1249 int sum_intersections;
1251 for (; it != leafs.end(); ++it) {
1252 pt = (*it)->getCenter();
1254 sum_intersections = 0;
1261 while (s[0] < _mesh.getMax()[0] + std::numeric_limits<T>::epsilon()) {
1262 node = _tree->find(s, (*it)->getMaxdepth());
1263 intersections = node->testIntersection(pt, dir);
1264 node->intersectRayNode(pt, dir, s);
1266 if (intersections > 0) {
1267 sum_intersections++;
1278 while (s[1] < _mesh.getMax()[1] + std::numeric_limits<T>::epsilon()) {
1279 node = _tree->find(s, (*it)->getMaxdepth());
1280 intersections = node->testIntersection(pt, dir);
1281 node->intersectRayNode(pt, dir, s);
1283 if (intersections > 0) {
1284 sum_intersections++;
1295 while (s[2] < _mesh.getMax()[2] + std::numeric_limits<T>::epsilon()) {
1296 node = _tree->find(s, (*it)->getMaxdepth());
1297 intersections = node->testIntersection(pt, dir);
1298 node->intersectRayNode(pt, dir, s);
1300 if (intersections > 0) {
1301 sum_intersections++;
1312 while (s[0] > _mesh.getMin()[0] - std::numeric_limits<T>::epsilon()) {
1313 node = _tree->find(s, (*it)->getMaxdepth());
1314 intersections = node->testIntersection(pt, dir);
1315 node->intersectRayNode(pt, dir, s);
1317 if (intersections > 0) {
1318 sum_intersections++;
1329 while (s[1] > _mesh.getMin()[1] - std::numeric_limits<T>::epsilon()) {
1330 node = _tree->find(s, (*it)->getMaxdepth());
1331 intersections = node->testIntersection(pt, dir);
1332 node->intersectRayNode(pt, dir, s);
1334 if (intersections > 0) {
1335 sum_intersections++;
1346 while (s[2] > _mesh.getMin()[2] - std::numeric_limits<T>::epsilon()) {
1347 node = _tree->find(s, (*it)->getMaxdepth());
1348 intersections = node->testIntersection(pt, dir);
1349 node->intersectRayNode(pt, dir, s);
1351 if (intersections > 0) {
1352 sum_intersections++;
1356 (*it)->setInside(sum_intersections > 5);
1364 if (isInsideRootTree(input)) {
1365 std::vector<T> tmp(input, input + 3);
1366 output[0] = _tree->find(tmp)->getInside();
1375 T coords = _tree->getRadius();
1377 return c[0] - coords < input[0] && input[0] < c[0] + coords && c[1] - coords < input[1]
1378 && input[1] < c[1] + coords && c[2] - coords < input[2] && input[2] < c[2] + coords;
1385 T coords = _tree->getRadius();
1388 for(
int i = 0; i < 3; ++i) {
1391 return closestPoint;
1402 Vector<T,3> extends = _mesh.getMax() - _mesh.getMin();
1406 Vector<T,3> center = _mesh.getMin() + 1 / 2. * extends;
1407 T step = _voxelSize / 1000., a = 0;
1409 for (
int i = 0; i < 3; i++) {
1413 if (!(_mesh.getMin()[0] < origin[0] && origin[0] < _mesh.getMax()[0]
1414 && _mesh.getMin()[1] < origin[1] && origin[1] < _mesh.getMax()[1]
1415 && _mesh.getMin()[2] < origin[2] && origin[2] < _mesh.getMax()[2])) {
1417 bool foundQ =
false;
1420 d = _mesh.getMin()[0];
1421 t = (d - origin[0]) / dir[0];
1422 pt[0] = origin[0] + (t + step) * dir[0];
1423 pt[1] = origin[1] + (t + step) * dir[1];
1424 pt[2] = origin[2] + (t + step) * dir[2];
1426 if (_mesh.getMin()[1] < pt[1] && pt[1] < _mesh.getMax()[1]
1427 && _mesh.getMin()[2] < pt[2] && pt[2] < _mesh.getMax()[2]) {
1431 else if (dir[0] < 0) {
1432 d = _mesh.getMax()[0];
1433 t = (d - origin[0]) / dir[0];
1434 pt[0] = origin[0] + (t + step) * dir[0];
1435 pt[1] = origin[1] + (t + step) * dir[1];
1436 pt[2] = origin[2] + (t + step) * dir[2];
1437 if (_mesh.getMin()[1] < pt[1] && pt[1] < _mesh.getMax()[1]
1438 && _mesh.getMin()[2] < pt[2] && pt[2] < _mesh.getMax()[2]) {
1443 if (dir[1] > 0 && !foundQ) {
1444 d = _mesh.getMin()[1];
1445 t = (d - origin[1]) / dir[1];
1446 pt[0] = origin[0] + (t + step) * dir[0];
1447 pt[1] = origin[1] + (t + step) * dir[1];
1448 pt[2] = origin[2] + (t + step) * dir[2];
1449 if (_mesh.getMin()[0] < pt[0] && pt[0] < _mesh.getMax()[0]
1450 && _mesh.getMin()[2] < pt[2] && pt[2] < _mesh.getMax()[2]) {
1454 else if (dir[1] < 0 && !foundQ) {
1455 d = _mesh.getMax()[1];
1456 t = (d - origin[1]) / dir[1];
1457 pt[0] = origin[0] + (t + step) * dir[0];
1458 pt[1] = origin[1] + (t + step) * dir[1];
1459 pt[2] = origin[2] + (t + step) * dir[2];
1460 if (_mesh.getMin()[0] < pt[0] && pt[0] < _mesh.getMax()[0]
1461 && _mesh.getMin()[2] < pt[2] && pt[2] < _mesh.getMax()[2]) {
1466 if (dir[2] > 0 && !foundQ) {
1467 d = _mesh.getMin()[2];
1468 t = (d - origin[2]) / dir[2];
1469 pt[0] = origin[0] + (t + step) * dir[0];
1470 pt[1] = origin[1] + (t + step) * dir[1];
1471 pt[2] = origin[2] + (t + step) * dir[2];
1472 if (_mesh.getMin()[0] < pt[0] && pt[0] < _mesh.getMax()[0]
1473 && _mesh.getMin()[1] < pt[1] && pt[1] < _mesh.getMax()[1]) {
1477 else if (dir[2] < 0 && !foundQ) {
1478 d = _mesh.getMax()[2];
1479 t = (d - origin[2]) / dir[2];
1480 pt[0] = origin[0] + (t + step) * dir[0];
1481 pt[1] = origin[1] + (t + step) * dir[1];
1482 pt[2] = origin[2] + (t + step) * dir[2];
1483 if (_mesh.getMin()[0] < pt[0] && pt[0] < _mesh.getMax()[0]
1484 && _mesh.getMin()[1] < pt[1] && pt[1] < _mesh.getMax()[1]) {
1494 while ((
util::fabs(pt[0] - center[0]) < extends[0])
1495 && (
util::fabs(pt[1] - center[1]) < extends[1])
1496 && (
util::fabs(pt[2] - center[2]) < extends[2])) {
1497 node = _tree->
find(pt);
1500 distance =
norm(vek);
1507 for (
int i = 0; i < 3; i++) {
1508 pt[i] = s[i] + step * dir[i];
1521 leafNode = _tree->
find(pt);
1524 const std::vector<unsigned int>& triangleIndices = leafNode->
getTriangles();
1525 for (
unsigned int idx : triangleIndices) {
1531 for (
const STLtriangle<T>& triangle : _mesh.getTriangles()) {
1538Vector<T,3> STLreader<T>::evalNormalOnSurface(
const PhysR<T,3>& pt,
const Vector<T,3>& fallbackNormal)
1541 unsigned countTriangles = 0;
1542 Vector<T,3>
normal(T(0));
1544 iterateOverCloseTriangles(pt, [&](
const STLtriangle<T>& triangle){
1553 if (countTriangles > 0) {
1554 return normal / countTriangles;
1558 return fallbackNormal;
1562template<SignMode SIGNMODE>
1563Vector<T,3> STLreader<T>::evalSurfaceNormal(
const Vector<T,3>& origin)
1566 Vector<T,3> closestPointOnSurface(0.);
1567 const STLtriangle<T>* closestTriangle =
nullptr;
1568 T
distance = std::numeric_limits<T>::max();
1569 const PhysR<T,3> pt(closestPointInBoundingBox(origin));
1571 iterateOverCloseTriangles(pt, [&](
const STLtriangle<T>& triangle) {
1573 PhysR<T,3> const currDistance = pt - pointOnTriangle;
1575 if (distance > currDistanceNorm) {
1578 closestPointOnSurface = pointOnTriangle;
1586 normal *= evalSignForSignedDistance<SIGNMODE>(origin, distance);
1589 normal = evalNormalOnSurface(closestPointOnSurface, closestTriangle->getNormal());
1606template<SignMode SIGNMODE>
1607Vector<T,3> STLreader<T>::evalSurfaceNormalForPseudoNormal(
const Vector<T,3>& origin, Vector<T,3> & outputPointOnSurface)
1610 Vector<T,3> closestPointOnSurface(0.);
1611 const STLtriangle<T>* closestTriangle =
nullptr;
1612 T
distance = std::numeric_limits<T>::max();
1613 const PhysR<T,3> pt(closestPointInBoundingBox(origin));
1615 iterateOverCloseTriangles(pt, [&](
const STLtriangle<T>& triangle) {
1617 PhysR<T,3> const currDistance = pt - pointOnTriangle;
1619 if (distance > currDistanceNorm) {
1622 closestPointOnSurface = pointOnTriangle;
1633 normal = evalNormalOnSurface(closestPointOnSurface, closestTriangle->getNormal());
1634 outputPointOnSurface = closestPointOnSurface;
1651template <
typename T>
1652template <SignMode SIGNMODE>
1653short STLreader<T>::evalSignForSignedDistance(
1654 const Vector<T,3>& pt, [[maybe_unused]]
const T distance, Vector<T,3> vecdist, STLtriangle<T> stlT)
1661 if(distance < _voxelSize) {
1663 sign = evalSignForSignedDistanceFromWindingNumber(pt);
1671 sign = evalSignForSignedDistanceFromCache(pt);
1675 sign = evalSignForSignedDistanceFromCache(pt);
1681short STLreader<T>::evalSignForSignedDistanceFromPseudonormal(
const Vector<T,3>& pseudonormal,
const Vector<T,3>& distance)
1683 const T projection = pseudonormal *
distance;
1685 if(projection > 0) {
1688 else if (projection < 0 ) {
1697short STLreader<T>::evalSignForSignedDistanceFromNormal(
const Vector<T,3>& normal,
const Vector<T,3>& distance)
1701 if(projection > 0) {
1704 else if (projection < 0 ) {
1714short STLreader<T>::evalSignForSignedDistanceFromWindingNumber(
const Vector<T,3>& pt)
1718 for (
const STLtriangle<T>& triangle : _mesh.getTriangles()) {
1723 const T aNorm =
norm(a);
1724 const T bNorm =
norm(b);
1725 const T cNorm =
norm(c);
1728 const T denominator = aNorm * bNorm * cNorm + (a*b) * cNorm + (b*c) * aNorm + (
c*a) * bNorm;
1730 windingNumber +=
util::atan2(numerator,denominator);
1741template <
typename T>
1744 return signedDistance<SignMode::CACHED>(input);
1747template <
typename T>
1750 return signedDistance<SignMode::EXACT>(input);
1756template <
typename T>
1757template <SignMode SIGNMODE>
1760 T distanceNorm = std::numeric_limits<T>::max();
1765 const auto evalDistance = [&](
const Vector<T,3>& pt) {
1766 iterateOverCloseTriangles(pt, [&](
const STLtriangle<T>& triangle) {
1768 triangle.closestPtPointTriangle(pt);
1769 const Vector<T, 3> currDistance = pt - currPointOnTriangle;
1771 distanceNorm =
util::min(distanceNorm, currDistanceNorm);
1779 if(!isInsideRootTree(input.
data())) {
1780 const PhysR<T,3> ptInsideTree = closestPointInBoundingBox(input);
1781 const T distance = evalDistance(ptInsideTree);
1782 extraDistance =
norm(ptInsideTree - input);
1783 return distance + extraDistance;
1785 const T distance = evalDistance(input);
1787 return evalSignForSignedDistance<SIGNMODE>(input, distance) * distance;
1795 this->operator()(&isInside, pt.
data());
1796 return (isInside ? -1 : 1);
1801template <
typename T>
1804 return surfaceNormal<SignMode::CACHED>(pos, meshSize);
1807template <
typename T>
1810 return surfaceNormal<SignMode::EXACT>(pos, meshSize);
1813template <
typename T>
1814template <SignMode SIGNMODE>
1817 return evalSurfaceNormal<SIGNMODE>(pos);
1825 clout <<
"voxelSize=" << _voxelSize <<
"; stlSize=" << _stlSize << std::endl;
1826 clout <<
"minPhysR(VoxelMesh)=(" << this->_myMin[0] <<
"," << this->_myMin[1]
1827 <<
"," << this->_myMin[2] <<
")";
1828 clout <<
"; maxPhysR(VoxelMesh)=(" << this->_myMax[0] <<
","
1829 << this->_myMax[1] <<
"," << this->_myMax[2] <<
")" << std::endl;
1835 _tree->write(_fName);
1841 if (stlName ==
"") {
1842 _mesh.write(_fName);
1845 _mesh.write(stlName);
1852 unsigned int noTris = _mesh.triangleSize();
1855 for (
unsigned int i = 0; i < noTris; i++) {
1856 center = _mesh.getTri(i).getCenter();
1858 center + _mesh.getTri(i).normal *
util::sqrt(3.) * _voxelSize)->getInside()) {
1861 _mesh.getTri(i).point[0] = _mesh.getTri(i).point[2];
1862 _mesh.getTri(i).point[2] = pt;
1863 _mesh.getTri(i).init();
1874 std::vector<Octree<T>*> leafs;
1875 _tree->getLeafs(leafs);
1876 for (
auto it = leafs.begin(); it != leafs.end(); ++it) {
1877 if ((*it)->getBoundaryNode()) {
1878 (*it)->setInside(
true);
bool closestIntersection(const Vector< T, 3 > &pt, const Vector< T, 3 > &direction, Vector< T, 3 > &q, T &a)
Test intersection of ray with all triangles in Octree q contains point of closest intersection to pt ...
void intersectRayNode(const Vector< T, 3 > &pt, const Vector< T, 3 > &dir, Vector< T, 3 > &s)
Computes intersection of ray with Octree boundaries.
int testIntersection(const Vector< T, 3 > &pt, const Vector< T, 3 > &dir, bool print=false)
Test intersection of ray with all triangles in Octree returns number of intersections.
Octree< T > * find(const Vector< T, 3 > &, const int &maxDepth=0)
Find the node containing the first param with remaining maxDepth.
const T getRadius() const
Gets radius.
const std::vector< unsigned int > & getTriangles() const
Gets numbers of triangles contained by this Octree.
class for marking output with some text
STLmesh(std::string, T stlSize=1.)
Constructs a new STLmesh from a file.
bool testRayIntersect(const std::set< unsigned int > &tris, const Vector< T, 3 > &pt, const Vector< T, 3 > &dir, Vector< T, 3 > &q, T &alpha)
Compute intersection between Ray and set of triangles; returns true if intersection is found.
void print(bool full=false)
Prints console output.
void write(std::string fName)
Writes STL mesh in Si units.
T signedDistance(const Vector< T, 3 > &input) override
Computes signed distance to closest triangle in direction of the surface normal Using the cached info...
void print()
Prints console output.
void writeSTL(std::string stlName="")
Writes STL mesh in Si units.
bool isInsideRootTree(const T input[])
Returns whether node is inside the top-level octree or not.
void setNormalsOutside()
Rearranges normals of triangles to point outside of geometry.
Vector< T, 3 > surfaceNormal(const Vector< T, 3 > &pos, const T meshSize=0) override
Finds and returns normal of the closest surface (triangle) Using the cached information (faster,...
Vector< T, 3 > closestPointInBoundingBox(const Vector< T, 3 > &input)
Returns the closest point in the bounding box If input is already inside, then it returns input.
void setBoundaryInsideNodes()
Every octree leaf intersected by the STL will be part of the inside nodes.
Vector< T, 3 > surfaceNormalExact(const Vector< T, 3 > &pos, const T meshSize=0) override
Finds and returns normal of the closest surface (triangle) Much slower, but more accurate.
STLreader(const std::string fName, T voxelSize, T stlSize=1, RayMode method=RayMode::FastRayZ, bool verbose=false, T overlap=0., T max=0.)
Constructs a new STLreader from a file.
bool operator()(bool output[], const T input[]) override
Returns whether node is inside or not.
bool distance(T &distance, const Vector< T, 3 > &origin, const Vector< T, 3 > &direction, int iC=-1) override
Computes distance to closest triangle intersection.
T signedDistanceExact(const Vector< T, 3 > &input) override
Computes exact signed distance to closest triangle in direction of the surface normal Much slower,...
void writeOctree()
Writes Octree.
constexpr const T * data() const any_platform
std::string getVtkOutDir() const
int getRank() const
Returns the process ID.
Wrapper functions that simplify the use of MPI.
platform_constant int c[Q][D]
platform_constant Fraction s[Q]
T triangle(Vector< T, 2 > p, Vector< T, 2 > a, Vector< T, 2 > b, Vector< T, 2 > c) any_platform
Exact signed distance to the surface of two-dimensional triangle.
Directories & directories()
Distribution< T > normal(T mean, T stddev)
bool distance(S &distance, const Vector< S, D > &origin, const Vector< S, D > &direction, S precision, S pitch, F1 isInside, F2 isInsideBoundingBox)
ADf< T, DIM > atan2(const T &y, const ADf< T, DIM > &x)
int sign(T val) any_platform
ADf< T, DIM > round(const ADf< T, DIM > &a)
Expr pow(Expr base, Expr exp)
bool nearZero(T a) any_platform
return true if a is close to zero
Top level namespace for all of OpenLB.
constexpr T norm_squared(const ScalarVector< T, D, IMPL > &a) any_platform
Squared euclidean vector norm.
constexpr T max(const ScalarVector< T, D, IMPL > &v)
Vector< T, D > PhysR
Type for spatial (physical) coordinates.
constexpr T norm(const ScalarVector< T, D, IMPL > &a) any_platform
Euclidean vector norm.
@ DoubleRay
Indicate function with ray in Y-direction(faster, less stable).
@ FastRayX
Old indicate function (slower, more stable)
@ FastRayY
Indicate function with ray in X-direction(faster, less stable).
@ Robust
Indicate function with ray in Z-direction(faster, less stable). Default option.
constexpr Vector< T, 3 > crossProduct3D(const ScalarVector< T, 3, IMPL > &a, const ScalarVector< T, 3, IMPL_ > &b) any_platform
constexpr Vector< T, D > normalize(const ScalarVector< T, D, IMPL > &a, T scale=T{1})
Octree - adapted from http://www.flipcode.com/archives/Octree_Implementation.shtml.
Definition of singletons: global, publicly available information.
Input in STL format – header file.
std::vector< T > getE0()
Returns Pt0-Pt1.
std::vector< T > getE1()
Returns Pt0-Pt2.
Vector< T, 3 > normal
normal of triangle
bool testRayIntersect(const Vector< T, 3 > &pt, const Vector< T, 3 > &dir, Vector< T, 3 > &q, T &alpha, const T &rad=T(), bool print=false)
Test intersection between ray and triangle.
bool getPointToEdgeDistances(const Vector< T, 3 > &input, Vector< T, 3 > &output, T sensitivity=1.e-15)
Returns true if the point is on a edge (smaller than sensitivity) and gives the perpendicular distanc...
void init()
Initializes triangle and precomputes member variables.
bool isVortexPoint(const Vector< T, 3 > &input, Vector< T, 3 > &P, T sensitivity=1.e-15)
Returns true if is near vortex (smaller than sensitivity) and saves in P the vortex points.
Vector< T, 3 > getCenter()
Returns center.
bool isEdgePoint(const Vector< T, 3 > &input, Vector< T, 3 > &P1, Vector< T, 3 > &P2, T sensitivity=1.e-15)
Returns true if is near edge (smaller than sensitivity) and not near vortex and saves in P1 and P2 th...
Vector< T, 3 > closestPtPointTriangle(const Vector< T, 3 > &pt) const
computes closest Point in a triangle to another point.
Vector< T, 3 > closestPointTo(Vector< T, 3 > physR)
Returns the closest point to physR on the triangle.
std::vector< Vector< T, 3 > > point
A triangle contains 3 Points.
bool isPointInside(const PhysR< T, 3 > &pt) const
Check whether a point is inside a triangle.