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>
58 Vector<T,3> A = point[0];
59 Vector<T,3> B = point[1];
60 Vector<T,3> C = point[2];
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];
103 Vector<T,3> center( T(0) );
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;
165 const Vector<T,3>& dir,
166 Vector<T,3>& q, T& alpha,
const T& rad,
170 Vector<T,3> testPt = pt + rad *
normal;
173 for (
int i = 0; i < 3; 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: "
194 if (
util::fabs(rn) < std::numeric_limits<T>::epsilon()) {
197 std::cout <<
"FALSE 1" << std::endl;
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;
272 const Vector<T,3>& pt)
const
275 const T nEps = -std::numeric_limits<T>::epsilon();
276 const T Eps = std::numeric_limits<T>::epsilon();
278 Vector<T,3> ab = point[1] - point[0];
279 Vector<T,3> ac = point[2] - point[0];
280 Vector<T,3> bc = point[2] - point[1];
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)
408 clout(std::cout,
"STLmesh")
410 std::ifstream f(fName.c_str(), std::ios::in);
411 _triangles.reserve(10000);
413 throw std::runtime_error(
"STL File not valid.");
418 const std::string asciiHeader =
"solid";
419 if (std::string(buf) == asciiHeader) {
420 f.seekg(0, std::ios::beg);
428 f >> s1 >> tri.normal[0] >> tri.normal[1] >> tri.normal[2];
430 f >> s0 >> tri.point[0][0] >> tri.point[0][1]
432 f >> s0 >> tri.point[1][0] >> tri.point[1][1]
434 f >> s0 >> tri.point[2][0] >> tri.point[2][1]
438 for (
int k = 0; k < 3; k++) {
439 tri.point[0][k] *= stlSize;
440 tri.point[1][k] *= stlSize;
441 tri.point[2][k] *= stlSize;
447 _min[0] = tri.point[0][0];
448 _min[1] = tri.point[0][1];
449 _min[2] = tri.point[0][2];
451 _max[0] = tri.point[0][0];
452 _max[1] = tri.point[0][1];
453 _max[2] = tri.point[0][2];
455 _min[0] = util::min(_min[0], tri.point[1][0]);
456 _min[1] = util::min(_min[1], tri.point[1][1]);
457 _min[2] = util::min(_min[2], tri.point[1][2]);
459 _max[0] = util::max(_max[0], tri.point[1][0]);
460 _max[1] = util::max(_max[1], tri.point[1][1]);
461 _max[2] = util::max(_max[2], tri.point[1][2]);
463 _min[0] = util::min(_min[0], tri.point[2][0]);
464 _min[1] = util::min(_min[1], tri.point[2][1]);
465 _min[2] = util::min(_min[2], tri.point[2][2]);
467 _max[0] = util::max(_max[0], tri.point[2][0]);
468 _max[1] = util::max(_max[1], tri.point[2][1]);
469 _max[2] = util::max(_max[2], tri.point[2][2]);
473 _min[0] = util::min(_min[0], tri.point[0][0]);
474 _min[1] = util::min(_min[1], tri.point[0][1]);
475 _min[2] = util::min(_min[2], tri.point[0][2]);
477 _max[0] = util::max(_max[0], tri.point[0][0]);
478 _max[1] = util::max(_max[1], tri.point[0][1]);
479 _max[2] = util::max(_max[2], tri.point[0][2]);
481 _min[0] = util::min(_min[0], tri.point[1][0]);
482 _min[1] = util::min(_min[1], tri.point[1][1]);
483 _min[2] = util::min(_min[2], tri.point[1][2]);
485 _max[0] = util::max(_max[0], tri.point[1][0]);
486 _max[1] = util::max(_max[1], tri.point[1][1]);
487 _max[2] = util::max(_max[2], tri.point[1][2]);
489 _min[0] = util::min(_min[0], tri.point[2][0]);
490 _min[1] = util::min(_min[1], tri.point[2][1]);
491 _min[2] = util::min(_min[2], tri.point[2][2]);
493 _max[0] = util::max(_max[0], tri.point[2][0]);
494 _max[1] = util::max(_max[1], tri.point[2][1]);
495 _max[2] = util::max(_max[2], tri.point[2][2]);
500 _triangles.push_back(tri);
502 _maxDist2 = util::max(distPoints(tri.point[0], tri.point[1]),
504 _maxDist2 = util::max(distPoints(tri.point[2], tri.point[1]),
506 _maxDist2 = util::max(distPoints(tri.point[0], tri.point[2]),
509 else if (s0 ==
"endsolid") {
517 f.open(fName.c_str(), std::ios::in | std::ios::binary);
522 throw std::runtime_error(
"STL File not valid.");
527 f.read(
reinterpret_cast<char *
>(&nFacets),
sizeof(int32_t));
530 throw std::runtime_error(
"STL File not valid.");
534 std::uint16_t uint16;
535 for (int32_t i = 0; i < nFacets; ++i) {
536 for (
unsigned int j = 0; j < 12; ++j) {
537 f.read(
reinterpret_cast<char *
>(&v[j]),
sizeof(
float));
539 f.read(
reinterpret_cast<char *
>(&uint16),
sizeof(std::uint16_t));
541 tri.normal[0] = v[0];
542 tri.normal[1] = v[1];
543 tri.normal[2] = v[2];
544 tri.point[0][0] = v[3];
545 tri.point[0][1] = v[4];
546 tri.point[0][2] = v[5];
547 tri.point[1][0] = v[6];
548 tri.point[1][1] = v[7];
549 tri.point[1][2] = v[8];
550 tri.point[2][0] = v[9];
551 tri.point[2][1] = v[10];
552 tri.point[2][2] = v[11];
554 for (
int k = 0; k < 3; k++) {
555 tri.point[0][k] *= stlSize;
556 tri.point[1][k] *= stlSize;
557 tri.point[2][k] *= stlSize;
560 _min[0] = tri.point[0][0];
561 _min[1] = tri.point[0][1];
562 _min[2] = tri.point[0][2];
564 _max[0] = tri.point[0][0];
565 _max[1] = tri.point[0][1];
566 _max[2] = tri.point[0][2];
568 _min[0] = util::min(_min[0], (T) tri.point[1][0]);
569 _min[1] = util::min(_min[1], (T) tri.point[1][1]);
570 _min[2] = util::min(_min[2], (T) tri.point[1][2]);
572 _max[0] = util::max(_max[0], (T) tri.point[1][0]);
573 _max[1] = util::max(_max[1], (T) tri.point[1][1]);
574 _max[2] = util::max(_max[2], (T) tri.point[1][2]);
576 _min[0] = util::min(_min[0], (T) tri.point[2][0]);
577 _min[1] = util::min(_min[1], (T) tri.point[2][1]);
578 _min[2] = util::min(_min[2], (T) tri.point[2][2]);
580 _max[0] = util::max(_max[0], (T) tri.point[2][0]);
581 _max[1] = util::max(_max[1], (T) tri.point[2][1]);
582 _max[2] = util::max(_max[2], (T) tri.point[2][2]);
586 _min[0] = util::min(_min[0], (T) tri.point[0][0]);
587 _min[1] = util::min(_min[1], (T) tri.point[0][1]);
588 _min[2] = util::min(_min[2], (T) tri.point[0][2]);
590 _max[0] = util::max(_max[0], (T) tri.point[0][0]);
591 _max[1] = util::max(_max[1], (T) tri.point[0][1]);
592 _max[2] = util::max(_max[2], (T) tri.point[0][2]);
594 _min[0] = util::min(_min[0], (T) tri.point[1][0]);
595 _min[1] = util::min(_min[1], (T) tri.point[1][1]);
596 _min[2] = util::min(_min[2], (T) tri.point[1][2]);
598 _max[0] = util::max(_max[0], (T) tri.point[1][0]);
599 _max[1] = util::max(_max[1], (T) tri.point[1][1]);
600 _max[2] = util::max(_max[2], (T) tri.point[1][2]);
602 _min[0] = util::min(_min[0], (T) tri.point[2][0]);
603 _min[1] = util::min(_min[1], (T) tri.point[2][1]);
604 _min[2] = util::min(_min[2], (T) tri.point[2][2]);
606 _max[0] = util::max(_max[0], (T) tri.point[2][0]);
607 _max[1] = util::max(_max[1], (T) tri.point[2][1]);
608 _max[2] = util::max(_max[2], (T) tri.point[2][2]);
611 _triangles.push_back(tri);
613 _maxDist2 = util::max(distPoints(tri.point[0], tri.point[1]), _maxDist2);
614 _maxDist2 = util::max(distPoints(tri.point[2], tri.point[1]), _maxDist2);
615 _maxDist2 = util::max(distPoints(tri.point[0], tri.point[2]), _maxDist2);
622STLmesh<T>::STLmesh(
const std::vector<std::vector<T>> meshPoints, T stlSize)
623 : _fName(
"meshPoints.stl"),
627 clout(std::cout,
"STLmesh")
629 _triangles.reserve(10000);
630 for (
size_t i = 0; i < meshPoints.size() / 3; i++) {
632 tri.point[0][0] = meshPoints[i*3 + 0][0];
633 tri.point[0][1] = meshPoints[i*3 + 0][1];
634 tri.point[0][2] = meshPoints[i*3 + 0][2];
636 tri.point[1][0] = meshPoints[i*3 + 1][0];
637 tri.point[1][1] = meshPoints[i*3 + 1][1];
638 tri.point[1][2] = meshPoints[i*3 + 1][2];
640 tri.point[2][0] = meshPoints[i*3 + 2][0];
641 tri.point[2][1] = meshPoints[i*3 + 2][1];
642 tri.point[2][2] = meshPoints[i*3 + 2][2];
643 for (
int k = 0; k < 3; k++) {
644 tri.point[0][k] *= stlSize;
645 tri.point[1][k] *= stlSize;
646 tri.point[2][k] *= stlSize;
652 _min[0] = tri.point[0][0];
653 _min[1] = tri.point[0][1];
654 _min[2] = tri.point[0][2];
656 _max[0] = tri.point[0][0];
657 _max[1] = tri.point[0][1];
658 _max[2] = tri.point[0][2];
660 _min[0] = util::min(_min[0], (T) tri.point[1][0]);
661 _min[1] = util::min(_min[1], (T) tri.point[1][1]);
662 _min[2] = util::min(_min[2], (T) tri.point[1][2]);
664 _max[0] = util::max(_max[0], (T) tri.point[1][0]);
665 _max[1] = util::max(_max[1], (T) tri.point[1][1]);
666 _max[2] = util::max(_max[2], (T) tri.point[1][2]);
668 _min[0] = util::min(_min[0], (T) tri.point[2][0]);
669 _min[1] = util::min(_min[1], (T) tri.point[2][1]);
670 _min[2] = util::min(_min[2], (T) tri.point[2][2]);
672 _max[0] = util::max(_max[0], (T) tri.point[2][0]);
673 _max[1] = util::max(_max[1], (T) tri.point[2][1]);
674 _max[2] = util::max(_max[2], (T) tri.point[2][2]);
678 _min[0] = util::min(_min[0], (T) tri.point[0][0]);
679 _min[1] = util::min(_min[1], (T) tri.point[0][1]);
680 _min[2] = util::min(_min[2], (T) tri.point[0][2]);
682 _max[0] = util::max(_max[0], (T) tri.point[0][0]);
683 _max[1] = util::max(_max[1], (T) tri.point[0][1]);
684 _max[2] = util::max(_max[2], (T) tri.point[0][2]);
686 _min[0] = util::min(_min[0], (T) tri.point[1][0]);
687 _min[1] = util::min(_min[1], (T) tri.point[1][1]);
688 _min[2] = util::min(_min[2], (T) tri.point[1][2]);
690 _max[0] = util::max(_max[0], (T) tri.point[1][0]);
691 _max[1] = util::max(_max[1], (T) tri.point[1][1]);
692 _max[2] = util::max(_max[2], (T) tri.point[1][2]);
694 _min[0] = util::min(_min[0], (T) tri.point[2][0]);
695 _min[1] = util::min(_min[1], (T) tri.point[2][1]);
696 _min[2] = util::min(_min[2], (T) tri.point[2][2]);
698 _max[0] = util::max(_max[0], (T) tri.point[2][0]);
699 _max[1] = util::max(_max[1], (T) tri.point[2][1]);
700 _max[2] = util::max(_max[2], (T) tri.point[2][2]);
704 _triangles.push_back(tri);
706 _maxDist2 = util::max(distPoints(tri.point[0], tri.point[1]),
708 _maxDist2 = util::max(distPoints(tri.point[2], tri.point[1]),
710 _maxDist2 = util::max(distPoints(tri.point[0], tri.point[2]),
716T STLmesh<T>::distPoints(Vertex<T,3>& p1, Vertex<T,3>& p2)
718 return util::pow(T(p1[0] - p2[0]), 2)
719 + util::pow(T(p1[1] - p2[1]), 2)
720 + util::pow(T(p1[2] - p2[2]), 2);
724void STLmesh<T>::print(
bool full)
728 clout <<
"Triangles: " << std::endl;
729 typename std::vector<STLtriangle<T> >::iterator it = _triangles.begin();
731 for (; it != _triangles.end(); ++it) {
732 clout << i++ <<
": " << it->point[0][0] <<
" " << it->point[0][1]
733 <<
" " << it->point[0][2] <<
" | " << it->point[1][0] <<
" "
734 << it->point[1][1] <<
" " << it->point[1][2] <<
" | "
735 << it->point[2][0] <<
" " << it->point[2][1] <<
" "
736 << it->point[2][2] << std::endl;
739 clout <<
"nTriangles=" << _triangles.size() <<
"; maxDist2=" << _maxDist2
741 clout <<
"minPhysR(StlMesh)=(" << getMin()[0] <<
"," << getMin()[1] <<
","
742 << getMin()[2] <<
")";
743 clout <<
"; maxPhysR(StlMesh)=(" << getMax()[0] <<
"," << getMax()[1] <<
","
744 << getMax()[2] <<
")" << std::endl;
748void STLmesh<T>::write(std::string fName)
751#ifdef PARALLEL_MODE_MPI
752 rank = singleton::mpi().getRank();
755 std::string fullName = singleton::directories().getVtkOutDir() + fName
757 std::ofstream f(fullName.c_str());
758 f <<
"solid ascii " << fullName <<
"\n";
760 for (
unsigned int i = 0; i < _triangles.size(); i++) {
761 f <<
"facet normal " << _triangles[i].normal[0] <<
" "
762 << _triangles[i].normal[1] <<
" " << _triangles[i].normal[2] <<
"\n";
763 f <<
" outer loop\n";
764 f <<
" vertex " << _triangles[i].point[0][0] <<
" "
765 << _triangles[i].point[0][1] <<
" " << _triangles[i].point[0][2]
767 f <<
" vertex " << _triangles[i].point[1][0] <<
" "
768 << _triangles[i].point[1][1] <<
" " << _triangles[i].point[1][2]
770 f <<
" vertex " << _triangles[i].point[2][0] <<
" "
771 << _triangles[i].point[2][1] <<
" " << _triangles[i].point[2][2]
779 clout <<
"Write ... OK" << std::endl;
783bool STLmesh<T>::testRayIntersect(
const std::set<unsigned int>& tris,
const Vector<T,3>& pt,
const Vector<T,3>& dir, Vector<T,3>& q, T& alpha)
785 std::set<unsigned int>::iterator it = tris.begin();
786 for (; it != tris.end(); ++it) {
787 if (_triangles[*it].testRayIntersect(pt, dir, q, alpha) && alpha < 1) {
799STLreader<T>::STLreader(
const std::string fName, T voxelSize, T stlSize,
800 RayMode method,
bool verbose, T overlap, T max)
801 : _voxelSize(voxelSize),
805 _mesh(fName, stlSize),
807 clout(std::cout,
"STLreader")
812 clout <<
"Voxelizing ..." << std::endl;
815 Vector<T,3> extension = _mesh.getMax() - _mesh.getMin();
816 if ( util::nearZero(max) ) {
817 max = util::max(extension[0], util::max(extension[1], extension[2])) + _voxelSize;
820 for (; _voxelSize * util::pow(2, j) < max; j++)
823 T radius = _voxelSize * util::pow(2, j - 1);
826 for (
unsigned i = 0; i < 3; i++) {
827 center[i] = (_mesh.getMin()[i] + _mesh.getMax()[i]) / 2. - _voxelSize / 4.;
831 _tree =
new Octree<T>(center, radius, &_mesh, j, _overlap);
834 for (
int i = 0; i < 3; i++) {
835 this->_myMin[i] = center[i] + _voxelSize / 2.;
836 this->_myMax[i] = center[i] - _voxelSize / 2.;
838 for (
int i = 0; i < 3; i++) {
839 while (this->_myMin[i] > _mesh.getMin()[i]) {
840 this->_myMin[i] -= _voxelSize;
842 while (this->_myMax[i] < _mesh.getMax()[i]) {
843 this->_myMax[i] += _voxelSize;
845 this->_myMax[i] -= _voxelSize;
846 this->_myMin[i] += _voxelSize;
851 case RayMode::Robust:
854 case RayMode::DoubleRay:
857 case RayMode::FastRayX:
860 case RayMode::FastRayY:
872 clout <<
"Voxelizing ... OK" << std::endl;
880STLreader<T>::STLreader(
const std::vector<std::vector<T>> meshPoints, T voxelSize, T stlSize,
881 RayMode method,
bool verbose, T overlap, T max)
882 : _voxelSize(voxelSize),
885 _fName(
"meshPoints.stl"),
886 _mesh(meshPoints, stlSize),
888 clout(std::cout,
"STLreader")
893 clout <<
"Voxelizing ..." << std::endl;
896 Vector<T,3> extension = _mesh.getMax() - _mesh.getMin();
897 if ( util::nearZero(max) ) {
898 max = util::max(extension[0], util::max(extension[1], extension[2])) + _voxelSize;
901 for (; _voxelSize * util::pow(2, j) < max; j++)
904 T radius = _voxelSize * util::pow(2, j - 1);
907 for (
unsigned i = 0; i < 3; i++) {
908 center[i] = (_mesh.getMin()[i] + _mesh.getMax()[i]) / 2. - _voxelSize / 4.;
913 _tree =
new Octree<T>(center, radius, &_mesh, j, _overlap);
916 for (
int i = 0; i < 3; i++) {
917 this->_myMin[i] = center[i] + _voxelSize / 2.;
918 this->_myMax[i] = center[i] - _voxelSize / 2.;
920 for (
int i = 0; i < 3; i++) {
921 while (this->_myMin[i] > _mesh.getMin()[i]) {
922 this->_myMin[i] -= _voxelSize;
924 while (this->_myMax[i] < _mesh.getMax()[i]) {
925 this->_myMax[i] += _voxelSize;
927 this->_myMax[i] -= _voxelSize;
928 this->_myMin[i] += _voxelSize;
946 case RayMode::Robust:
949 case RayMode::DoubleRay:
952 case RayMode::FastRayX:
955 case RayMode::FastRayY:
969 clout <<
"Voxelizing ... OK" << std::endl;
974STLreader<T>::~STLreader()
986void STLreader<T>::indicate1()
988 std::vector<Octree<T>*> leafs;
989 _tree->getLeafs(leafs);
990 typename std::vector<Octree<T>*>::iterator it = leafs.begin();
991 Vector<T,3> dir, pt,
s;
993 int intersections = 0;
995 Octree<T>* node =
nullptr;
996 T step = 1. / 1000. * _voxelSize;
997 for (; it != leafs.end(); ++it) {
1000 pt = (*it)->getCenter();
1008 while (s[0] < _mesh.getMax()[0] + std::numeric_limits<T>::epsilon()) {
1009 node = _tree->find(s, (*it)->getMaxdepth());
1010 intersections += node->testIntersection(pt, dir);
1011 node->intersectRayNode(pt, dir, s);
1014 inside += (intersections % 2);
1022 while (s[1] < _mesh.getMax()[1] + std::numeric_limits<T>::epsilon()) {
1023 node = _tree->find(s, (*it)->getMaxdepth());
1024 intersections += node->testIntersection(pt, dir);
1025 node->intersectRayNode(pt, dir, s);
1028 inside += (intersections % 2);
1036 while (s[2] < _mesh.getMax()[2] + std::numeric_limits<T>::epsilon()) {
1037 node = _tree->find(s, (*it)->getMaxdepth());
1038 intersections += node->testIntersection(pt, dir);
1039 node->intersectRayNode(pt, dir, s);
1042 inside += (intersections % 2);
1043 (*it)->setInside(inside > 1);
1052void STLreader<T>::indicate2()
1054 T rad = _tree->getRadius();
1055 Vector<T,3> rayPt = _tree->getCenter() - rad + .5 * _voxelSize;
1056 Vector<T,3> pt = rayPt;
1063 T step = 1. / 1000. * _voxelSize;
1065 Octree<T>* node =
nullptr;
1066 unsigned short rayInside = 0;
1067 Vector<T,3> nodeInters;
1068 while (pt[0] < _mesh.getMax()[0] + std::numeric_limits<T>::epsilon()) {
1069 node = _tree->find(pt);
1071 nodeInters[2] = node->getCenter()[2] - node->getRadius();
1073 while (pt[1] < _mesh.getMax()[1] + std::numeric_limits<T>::epsilon()) {
1074 node = _tree->find(pt);
1076 nodeInters[2] = node->getCenter()[2] - node->getRadius();
1078 while (pt[2] < _mesh.getMax()[2] + std::numeric_limits<T>::epsilon()) {
1079 node = _tree->find(pt);
1080 node->checkRay(nodeInters, rayDir, rayInside);
1081 node->intersectRayNode(pt, rayDir, nodeInters);
1082 pt = nodeInters + step * rayDir;
1085 pt[1] += _voxelSize;
1088 pt[0] += _voxelSize;
1099void STLreader<T>::indicate2_Xray()
1101 T rad = _tree->getRadius();
1102 Vector<T,3> rayPt = _tree->getCenter() - rad + .5 * _voxelSize;
1103 Vector<T,3> pt = rayPt;
1110 T step = 1. / 1000. * _voxelSize;
1112 Octree<T>* node =
nullptr;
1113 unsigned short rayInside = 0;
1114 Vector<T,3> nodeInters;
1115 while (pt[2] < _mesh.getMax()[2] + std::numeric_limits<T>::epsilon()) {
1116 node = _tree->find(pt);
1118 nodeInters[0] = node->getCenter()[0] - node->getRadius();
1120 while (pt[1] < _mesh.getMax()[1] + std::numeric_limits<T>::epsilon()) {
1121 node = _tree->find(pt);
1123 nodeInters[0] = node->getCenter()[0] - node->getRadius();
1125 while (pt[0] < _mesh.getMax()[0] + std::numeric_limits<T>::epsilon()) {
1126 node = _tree->find(pt);
1127 node->checkRay(nodeInters, rayDir, rayInside);
1128 node->intersectRayNode(pt, rayDir, nodeInters);
1129 pt = nodeInters + step * rayDir;
1132 pt[1] += _voxelSize;
1135 pt[2] += _voxelSize;
1145void STLreader<T>::indicate2_Yray()
1147 T rad = _tree->getRadius();
1148 Vector<T,3> rayPt = _tree->getCenter() - rad + .5 * _voxelSize;
1149 Vector<T,3> pt = rayPt;
1156 T step = 1. / 1000. * _voxelSize;
1158 Octree<T>* node =
nullptr;
1159 unsigned short rayInside = 0;
1160 Vector<T,3> nodeInters;
1161 while (pt[2] < _mesh.getMax()[2] + std::numeric_limits<T>::epsilon()) {
1162 node = _tree->find(pt);
1164 nodeInters[1] = node->getCenter()[1] - node->getRadius();
1166 while (pt[0] < _mesh.getMax()[0] + std::numeric_limits<T>::epsilon()) {
1167 node = _tree->find(pt);
1169 nodeInters[1] = node->getCenter()[1] - node->getRadius();
1171 while (pt[1] < _mesh.getMax()[1] + std::numeric_limits<T>::epsilon()) {
1172 node = _tree->find(pt);
1173 node->checkRay(nodeInters, rayDir, rayInside);
1174 node->intersectRayNode(pt, rayDir, nodeInters);
1175 pt = nodeInters + step * rayDir;
1178 pt[0] += _voxelSize;
1181 pt[2] += _voxelSize;
1190void STLreader<T>::indicate3()
1192 std::vector<Octree<T>*> leafs;
1193 _tree->getLeafs(leafs);
1194 typename std::vector<Octree<T>*>::iterator it = leafs.begin();
1196 Vector<T,3> dir, pt,
s;
1197 Octree<T>* node =
nullptr;
1198 T step = 1. / 1000. * _voxelSize;
1200 int sum_intersections;
1202 for (; it != leafs.end(); ++it) {
1203 pt = (*it)->getCenter();
1205 sum_intersections = 0;
1212 while (s[0] < _mesh.getMax()[0] + std::numeric_limits<T>::epsilon()) {
1213 node = _tree->find(s, (*it)->getMaxdepth());
1214 intersections = node->testIntersection(pt, dir);
1215 node->intersectRayNode(pt, dir, s);
1217 if (intersections > 0) {
1218 sum_intersections++;
1229 while (s[1] < _mesh.getMax()[1] + std::numeric_limits<T>::epsilon()) {
1230 node = _tree->find(s, (*it)->getMaxdepth());
1231 intersections = node->testIntersection(pt, dir);
1232 node->intersectRayNode(pt, dir, s);
1234 if (intersections > 0) {
1235 sum_intersections++;
1246 while (s[2] < _mesh.getMax()[2] + std::numeric_limits<T>::epsilon()) {
1247 node = _tree->find(s, (*it)->getMaxdepth());
1248 intersections = node->testIntersection(pt, dir);
1249 node->intersectRayNode(pt, dir, s);
1251 if (intersections > 0) {
1252 sum_intersections++;
1263 while (s[0] > _mesh.getMin()[0] - std::numeric_limits<T>::epsilon()) {
1264 node = _tree->find(s, (*it)->getMaxdepth());
1265 intersections = node->testIntersection(pt, dir);
1266 node->intersectRayNode(pt, dir, s);
1268 if (intersections > 0) {
1269 sum_intersections++;
1280 while (s[1] > _mesh.getMin()[1] - std::numeric_limits<T>::epsilon()) {
1281 node = _tree->find(s, (*it)->getMaxdepth());
1282 intersections = node->testIntersection(pt, dir);
1283 node->intersectRayNode(pt, dir, s);
1285 if (intersections > 0) {
1286 sum_intersections++;
1297 while (s[2] > _mesh.getMin()[2] - std::numeric_limits<T>::epsilon()) {
1298 node = _tree->find(s, (*it)->getMaxdepth());
1299 intersections = node->testIntersection(pt, dir);
1300 node->intersectRayNode(pt, dir, s);
1302 if (intersections > 0) {
1303 sum_intersections++;
1307 (*it)->setInside(sum_intersections > 5);
1312bool STLreader<T>::operator() (
bool output[],
const T input[])
1315 if (isInsideRootTree(input)) {
1316 std::vector<T> tmp(input, input + 3);
1317 output[0] = _tree->find(tmp)->getInside();
1324bool STLreader<T>::isInsideRootTree(
const T input[])
1326 T coords = _tree->getRadius();
1327 Vector<T,3>
c(_tree->getCenter());
1328 return c[0] - coords < input[0] && input[0] <
c[0] + coords &&
c[1] - coords < input[1]
1329 && input[1] <
c[1] + coords &&
c[2] - coords < input[2] && input[2] <
c[2] + coords;
1334Vector<T,3> STLreader<T>::closestPointInBoundingBox(
const Vector<T,3>& input)
1336 T coords = _tree->getRadius();
1337 Vector<T,3>
c(_tree->getCenter());
1338 Vector<T,3> closestPoint;
1339 for(
int i = 0; i < 3; ++i) {
1340 closestPoint[i] = util::max(c[i] - coords, util::min(c[i] + coords, input[i]));
1342 return closestPoint;
1347bool STLreader<T>::distance(T& distance,
const Vector<T,3>& origin,
1348 const Vector<T,3>& direction,
int iC)
1350 Octree<T>* node =
nullptr;
1351 Vector<T,3> dir(direction);
1353 Vector<T,3> extends = _mesh.getMax() - _mesh.getMin();
1354 Vector<T,3> pt(origin);
1357 Vector<T,3> center = _mesh.getMin() + 1 / 2. * extends;
1358 T step = _voxelSize / 1000., a = 0;
1360 for (
int i = 0; i < 3; i++) {
1364 if (!(_mesh.getMin()[0] < origin[0] && origin[0] < _mesh.getMax()[0]
1365 && _mesh.getMin()[1] < origin[1] && origin[1] < _mesh.getMax()[1]
1366 && _mesh.getMin()[2] < origin[2] && origin[2] < _mesh.getMax()[2])) {
1368 bool foundQ =
false;
1371 d = _mesh.getMin()[0];
1372 t = (
d - origin[0]) / dir[0];
1373 pt[0] = origin[0] + (
t + step) * dir[0];
1374 pt[1] = origin[1] + (
t + step) * dir[1];
1375 pt[2] = origin[2] + (
t + step) * dir[2];
1377 if (_mesh.getMin()[1] < pt[1] && pt[1] < _mesh.getMax()[1]
1378 && _mesh.getMin()[2] < pt[2] && pt[2] < _mesh.getMax()[2]) {
1382 else if (dir[0] < 0) {
1383 d = _mesh.getMax()[0];
1384 t = (
d - origin[0]) / dir[0];
1385 pt[0] = origin[0] + (
t + step) * dir[0];
1386 pt[1] = origin[1] + (
t + step) * dir[1];
1387 pt[2] = origin[2] + (
t + step) * dir[2];
1388 if (_mesh.getMin()[1] < pt[1] && pt[1] < _mesh.getMax()[1]
1389 && _mesh.getMin()[2] < pt[2] && pt[2] < _mesh.getMax()[2]) {
1394 if (dir[1] > 0 && !foundQ) {
1395 d = _mesh.getMin()[1];
1396 t = (
d - origin[1]) / dir[1];
1397 pt[0] = origin[0] + (
t + step) * dir[0];
1398 pt[1] = origin[1] + (
t + step) * dir[1];
1399 pt[2] = origin[2] + (
t + step) * dir[2];
1400 if (_mesh.getMin()[0] < pt[0] && pt[0] < _mesh.getMax()[0]
1401 && _mesh.getMin()[2] < pt[2] && pt[2] < _mesh.getMax()[2]) {
1405 else if (dir[1] < 0 && !foundQ) {
1406 d = _mesh.getMax()[1];
1407 t = (
d - origin[1]) / dir[1];
1408 pt[0] = origin[0] + (
t + step) * dir[0];
1409 pt[1] = origin[1] + (
t + step) * dir[1];
1410 pt[2] = origin[2] + (
t + step) * dir[2];
1411 if (_mesh.getMin()[0] < pt[0] && pt[0] < _mesh.getMax()[0]
1412 && _mesh.getMin()[2] < pt[2] && pt[2] < _mesh.getMax()[2]) {
1417 if (dir[2] > 0 && !foundQ) {
1418 d = _mesh.getMin()[2];
1419 t = (
d - origin[2]) / dir[2];
1420 pt[0] = origin[0] + (
t + step) * dir[0];
1421 pt[1] = origin[1] + (
t + step) * dir[1];
1422 pt[2] = origin[2] + (
t + step) * dir[2];
1423 if (_mesh.getMin()[0] < pt[0] && pt[0] < _mesh.getMax()[0]
1424 && _mesh.getMin()[1] < pt[1] && pt[1] < _mesh.getMax()[1]) {
1428 else if (dir[2] < 0 && !foundQ) {
1429 d = _mesh.getMax()[2];
1430 t = (
d - origin[2]) / dir[2];
1431 pt[0] = origin[0] + (
t + step) * dir[0];
1432 pt[1] = origin[1] + (
t + step) * dir[1];
1433 pt[2] = origin[2] + (
t + step) * dir[2];
1434 if (_mesh.getMin()[0] < pt[0] && pt[0] < _mesh.getMax()[0]
1435 && _mesh.getMin()[1] < pt[1] && pt[1] < _mesh.getMax()[1]) {
1445 while ((util::fabs(pt[0] - center[0]) < extends[0])
1446 && (util::fabs(pt[1] - center[1]) < extends[1])
1447 && (util::fabs(pt[2] - center[2]) < extends[2])) {
1448 node = _tree->find(pt);
1449 if (node->closestIntersection(Vector<T,3>(origin), dir, q, a)) {
1450 Vector<T,3> vek(q - Vector<T,3>(origin));
1455 Octree<T>* tmpNode = _tree->find(pt);
1456 tmpNode->intersectRayNode(pt, dir, s);
1457 for (
int i = 0; i < 3; i++) {
1458 pt[i] =
s[i] + step * dir[i];
1468void STLreader<T>::iterateOverCloseTriangles(
const PhysR<T,3>& pt, F func, Octree<T>* leafNode) {
1470 leafNode = _tree->find(pt);
1472 if (leafNode && !leafNode->getTriangles().empty()) {
1473 const std::vector<unsigned int>& triangleIndices = leafNode->getTriangles();
1474 for (
unsigned int idx : triangleIndices) {
1475 const STLtriangle<T>&
triangle = _mesh.getTri(idx);
1480 for (
const STLtriangle<T>& triangle : _mesh.getTriangles()) {
1487Vector<T,3> STLreader<T>::evalNormalOnSurface(
const PhysR<T,3>& pt,
const Vector<T,3>& fallbackNormal)
1490 unsigned countTriangles = 0;
1491 Vector<T,3>
normal(T(0));
1493 iterateOverCloseTriangles(pt, [&](
const STLtriangle<T>& triangle){
1502 if (countTriangles > 0) {
1503 return normal / countTriangles;
1507 return fallbackNormal;
1511template<SignMode SIGNMODE>
1512Vector<T,3> STLreader<T>::evalSurfaceNormal(
const Vector<T,3>& origin)
1515 Vector<T,3> closestPointOnSurface(0.);
1516 const STLtriangle<T>* closestTriangle =
nullptr;
1517 T
distance = std::numeric_limits<T>::max();
1518 const PhysR<T,3> pt(closestPointInBoundingBox(origin));
1520 iterateOverCloseTriangles(pt, [&](
const STLtriangle<T>& triangle) {
1521 PhysR<T,3>
const pointOnTriangle =
triangle.closestPtPointTriangle(pt);
1522 PhysR<T,3>
const currDistance = pt - pointOnTriangle;
1524 if (distance > currDistanceNorm) {
1527 closestPointOnSurface = pointOnTriangle;
1533 if (!util::nearZero(distance)) {
1535 normal *= evalSignForSignedDistance<SIGNMODE>(origin, distance);
1538 normal = evalNormalOnSurface(closestPointOnSurface, closestTriangle->getNormal());
1555template<SignMode SIGNMODE>
1556Vector<T,3> STLreader<T>::evalSurfaceNormalForPseudoNormal(
const Vector<T,3>& origin, Vector<T,3> & outputPointOnSurface)
1559 Vector<T,3> closestPointOnSurface(0.);
1560 const STLtriangle<T>* closestTriangle =
nullptr;
1561 T
distance = std::numeric_limits<T>::max();
1562 const PhysR<T,3> pt(closestPointInBoundingBox(origin));
1564 iterateOverCloseTriangles(pt, [&](
const STLtriangle<T>& triangle) {
1565 PhysR<T,3>
const pointOnTriangle =
triangle.closestPtPointTriangle(pt);
1566 PhysR<T,3>
const currDistance = pt - pointOnTriangle;
1568 if (distance > currDistanceNorm) {
1571 closestPointOnSurface = pointOnTriangle;
1582 normal = evalNormalOnSurface(closestPointOnSurface, closestTriangle->getNormal());
1583 outputPointOnSurface = closestPointOnSurface;
1600template <
typename T>
1601template <SignMode SIGNMODE>
1602short STLreader<T>::evalSignForSignedDistance(
1603 const Vector<T,3>& pt, [[maybe_unused]]
const T distance, Vector<T,3> vecdist, STLtriangle<T> stlT)
1607 if constexpr (SIGNMODE == SignMode::EXACT)
1610 if(distance < _voxelSize) {
1612 sign = evalSignForSignedDistanceFromWindingNumber(pt);
1620 sign = evalSignForSignedDistanceFromCache(pt);
1624 sign = evalSignForSignedDistanceFromCache(pt);
1630short STLreader<T>::evalSignForSignedDistanceFromPseudonormal(
const Vector<T,3>& pseudonormal,
const Vector<T,3>& distance)
1632 const T projection = pseudonormal *
distance;
1634 if(projection > 0) {
1637 else if (projection < 0 ) {
1646short STLreader<T>::evalSignForSignedDistanceFromNormal(
const Vector<T,3>& normal,
const Vector<T,3>& distance)
1650 if(projection > 0) {
1653 else if (projection < 0 ) {
1663short STLreader<T>::evalSignForSignedDistanceFromWindingNumber(
const Vector<T,3>& pt)
1667 for (
const STLtriangle<T>& triangle : _mesh.getTriangles()) {
1668 const PhysR<T,3> a =
triangle.point[0] - pt;
1669 const PhysR<T,3> b =
triangle.point[1] - pt;
1670 const PhysR<T,3>
c =
triangle.point[2] - pt;
1672 const T aNorm =
norm(a);
1673 const T bNorm =
norm(b);
1674 const T cNorm =
norm(c);
1677 const T denominator = aNorm * bNorm * cNorm + (a*b) * cNorm + (b*c) * aNorm + (
c*a) * bNorm;
1679 windingNumber += util::atan2(numerator,denominator);
1683 if(
int(util::round(windingNumber))%2 == 0) {
1690template <
typename T>
1691T STLreader<T>::signedDistance(
const Vector<T, 3>& input)
1693 return signedDistance<SignMode::CACHED>(input);
1696template <
typename T>
1697T STLreader<T>::signedDistanceExact(
const Vector<T, 3>& input)
1699 return signedDistance<SignMode::EXACT>(input);
1705template <
typename T>
1706template <SignMode SIGNMODE>
1707T STLreader<T>::signedDistance(
const Vector<T, 3>& input)
1709 T distanceNorm = std::numeric_limits<T>::max();
1714 const auto evalDistance = [&](
const Vector<T,3>& pt) {
1715 iterateOverCloseTriangles(pt, [&](
const STLtriangle<T>& triangle) {
1716 const PhysR<T, 3> currPointOnTriangle =
1717 triangle.closestPtPointTriangle(pt);
1718 const Vector<T, 3> currDistance = pt - currPointOnTriangle;
1720 distanceNorm = util::min(distanceNorm, currDistanceNorm);
1725 return util::sqrt(distanceNorm);
1728 if(!isInsideRootTree(input.data())) {
1729 const PhysR<T,3> ptInsideTree = closestPointInBoundingBox(input);
1730 const T
distance = evalDistance(ptInsideTree);
1731 extraDistance =
norm(ptInsideTree - input);
1734 const T
distance = evalDistance(input);
1736 return evalSignForSignedDistance<SIGNMODE>(input, distance) *
distance;
1741short STLreader<T>::evalSignForSignedDistanceFromCache(
const Vector<T,3>& pt)
1744 this->operator()(&isInside, pt.data());
1745 return (isInside ? -1 : 1);
1779template <
typename T>
1780Vector<T,3> STLreader<T>::surfaceNormal(
const Vector<T,3>& pos,
const T meshSize)
1782 return surfaceNormal<SignMode::CACHED>(pos, meshSize);
1785template <
typename T>
1786Vector<T,3> STLreader<T>::surfaceNormalExact(
const Vector<T,3>& pos,
const T meshSize)
1788 return surfaceNormal<SignMode::EXACT>(pos, meshSize);
1791template <
typename T>
1792template <SignMode SIGNMODE>
1793Vector<T,3> STLreader<T>::surfaceNormal(
const Vector<T,3>& pos,
const T meshSize)
1795 return evalSurfaceNormal<SIGNMODE>(pos);
1799void STLreader<T>::print()
1803 clout <<
"voxelSize=" << _voxelSize <<
"; stlSize=" << _stlSize << std::endl;
1804 clout <<
"minPhysR(VoxelMesh)=(" << this->_myMin[0] <<
"," << this->_myMin[1]
1805 <<
"," << this->_myMin[2] <<
")";
1806 clout <<
"; maxPhysR(VoxelMesh)=(" << this->_myMax[0] <<
","
1807 << this->_myMax[1] <<
"," << this->_myMax[2] <<
")" << std::endl;
1811void STLreader<T>::writeOctree()
1813 _tree->write(_fName);
1817void STLreader<T>::writeSTL(std::string stlName)
1819 if (stlName ==
"") {
1820 _mesh.write(_fName);
1823 _mesh.write(stlName);
1828void STLreader<T>::setNormalsOutside()
1830 unsigned int noTris = _mesh.triangleSize();
1833 for (
unsigned int i = 0; i < noTris; i++) {
1834 center = _mesh.getTri(i).getCenter();
1836 center + _mesh.getTri(i).normal * util::sqrt(3.) * _voxelSize)->getInside()) {
1838 Vector<T,3> pt(_mesh.getTri(i).point[0]);
1839 _mesh.getTri(i).point[0] = _mesh.getTri(i).point[2];
1840 _mesh.getTri(i).point[2] = pt;
1841 _mesh.getTri(i).init();
1850void STLreader<T>::setBoundaryInsideNodes()
1852 std::vector<Octree<T>*> leafs;
1853 _tree->getLeafs(leafs);
1854 for (
auto it = leafs.begin(); it != leafs.end(); ++it) {
1855 if ((*it)->getBoundaryNode()) {
1856 (*it)->setInside(
true);
class for marking output with some text
STLmesh(std::string, T stlSize=1.)
Constructs a new STLmesh from a file.
Wrapper functions that simplify the use of MPI.
platform_constant int c[Q][D]
platform_constant Fraction s[Q]
platform_constant Fraction t[Q]
constexpr int q() any_platform
constexpr int d() any_platform
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.
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)
int sign(T val) any_platform
Expr pow(Expr base, Expr exp)
void print(U data, const std::string &name="", OstreamManager clout=OstreamManager(std::cout,"print"), const char delimiter=',')
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.
Vector< T, D > PhysR
Type for spatial (physical) coordinates.
std::string getName(OperatorScope scope)
Returns human-readable name of scope.
constexpr T norm(const ScalarVector< T, D, IMPL > &a) any_platform
Euclidean vector norm.
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.
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.
bool isPointInside(const PhysR< T, 3 > &pt) const
Check whether a point is inside a triangle.