OpenLB 1.8.1
Loading...
Searching...
No Matches
stlReader.hh
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2010-2024 Thomas Henn, Mathias J. Krause, Jonathan Jeppener-Haltenhoff, Christoph Gaul
4 * E-mail contact: info@openlb.net
5 * The most recent release of OpenLB can be downloaded at
6 * <http://www.openlb.net/>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23
28#ifndef STL_READER_HH
29#define STL_READER_HH
30
31
32#include <iostream>
33#include <sstream>
34#include <fstream>
35#include <stdexcept>
36#include "core/singleton.h"
38#include "octree.hh"
39#include "stlReader.h"
40
41#ifdef FEATURE_VTK
42#include <vtkSmartPointer.h>
43#include <vtkUnstructuredGrid.h>
44#include <vtkPoints.h>
45#include <vtkCellArray.h>
46#include <vtkFloatArray.h>
47#include <vtkPointData.h>
48#include <vtkTriangle.h>
49#include <vtkXMLUnstructuredGridWriter.h>
50#endif
51
52// All OpenLB code is contained in this namespace.
53namespace olb {
54
55template<typename T>
57{
58 Vector<T,3> A = point[0];
59 Vector<T,3> B = point[1];
60 Vector<T,3> C = point[2];
61 Vector<T,3> b, c;
62 T bb = 0., bc = 0., cc = 0.;
63
64 for (int i = 0; i < 3; i++) {
65 b[i] = B[i] - A[i];
66 c[i] = C[i] - A[i];
67 bb += b[i] * b[i];
68 bc += b[i] * c[i];
69 cc += c[i] * c[i];
70 }
71
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];
75
76 T norm = util::sqrt(
77 util::pow(normal[0], 2) + util::pow(normal[1], 2) + util::pow(normal[2], 2));
78 normal[0] /= norm;
79 normal[1] /= norm;
80 normal[2] /= norm;
81
82 T D = 1.0 / (cc * bb - bc * bc);
83 T bbD = bb * D;
84 T bcD = bc * D;
85 T ccD = cc * D;
86
87 kBeta = 0.;
88 kGamma = 0.;
89 d = 0.;
90
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];
97 }
98}
99
100template<typename T>
102{
103 Vector<T,3> center( T(0) );
104
105 center[0] = (point[0][0] + point[1][0]
106 + point[2][0]) / 3.;
107 center[1] = (point[0][1] + point[1][1]
108 + point[2][1]) / 3.;
109 center[2] = (point[0][2] + point[1][2]
110 + point[2][2]) / 3.;
111
112 return center;
113}
114
115template<typename T>
116std::vector<T> STLtriangle<T>::getE0()
117{
118 Vector<T,3> vec;
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];
122 return vec;
123}
124
125template<typename T>
126std::vector<T> STLtriangle<T>::getE1()
127{
128 Vector<T,3> vec;
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];
132 return vec;
133}
134
135template<typename T>
137{
138 // tests with T=double and T=float show that the epsilon must be increased
139 const T epsilon = std::numeric_limits<BaseType<T>>::epsilon()*T(10);
140
141 const T beta = pt * uBeta + kBeta;
142 const T gamma = pt * uGamma + kGamma;
143
144 // check if approximately equal
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;
147 return (beta >= T(0) || util::nearZero(beta, epsilon))
148 && (gamma >= T(0) || util::nearZero(gamma, epsilon))
149 && (alpha >= T(0) || util::nearZero(alpha, epsilon));
150 }
151 return false;
152}
153
154/* Schnitttest nach
155 * http://www.uninformativ.de/bin/RaytracingSchnitttests-76a577a-CC-BY.pdf
156 *
157 * Creative Commons Namensnennung 3.0 Deutschland
158 * http://creativecommons.org/licenses/by/3.0/de/
159 *
160 * P. Hofmann, 22. August 2010
161 *
162 */
163template<typename T>
165 const Vector<T,3>& dir,
166 Vector<T,3>& q, T& alpha, const T& rad,
167 bool print)
168{
169 T rn = 0.;
170 Vector<T,3> testPt = pt + rad * normal;
171 /* Vector<T,3> help; */
172
173 for (int i = 0; i < 3; i++) {
174 rn += dir[i] * normal[i];
175 }
176#ifdef OLB_DEBUG
177
178 if (print) {
179 std::cout << "Pt: " << pt[0] << " " << pt[1] << " " << pt[2] << std::endl;
180 }
181 if (print)
182 std::cout << "testPt: " << testPt[0] << " " << testPt[1] << " " << testPt[2]
183 << std::endl;
184 if (print)
185 std::cout << "PosNeg: "
186 << normal[0] * testPt[0] + normal[1] * testPt[1] + normal[2] * testPt[2]
187 - d << std::endl;
188 if (print)
189 std::cout << "Normal: " << normal[0] << " " << normal[1] << " " << normal[2]
190 << std::endl;
191#endif
192
193 // Schnitttest Flugrichtung -> Ebene
194 if (util::fabs(rn) < std::numeric_limits<T>::epsilon()) {
195#ifdef OLB_DEBUG
196 if (print) {
197 std::cout << "FALSE 1" << std::endl;
198 }
199#endif
200 return false;
201 }
202 alpha = d - testPt[0] * normal[0] - testPt[1] * normal[1] - testPt[2] * normal[2];
203 // alpha -= testPt[i] * normal[i];
204 alpha /= rn;
205
206 // Abstand Partikel Ebene
207 if (alpha < -std::numeric_limits<T>::epsilon()) {
208#ifdef OLB_DEBUG
209 if (print) {
210 std::cout << "FALSE 2" << std::endl;
211 }
212#endif
213 return false;
214 }
215 for (int i = 0; i < 3; i++) {
216 q[i] = testPt[i] + alpha * dir[i];
217 }
218 T beta = kBeta;
219 for (int i = 0; i < 3; i++) {
220 beta += uBeta[i] * q[i];
221 }
222#ifdef OLB_DEBUG
223 T dist = util::sqrt(
224 util::pow(q[0] - testPt[0], 2) + util::pow(q[1] - testPt[1], 2)
225 + util::pow(q[2] - testPt[2], 2));
226#endif
227
228 // Schnittpunkt q in der Ebene?
229 if (beta < -std::numeric_limits<T>::epsilon()) {
230#ifdef OLB_DEBUG
231
232 if (print) {
233 std::cout << "FALSE 3 BETA " << beta << " DIST " << dist << std::endl;
234 }
235#endif
236 return false;
237 }
238 T gamma = kGamma;
239 for (int i = 0; i < 3; i++) {
240 gamma += uGamma[i] * q[i];
241 }
242 if (gamma < -std::numeric_limits<T>::epsilon()) {
243#ifdef OLB_DEBUG
244 if (print) {
245 std::cout << "FALSE 4 GAMMA " << gamma << " DIST " << dist << std::endl;
246 }
247#endif
248 return false;
249 }
250 if (1. - beta - gamma < -std::numeric_limits<T>::epsilon()) {
251#ifdef OLB_DEBUG
252 if (print)
253 std::cout << "FALSE 5 VAL " << 1 - beta - gamma << " DIST " << dist
254 << std::endl;
255#endif
256 return false;
257 }
258#ifdef OLB_DEBUG
259 if (print) {
260 std::cout << "TRUE" << " GAMMA " << gamma << " BETA " << beta << std::endl;
261 }
262#endif
263 return true;
264}
265
270template<typename T>
272 const Vector<T,3>& pt) const
273{
274
275 const T nEps = -std::numeric_limits<T>::epsilon();
276 const T Eps = std::numeric_limits<T>::epsilon();
277
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];
281
282 T snom = (pt - point[0])*ab;
283 T sdenom = (pt - point[1])*(point[0] - point[1]);
284
285 T tnom = (pt - point[0])*ac;
286 T tdenom = (pt - point[2])*(point[0] - point[2]);
287
288 if (snom < nEps && tnom < nEps) {
289 return point[0];
290 }
291
292 T unom = (pt - point[1])*bc;
293 T udenom = (pt - point[2])*(point[1] - point[2]);
294
295 if (sdenom < nEps && unom < nEps) {
296 return point[1];
297 }
298 if (tdenom < nEps && udenom < nEps) {
299 return point[2];
300 }
301
302 T vc = normal*crossProduct3D(point[0] - pt, point[1] - pt);
303
304 if (vc < nEps && snom > Eps && sdenom > Eps) {
305 return point[0] + snom / (snom + sdenom) * ab;
306 }
307
308 T va = normal*crossProduct3D(point[1] - pt, point[2] - pt);
309
310 if (va < nEps && unom > Eps && udenom > Eps) {
311 return point[1] + unom / (unom + udenom) * bc;
312 }
313
314 T vb = normal*crossProduct3D(point[2] - pt, point[0] - pt);
315
316 if (vb < nEps && tnom > Eps && tdenom > Eps) {
317 return point[0] + tnom / (tnom + tdenom) * ac;
318 }
319
320 T u = va / (va + vb + vc);
321 T v = vb / (va + vb + vc);
322 T w = 1. - u - v;
323
324 return u * point[0] + v * point[1] + w * point[2];
325}
326
327template<typename T>
328bool STLtriangle<T>::getPointToEdgeDistances(const Vector<T,3>& input, Vector<T,3>& output, T sensitivity)
329{
330 auto P1 = point[0];
331 auto P2 = point[1];
332 output[0] = norm(crossProduct3D(P2-input,P1-P2))/norm(P1-P2);
333 P1 = point[0];
334 P2 = point[2];
335 output[1] = norm(crossProduct3D(P2-input,P1-P2))/norm(P1-P2);
336 P1 = point[1];
337 P2 = point[2];
338 output[2] = norm(crossProduct3D(P2-input,P1-P2))/norm(P1-P2);
339 return true;
340}
341
342template<typename T>
343bool STLtriangle<T>::isEdgePoint (const Vector<T,3> & input, Vector<T,3>& P1, Vector<T,3> & P2, T sensitivity )
344{
345 using namespace std;
346 if(input[0] < sensitivity && input[1] >= sensitivity && input[2] >= sensitivity )
347 {
348 P1 = point[0];
349 P2 = point[1];
350 //cout << "edge point " << P1 << " " << P2 << std::endl;
351 return true;
352 }
353 if(input[0] >= sensitivity && input[1] < sensitivity && input[2] >= sensitivity )
354 {
355 P1 = point[0];
356 P2 = point[2];
357 //cout << "edge point" << P1 << " " << P2 << std::endl;
358 return true;
359 }
360 if(input[0] >= sensitivity && input[1] >= sensitivity && input[2] < sensitivity )
361 {
362 P1 = point[1];
363 P2 = point[2];
364 //cout << "edge point" << P1 << " " << P2 << std::endl;
365 return true;
366 }
367 return false;
368}
369
370template<typename T>
371bool STLtriangle<T>::isVortexPoint (const Vector<T,3> & input,Vector<T,3>& P, T sensitivity )
372{
373 olb::OstreamManager clout = OstreamManager(std::cout, "STLtriangle");
374 using namespace std;
375 if (input[0] < sensitivity && input[1] < sensitivity && input[2] < sensitivity )
376 {
377 cout << "Error isVortexPoint! Possible reduce sensitivity!" << std::endl;
378 return false;
379 }
380 if(input[0] < sensitivity && input[1] < sensitivity)
381 {
382 P = point[0];
383 //cout << "vortex point " << P << std::endl;
384 return true;
385 }
386 if(input[0] < sensitivity && input[2] < sensitivity)
387 {
388 P = point[1];
389 //cout << "vortex point " << P << std::endl;
390 return true;
391 }
392 if(input[1] < sensitivity && input[2] < sensitivity)
393 {
394 P = point[2];
395 //cout << "vortex point " << P << std::endl;
396 return true;
397 }
398 return false;
399}
400
401template<typename T>
403 const auto AB = point[1] - point[0];
404 const auto AC = point[2] - point[0];
405 const auto AP = physR - point[0];
406
407 const auto d1 = AB * AP;
408 const auto d2 = AC * AP;
409 if (d1 <= T{0} && d2 <= T{0}) {
410 return point[0];
411 }
412
413 auto BP = physR - point[1];
414 auto d3 = AB * BP;
415 auto d4 = AC * BP;
416 if (d3 >= T{0} && d4 <= d3) {
417 return point[1];
418 }
419
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;
424 }
425
426 auto CP = physR - point[2];
427 auto d5 = AB * CP;
428 auto d6 = AC * CP;
429 if (d6 >= T{0} && d5 <= d6) {
430 return point[2];
431 }
432
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;
437 }
438
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]);
443 }
444
445 auto denom = 1.0 / (va + vb + vc);
446 auto v = vb * denom;
447 auto w = vc * denom;
448 return point[0] + AB * v + AC * w;
449}
450
451template<typename T>
452STLmesh<T>::STLmesh(std::string fName, T stlSize)
453 : _fName(fName),
454 _min(T()),
455 _max(T()),
456 _maxDist2(0),
457 clout(std::cout, "STLmesh")
458{
459 std::ifstream f(fName.c_str(), std::ios::in);
460 _triangles.reserve(10000);
461 if (!f.good()) {
462 throw std::runtime_error("STL File not valid.");
463 }
464 char buf[6];
465 buf[5] = 0;
466 f.read(buf, 5);
467 const std::string asciiHeader = "solid";
468 if (std::string(buf) == asciiHeader) {
469 f.seekg(0, std::ios::beg);
470 if (f.good()) {
471 std::string s0, s1;
472 int i = 0;
473 while (!f.eof()) {
474 f >> s0;
475 if (s0 == "facet") {
476 STLtriangle<T> tri;
477 f >> s1 >> tri.normal[0] >> tri.normal[1] >> tri.normal[2];
478 f >> s0 >> s1;
479 f >> s0 >> tri.point[0][0] >> tri.point[0][1]
480 >> tri.point[0][2];
481 f >> s0 >> tri.point[1][0] >> tri.point[1][1]
482 >> tri.point[1][2];
483 f >> s0 >> tri.point[2][0] >> tri.point[2][1]
484 >> tri.point[2][2];
485 f >> s0;
486 f >> s0;
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;
491 }
492 if (i == 0) {
493 _min = T();
494 _max = T();
495
496 _min[0] = tri.point[0][0];
497 _min[1] = tri.point[0][1];
498 _min[2] = tri.point[0][2];
499
500 _max[0] = tri.point[0][0];
501 _max[1] = tri.point[0][1];
502 _max[2] = tri.point[0][2];
503
504 _min[0] = util::min(_min[0], tri.point[1][0]);
505 _min[1] = util::min(_min[1], tri.point[1][1]);
506 _min[2] = util::min(_min[2], tri.point[1][2]);
507
508 _max[0] = util::max(_max[0], tri.point[1][0]);
509 _max[1] = util::max(_max[1], tri.point[1][1]);
510 _max[2] = util::max(_max[2], tri.point[1][2]);
511
512 _min[0] = util::min(_min[0], tri.point[2][0]);
513 _min[1] = util::min(_min[1], tri.point[2][1]);
514 _min[2] = util::min(_min[2], tri.point[2][2]);
515
516 _max[0] = util::max(_max[0], tri.point[2][0]);
517 _max[1] = util::max(_max[1], tri.point[2][1]);
518 _max[2] = util::max(_max[2], tri.point[2][2]);
519
520 }
521 else {
522 _min[0] = util::min(_min[0], tri.point[0][0]);
523 _min[1] = util::min(_min[1], tri.point[0][1]);
524 _min[2] = util::min(_min[2], tri.point[0][2]);
525
526 _max[0] = util::max(_max[0], tri.point[0][0]);
527 _max[1] = util::max(_max[1], tri.point[0][1]);
528 _max[2] = util::max(_max[2], tri.point[0][2]);
529
530 _min[0] = util::min(_min[0], tri.point[1][0]);
531 _min[1] = util::min(_min[1], tri.point[1][1]);
532 _min[2] = util::min(_min[2], tri.point[1][2]);
533
534 _max[0] = util::max(_max[0], tri.point[1][0]);
535 _max[1] = util::max(_max[1], tri.point[1][1]);
536 _max[2] = util::max(_max[2], tri.point[1][2]);
537
538 _min[0] = util::min(_min[0], tri.point[2][0]);
539 _min[1] = util::min(_min[1], tri.point[2][1]);
540 _min[2] = util::min(_min[2], tri.point[2][2]);
541
542 _max[0] = util::max(_max[0], tri.point[2][0]);
543 _max[1] = util::max(_max[1], tri.point[2][1]);
544 _max[2] = util::max(_max[2], tri.point[2][2]);
545 }
546
547 i++;
548 tri.init();
549 _triangles.push_back(tri);
550
551 _maxDist2 = util::max(distPoints(tri.point[0], tri.point[1]),
552 _maxDist2);
553 _maxDist2 = util::max(distPoints(tri.point[2], tri.point[1]),
554 _maxDist2);
555 _maxDist2 = util::max(distPoints(tri.point[0], tri.point[2]),
556 _maxDist2);
557 }
558 else if (s0 == "endsolid") {
559 break;
560 }
561 }
562 }
563 }
564 else {
565 f.close();
566 f.open(fName.c_str(), std::ios::in | std::ios::binary);
567 char comment[80];
568 f.read(comment, 80);
569
570 if (!f.good()) {
571 throw std::runtime_error("STL File not valid.");
572 }
573
574 comment[79] = 0;
575 int32_t nFacets;
576 f.read(reinterpret_cast<char *>(&nFacets), sizeof(int32_t));
577
578 if (!f.good()) {
579 throw std::runtime_error("STL File not valid.");
580 }
581
582 float v[12];
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));
587 }
588 f.read(reinterpret_cast<char *>(&uint16), sizeof(std::uint16_t));
589 STLtriangle<T> tri;
590 tri.normal[0] = v[0];
591 tri.normal[1] = v[1];
592 tri.normal[2] = v[2];
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];
602
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;
607 }
608 if (i == 0) {
609 _min[0] = tri.point[0][0];
610 _min[1] = tri.point[0][1];
611 _min[2] = tri.point[0][2];
612
613 _max[0] = tri.point[0][0];
614 _max[1] = tri.point[0][1];
615 _max[2] = tri.point[0][2];
616
617 _min[0] = util::min(_min[0], (T) tri.point[1][0]);
618 _min[1] = util::min(_min[1], (T) tri.point[1][1]);
619 _min[2] = util::min(_min[2], (T) tri.point[1][2]);
620
621 _max[0] = util::max(_max[0], (T) tri.point[1][0]);
622 _max[1] = util::max(_max[1], (T) tri.point[1][1]);
623 _max[2] = util::max(_max[2], (T) tri.point[1][2]);
624
625 _min[0] = util::min(_min[0], (T) tri.point[2][0]);
626 _min[1] = util::min(_min[1], (T) tri.point[2][1]);
627 _min[2] = util::min(_min[2], (T) tri.point[2][2]);
628
629 _max[0] = util::max(_max[0], (T) tri.point[2][0]);
630 _max[1] = util::max(_max[1], (T) tri.point[2][1]);
631 _max[2] = util::max(_max[2], (T) tri.point[2][2]);
632
633 }
634 else {
635 _min[0] = util::min(_min[0], (T) tri.point[0][0]);
636 _min[1] = util::min(_min[1], (T) tri.point[0][1]);
637 _min[2] = util::min(_min[2], (T) tri.point[0][2]);
638
639 _max[0] = util::max(_max[0], (T) tri.point[0][0]);
640 _max[1] = util::max(_max[1], (T) tri.point[0][1]);
641 _max[2] = util::max(_max[2], (T) tri.point[0][2]);
642
643 _min[0] = util::min(_min[0], (T) tri.point[1][0]);
644 _min[1] = util::min(_min[1], (T) tri.point[1][1]);
645 _min[2] = util::min(_min[2], (T) tri.point[1][2]);
646
647 _max[0] = util::max(_max[0], (T) tri.point[1][0]);
648 _max[1] = util::max(_max[1], (T) tri.point[1][1]);
649 _max[2] = util::max(_max[2], (T) tri.point[1][2]);
650
651 _min[0] = util::min(_min[0], (T) tri.point[2][0]);
652 _min[1] = util::min(_min[1], (T) tri.point[2][1]);
653 _min[2] = util::min(_min[2], (T) tri.point[2][2]);
654
655 _max[0] = util::max(_max[0], (T) tri.point[2][0]);
656 _max[1] = util::max(_max[1], (T) tri.point[2][1]);
657 _max[2] = util::max(_max[2], (T) tri.point[2][2]);
658 }
659 tri.init();
660 _triangles.push_back(tri);
661
662 _maxDist2 = util::max(distPoints(tri.point[0], tri.point[1]), _maxDist2);
663 _maxDist2 = util::max(distPoints(tri.point[2], tri.point[1]), _maxDist2);
664 _maxDist2 = util::max(distPoints(tri.point[0], tri.point[2]), _maxDist2);
665 }
666 }
667 f.close();
668}
669
670template<typename T>
671STLmesh<T>::STLmesh(const std::vector<std::vector<T>> meshPoints, T stlSize)
672 : _fName("meshPoints.stl"),
673 _min(T()),
674 _max(T()),
675 _maxDist2(0),
676 clout(std::cout, "STLmesh")
677{
678 _triangles.reserve(10000);
679 for (size_t i = 0; i < meshPoints.size() / 3; i++) {
680 STLtriangle<T> tri;
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];
684
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];
688
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;
696 }
697 if (i == 0) {
698 _min*=T();
699 _max*=T();
700
701 _min[0] = tri.point[0][0];
702 _min[1] = tri.point[0][1];
703 _min[2] = tri.point[0][2];
704
705 _max[0] = tri.point[0][0];
706 _max[1] = tri.point[0][1];
707 _max[2] = tri.point[0][2];
708
709 _min[0] = util::min(_min[0], (T) tri.point[1][0]);
710 _min[1] = util::min(_min[1], (T) tri.point[1][1]);
711 _min[2] = util::min(_min[2], (T) tri.point[1][2]);
712
713 _max[0] = util::max(_max[0], (T) tri.point[1][0]);
714 _max[1] = util::max(_max[1], (T) tri.point[1][1]);
715 _max[2] = util::max(_max[2], (T) tri.point[1][2]);
716
717 _min[0] = util::min(_min[0], (T) tri.point[2][0]);
718 _min[1] = util::min(_min[1], (T) tri.point[2][1]);
719 _min[2] = util::min(_min[2], (T) tri.point[2][2]);
720
721 _max[0] = util::max(_max[0], (T) tri.point[2][0]);
722 _max[1] = util::max(_max[1], (T) tri.point[2][1]);
723 _max[2] = util::max(_max[2], (T) tri.point[2][2]);
724
725 }
726 else {
727 _min[0] = util::min(_min[0], (T) tri.point[0][0]);
728 _min[1] = util::min(_min[1], (T) tri.point[0][1]);
729 _min[2] = util::min(_min[2], (T) tri.point[0][2]);
730
731 _max[0] = util::max(_max[0], (T) tri.point[0][0]);
732 _max[1] = util::max(_max[1], (T) tri.point[0][1]);
733 _max[2] = util::max(_max[2], (T) tri.point[0][2]);
734
735 _min[0] = util::min(_min[0], (T) tri.point[1][0]);
736 _min[1] = util::min(_min[1], (T) tri.point[1][1]);
737 _min[2] = util::min(_min[2], (T) tri.point[1][2]);
738
739 _max[0] = util::max(_max[0], (T) tri.point[1][0]);
740 _max[1] = util::max(_max[1], (T) tri.point[1][1]);
741 _max[2] = util::max(_max[2], (T) tri.point[1][2]);
742
743 _min[0] = util::min(_min[0], (T) tri.point[2][0]);
744 _min[1] = util::min(_min[1], (T) tri.point[2][1]);
745 _min[2] = util::min(_min[2], (T) tri.point[2][2]);
746
747 _max[0] = util::max(_max[0], (T) tri.point[2][0]);
748 _max[1] = util::max(_max[1], (T) tri.point[2][1]);
749 _max[2] = util::max(_max[2], (T) tri.point[2][2]);
750 }
751
752 tri.init();
753 _triangles.push_back(tri);
754
755 _maxDist2 = util::max(distPoints(tri.point[0], tri.point[1]),
756 _maxDist2);
757 _maxDist2 = util::max(distPoints(tri.point[2], tri.point[1]),
758 _maxDist2);
759 _maxDist2 = util::max(distPoints(tri.point[0], tri.point[2]),
760 _maxDist2);
761 }
762}
763
764template<typename T>
766{
767 return util::pow(T(p1[0] - p2[0]), 2)
768 + util::pow(T(p1[1] - p2[1]), 2)
769 + util::pow(T(p1[2] - p2[2]), 2);
770}
771
772template<typename T>
773void STLmesh<T>::print(bool full)
774{
775 if (full) {
776 int i = 0;
777 clout << "Triangles: " << std::endl;
778 typename std::vector<STLtriangle<T> >::iterator it = _triangles.begin();
779
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;
786 }
787 }
788 clout << "nTriangles=" << _triangles.size() << "; maxDist2=" << _maxDist2
789 << std::endl;
790 clout << "minPhysR(StlMesh)=(" << getMin()[0] << "," << getMin()[1] << ","
791 << getMin()[2] << ")";
792 clout << "; maxPhysR(StlMesh)=(" << getMax()[0] << "," << getMax()[1] << ","
793 << getMax()[2] << ")" << std::endl;
794}
795
796template<typename T>
797void STLmesh<T>::write(std::string fName)
798{
799 int rank = 0;
800#ifdef PARALLEL_MODE_MPI
801 rank = singleton::mpi().getRank();
802#endif
803 if (rank == 0) {
804 std::string fullName = singleton::directories().getVtkOutDir() + fName
805 + ".stl";
806 std::ofstream f(fullName.c_str());
807 f << "solid ascii " << fullName << "\n";
808
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]
815 << "\n";
816 f << " vertex " << _triangles[i].point[1][0] << " "
817 << _triangles[i].point[1][1] << " " << _triangles[i].point[1][2]
818 << "\n";
819 f << " vertex " << _triangles[i].point[2][0] << " "
820 << _triangles[i].point[2][1] << " " << _triangles[i].point[2][2]
821 << "\n";
822 f << " endloop\n";
823 f << "endfacet\n";
824 }
825 f << "endsolid\n";
826 f.close();
827 }
828 /*if (_verbose)*/clout << "Write ... OK" << std::endl;
829}
830
831template<typename T>
832bool 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)
833{
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) {
837 return true;
838 }
839 }
840 return false;
841}
842
843
844/*
845 * STLReader functions
846 */
847template<typename T>
848STLreader<T>::STLreader(const std::string fName, T voxelSize, T stlSize,
849 RayMode method, bool verbose, T overlap, T max)
850 : _voxelSize(voxelSize),
851 _stlSize(stlSize),
852 _overlap(overlap),
853 _fName(fName),
854 _mesh(fName, stlSize),
855 _verbose(verbose),
856 clout(std::cout, "STLreader")
857{
858 this->getName() = "STLreader";
859
860 if (_verbose) {
861 clout << "Voxelizing ..." << std::endl;
862 }
863
864 Vector<T,3> extension = _mesh.getMax() - _mesh.getMin();
865 if ( util::nearZero(max) ) {
866 max = util::max(extension[0], util::max(extension[1], extension[2])) + _voxelSize;
867 }
868 int j = 0;
869 for (; _voxelSize * util::pow(2, j) < max; j++)
870 ;
871 Vector<T,3> center;
872 T radius = _voxelSize * util::pow(2, j - 1);
873
875 for (unsigned i = 0; i < 3; i++) {
876 center[i] = (_mesh.getMin()[i] + _mesh.getMax()[i]) / 2. - _voxelSize / 4.;
877 }
878
880 _tree = new Octree<T>(center, radius, &_mesh, j, _overlap);
881
883 for (int i = 0; i < 3; i++) {
884 this->_myMin[i] = center[i] + _voxelSize / 2.;
885 this->_myMax[i] = center[i] - _voxelSize / 2.;
886 }
887 for (int i = 0; i < 3; i++) {
888 while (this->_myMin[i] > _mesh.getMin()[i]) {
889 this->_myMin[i] -= _voxelSize;
890 }
891 while (this->_myMax[i] < _mesh.getMax()[i]) {
892 this->_myMax[i] += _voxelSize;
893 }
894 this->_myMax[i] -= _voxelSize;
895 this->_myMin[i] += _voxelSize;
896 }
897
899 switch (method) {
900 case RayMode::Robust:
901 indicate1();
902 break;
904 indicate3();
905 break;
907 indicate2_Xray();
908 break;
910 indicate2_Yray();
911 break;
912 default:
913 indicate2();
914 break;
915 }
916
917 if (_verbose) {
918 print();
919 }
920 if (_verbose) {
921 clout << "Voxelizing ... OK" << std::endl;
922 }
923}
924
925/*
926 * STLReader functions
927 */
928template<typename T>
929STLreader<T>::STLreader(const std::vector<std::vector<T>> meshPoints, T voxelSize, T stlSize,
930 RayMode method, bool verbose, T overlap, T max)
931 : _voxelSize(voxelSize),
932 _stlSize(stlSize),
933 _overlap(overlap),
934 _fName("meshPoints.stl"),
935 _mesh(meshPoints, stlSize),
936 _verbose(verbose),
937 clout(std::cout, "STLreader")
938{
939 this->getName() = "STLreader";
940
941 if (_verbose) {
942 clout << "Voxelizing ..." << std::endl;
943 }
944
945 Vector<T,3> extension = _mesh.getMax() - _mesh.getMin();
946 if ( util::nearZero(max) ) {
947 max = util::max(extension[0], util::max(extension[1], extension[2])) + _voxelSize;
948 }
949 int j = 0;
950 for (; _voxelSize * util::pow(2, j) < max; j++)
951 ;
952 Vector<T,3> center;
953 T radius = _voxelSize * util::pow(2, j - 1);
954
956 for (unsigned i = 0; i < 3; i++) {
957 center[i] = (_mesh.getMin()[i] + _mesh.getMax()[i]) / 2. - _voxelSize / 4.;
958 }
959
961
962 _tree = new Octree<T>(center, radius, &_mesh, j, _overlap);
963
965 for (int i = 0; i < 3; i++) {
966 this->_myMin[i] = center[i] + _voxelSize / 2.;
967 this->_myMax[i] = center[i] - _voxelSize / 2.;
968 }
969 for (int i = 0; i < 3; i++) {
970 while (this->_myMin[i] > _mesh.getMin()[i]) {
971 this->_myMin[i] -= _voxelSize;
972 }
973 while (this->_myMax[i] < _mesh.getMax()[i]) {
974 this->_myMax[i] += _voxelSize;
975 }
976 this->_myMax[i] -= _voxelSize;
977 this->_myMin[i] += _voxelSize;
978 }
979 //automaticly choose the method with minimum extension in its direction
980
981 /*if(extension[0] == std::min_element(extension.begin(), extension.end())){
982 method = 4;
983 }
984 else if(extension[1] == std::min_element(extension.begin(), extension.end())){
985 method = 5;
986 }
987 else if(extension[2] == std::min_element(extension.begin(), extension.end())){
988 method = 0;
989 }
990 */
991
992
993 // Indicate nodes of the tree. (Inside/Outside)
994 switch (method) {
995 case RayMode::Robust:
996 indicate1();
997 break;
999 indicate3();
1000 break;
1001 case RayMode::FastRayX:
1002 indicate2_Xray();
1003 break;
1004 case RayMode::FastRayY:
1005 indicate2_Yray();
1006 break;
1007 default:
1008 indicate2();
1009 break;
1010 }
1011
1013
1014 if (_verbose) {
1015 print();
1016 }
1017 if (_verbose) {
1018 clout << "Voxelizing ... OK" << std::endl;
1019 }
1020}
1021
1022template<typename T>
1024{
1025 delete _tree;
1026}
1027
1028/*
1029 * Old indicate function (slower, more stable)
1030 * Define three rays (X-, Y-, Z-direction) for each leaf and count intersections
1031 * with STL for each ray. Odd number of intersection means inside (Majority vote).
1032 */
1033
1034template<typename T>
1036{
1037 std::vector<Octree<T>*> leafs;
1038 _tree->getLeafs(leafs);
1039 typename std::vector<Octree<T>*>::iterator it = leafs.begin();
1040 Vector<T,3> dir, pt, s;
1041
1042 int intersections = 0;
1043 int inside = 0;
1044 Octree<T>* node = nullptr;
1045 T step = 1. / 1000. * _voxelSize;
1046 for (; it != leafs.end(); ++it) {
1047 inside = 0;
1048
1049 pt = (*it)->getCenter();
1050 intersections = 0;
1051 s = pt; // + step;
1052
1054 dir[0] = 1;
1055 dir[1] = 0;
1056 dir[2] = 0;
1057 while (s[0] < _mesh.getMax()[0] + std::numeric_limits<T>::epsilon()) {
1058 node = _tree->find(s, (*it)->getMaxdepth());
1059 intersections += node->testIntersection(pt, dir);
1060 node->intersectRayNode(pt, dir, s);
1061 s = s + step * dir;
1062 }
1063 inside += (intersections % 2);
1064
1066 intersections = 0;
1067 s = pt; // + step;
1068 dir[0] = 0;
1069 dir[1] = 1;
1070 dir[2] = 0;
1071 while (s[1] < _mesh.getMax()[1] + std::numeric_limits<T>::epsilon()) {
1072 node = _tree->find(s, (*it)->getMaxdepth());
1073 intersections += node->testIntersection(pt, dir);
1074 node->intersectRayNode(pt, dir, s);
1075 s = s + step * dir;
1076 }
1077 inside += (intersections % 2);
1078
1080 intersections = 0;
1081 s = pt; // + step;
1082 dir[0] = 0;
1083 dir[1] = 0;
1084 dir[2] = 1;
1085 while (s[2] < _mesh.getMax()[2] + std::numeric_limits<T>::epsilon()) {
1086 node = _tree->find(s, (*it)->getMaxdepth());
1087 intersections += node->testIntersection(pt, dir);
1088 node->intersectRayNode(pt, dir, s);
1089 s = s + step * dir;
1090 }
1091 inside += (intersections % 2);
1092 (*it)->setInside(inside > 1);
1093 }
1094}
1095
1096/*
1097 * New indicate function (faster, less stable)
1098 * Define ray in Z-direction for each Voxel in XY-layer. Indicate all nodes on the fly.
1099 */
1100template<typename T>
1101void STLreader<T>::indicate2()
1102{
1103 T rad = _tree->getRadius();
1104 Vector<T,3> rayPt = _tree->getCenter() - rad + .5 * _voxelSize;
1105 Vector<T,3> pt = rayPt;
1106 Vector<T,3> rayDir;
1107 rayDir[0] = 0.;
1108 rayDir[1] = 0.;
1109 rayDir[2] = 1.;
1110 //Vector<T,3> maxEdge = _tree->getCenter() + rad;
1111
1112 T step = 1. / 1000. * _voxelSize;
1113
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);
1119 nodeInters = pt;
1120 nodeInters[2] = node->getCenter()[2] - node->getRadius();
1121 rayInside = 0;
1122 while (pt[1] < _mesh.getMax()[1] + std::numeric_limits<T>::epsilon()) {
1123 node = _tree->find(pt);
1124 nodeInters = pt;
1125 nodeInters[2] = node->getCenter()[2] - node->getRadius();
1126 rayInside = 0;
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;
1132 }
1133 pt[2] = rayPt[2];
1134 pt[1] += _voxelSize;
1135 }
1136 pt[1] = rayPt[1];
1137 pt[0] += _voxelSize;
1138 }
1139}
1140
1141
1142/*
1143 * New indicate function (faster, less stable)
1144 * Define ray in X-direction for each Voxel in YZ-layer. Indicate all nodes on the fly.
1145 */
1146
1147template<typename T>
1148void STLreader<T>::indicate2_Xray()
1149{
1150 T rad = _tree->getRadius();
1151 Vector<T,3> rayPt = _tree->getCenter() - rad + .5 * _voxelSize;
1152 Vector<T,3> pt = rayPt;
1153 Vector<T,3> rayDir;
1154 rayDir[0] = 1.;
1155 rayDir[1] = 0.;
1156 rayDir[2] = 0.;
1157 //Vector<T,3> maxEdge = _tree->getCenter() + rad;
1158
1159 T step = 1. / 1000. * _voxelSize;
1160
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);
1166 nodeInters = pt;
1167 nodeInters[0] = node->getCenter()[0] - node->getRadius();
1168 rayInside = 0;
1169 while (pt[1] < _mesh.getMax()[1] + std::numeric_limits<T>::epsilon()) {
1170 node = _tree->find(pt);
1171 nodeInters = pt;
1172 nodeInters[0] = node->getCenter()[0] - node->getRadius();
1173 rayInside = 0;
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;
1179 }
1180 pt[0] = rayPt[0];
1181 pt[1] += _voxelSize;
1182 }
1183 pt[1] = rayPt[1];
1184 pt[2] += _voxelSize;
1185 }
1186}
1187
1188/*
1189 * New indicate function (faster, less stable)
1190 * Define ray in Y-direction for each Voxel in XZ-layer. Indicate all nodes on the fly.
1191 */
1192
1193template<typename T>
1194void STLreader<T>::indicate2_Yray()
1195{
1196 T rad = _tree->getRadius();
1197 Vector<T,3> rayPt = _tree->getCenter() - rad + .5 * _voxelSize;
1198 Vector<T,3> pt = rayPt;
1199 Vector<T,3> rayDir;
1200 rayDir[0] = 0.;
1201 rayDir[1] = 1.;
1202 rayDir[2] = 0.;
1203 //Vector<T,3> maxEdge = _tree->getCenter() + rad;
1204
1205 T step = 1. / 1000. * _voxelSize;
1206
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);
1212 nodeInters = pt;
1213 nodeInters[1] = node->getCenter()[1] - node->getRadius();
1214 rayInside = 0;
1215 while (pt[0] < _mesh.getMax()[0] + std::numeric_limits<T>::epsilon()) {
1216 node = _tree->find(pt);
1217 nodeInters = pt;
1218 nodeInters[1] = node->getCenter()[1] - node->getRadius();
1219 rayInside = 0;
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;
1225 }
1226 pt[1] = rayPt[1];
1227 pt[0] += _voxelSize;
1228 }
1229 pt[0] = rayPt[0];
1230 pt[2] += _voxelSize;
1231 }
1232}
1233
1234/*
1235 * Double ray approach: two times (X-, Y-, Z-direction) for each leaf.
1236 * Could be use to deal with double layer triangles and face intersections.
1237 */
1238template<typename T>
1239void STLreader<T>::indicate3()
1240{
1241 std::vector<Octree<T>*> leafs;
1242 _tree->getLeafs(leafs);
1243 typename std::vector<Octree<T>*>::iterator it = leafs.begin();
1244
1245 Vector<T,3> dir, pt, s;
1246 Octree<T>* node = nullptr;
1247 T step = 1. / 1000. * _voxelSize;
1248 int intersections;
1249 int sum_intersections;
1250
1251 for (; it != leafs.end(); ++it) {
1252 pt = (*it)->getCenter();
1253 intersections = 0;
1254 sum_intersections = 0;
1255 s = pt; // + step;
1256
1258 dir[0] = 1;
1259 dir[1] = 0;
1260 dir[2] = 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);
1265 s = s + step * dir;
1266 if (intersections > 0) {
1267 sum_intersections++;
1268 break;
1269 }
1270 }
1271
1273 intersections = 0;
1274 s = pt; // + step;
1275 dir[0] = 0;
1276 dir[1] = 1;
1277 dir[2] = 0;
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);
1282 s = s + step * dir;
1283 if (intersections > 0) {
1284 sum_intersections++;
1285 break;
1286 }
1287 }
1288
1290 intersections = 0;
1291 s = pt; // + step;
1292 dir[0] = 0;
1293 dir[1] = 0;
1294 dir[2] = 1;
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);
1299 s = s + step * dir;
1300 if (intersections > 0) {
1301 sum_intersections++;
1302 break;
1303 }
1304 }
1305
1307 intersections = 0;
1308 s = pt; // + step;
1309 dir[0] = -1;
1310 dir[1] = 0;
1311 dir[2] = 0;
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);
1316 s = s + step * dir;
1317 if (intersections > 0) {
1318 sum_intersections++;
1319 break;
1320 }
1321 }
1322
1324 intersections = 0;
1325 s = pt; // + step;
1326 dir[0] = 0;
1327 dir[1] = -1;
1328 dir[2] = 0;
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);
1333 s = s + step * dir;
1334 if (intersections > 0) {
1335 sum_intersections++;
1336 break;
1337 }
1338 }
1339
1341 intersections = 0;
1342 s = pt; // + step;
1343 dir[0] = 0;
1344 dir[1] = 0;
1345 dir[2] = -1;
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);
1350 s = s + step * dir;
1351 if (intersections > 0) {
1352 sum_intersections++;
1353 break;
1354 }
1355 }
1356 (*it)->setInside(sum_intersections > 5);
1357 }
1358}
1359
1360template<typename T>
1361bool STLreader<T>::operator() (bool output[], const T input[])
1362{
1363 output[0] = false;
1364 if (isInsideRootTree(input)) {
1365 std::vector<T> tmp(input, input + 3);
1366 output[0] = _tree->find(tmp)->getInside();
1367 }
1368 return true;
1369}
1370
1371
1372template<typename T>
1374{
1375 T coords = _tree->getRadius();
1376 Vector<T,3> c(_tree->getCenter());
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;
1379}
1380
1381
1382template<typename T>
1384{
1385 T coords = _tree->getRadius();
1386 Vector<T,3> c(_tree->getCenter());
1387 Vector<T,3> closestPoint;
1388 for(int i = 0; i < 3; ++i) {
1389 closestPoint[i] = util::max(c[i] - coords, util::min(c[i] + coords, input[i]));
1390 }
1391 return closestPoint;
1392}
1393
1394
1395template<typename T>
1396bool STLreader<T>::distance(T& distance, const Vector<T,3>& origin,
1397 const Vector<T,3>& direction, int iC)
1398{
1399 Octree<T>* node = nullptr;
1400 Vector<T,3> dir(direction);
1401 dir = normalize(dir);
1402 Vector<T,3> extends = _mesh.getMax() - _mesh.getMin();
1403 Vector<T,3> pt(origin);
1404 Vector<T,3> q;
1405 Vector<T,3> s;
1406 Vector<T,3> center = _mesh.getMin() + 1 / 2. * extends;
1407 T step = _voxelSize / 1000., a = 0;
1408
1409 for (int i = 0; i < 3; i++) {
1410 extends[i] /= 2.;
1411 }
1412
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])) {
1416 T t = T(), d = T();
1417 bool foundQ = false;
1418
1419 if (dir[0] > 0) {
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];
1425
1426 if (_mesh.getMin()[1] < pt[1] && pt[1] < _mesh.getMax()[1]
1427 && _mesh.getMin()[2] < pt[2] && pt[2] < _mesh.getMax()[2]) {
1428 foundQ = true;
1429 }
1430 }
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]) {
1439 foundQ = true;
1440 }
1441 }
1442
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]) {
1451 foundQ = true;
1452 }
1453 }
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]) {
1462 foundQ = true;
1463 }
1464 }
1465
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]) {
1474 foundQ = true;
1475 }
1476 }
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]) {
1485 foundQ = true;
1486 }
1487 }
1488
1489 if (!foundQ) {
1490 return false;
1491 }
1492 }
1493
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);
1498 if (node->closestIntersection(Vector<T,3>(origin), dir, q, a)) {
1499 Vector<T,3> vek(q - Vector<T,3>(origin));
1500 distance = norm(vek);
1501 return true;
1502 }
1503 else {
1504 Octree<T>* tmpNode = _tree->find(pt);
1505 if (tmpNode) {
1506 tmpNode->intersectRayNode(pt, dir, s);
1507 for (int i = 0; i < 3; i++) {
1508 pt[i] = s[i] + step * dir[i];
1509 }
1510 }
1511 }
1512 }
1513
1514 return false;
1515}
1516
1517template<typename T>
1518template<typename F>
1519void STLreader<T>::iterateOverCloseTriangles(const PhysR<T,3>& pt, F func, Octree<T>* leafNode) {
1520 // Find the leaf node in the Octree that contains the input point
1521 leafNode = _tree->find(pt);
1522
1523 if (leafNode && !leafNode->getTriangles().empty()) {
1524 const std::vector<unsigned int>& triangleIndices = leafNode->getTriangles();
1525 for (unsigned int idx : triangleIndices) {
1526 const STLtriangle<T>& triangle = _mesh.getTri(idx);
1527 func(triangle);
1528 }
1529 }
1530 else {
1531 for (const STLtriangle<T>& triangle : _mesh.getTriangles()) {
1532 func(triangle);
1533 }
1534 }
1535};
1536
1537template<typename T>
1538Vector<T,3> STLreader<T>::evalNormalOnSurface(const PhysR<T,3>& pt, const Vector<T,3>& fallbackNormal)
1539{
1540 // Check if the position is on the corner of a triangle
1541 unsigned countTriangles = 0;
1542 Vector<T,3> normal(T(0));
1543
1544 iterateOverCloseTriangles(pt, [&](const STLtriangle<T>& triangle){
1545 // TODO: Calculate angle-weighted psuedonormal (see 10.1109/TVCG.2005.49) in case the point lies on corners
1546 // Edges correspond to an unweighted average (as calculated below) anyway
1547 if (triangle.isPointInside(pt)) {
1548 ++countTriangles;
1549 normal+=triangle.getNormal();
1550 }
1551 });
1552
1553 if (countTriangles > 0) {
1554 return normal / countTriangles;
1555 }
1556
1557 // If the provided point isn't located on the surface, return the predefined fallback
1558 return fallbackNormal;
1559}
1560
1561template<typename T>
1562template<SignMode SIGNMODE>
1563Vector<T,3> STLreader<T>::evalSurfaceNormal(const Vector<T,3>& origin)
1564{
1565 Vector<T,3> normal(0.);
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));
1570
1571 iterateOverCloseTriangles(pt, [&](const STLtriangle<T>& triangle) {
1572 PhysR<T,3> const pointOnTriangle = triangle.closestPtPointTriangle(pt);
1573 PhysR<T,3> const currDistance = pt - pointOnTriangle;
1574 T currDistanceNorm = norm_squared(currDistance);
1575 if (distance > currDistanceNorm) {
1576 normal = currDistance;
1577 distance = currDistanceNorm;
1578 closestPointOnSurface = pointOnTriangle;
1579 closestTriangle = &triangle;
1580 }
1581 });
1582
1583 distance = util::sqrt(distance);
1584 if (!util::nearZero(distance)) {
1586 normal *= evalSignForSignedDistance<SIGNMODE>(origin, distance);
1587 }
1588 else {
1589 normal = evalNormalOnSurface(closestPointOnSurface, closestTriangle->getNormal());
1590 // The below isn't necessary because all normals are set to point outside by default (see constructor)
1591
1592 /* const T tmpStepSize = _voxelSize * T{0.01}; */
1593 /* const short signBefore = evalSignForSignedDistance(origin - tmpStepSize * normal, *closestTriangle); */
1594 /* const short signAfter = evalSignForSignedDistance(origin + tmpStepSize * normal, *closestTriangle); */
1595
1596 /* if(signBefore > 0 || signAfter < 0) { */
1597 /* normal *= T{-1}; */
1598 /* } */
1599 }
1600
1601 return normal;
1602}
1603
1604
1605template<typename T>
1606template<SignMode SIGNMODE>
1607Vector<T,3> STLreader<T>::evalSurfaceNormalForPseudoNormal(const Vector<T,3>& origin, Vector<T,3> & outputPointOnSurface)
1608{
1609 Vector<T,3> normal(0.);
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));
1614
1615 iterateOverCloseTriangles(pt, [&](const STLtriangle<T>& triangle) {
1616 PhysR<T,3> const pointOnTriangle = triangle.closestPtPointTriangle(pt);
1617 PhysR<T,3> const currDistance = pt - pointOnTriangle;
1618 T currDistanceNorm = norm_squared(currDistance);
1619 if (distance > currDistanceNorm) {
1620 normal = currDistance;
1621 distance = currDistanceNorm;
1622 closestPointOnSurface = pointOnTriangle;
1623 closestTriangle = &triangle;
1624 }
1625 });
1626
1627/* distance = util::sqrt(distance);
1628 if (!util::nearZero(distance)) {
1629 normal = normal/distance;
1630 normal *= evalSignForSignedDistance<SIGNMODE>(origin, distance);
1631 }
1632 else { */
1633 normal = evalNormalOnSurface(closestPointOnSurface, closestTriangle->getNormal());
1634 outputPointOnSurface = closestPointOnSurface;
1635
1636 // The below isn't necessary because all normals are set to point outside by default (see constructor)
1637
1638 /* const T tmpStepSize = _voxelSize * T{0.01}; */
1639 /* const short signBefore = evalSignForSignedDistance(origin - tmpStepSize * normal, *closestTriangle); */
1640 /* const short signAfter = evalSignForSignedDistance(origin + tmpStepSize * normal, *closestTriangle); */
1641
1642 /* if(signBefore > 0 || signAfter < 0) { */
1643 /* normal *= T{-1}; */
1644 /* } */
1645 //}
1646
1647 return normal;
1648}
1649
1650
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)
1655{
1656 short sign;
1657
1658 if constexpr (SIGNMODE == SignMode::EXACT)
1659 {
1660
1661 if(distance < _voxelSize) {
1662
1663 sign = evalSignForSignedDistanceFromWindingNumber(pt);
1664 //sign = evalSignForSignedDistanceFromNormal(stlT.getNormal(), vecdist);
1665 /* Vector<T,3> closestPointOnSurface (0.);
1666 Vector<T,3> normal = evalSurfaceNormalForPseudoNormal<SignMode::EXACT>(pt,closestPointOnSurface);
1667 sign = evalSignForSignedDistanceFromNormal(normal, pt - closestPointOnSurface);*/
1668 }
1669 else
1670 {
1671 sign = evalSignForSignedDistanceFromCache(pt);
1672 }
1673 }
1674 else {
1675 sign = evalSignForSignedDistanceFromCache(pt);
1676 }
1677 return sign;
1678}
1679
1680template<typename T>
1681short STLreader<T>::evalSignForSignedDistanceFromPseudonormal(const Vector<T,3>& pseudonormal, const Vector<T,3>& distance)
1682{
1683 const T projection = pseudonormal * distance;
1684
1685 if(projection > 0) {
1686 return 1;
1687 }
1688 else if (projection < 0 ) {
1689 return -1;
1690 }
1691 return 0;
1692}
1693
1694
1695//aproximation not working for concave surfaces
1696template<typename T>
1697short STLreader<T>::evalSignForSignedDistanceFromNormal(const Vector<T,3>& normal, const Vector<T,3>& distance)
1698{
1699 const T projection = normal * distance;
1700
1701 if(projection > 0) {
1702 return 1;
1703 }
1704 else if (projection < 0 ) {
1705 return -1;
1706 }
1707 return 0;
1708}
1709
1710
1711
1712
1713template<typename T>
1714short STLreader<T>::evalSignForSignedDistanceFromWindingNumber(const Vector<T,3>& pt)
1715{
1716 T windingNumber{0};
1717
1718 for (const STLtriangle<T>& triangle : _mesh.getTriangles()) {
1719 const PhysR<T,3> a = triangle.point[0] - pt;
1720 const PhysR<T,3> b = triangle.point[1] - pt;
1721 const PhysR<T,3> c = triangle.point[2] - pt;
1722
1723 const T aNorm = norm(a);
1724 const T bNorm = norm(b);
1725 const T cNorm = norm(c);
1726
1727 const T numerator = a * crossProduct3D(b, c);
1728 const T denominator = aNorm * bNorm * cNorm + (a*b) * cNorm + (b*c) * aNorm + (c*a) * bNorm;
1729
1730 windingNumber += util::atan2(numerator,denominator);
1731 }
1732 windingNumber *= 2;
1733
1734 if(int(util::round(windingNumber))%2 == 0) {
1735 return 1;
1736 }
1737 return -1;
1738}
1739
1740
1741template <typename T>
1743{
1744 return signedDistance<SignMode::CACHED>(input);
1745}
1746
1747template <typename T>
1749{
1750 return signedDistance<SignMode::EXACT>(input);
1751}
1752
1753
1754
1755
1756template <typename T>
1757template <SignMode SIGNMODE>
1759{
1760 T distanceNorm = std::numeric_limits<T>::max();
1761 //Vector<T,3> distVec (std::numeric_limits<T>::max(),std::numeric_limits<T>::max(),std::numeric_limits<T>::max());
1762 T extraDistance{};
1763 //STLtriangle<T> stlT;
1764
1765 const auto evalDistance = [&](const Vector<T,3>& pt) {
1766 iterateOverCloseTriangles(pt, [&](const STLtriangle<T>& triangle) {
1767 const PhysR<T, 3> currPointOnTriangle =
1768 triangle.closestPtPointTriangle(pt);
1769 const Vector<T, 3> currDistance = pt - currPointOnTriangle;
1770 T currDistanceNorm = norm_squared(currDistance);
1771 distanceNorm = util::min(distanceNorm, currDistanceNorm);
1772 /* if(distanceNorm -currDistanceNorm < std::numeric_limits<T>::min())
1773 {distVec = currDistanceNorm;
1774 stlT = triangle;}*/
1775 });
1776 return util::sqrt(distanceNorm);
1777 };
1778
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;
1784 }
1785 const T distance = evalDistance(input);
1786
1787 return evalSignForSignedDistance<SIGNMODE>(input, distance) * distance;
1788}
1789
1790
1791template<typename T>
1793{
1794 bool isInside;
1795 this->operator()(&isInside, pt.data());
1796 return (isInside ? -1 : 1);
1797}
1798
1799
1800
1801template <typename T>
1803{
1804 return surfaceNormal<SignMode::CACHED>(pos, meshSize);
1805}
1806
1807template <typename T>
1809{
1810 return surfaceNormal<SignMode::EXACT>(pos, meshSize);
1811}
1812
1813template <typename T>
1814template <SignMode SIGNMODE>
1816{
1817 return evalSurfaceNormal<SIGNMODE>(pos);
1818}
1819
1820template<typename T>
1822{
1823 _mesh.print();
1824 _tree->print();
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;
1830}
1831
1832template<typename T>
1834{
1835 _tree->write(_fName);
1836}
1837
1838template<typename T>
1839void STLreader<T>::writeSTL(std::string stlName)
1840{
1841 if (stlName == "") {
1842 _mesh.write(_fName);
1843 }
1844 else {
1845 _mesh.write(stlName);
1846 }
1847}
1848
1849template<typename T>
1851{
1852 unsigned int noTris = _mesh.triangleSize();
1853 Vector<T,3> center;
1854 //Octree<T>* node = nullptr;
1855 for (unsigned int i = 0; i < noTris; i++) {
1856 center = _mesh.getTri(i).getCenter();
1857 if (_tree->find(
1858 center + _mesh.getTri(i).normal * util::sqrt(3.) * _voxelSize)->getInside()) {
1859 // cout << "Wrong direction" << std::endl;
1860 Vector<T,3> pt(_mesh.getTri(i).point[0]);
1861 _mesh.getTri(i).point[0] = _mesh.getTri(i).point[2];
1862 _mesh.getTri(i).point[2] = pt;
1863 _mesh.getTri(i).init();
1864 // _mesh.getTri(i).getNormal()[0] *= -1.;
1865 // _mesh.getTri(i).getNormal()[1] *= -1.;
1866 // _mesh.getTri(i).getNormal()[2] *= -1.;
1867 }
1868 }
1869}
1870
1871template<typename T>
1873{
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);
1879 }
1880 }
1881}
1882
1883} // namespace olb
1884
1885#endif
std::string & getName()
Definition genericF.hh:51
Vector< S, 3 > _myMax
Vector< S, 3 > _myMin
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 ...
Definition octree.hh:669
void intersectRayNode(const Vector< T, 3 > &pt, const Vector< T, 3 > &dir, Vector< T, 3 > &s)
Computes intersection of ray with Octree boundaries.
Definition octree.hh:676
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.
Definition octree.hh:324
Octree< T > * find(const Vector< T, 3 > &, const int &maxDepth=0)
Find the node containing the first param with remaining maxDepth.
Definition octree.hh:263
const T getRadius() const
Gets radius.
Definition octree.h:124
const std::vector< unsigned int > & getTriangles() const
Gets numbers of triangles contained by this Octree.
Definition octree.h:114
class for marking output with some text
STLmesh(std::string, T stlSize=1.)
Constructs a new STLmesh from a file.
Definition stlReader.hh:452
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.
Definition stlReader.hh:832
void print(bool full=false)
Prints console output.
Definition stlReader.hh:773
void write(std::string fName)
Writes STL mesh in Si units.
Definition stlReader.hh:797
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.
~STLreader() override
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.
Definition stlReader.hh:848
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.
Plain old scalar vector.
constexpr const T * data() const any_platform
Definition vector.h:172
std::string getVtkOutDir() const
Definition singleton.h:103
int getRank() const
Returns the process ID.
Wrapper functions that simplify the use of MPI.
platform_constant int c[Q][D]
Definition functions.h:57
platform_constant Fraction s[Q]
Definition mrt.h:65
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.
Definition sdf.h:152
MpiManager & mpi()
Directories & directories()
Definition singleton.h:162
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)
Expr sqrt(Expr x)
Definition expr.cpp:225
ADf< T, DIM > atan2(const T &y, const ADf< T, DIM > &x)
Definition aDiff.h:623
Expr min(Expr a, Expr b)
Definition expr.cpp:249
Expr max(Expr a, Expr b)
Definition expr.cpp:245
int sign(T val) any_platform
Definition util.h:53
ADf< T, DIM > round(const ADf< T, DIM > &a)
Definition aDiff.h:928
Expr pow(Expr base, Expr exp)
Definition expr.cpp:235
Expr fabs(Expr x)
Definition expr.cpp:230
bool nearZero(T a) any_platform
return true if a is close to zero
Definition util.h:402
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)
Definition vector.h:466
Vector< T, D > PhysR
Type for spatial (physical) coordinates.
constexpr T norm(const ScalarVector< T, D, IMPL > &a) any_platform
Euclidean vector norm.
RayMode
Definition stlReader.h:209
@ 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
Definition vector.h:263
constexpr Vector< T, D > normalize(const ScalarVector< T, D, IMPL > &a, T scale=T{1})
Definition vector.h:284
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.
Definition stlReader.hh:116
std::vector< T > getE1()
Returns Pt0-Pt2.
Definition stlReader.hh:126
Vector< T, 3 > normal
normal of triangle
Definition stlReader.h:70
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.
Definition stlReader.hh:164
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...
Definition stlReader.hh:328
void init()
Initializes triangle and precomputes member variables.
Definition stlReader.hh:56
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.
Definition stlReader.hh:371
Vector< T, 3 > getCenter()
Returns center.
Definition stlReader.hh:101
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...
Definition stlReader.hh:343
Vector< T, 3 > closestPtPointTriangle(const Vector< T, 3 > &pt) const
computes closest Point in a triangle to another point.
Definition stlReader.hh:271
Vector< T, 3 > closestPointTo(Vector< T, 3 > physR)
Returns the closest point to physR on the triangle.
Definition stlReader.hh:402
std::vector< Vector< T, 3 > > point
A triangle contains 3 Points.
Definition stlReader.h:67
bool isPointInside(const PhysR< T, 3 > &pt) const
Check whether a point is inside a triangle.
Definition stlReader.hh:136