28#ifndef BLOCK_LATTICE_STL_READER_HH
29#define BLOCK_LATTICE_STL_READER_HH
52 int method,
bool verbose, T overlap, T max)
53 : _cuboidGeometry (cbg3d),
55 _voxelSize(voxelSize),
59 _mesh(fName, stlSize),
61 clout(std::cout,
"BlockLatticeSTLreader")
63 this->
getName() =
"BlockLatticeSTLreader";
66 clout <<
"Voxelizing ..." << std::endl;
69 Vector<T,3> extension = _mesh.getMax() - _mesh.getMin();
74 for (; _voxelSize *
util::pow(2, j) < max; j++)
77 T radius = _voxelSize *
util::pow(2, j - 1);
80 for (
unsigned i = 0; i < 3; i++) {
81 center[i] = (_mesh.getMin()[i] + _mesh.getMax()[i]) / 2. - _voxelSize / 4.;
85 _tree =
new Octree<T>(center, radius, &_mesh, j, _overlap);
88 for (
int i = 0; i < 3; i++) {
89 this->
_myMin[i] = center[i] + _voxelSize / 2.;
90 this->
_myMax[i] = center[i] - _voxelSize / 2.;
92 for (
int i = 0; i < 3; i++) {
93 while (this->
_myMin[i] > _mesh.getMin()[i]) {
94 this->
_myMin[i] -= _voxelSize;
96 while (this->
_myMax[i] < _mesh.getMax()[i]) {
97 this->
_myMax[i] += _voxelSize;
99 this->
_myMax[i] -= _voxelSize;
100 this->
_myMin[i] += _voxelSize;
126 clout <<
"creating of the lists for signed distance function"<< std::endl;
127 _trianglesInCuboidList.resize(_loadBalancer.size());
129 for(
int iC=0; iC < _loadBalancer.size();iC++)
132 int globC = _loadBalancer.glob(iC);
133 auto& cuboid = _cuboidGeometry.get(globC);
137 if (cuboid.checkInters(center[0], center[1], center[2], 3))
139 _trianglesInCuboidList[iC].push_back(triangle);
148 clout <<
"Voxelizing ... OK" << std::endl;
157 int method,
bool verbose, T overlap, T max)
158 : _voxelSize(voxelSize),
161 _fName(
"meshPoints.stl"),
162 _mesh(meshPoints, stlSize),
164 clout(std::cout,
"BlockLatticeSTLreader")
166 this->
getName() =
"BlockLatticeSTLreader";
169 clout <<
"Voxelizing ..." << std::endl;
172 Vector<T,3> extension = _mesh.getMax() - _mesh.getMin();
177 for (; _voxelSize *
util::pow(2, j) < max; j++)
180 T radius = _voxelSize *
util::pow(2, j - 1);
183 for (
unsigned i = 0; i < 3; i++) {
184 center[i] = (_mesh.getMin()[i] + _mesh.getMax()[i]) / 2. - _voxelSize / 4.;
189 _tree =
new Octree<T>(center, radius, &_mesh, j, _overlap);
192 for (
int i = 0; i < 3; i++) {
193 this->
_myMin[i] = center[i] + _voxelSize / 2.;
194 this->
_myMax[i] = center[i] - _voxelSize / 2.;
196 for (
int i = 0; i < 3; i++) {
197 while (this->
_myMin[i] > _mesh.getMin()[i]) {
198 this->
_myMin[i] -= _voxelSize;
200 while (this->
_myMax[i] < _mesh.getMax()[i]) {
201 this->
_myMax[i] += _voxelSize;
203 this->
_myMax[i] -= _voxelSize;
204 this->
_myMin[i] += _voxelSize;
243 clout <<
"Voxelizing ... OK" << std::endl;
262 std::vector<Octree<T>*> leafs;
263 _tree->getLeafs(leafs);
264 typename std::vector<Octree<T>*>::iterator it = leafs.begin();
267 int intersections = 0;
270 T step = 1. / 1000. * _voxelSize;
271 for (; it != leafs.end(); ++it) {
274 pt = (*it)->getCenter();
282 while (s[0] < _mesh.getMax()[0] + std::numeric_limits<T>::epsilon()) {
283 node = _tree->
find(s, (*it)->getMaxdepth());
288 inside += (intersections % 2);
296 while (s[1] < _mesh.getMax()[1] + std::numeric_limits<T>::epsilon()) {
297 node = _tree->
find(s, (*it)->getMaxdepth());
302 inside += (intersections % 2);
310 while (s[2] < _mesh.getMax()[2] + std::numeric_limits<T>::epsilon()) {
311 node = _tree->
find(s, (*it)->getMaxdepth());
316 inside += (intersections % 2);
317 (*it)->setInside(inside > 1);
326void BlockLatticeSTLreader<T>::indicate2()
328 T rad = _tree->getRadius();
329 Vector<T,3> rayPt = _tree->getCenter() - rad + .5 * _voxelSize;
330 Vector<T,3> pt = rayPt;
337 T step = 1. / 1000. * _voxelSize;
339 Octree<T>* node =
nullptr;
340 unsigned short rayInside = 0;
341 Vector<T,3> nodeInters;
342 while (pt[0] < _mesh.getMax()[0] + std::numeric_limits<T>::epsilon()) {
343 node = _tree->
find(pt);
345 nodeInters[2] = node->getCenter()[2] - node->getRadius();
347 while (pt[1] < _mesh.getMax()[1] + std::numeric_limits<T>::epsilon()) {
348 node = _tree->find(pt);
350 nodeInters[2] = node->getCenter()[2] - node->getRadius();
352 while (pt[2] < _mesh.getMax()[2] + std::numeric_limits<T>::epsilon()) {
353 node = _tree->find(pt);
354 node->checkRay(nodeInters, rayDir, rayInside);
355 node->intersectRayNode(pt, rayDir, nodeInters);
356 pt = nodeInters + step * rayDir;
374void BlockLatticeSTLreader<T>::indicate2_Xray()
376 T rad = _tree->getRadius();
377 Vector<T,3> rayPt = _tree->getCenter() - rad + .5 * _voxelSize;
378 Vector<T,3> pt = rayPt;
385 T step = 1. / 1000. * _voxelSize;
387 Octree<T>* node =
nullptr;
388 unsigned short rayInside = 0;
389 Vector<T,3> nodeInters;
390 while (pt[2] < _mesh.getMax()[2] + std::numeric_limits<T>::epsilon()) {
391 node = _tree->find(pt);
393 nodeInters[0] = node->getCenter()[0] - node->getRadius();
395 while (pt[1] < _mesh.getMax()[1] + std::numeric_limits<T>::epsilon()) {
396 node = _tree->find(pt);
398 nodeInters[0] = node->getCenter()[0] - node->getRadius();
400 while (pt[0] < _mesh.getMax()[0] + std::numeric_limits<T>::epsilon()) {
401 node = _tree->find(pt);
402 node->checkRay(nodeInters, rayDir, rayInside);
403 node->intersectRayNode(pt, rayDir, nodeInters);
404 pt = nodeInters + step * rayDir;
420void BlockLatticeSTLreader<T>::indicate2_Yray()
422 T rad = _tree->getRadius();
423 Vector<T,3> rayPt = _tree->getCenter() - rad + .5 * _voxelSize;
424 Vector<T,3> pt = rayPt;
431 T step = 1. / 1000. * _voxelSize;
433 Octree<T>* node =
nullptr;
434 unsigned short rayInside = 0;
435 Vector<T,3> nodeInters;
436 while (pt[2] < _mesh.getMax()[2] + std::numeric_limits<T>::epsilon()) {
437 node = _tree->find(pt);
439 nodeInters[1] = node->getCenter()[1] - node->getRadius();
441 while (pt[0] < _mesh.getMax()[0] + std::numeric_limits<T>::epsilon()) {
442 node = _tree->find(pt);
444 nodeInters[1] = node->getCenter()[1] - node->getRadius();
446 while (pt[1] < _mesh.getMax()[1] + std::numeric_limits<T>::epsilon()) {
447 node = _tree->find(pt);
448 node->checkRay(nodeInters, rayDir, rayInside);
449 node->intersectRayNode(pt, rayDir, nodeInters);
450 pt = nodeInters + step * rayDir;
465void BlockLatticeSTLreader<T>::indicate3()
467 std::vector<Octree<T>*> leafs;
468 _tree->getLeafs(leafs);
469 typename std::vector<Octree<T>*>::iterator it = leafs.begin();
471 Vector<T,3> dir, pt,
s;
472 Octree<T>* node =
nullptr;
473 T step = 1. / 1000. * _voxelSize;
475 int sum_intersections;
477 for (; it != leafs.end(); ++it) {
478 pt = (*it)->getCenter();
480 sum_intersections = 0;
487 while (s[0] < _mesh.getMax()[0] + std::numeric_limits<T>::epsilon()) {
488 node = _tree->find(s, (*it)->getMaxdepth());
489 intersections = node->testIntersection(pt, dir);
490 node->intersectRayNode(pt, dir, s);
492 if (intersections > 0) {
504 while (s[1] < _mesh.getMax()[1] + std::numeric_limits<T>::epsilon()) {
505 node = _tree->find(s, (*it)->getMaxdepth());
506 intersections = node->testIntersection(pt, dir);
507 node->intersectRayNode(pt, dir, s);
509 if (intersections > 0) {
521 while (s[2] < _mesh.getMax()[2] + std::numeric_limits<T>::epsilon()) {
522 node = _tree->find(s, (*it)->getMaxdepth());
523 intersections = node->testIntersection(pt, dir);
524 node->intersectRayNode(pt, dir, s);
526 if (intersections > 0) {
538 while (s[0] > _mesh.getMin()[0] - std::numeric_limits<T>::epsilon()) {
539 node = _tree->find(s, (*it)->getMaxdepth());
540 intersections = node->testIntersection(pt, dir);
541 node->intersectRayNode(pt, dir, s);
543 if (intersections > 0) {
555 while (s[1] > _mesh.getMin()[1] - std::numeric_limits<T>::epsilon()) {
556 node = _tree->find(s, (*it)->getMaxdepth());
557 intersections = node->testIntersection(pt, dir);
558 node->intersectRayNode(pt, dir, s);
560 if (intersections > 0) {
572 while (s[2] > _mesh.getMin()[2] - std::numeric_limits<T>::epsilon()) {
573 node = _tree->find(s, (*it)->getMaxdepth());
574 intersections = node->testIntersection(pt, dir);
575 node->intersectRayNode(pt, dir, s);
577 if (intersections > 0) {
582 (*it)->setInside(sum_intersections > 5);
590 T coords = _tree->getRadius();
592 if (c[0] - coords < input[0] && input[0] < c[0] + coords && c[1] - coords < input[1]
593 && input[1] < c[1] + coords && c[2] - coords < input[2] && input[2] < c[2] + coords) {
594 std::vector<T> tmp(input, input + 3);
595 output[0] = _tree->find(tmp)->getInside();
607 Vector<T,3> extends = _mesh.getMax() - _mesh.getMin();
611 Vector<T,3> center = _mesh.getMin() + 1 / 2. * extends;
612 T step = _voxelSize / 1000., a = 0;
614 for (
int i = 0; i < 3; i++) {
618 if (!(_mesh.getMin()[0] < origin[0] && origin[0] < _mesh.getMax()[0]
619 && _mesh.getMin()[1] < origin[1] && origin[1] < _mesh.getMax()[1]
620 && _mesh.getMin()[2] < origin[2] && origin[2] < _mesh.getMax()[2])) {
625 d = _mesh.getMin()[0];
626 t = (d - origin[0]) / dir[0];
627 pt[0] = origin[0] + (t + step) * dir[0];
628 pt[1] = origin[1] + (t + step) * dir[1];
629 pt[2] = origin[2] + (t + step) * dir[2];
631 if (_mesh.getMin()[1] < pt[1] && pt[1] < _mesh.getMax()[1]
632 && _mesh.getMin()[2] < pt[2] && pt[2] < _mesh.getMax()[2]) {
636 else if (dir[0] < 0) {
637 d = _mesh.getMax()[0];
638 t = (d - origin[0]) / dir[0];
639 pt[0] = origin[0] + (t + step) * dir[0];
640 pt[1] = origin[1] + (t + step) * dir[1];
641 pt[2] = origin[2] + (t + step) * dir[2];
642 if (_mesh.getMin()[1] < pt[1] && pt[1] < _mesh.getMax()[1]
643 && _mesh.getMin()[2] < pt[2] && pt[2] < _mesh.getMax()[2]) {
648 if (dir[1] > 0 && !foundQ) {
649 d = _mesh.getMin()[1];
650 t = (d - origin[1]) / dir[1];
651 pt[0] = origin[0] + (t + step) * dir[0];
652 pt[1] = origin[1] + (t + step) * dir[1];
653 pt[2] = origin[2] + (t + step) * dir[2];
654 if (_mesh.getMin()[0] < pt[0] && pt[0] < _mesh.getMax()[0]
655 && _mesh.getMin()[2] < pt[2] && pt[2] < _mesh.getMax()[2]) {
659 else if (dir[1] < 0 && !foundQ) {
660 d = _mesh.getMax()[1];
661 t = (d - origin[1]) / dir[1];
662 pt[0] = origin[0] + (t + step) * dir[0];
663 pt[1] = origin[1] + (t + step) * dir[1];
664 pt[2] = origin[2] + (t + step) * dir[2];
665 if (_mesh.getMin()[0] < pt[0] && pt[0] < _mesh.getMax()[0]
666 && _mesh.getMin()[2] < pt[2] && pt[2] < _mesh.getMax()[2]) {
671 if (dir[2] > 0 && !foundQ) {
672 d = _mesh.getMin()[2];
673 t = (d - origin[2]) / dir[2];
674 pt[0] = origin[0] + (t + step) * dir[0];
675 pt[1] = origin[1] + (t + step) * dir[1];
676 pt[2] = origin[2] + (t + step) * dir[2];
677 if (_mesh.getMin()[0] < pt[0] && pt[0] < _mesh.getMax()[0]
678 && _mesh.getMin()[1] < pt[1] && pt[1] < _mesh.getMax()[1]) {
682 else if (dir[2] < 0 && !foundQ) {
683 d = _mesh.getMax()[2];
684 t = (d - origin[2]) / dir[2];
685 pt[0] = origin[0] + (t + step) * dir[0];
686 pt[1] = origin[1] + (t + step) * dir[1];
687 pt[2] = origin[2] + (t + step) * dir[2];
688 if (_mesh.getMin()[0] < pt[0] && pt[0] < _mesh.getMax()[0]
689 && _mesh.getMin()[1] < pt[1] && pt[1] < _mesh.getMax()[1]) {
699 while ((
util::fabs(pt[0] - center[0]) < extends[0])
700 && (
util::fabs(pt[1] - center[1]) < extends[1])
701 && (
util::fabs(pt[2] - center[2]) < extends[2])) {
702 node = _tree->
find(pt);
705 distance =
norm(vek);
711 for (
int i = 0; i < 3; i++) {
712 pt[i] = s[i] + step * dir[i];
718 clout <<
"Returning false" << std::endl;
727 unsigned countTriangles = 0;
731 if (triangle.isPointInside(pt)) {
733 normal+=triangle.getNormal();
736 if (countTriangles > 0) {
737 return normal / countTriangles;
745Vector<T,3> BlockLatticeSTLreader<T>::evalSurfaceNormal(
const Vector<T,3>& origin)
747 Vector<T,3> normal(0.);
748 PhysR<T,3> closestPoint;
749 T
distance = std::numeric_limits<T>::max();
751 for (
const STLtriangle<T>& triangle : _mesh.getTriangles()) {
752 PhysR<T,3>
const pointOnTriangle =
triangle.closestPtPointTriangle(origin);
754 if (
triangle.isPointInside(pointOnTriangle))
756 PhysR<T,3>
const currDistance = pointOnTriangle - origin;
757 T currDistanceNorm =
norm(currDistance);
759 std::cout <<
"util near zero" << std::endl;
760 return findNormalOnSurface(origin);
762 else if (distance > currDistanceNorm) {
763 normal = currDistance;
765 closestPoint = pointOnTriangle;
789 T distance = std::numeric_limits<T>::max();
790 auto& triangles = _trianglesInCuboidList[iC];
795 PhysR<T,3> pointOnTriangle = triangle.closestPtPointTriangle(input);
796 T distance2 =
util::min(distance,
norm(pointOnTriangle - input));
798 if(distance2 < distance && triangle.isPointInside(pointOnTriangle))
801 _triangle = triangle;
802 normal =
normalize(pointOnTriangle - input);
821 int globC = _cuboidGeometry.get_iC(input, 0);
822 if (_loadBalancer.isLocal(globC)) {
823 iC = _loadBalancer.loc(globC);
825 globC = _cuboidGeometry.get_iC(input, 3);
826 if (_loadBalancer.isLocal(globC)) {
827 iC = _loadBalancer.loc(globC);
829 throw std::runtime_error(
"Distance origin must be located within local cuboid (overlap)");
832 return signedDistance(iC, input);
838 return evalSurfaceNormal(pos);
846 clout <<
"voxelSize=" << _voxelSize <<
"; stlSize=" << _stlSize << std::endl;
847 clout <<
"minPhysR(VoxelMesh)=(" << this->_myMin[0] <<
"," << this->_myMin[1]
848 <<
"," << this->_myMin[2] <<
")";
849 clout <<
"; maxPhysR(VoxelMesh)=(" << this->_myMax[0] <<
","
850 << this->_myMax[1] <<
"," << this->_myMax[2] <<
")" << std::endl;
856 _tree->write(_fName);
866 _mesh.write(stlName);
873 unsigned int noTris = _mesh.triangleSize();
876 for (
unsigned int i = 0; i < noTris; i++) {
877 center = _mesh.getTri(i).getCenter();
879 center + _mesh.getTri(i).normal *
util::sqrt(3.) * _voxelSize)->getInside()) {
882 _mesh.getTri(i).point[0].coords = _mesh.getTri(i).point[2].coords;
883 _mesh.getTri(i).point[2].coords = pt;
884 _mesh.getTri(i).init();
895 std::vector<Octree<T>*> leafs;
896 _tree->getLeafs(leafs);
897 for (
auto it = leafs.begin(); it != leafs.end(); ++it) {
898 if ((*it)->getBoundaryNode()) {
899 (*it)->setInside(
true);
Input in STL format – header file.
void writeSTL(std::string stlName="")
Writes STL mesh in Si units.
~BlockLatticeSTLreader() override
T signedDistance(int locC, const Vector< T, 3 > &input)
Computes signed distance to closest triangle in direction of the surface normal in local cuboid locC.
BlockLatticeSTLreader(CuboidGeometry3D< T > &cbg3d, LoadBalancer< T > &hlb, const std::string fName, T voxelSize, T stlSize=1, int method=2, bool verbose=false, T overlap=0., T max=0.)
Constructs a new BlockLatticeSTLreader from a file.
void print()
Prints console output.
void writeOctree()
Writes Octree.
bool operator()(bool output[], const T input[]) override
Returns whether node is inside or not.
void setBoundaryInsideNodes()
Every octree leaf intersected by the STL will be part of the inside nodes.
Vector< T, 3 > surfaceNormal(const Vector< T, 3 > &pos, const T meshSize=0) override
Finds and returns normal of the closest surface (triangle)
void setNormalsOutside()
Rearranges normals of triangles to point outside of geometry.
bool distance(T &distance, const Vector< T, 3 > &origin, const Vector< T, 3 > &direction, int iC=-1) override
Computes distance to closest triangle intersection.
A cuboid geometry represents a voxel mesh.
std::string & getName()
read and write access to name
Base class for all LoadBalancer.
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.
Wrapper functions that simplify the use of MPI.
platform_constant Fraction t[Q]
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.
cpu::simd::Pack< T > sqrt(cpu::simd::Pack< T > value)
bool distance(S &distance, const Vector< S, D > &origin, const Vector< S, D > &direction, S precision, S pitch, F1 isInside, F2 isInsideBoundingBox)
cpu::simd::Pack< T > min(cpu::simd::Pack< T > rhs, cpu::simd::Pack< T > lhs)
cpu::simd::Pack< T > max(cpu::simd::Pack< T > rhs, cpu::simd::Pack< T > lhs)
cpu::simd::Pack< T > pow(cpu::simd::Pack< T > base, cpu::simd::Pack< T > exp)
cpu::simd::Pack< T > fabs(cpu::simd::Pack< T > value)
T dotProduct3D(const Vector< T, 3 > &a, const Vector< T, 3 > &b)
dot product, only valid in 3d
bool nearZero(const ADf< T, DIM > &a)
Top level namespace for all of OpenLB.
constexpr T norm(const ScalarVector< T, D, IMPL > &a)
Euclidean vector norm.
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.
Vector< T, 3 > & getNormal()
Return write access to normal.