Loading...
Searching...
No Matches
CG_elem.cpp
1/*---------------------------------------------------------------------------*\
2 *
3 * bitpit
4 *
5 * Copyright (C) 2015-2021 OPTIMAD engineering Srl
6 *
7 * -------------------------------------------------------------------------
8 * License
9 * This file is part of bitpit.
10 *
11 * bitpit is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License v3 (LGPL)
13 * as published by the Free Software Foundation.
14 *
15 * bitpit is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 * License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with bitpit. If not, see <http://www.gnu.org/licenses/>.
22 *
23\*---------------------------------------------------------------------------*/
24
25# include <cmath>
26# include <memory>
27# include <string>
28# include <iostream>
29
30# include <assert.h>
31
32# include "../patchkernel/element_reference.hpp"
33# include "bitpit_operators.hpp"
34
35# include "CG.hpp"
36# include "CG_private.hpp"
37
38
39namespace bitpit{
40
41namespace CGElem{
42
43
48
65void _projectPointsTriangle( int nPoints, array3D const *points, array3D const &Q0, array3D const &Q1, array3D const &Q2, array3D *proj, double *lambda )
66{
67 assert( validTriangle(Q0,Q1,Q2) );
68
69 array3D v0 = Q1 - Q0;
70 array3D v1 = Q2 - Q0;
71
72 array3D n = crossProduct(v0, v1);
73 double n2 = dotProduct(n, n);
74
75 for( int i=0; i<nPoints; ++i){
76 array3D v2 = points[i] - Q0;
77
78 double *pointLambda = lambda + 3 * i;
79 pointLambda[2] = dotProduct(crossProduct(v0, v2), n) / n2;
80 pointLambda[1] = dotProduct(crossProduct(v2, v1), n) / n2;
81 pointLambda[0] = 1. - pointLambda[1] - pointLambda[2];
82
83 array3D *pointProjections = proj + i;
84 *pointProjections = restrictPointTriangle( Q0, Q1, Q2, pointLambda);
85 }
86}
87
105bool _intersectBoxTriangle(array3D const &A0, array3D const &A1, array3D const &V0, array3D const &V1, array3D const &V2, bool interiorTriangleVertices, bool triangleEdgeBoxHullIntersections, bool triangleBoxEdgeIntersections, std::vector<array3D> *intrPtr, std::vector<int> *flagPtr, int dim, const double distanceTolerance)
106{
107
108 bool intersect(false);
109 bool addFlag( flagPtr!=nullptr);
110 bool computeIntersection(interiorTriangleVertices||triangleBoxEdgeIntersections||triangleEdgeBoxHullIntersections);
111
112 assert( ! (computeIntersection && (intrPtr==nullptr) ) );
113
114 if(computeIntersection){
115 intrPtr->clear();
116 }
117
118 if(addFlag){
119 flagPtr->clear();
120 }
121
122 //check if Triangle Boundig Box and Box overlap -> necessary condition
123 array3D B0, B1;
124 computeAABBTriangle( V0, V1, V2, B0, B1);
125
126 if( !intersectBoxBox( A0, A1, B0, B1, dim, distanceTolerance) ) {
127 return false;
128 }
129
130 //check if triangle vertices are within the box
131 for( int i=0; i<3; ++i){
132 vertexOfTriangle(i, V0, V1, V2, B0);
133 if( intersectPointBox(B0, A0, A1, dim, distanceTolerance) ){
134 intersect = true;
135 if(!interiorTriangleVertices) break;
136
137 intrPtr->push_back(B0);
138 if(addFlag) flagPtr->push_back(0);
139 }
140 }
141
142 //check if triangle edges and box faces intersect
143 if( !intersect || triangleEdgeBoxHullIntersections) {
144
145 for( int edge=0; edge<3; ++edge){
146
147 edgeOfTriangle(edge, V0, V1, V2, B0, B1);
148
149 if(dim==2){
150 array3D p;
151 array3D faceVertex0, faceVertex1;
152
153 for( int face=0; face<4; ++face){
154 edgeOfBox( face, A0, A1, faceVertex0, faceVertex1);
155
156 if( intersectSegmentSegment(B0, B1, faceVertex0, faceVertex1, p, distanceTolerance) ){
157 intersect=true;
158 if(!triangleEdgeBoxHullIntersections) break;
159
160 intrPtr->push_back(p);
161 if(addFlag) flagPtr->push_back(1);
162 }
163
164 }
165
166 } else if(dim==3){
167 array3D p;
168 std::array<array3D, 4> V;
169
170 for( int face=0; face<6; ++face){
171 faceOfBox( face, A0, A1, V[0], V[1], V[2], V[3] );
172
173 if( intersectSegmentPolygon( B0, B1, V.size(), V.data(), p, distanceTolerance ) ) {
174 intersect=true;
175 if(!triangleEdgeBoxHullIntersections) break;
176
177 intrPtr->push_back(p);
178 if(addFlag) flagPtr->push_back(1);
179 }
180 }
181 }
182 }
183 }
184
185 //check if triangle and box edges (dim=3) or box vertices (dim=2) intersect
186 if( !intersect || triangleBoxEdgeIntersections ) {
187
188 array3D p;
189
190 if(dim==2){
191 for( int i=0; i<4; ++i){
192 vertexOfBox( i, A0, A1, B0);
193 if( intersectPointTriangle(B0,V0,V1,V2,distanceTolerance)) {
194 intersect = true;
195 if(!triangleBoxEdgeIntersections) break;
196
197 intrPtr->push_back(B0);
198 if(addFlag) flagPtr->push_back(2);
199 }
200 }
201
202 } else if(dim==3){
203 for( int i=0; i<12; ++i){
204 edgeOfBox( i, A0, A1, B0, B1);
205 if( intersectSegmentTriangle(B0,B1,V0,V1,V2,p,distanceTolerance)) {
206 intersect = true;
207 if(!triangleBoxEdgeIntersections) break;
208
209 intrPtr->push_back(p);
210 if(addFlag) flagPtr->push_back(2);
211 }
212 }
213 }
214 }
215
216 return intersect;
217}
218
234bool _intersectSegmentBox(array3D const &V0, array3D const &V1, array3D const &A0, array3D const &A1, bool interiorSegmentVertice, bool segmentBoxHullIntersection, std::vector<array3D> *intrPtr, std::vector<int> *flagPtr, int dim, const double distanceTolerance)
235{
236
237 bool intersect(false);
238
239 bool addFlag(flagPtr!=nullptr);
240 bool computeIntersection(interiorSegmentVertice||segmentBoxHullIntersection);
241
242 assert( ! (computeIntersection && (intrPtr==nullptr) ) );
243
244 if(computeIntersection){
245 intrPtr->clear();
246 }
247
248 if(addFlag){
249 flagPtr->clear();
250 }
251
252 array3D p, B0, B1;
253
254 //check if segment boundig box and Box overlap
255 computeAABBSegment( V0, V1, B0, B1);
256 if( !intersectBoxBox( A0, A1, B0, B1, dim, distanceTolerance) ) {
257 return false;
258 }
259
260 //check segment points
261 for( int i=0; i<2; ++i){
262 vertexOfSegment(i, V0, V1, B0);
263
264 if( intersectPointBox(B0,A0,A1,dim,distanceTolerance) ){
265 intersect = true;
266 if(!interiorSegmentVertice) break;
267
268 intrPtr->push_back(B0);
269 if(addFlag) flagPtr->push_back(0);
270 }
271 }
272
273 //check if segment intersects outer hull of box
274 if( !intersect || segmentBoxHullIntersection){
275 if( dim == 2){ //check if box edge and segment intersect
276
277 for( int i=0; i<4; ++i){
278 edgeOfBox( i, A0, A1, B0, B1);
279
280 if( intersectSegmentSegment(B0,B1,V0,V1,p,distanceTolerance)) {
281 intersect = true;
282 if(!segmentBoxHullIntersection) break;
283
284 intrPtr->push_back(p);
285 if(addFlag) flagPtr->push_back(1);
286 }
287 }
288
289
290 } else if( dim==3 ) { //3D check if box face and segment intersect
291
292 std::array<array3D, 4> E;
293
294 for( int i=0; i<6; ++i){
295 faceOfBox( i, A0, A1, E[0], E[1], E[2], E[3]);
296
297 if( intersectSegmentPolygon(V0,V1,E.size(),E.data(),p,distanceTolerance) ) {
298 intersect = true;
299 if(!segmentBoxHullIntersection) break;
300
301 intrPtr->push_back(p);
302 if(addFlag) flagPtr->push_back(1);
303 }
304 }
305 }
306 }
307
308 return intersect;
309
310}
311
325bool _intersectPlaneBox(array3D const &P, array3D const &N, array3D const &A0, array3D const &A1, std::vector<array3D> *intrPtr, int dim, const double distanceTolerance)
326{
327
328 bool intersect(false);
329 bool computeIntersection(intrPtr);
330
331 if(computeIntersection){
332 intrPtr->clear();
333 } else if( intersectPointBox(P,A0,A1,dim,distanceTolerance)) {
334 return true;
335 }
336
337 // check if plane intersects the edges of the box
338 // and store eventually intersection points
339 int edgeCount = (dim==2) ? 4 : 12;
340 array3D E0, E1, V;
341
342 for(int i=0; i<edgeCount; ++i){
343 edgeOfBox(i, A0, A1, E0, E1);
344
345 if( intersectSegmentPlane( E0, E1, P, N, V, distanceTolerance) ){
346 intersect = true;
347
348 if(intrPtr){
349 intrPtr->push_back(V);
350 } else {
351 break;
352 }
353 }
354 }
355
356
357 // sort intersection points in couterclock-wise sense
358 if( dim==3 && intrPtr && intersect){
359
360 const array3D origin = intrPtr->at(0);
361
362 std::sort(intrPtr->begin(), intrPtr->end(), [&](const array3D &lhs, const array3D &rhs) -> bool {
363 array3D v = crossProduct(lhs-origin,rhs-origin);
364 return dotProduct(v, N) < 0;
365 } );
366 }
367
368 return intersect;
369}
370
387bool _intersectBoxPolygon(array3D const &A0, array3D const &A1, std::size_t nVS, array3D const *VS, bool innerPolygonPoints, bool polygonEdgeBoxHullIntersection, bool polygonBoxEdgeIntersections, std::vector<array3D> *intrPtr, std::vector<int> *flagPtr, int dim, const double distanceTolerance)
388{
389
390 bool intersect(false);
391 bool addFlag(flagPtr!=nullptr);
392 bool computeIntersection(innerPolygonPoints || polygonEdgeBoxHullIntersection || polygonBoxEdgeIntersections);
393
394 assert( ! (computeIntersection && (intrPtr==nullptr) ) );
395
396 if(computeIntersection){
397 intrPtr->clear();
398 }
399
400 if(addFlag){
401 flagPtr->clear();
402 }
403
404 array3D V0, V1, V2;
405
406 //check if simplex boundig box and box overlap -> necessary condition
407 computeAABBPolygon( nVS, VS, V0, V1);
408 if( !intersectBoxBox( A0, A1, V0, V1, dim, distanceTolerance) ) {
409 return false;
410 }
411
412 std::vector<array3D> partialIntr;
413 std::vector<int> partialFlag;
414
415 // check if triangle vertices lie within box
416 // or if triangles intersect edges of box
417 computeIntersection = innerPolygonPoints || polygonBoxEdgeIntersections;
418 int trianglesCount = polygonSubtriangleCount(nVS, VS);
419 for (int triangle=0; triangle<trianglesCount; ++triangle) {
420 subtriangleOfPolygon(triangle, nVS, VS, V0, V1, V2);
421
422 if( _intersectBoxTriangle( A0, A1, V0, V1, V2, innerPolygonPoints, false, polygonBoxEdgeIntersections, &partialIntr, &partialFlag, dim, distanceTolerance ) ){
423
424 intersect = true;
425 if(!computeIntersection) break;
426
427 int intrCount = partialIntr.size();
428 for( int i=0; i<intrCount; ++i){
429 // Get the intersection point
430 //
431 // Polygon triangulation adds a dummy vertex at the centroid of the polygon (V0).
432 // This vertex should not be taken into account for intersection identification.
433 array3D &candidateCoord = partialIntr[i];
434 if (utils::DoubleFloatingEqual()(norm2(V0 - candidateCoord), 0., distanceTolerance )) {
435 continue;
436 }
437
438 int candidateFlag = partialFlag[i];
439
440 //prune duplicate points
441 auto PItr = intrPtr->begin();
442 bool iterate = (PItr!=intrPtr->end());
443 while(iterate){
444
445 iterate = !utils::DoubleFloatingEqual()( norm2( *PItr -candidateCoord ), 0., distanceTolerance );
446
447 if(iterate){
448 ++PItr;
449 }
450 iterate &= PItr!=intrPtr->end();
451 }
452
453 if(PItr!=intrPtr->end()){
454 continue;
455 }
456
457 intrPtr->push_back(candidateCoord);
458 if(addFlag){
459 flagPtr->push_back(candidateFlag);
460 }
461 }
462 }
463 }
464
465 // check if edges of polygon intersect box face
466 computeIntersection = polygonEdgeBoxHullIntersection;
467 int edgesCount = polygonEdgesCount(nVS, VS);
468 if(!intersect || polygonEdgeBoxHullIntersection){
469 for (int edge=0; edge<edgesCount; ++edge) {
470 edgeOfPolygon(edge, nVS, VS, V0, V1);
471
472 if( _intersectSegmentBox( V0, V1, A0, A1, false, polygonEdgeBoxHullIntersection, &partialIntr, &partialFlag, dim, distanceTolerance) ){
473
474 intersect = true;
475 if(!computeIntersection) break;
476
477 int intrCount = partialIntr.size();
478 for( int i=0; i<intrCount; ++i){
479
480 array3D &candidateCoord = partialIntr[i];
481 int candidateFlag = partialFlag[i];
482
483 //prune duplicate points
484 auto PItr = intrPtr->begin();
485 bool iterate = (PItr!=intrPtr->end());
486 while(iterate){
487
488 iterate = !utils::DoubleFloatingEqual()( norm2( *PItr -candidateCoord ), 0., distanceTolerance );
489
490 if(iterate){
491 ++PItr;
492 }
493 iterate &= PItr!=intrPtr->end();
494 }
495
496 if(PItr!=intrPtr->end()){
497 continue;
498 }
499
500 intrPtr->push_back(candidateCoord);
501 if(addFlag){
502 flagPtr->push_back(candidateFlag);
503 }
504 }
505 }
506 }
507 }
508
509 return intersect;
510}
511
518bool validSegment(const array3D &P0, const array3D &P1 )
519{
520 return !utils::DoubleFloatingEqual()( norm2(P1-P0), 0.);
521}
522
529bool validLine(const array3D &P, const array3D &n )
530{
531 BITPIT_UNUSED(P);
532 return utils::DoubleFloatingEqual()( norm2(n), 1.);
533}
534
541bool validPlane(const array3D &P, const array3D &n )
542{
543 BITPIT_UNUSED(P);
544 return utils::DoubleFloatingEqual()( norm2(n), 1.);
545}
546
554bool validTriangle(const array3D &P0, const array3D &P1, const array3D &P2 )
555{
556
557 array3D v0 = P1 -P0;
558 if( utils::DoubleFloatingEqual()( norm2(v0), 0.) ){
559 return false;
560 }
561
562 array3D v1 = P2 -P1;
563 if( utils::DoubleFloatingEqual()( norm2(v1), 0.) ){
564 return false;
565 }
566
567 array3D v2 = P0 -P2;
568 if( utils::DoubleFloatingEqual()( norm2(v2), 0.) ){
569 return false;
570 }
571
572 array3D n = crossProduct( v0, -1.*v2);
573 if( utils::DoubleFloatingEqual()( norm2(n), 0. ) ){
574 return false;
575 }
576
577 return true;
578}
579
586bool validBarycentric(double const *lambdaPtr, int n )
587{
588
589 double sum(-1.);
590 double maxValue(0.);
591
592 for(int i=0; i<n; ++i){
593
594 double value = lambdaPtr[i];
595 if( std::abs(value) > std::abs(maxValue) ){
596 sum -= maxValue;
597 maxValue = -value;
598
599 } else {
600 sum += value;
601
602 }
603
604 }
605
606 double tolerance = std::max(1., std::abs(maxValue)) * std::numeric_limits<double>::epsilon();
607 return utils::DoubleFloatingEqual()(sum, maxValue, tolerance);
608}
609
619int convertBarycentricToFlagSegment( std::array<double,2> const &lambda, double tolerance)
620{
621
622 return convertBarycentricToFlagSegment( lambda.data(), tolerance);
623}
624
634int convertBarycentricToFlagSegment( const double *lambda, double tolerance)
635{
636
637 assert( validBarycentric(&lambda[0],2) );
638
639 if ( lambda[0] > 1. || utils::DoubleFloatingEqual()( lambda[0], 1., tolerance ) ) {
640 return 1;
641
642 } else if ( lambda[1] > 1. || utils::DoubleFloatingEqual()( lambda[1], 1., tolerance ) ) {
643 return 2;
644
645 }
646
647 return 0;
648}
649
659int convertBarycentricToFlagTriangle( array3D const &lambda, double tolerance)
660{
661 return convertBarycentricToFlagPolygon( 3, lambda.data(), tolerance);
662}
663
673int convertBarycentricToFlagTriangle( const double *lambda, double tolerance)
674{
675 return convertBarycentricToFlagPolygon( 3, lambda, tolerance);
676}
677
687int convertBarycentricToFlagPolygon( std::vector<double> const &lambda, double tolerance)
688{
689 return convertBarycentricToFlagPolygon( lambda.size(), lambda.data(), tolerance);
690}
691
702int convertBarycentricToFlagPolygon( std::size_t nLambda, double const *lambda, double tolerance)
703{
704
705 assert( validBarycentric(&lambda[0],nLambda) );
706
707 int count = 0;
708 std::size_t lastPositive = std::numeric_limits<std::size_t>::max();
709 for( std::size_t i=0; i<nLambda; ++i){
710 if ( lambda[i] < 0. || utils::DoubleFloatingEqual()( lambda[i], 0., tolerance ) ) {
711 continue;
712 }
713
714 ++count;
715 if (count > 2) {
716 return 0;
717 }
718
719 if (lastPositive != 0 || i == 1) {
720 lastPositive = i;
721 }
722 }
723
724 if( count == 1){
725 count = lastPositive + 1;
726
727 } else if (count==2) {
728 if (lastPositive != 0) {
729 count = - static_cast<int>(lastPositive);
730 } else {
731 count = - static_cast<int>(nLambda);
732 }
733
734 }
735
736 return count;
737}
738
751void computeGeneralizedBarycentric( array3D const &p, std::vector<array3D> const &vertex, std::vector<double> &lambda)
752{
753 computeGeneralizedBarycentric( p, vertex.size(), vertex.data(), lambda);
754}
755
769void computeGeneralizedBarycentric( array3D const &p, std::size_t nVertices, array3D const *vertex, std::vector<double> &lambda)
770{
771 lambda.resize(nVertices);
772
773 computeGeneralizedBarycentric( p, nVertices, vertex, lambda.data());
774}
775
789void computeGeneralizedBarycentric( array3D const &p, std::size_t nVertices, array3D const *vertex, double *lambda)
790{
791 const int MAX_ELEM_VERTICES = 8;
792 BITPIT_CREATE_WORKSPACE(area, double, nVertices, MAX_ELEM_VERTICES);
793
794 for( std::size_t i=0; i<nVertices; ++i){
795 int next = (i +1) %nVertices;
796 area[i] = areaTriangle( vertex[i], vertex[next], p);
797 }
798
799 double sumWeight(0);
800
801 for( std::size_t i=0; i<nVertices; ++i){
802 std::size_t prev = (i +nVertices -1) %nVertices;
803 std::size_t next = (i +1) %nVertices;
804 lambda[i] = areaTriangle(vertex[prev], vertex[i], vertex[next]);
805
806 for( std::size_t j=0; j<nVertices; ++j){
807 if( j==prev || j==i){
808 continue;
809 }
810
811 lambda[i] *= area[j];
812 }
813
814 sumWeight += lambda[i];
815 }
816
817 for( std::size_t i=0; i<nVertices; ++i){
818 lambda[i] /= sumWeight;
819 }
820}
821
829array3D reconstructPointFromBarycentricSegment(array3D const &Q0, array3D const &Q1, std::array<double,2> const &lambda)
830{
831 assert( validBarycentric(&lambda[0],2) );
832
833 return lambda[0]*Q0 +lambda[1]*Q1;
834}
835
843array3D reconstructPointFromBarycentricSegment(array3D const &Q0, array3D const &Q1, double const *lambda)
844{
845 assert( validBarycentric(&lambda[0],2) );
846
847 return lambda[0]*Q0 +lambda[1]*Q1;
848}
849
858array3D reconstructPointFromBarycentricTriangle(array3D const &Q0, array3D const &Q1, array3D const &Q2, array3D const &lambda)
859{
860 assert( validBarycentric(&lambda[0],3) );
861
862 return lambda[0]*Q0 +lambda[1]*Q1 +lambda[2]*Q2;
863}
864
873array3D reconstructPointFromBarycentricTriangle(array3D const &Q0, array3D const &Q1, array3D const &Q2, double const *lambda)
874{
875 assert( validBarycentric(&lambda[0],3) );
876
877 return lambda[0]*Q0 +lambda[1]*Q1 +lambda[2]*Q2;
878}
879
893array3D rotatePoint(const array3D &P, const array3D &n0, const array3D &n1, double angle)
894{
895 // Check if the axis is valid
896 double axisNorm = norm2(n1 - n0);
897 if (utils::DoubleFloatingEqual()(axisNorm, 0.)) {
898 return P;
899 }
900
901 // Transform point to a coordinates system centered in n0
902 array3D Q = P - n0;
903
904 // Rotate the point
905 std::array<double, 3> axis = (n1 - n0) / axisNorm;
906 double axis_dot = dotProduct(axis, Q);
907 std::array<double, 3> axis_cross = crossProduct(axis, Q);
908
909 double angle_cos = std::cos(angle);
910 double angle_sin = std::sin(angle);
911
912 Q[0] = Q[0] * angle_cos + axis[0] * axis_dot * (1. - angle_cos) + axis_cross[0] * angle_sin;
913 Q[1] = Q[1] * angle_cos + axis[1] * axis_dot * (1. - angle_cos) + axis_cross[1] * angle_sin;
914 Q[2] = Q[2] * angle_cos + axis[2] * axis_dot * (1. - angle_cos) + axis_cross[2] * angle_sin;
915
916 // Transform point back to the original coordinate system
917 Q = Q + n0;
918
919 return Q;
920}
921
928array3D reconstructPointFromBarycentricPolygon( std::vector<array3D> const &V, std::vector<double> const &lambda)
929{
930 return reconstructPointFromBarycentricPolygon( V.size(), V.data(), lambda);
931}
932
940array3D reconstructPointFromBarycentricPolygon( std::size_t nV, array3D const *V, std::vector<double> const &lambda)
941{
942 return reconstructPointFromBarycentricPolygon(nV, V, lambda.data());
943}
944
952array3D reconstructPointFromBarycentricPolygon( std::size_t nV, array3D const *V, double const *lambda)
953{
954 assert( validBarycentric(lambda, nV) );
955
956 array3D xP = {{0.,0.,0.}};
957 for(std::size_t i=0; i<nV; ++i){
958 xP += lambda[i]*V[i];
959 }
960
961 return xP;
962}
963
971array3D projectPointLine( array3D const &P, array3D const &Q, array3D const &n )
972{
973 assert( validLine(Q,n) );
974 return Q + dotProduct(P - Q, n) * n;
975}
976
984array3D projectPointPlane( array3D const &P, array3D const &Q, array3D const &n )
985{
986 assert( validPlane(Q,n) );
987 return P - dotProduct(P - Q, n) * n;
988}
989
997array3D projectPointSegment( array3D const &P, array3D const &Q0, array3D const &Q1)
998{
999
1000 std::array<double,2> lambda;
1001 return projectPointSegment( P, Q0, Q1, &lambda[0] );
1002}
1003
1012array3D projectPointSegment( array3D const &P, array3D const &Q0, array3D const &Q1, std::array<double,2> &lambda )
1013{
1014 return projectPointSegment( P, Q0, Q1, &lambda[0]);
1015}
1016
1025array3D projectPointSegment( array3D const &P, array3D const &Q0, array3D const &Q1, double *lambda )
1026{
1027
1028 assert( validSegment(Q0,Q1) );
1029
1030 array3D n = Q1 -Q0;
1031 double t = -dotProduct(n,Q0-P) / dotProduct(n,n);
1032
1033 // Restrict projection onto the segment
1034 t = std::max( std::min( t, 1.), 0. );
1035
1036 lambda[0] = 1. - t;
1037 lambda[1] = t;
1038
1039 return reconstructPointFromBarycentricSegment( Q0, Q1, lambda);
1040}
1041
1050array3D projectPointTriangle( array3D const &P, array3D const &Q0, array3D const &Q1, array3D const &Q2)
1051{
1052 array3D xP;
1053 array3D lambda;
1054 _projectPointsTriangle( 1, &P, Q0, Q1, Q2, &xP, lambda.data() );
1055 return xP;
1056}
1057
1067array3D projectPointTriangle( array3D const &P, array3D const &Q0, array3D const &Q1, array3D const &Q2, array3D &lambda)
1068{
1069 return projectPointTriangle( P, Q0, Q1, Q2, lambda.data() );
1070}
1071
1081array3D projectPointTriangle( array3D const &P, array3D const &Q0, array3D const &Q1, array3D const &Q2, double *lambda)
1082{
1083 array3D xP;
1084 _projectPointsTriangle( 1, &P, Q0, Q1, Q2, &xP, lambda );
1085
1086 return xP;
1087}
1088
1097array3D restrictPointTriangle( array3D const &Q0, array3D const &Q1, array3D const &Q2, array3D &lambda)
1098{
1099 return restrictPointTriangle( Q0, Q1, Q2, &lambda[0] );
1100}
1101
1110array3D restrictPointTriangle( array3D const &Q0, array3D const &Q1, array3D const &Q2, double *lambda)
1111{
1112
1113 assert( validBarycentric(&lambda[0], 3) );
1114
1115 int count = 0;
1116 std::array<int,2> negatives = {{ 0, 0 }};
1117
1118 for( int i=0; i<3; ++i){
1119 if( lambda[i] < 0){
1120 negatives[count] = i;
1121 ++count;
1122 }
1123 }
1124
1125 if( count == 0){
1126 return reconstructPointFromBarycentricTriangle( Q0, Q1, Q2, lambda );
1127 }
1128
1129 std::array<const array3D*,3> r = {{&Q0, &Q1, &Q2}};
1130 if( count == 1){
1131 std::array<double,2> lambdaLocal;
1132 int vertex0 = (negatives[0] +1) %3;
1133 int vertex1 = (vertex0 +1) %3;
1134 array3D P = reconstructPointFromBarycentricTriangle( Q0, Q1, Q2, lambda );
1135 array3D xP = projectPointSegment(P, *r[vertex0], *r[vertex1], lambdaLocal);
1136 lambda[negatives[0]] = 0.;
1137 lambda[vertex0] = lambdaLocal[0];
1138 lambda[vertex1] = lambdaLocal[1];
1139 return xP;
1140
1141 } else {
1142 int vertex0 = 3 -negatives[0] -negatives[1];
1143 int vertex1 = (vertex0 +1) %3;
1144 int vertex2 = (vertex1 +1) %3;
1145
1146 array3D s01 = *r[vertex1] - *r[vertex0];
1147 array3D s02 = *r[vertex2] - *r[vertex0];
1148
1149 if(dotProduct(s01,s02) >= 0 ){
1150 lambda[0] = 0.;
1151 lambda[1] = 0.;
1152 lambda[2] = 0.;
1153 lambda[vertex0] = 1.;
1154 return *r[vertex0];
1155
1156 } else {
1157 std::array<double,2> lambdaLocal01, lambdaLocal02;
1158 array3D P = reconstructPointFromBarycentricTriangle( Q0, Q1, Q2, lambda );
1159
1160 array3D xP01 = projectPointSegment(P, *r[vertex0], *r[vertex1], lambdaLocal01);
1161 array3D xP02 = projectPointSegment(P, *r[vertex0], *r[vertex2], lambdaLocal02);
1162
1163 if( norm2(P-xP01) <= norm2(P-xP02) ){
1164 lambda[vertex0] = lambdaLocal01[0];
1165 lambda[vertex1] = lambdaLocal01[1];
1166 lambda[vertex2] = 0.;
1167 return xP01;
1168
1169 } else {
1170 lambda[vertex0] = lambdaLocal02[0];
1171 lambda[vertex1] = 0;
1172 lambda[vertex2] = lambdaLocal02[1];
1173 return xP02;
1174 }
1175
1176 }
1177
1178 }
1179
1180 BITPIT_UNREACHABLE("CANNOT REACH");
1181
1182}
1183
1194std::vector<array3D> projectCloudTriangle( std::vector<array3D> const &cloud, array3D const &Q0, array3D const &Q1, array3D const &Q2, std::vector<array3D> &lambda )
1195{
1196
1197 int cloudCount(cloud.size());
1198
1199 std::vector<array3D> xP(cloudCount);
1200
1201 lambda.resize(cloudCount);
1202
1203 _projectPointsTriangle( cloudCount, cloud.data(), Q0, Q1, Q2, xP.data(), &lambda[0][0]);
1204
1205 return xP;
1206
1207}
1208
1215array3D projectPointPolygon( array3D const &P, std::vector<array3D> const &V)
1216{
1217 return projectPointPolygon( P, V.size(), V.data());
1218}
1219
1227array3D projectPointPolygon( array3D const &P, std::size_t nV, array3D const *V)
1228{
1229 std::vector<double> lambda(nV);
1230 return projectPointPolygon( P, nV, V, lambda);
1231}
1232
1240array3D projectPointPolygon( array3D const &P, std::vector<array3D> const &V, std::vector<double> &lambda)
1241{
1242 return projectPointPolygon( P, V.size(), V.data(), lambda);
1243}
1244
1253array3D projectPointPolygon( array3D const &P, std::size_t nV, array3D const *V, std::vector<double> &lambda)
1254{
1255 lambda.resize(nV);
1256
1257 return projectPointPolygon(P, nV, V, lambda.data());
1258}
1259
1268array3D projectPointPolygon( array3D const &P, std::size_t nV, array3D const *V, double *lambda)
1269{
1270 array3D xP;
1271
1272 double distance, minDistance(std::numeric_limits<double>::max());
1273 int minTriangle = -1;
1274 array3D V0, V1, V2;
1275 array3D localLambda = std::numeric_limits<double>::max() * array3D{{1., 1., 1.}};
1276 array3D minLambda = std::numeric_limits<double>::max() * array3D{{1., 1., 1.}};
1277
1278 // Compute the distance from each triangle in the simplex
1279 int triangleCount = polygonSubtriangleCount(nV, V);
1280
1281 for (int triangle=0; triangle < triangleCount; ++triangle) {
1282
1283 subtriangleOfPolygon( triangle, nV, V, V0, V1, V2);
1284
1285 distance = distancePointTriangle(P, V0, V1, V2, localLambda);
1286
1287 if (distance <= minDistance) {
1288
1289 minDistance = distance;
1290
1291 minLambda = localLambda;
1292 minTriangle = triangle;
1293 }
1294
1295 } //next triangle
1296
1297 assert(minTriangle >= 0);
1298 subtriangleOfPolygon( minTriangle, nV, V, V0, V1, V2);
1299 xP = reconstructPointFromBarycentricTriangle( V0, V1, V2, minLambda);
1300
1301 computeGeneralizedBarycentric( xP, nV, V, lambda);
1302
1303 return xP;
1304
1305}
1306
1315array3D projectPointCone( array3D const &point, array3D const &apex, array3D const &axis, double alpha)
1316{
1317
1318
1319 if( alpha <= BITPIT_PI_2 ) { //accute cone angle
1320
1321 array3D versor = point-apex;
1322 versor /= norm2(versor);
1323
1324 double cosPointAxis = dotProduct(versor,axis);
1325 double cosCriticalAngle = cos(alpha+BITPIT_PI_2);
1326
1327 if( cosPointAxis <= cosCriticalAngle ){ //point projects on cone apex
1328 return apex;
1329
1330 } else { // point projects on cone surface
1331
1332 array3D planeNormal = crossProduct(axis,versor);
1333 planeNormal /= norm2(planeNormal);
1334
1335 array3D direction = rotateVector(axis,planeNormal,alpha);
1336
1337 return projectPointLine(point,apex,direction);
1338
1339 }
1340
1341 } else { // abtuse cone angle -> project on complement
1342 return projectPointCone( point, apex, -1.*axis, BITPIT_PI-alpha);
1343
1344 }
1345
1346}
1347
1356double distancePointLine( array3D const &P, array3D const &Q, array3D const &n, array3D &xP)
1357{
1358 xP = projectPointLine(P,Q,n);
1359 return norm2( P-xP);
1360}
1361
1370double distancePointPlane( array3D const &P, array3D const &Q, array3D const &n, array3D &xP)
1371{
1372 xP = projectPointPlane(P,Q,n);
1373 return norm2(P-xP);
1374}
1375
1383double distancePointSegment( array3D const &P, array3D const &Q0, array3D const &Q1)
1384{
1385 array3D xP = projectPointSegment( P, Q0, Q1);
1386 return norm2(P-xP);
1387}
1388
1397double distancePointSegment( array3D const &P, array3D const &Q0, array3D const &Q1, std::array<double,2> &lambda)
1398{
1399 array3D xP = projectPointSegment( P, Q0, Q1, lambda);
1400 return norm2(P-xP);
1401}
1402
1411double distancePointTriangle( array3D const &P, array3D const &Q0, array3D const &Q1, array3D const &Q2)
1412{
1413 array3D xP = projectPointTriangle(P, Q0, Q1, Q2);
1414 return norm2(P-xP);
1415}
1416
1426double distancePointTriangle( array3D const &P, array3D const &Q0, array3D const &Q1, array3D const &Q2, array3D &lambda)
1427{
1428 array3D xP = projectPointTriangle(P, Q0, Q1, Q2, lambda);
1429 return norm2(P-xP);
1430}
1431
1440double distancePointCone( array3D const &point, array3D const &apex, array3D const &axis, double alpha)
1441{
1442 array3D xP = projectPointCone( point, apex, axis, alpha);
1443 return norm2(point-xP);
1444}
1445
1454std::vector<double> distanceCloudTriangle( std::vector<array3D> const &cloud, array3D const &Q0, array3D const &Q1, array3D const &Q2)
1455{
1456 std::vector<array3D> lambda(cloud.size());
1457 return distanceCloudTriangle( cloud, Q0, Q1, Q2, lambda);
1458}
1459
1469std::vector<double> distanceCloudTriangle( std::vector<array3D> const &cloud, array3D const &Q0, array3D const &Q1, array3D const &Q2, std::vector<array3D> &lambda )
1470{
1471 int N(cloud.size());
1472
1473 lambda.resize(N);
1474
1475 std::vector<array3D> xP(N);
1476 _projectPointsTriangle( N, cloud.data(), Q0, Q1, Q2, xP.data(), &lambda[0][0]);
1477
1478 std::vector<double> d(N);
1479 std::vector<double>::iterator distance = d.begin();
1480
1481 std::vector<array3D>::iterator projection = xP.begin();
1482 for( const auto &point : cloud){
1483 *distance = norm2( point - *projection);
1484
1485 ++projection;
1486 ++distance;
1487 }
1488
1489 return d;
1490}
1491
1500double distancePointPolygon( array3D const &P, std::vector<array3D> const &V, array3D &xP, int &flag)
1501{
1502 return distancePointPolygon( P, V.size(), V.data(), xP, flag);
1503}
1504
1514double distancePointPolygon( array3D const &P, std::size_t nV, array3D const *V, array3D &xP, int &flag)
1515{
1516 const int MAX_ELEM_VERTICES = 8;
1517 BITPIT_CREATE_WORKSPACE(lambda, double, nV, MAX_ELEM_VERTICES);
1518
1519 double distance = distancePointPolygon( P, nV, V, lambda);
1520 xP = reconstructPointFromBarycentricPolygon( nV, V, lambda );
1521 flag = convertBarycentricToFlagPolygon( nV, lambda );
1522
1523 return distance;
1524}
1525
1532double distancePointPolygon( array3D const &P, std::vector<array3D> const &V)
1533{
1534 return distancePointPolygon( P, V.size(), V.data());
1535}
1536
1544double distancePointPolygon( array3D const &P, std::size_t nV, array3D const *V)
1545{
1546 std::vector<double> lambda(nV);
1547 return distancePointPolygon( P, nV, V, lambda);
1548}
1549
1557double distancePointPolygon( array3D const &P, std::vector<array3D> const &V,std::vector<double> &lambda)
1558{
1559 return distancePointPolygon(P, V.size(), V.data(), lambda);
1560}
1561
1570double distancePointPolygon( array3D const &P, std::size_t nV, array3D const *V,std::vector<double> &lambda)
1571{
1572 lambda.resize(nV);
1573
1574 return distancePointPolygon(P, nV, V, lambda.data());
1575}
1576
1585double distancePointPolygon( array3D const &P, std::size_t nV, array3D const *V, double *lambda)
1586{
1587 array3D xP = projectPointPolygon( P, nV, V, lambda);
1588 return norm2(P-xP);
1589}
1590
1599std::vector<double> distanceCloudPolygon( std::vector<array3D> const &cloud, std::vector<array3D> const &V, std::vector<array3D> &xP, std::vector<int> &flag)
1600{
1601 return distanceCloudPolygon( cloud, V.size(), V.data(), xP, flag);
1602}
1603
1613std::vector<double> distanceCloudPolygon( std::vector<array3D> const &cloud, std::size_t nV, array3D const *V, std::vector<array3D> &xP, std::vector<int> &flag)
1614{
1615 int cloudCount( cloud.size() );
1616
1617 std::vector<std::vector<double>> lambda( cloudCount, std::vector<double> (nV));
1618 std::vector<double> d = distanceCloudPolygon( cloud, nV, V, lambda);
1619
1620 xP.resize(cloudCount);
1621 std::vector<array3D>::iterator xPItr = xP.begin();
1622
1623 flag.resize(cloudCount);
1624 std::vector<int>::iterator flagItr = flag.begin();
1625
1626 for( const auto &l : lambda){
1627 *flagItr = convertBarycentricToFlagPolygon( l );
1628 *xPItr = reconstructPointFromBarycentricPolygon( nV, V, l );
1629
1630 ++xPItr;
1631 ++flagItr;
1632 }
1633
1634 return d;
1635}
1636
1643std::vector<double> distanceCloudPolygon( std::vector<array3D> const &P, std::vector<array3D> const &V)
1644{
1645 return distanceCloudPolygon( P, V.size(), V.data());
1646}
1647
1655std::vector<double> distanceCloudPolygon( std::vector<array3D> const &P, std::size_t nV, array3D const *V)
1656{
1657 int cloudCount(P.size());
1658
1659 std::vector<double> d(cloudCount,std::numeric_limits<double>::max());
1660
1661 int triangleCount = polygonSubtriangleCount(nV, V);
1662 array3D V0, V1, V2;
1663
1664 for (int triangle=0; triangle < triangleCount; ++triangle) { // foreach triangle
1665 subtriangleOfPolygon( triangle, nV, V, V0, V1, V2);
1666 std::vector<double> dT = distanceCloudTriangle(P, V0, V1, V2);
1667
1668 d = min(d,dT);
1669 }
1670
1671 return d;
1672}
1673
1681std::vector<double> distanceCloudPolygon( std::vector<array3D> const &cloud, std::vector<array3D> const &V, std::vector<std::vector<double>> &lambda)
1682{
1683 return distanceCloudPolygon( cloud, V.size(), V.data(), lambda);
1684}
1685
1694std::vector<double> distanceCloudPolygon( std::vector<array3D> const &cloud, std::size_t nV, array3D const *V, std::vector<std::vector<double>> &lambda)
1695{
1696 int cloudCount(cloud.size()), vertexCount(nV);
1697
1698 std::vector<double> d(cloudCount,std::numeric_limits<double>::max());
1699 lambda.resize(cloudCount, std::vector<double>(vertexCount,0) );
1700
1701 std::vector<double> dTemp(cloudCount);
1702 std::vector<array3D> lambdaTemp(cloudCount);
1703 int triangleCount = polygonSubtriangleCount(nV, V);
1704 array3D V0, V1, V2;
1705
1706 for (int triangle=0; triangle < triangleCount; ++triangle) { // foreach triangle
1707 subtriangleOfPolygon( triangle, nV, V, V0, V1, V2);
1708 dTemp = distanceCloudTriangle(cloud, V0, V1, V2, lambdaTemp);
1709
1710 for(int i=0; i< cloudCount; ++i){
1711 if( dTemp[i] < d[i]){
1712 d[i] = dTemp[i];
1713 std::copy( lambdaTemp[i].begin(), lambdaTemp[i].end(), lambda[i].begin());
1714 }
1715 }
1716 }
1717
1718 return d;
1719}
1720
1729double distanceLineLine( array3D const &P0, array3D const &n0, array3D const &P1, array3D const &n1)
1730{
1731 array3D xP0, xP1;
1732 return distanceLineLine( P0, n0, P1, n1, xP0, xP1);
1733}
1734
1745double distanceLineLine( array3D const &P0, array3D const &n0, array3D const &P1, array3D const &n1, array3D &xP0, array3D &xP1)
1746{
1747 assert( validLine(P0,n0) );
1748 assert( validLine(P1,n1) );
1749
1750 double n01 = dotProduct(n0,n1);
1751 double det = 1. - n01*n01;
1752
1753 // check if lines are parallel
1754 if( std::abs(det) < 1.e-12){
1755 double distance = distancePointLine(P0, P1, n1, xP1);
1756 xP0 = projectPointLine(xP1, P0, n0);
1757 return distance;
1758 }
1759
1760
1761 array3D dP = P1-P0;
1762 double rhs0 = dotProduct(dP,n0);
1763 double rhs1 = -dotProduct(dP,n1);
1764
1765 double det0 = rhs0 +rhs1*n01;
1766 double det1 = rhs1 +rhs0*n01;
1767
1768 double s0 = det0/det;
1769 double s1 = det1/det;
1770
1771 xP0 = P0 +s0*n0;
1772 xP1 = P1 +s1*n1;
1773
1774 return norm2( xP0 - xP1);
1775}
1776
1787bool intersectLineLine( array3D const &P1, array3D const &n1, array3D const &P2, array3D const &n2, array3D &P, double distanceTolerance)
1788{
1789 array3D xP1, xP2;
1790 if( distanceLineLine(P1,n1,P2,n2,xP1,xP2) < distanceTolerance){
1791 P = xP1;
1792 return true;
1793 }
1794
1795 return false;
1796}
1797
1808bool intersectSegmentSegment( array3D const &P1, array3D const &P2, array3D const &Q1, array3D const &Q2, array3D &x, double distanceTolerance)
1809{
1810 assert( validSegment(P1,P2) );
1811 assert( validSegment(Q1,Q2) );
1812
1813 array3D nP = P2 - P1;
1814 nP /= norm2(nP);
1815
1816 array3D nQ = Q2 - Q1;
1817 nQ /= norm2(nQ);
1818
1819 array3D temp;
1820 if( intersectLineLine(P1, nP, Q1, nQ, temp, distanceTolerance) && intersectPointSegment( temp, P1, P2, distanceTolerance) && intersectPointSegment(temp, Q1, Q2, distanceTolerance) ){
1821 x = temp;
1822 return true;
1823 }
1824
1825 return false;
1826}
1827
1839bool intersectLinePlane( array3D const &P1, array3D const &n1, array3D const &P2, array3D const &n2, array3D &P, const double coplanarityTolerance)
1840{
1841
1842 assert( validLine(P1,n1) );
1843 assert( validPlane(P2,n2) );
1844
1845 // ========================================================================== //
1846 // CHECK DEGENERATE CASES //
1847 // ========================================================================== //
1848 double s = dotProduct(n1, n2);
1849 if (std::abs(s) < std::cos(0.5*BITPIT_PI-coplanarityTolerance)) {
1850 return false;
1851 }
1852
1853 // ========================================================================== //
1854 // FIND INTERSECTION POINTS //
1855 // ========================================================================== //
1856 double xi = -dotProduct(P1 - P2, n2) /s;
1857 P = P1 + xi *n1;
1858
1859 return true;
1860}
1861
1872bool intersectSegmentPlane( array3D const &Q1, array3D const &Q2, array3D const &P2, array3D const &n2, array3D &P, const double distanceTolerance)
1873{
1874
1875 assert( validSegment(Q1,Q2) );
1876 assert( validPlane(P2,n2) );
1877
1878 array3D n = Q2 - Q1;
1879 n /= norm2(n);
1880
1881 array3D xP;
1882 if ( intersectLinePlane(Q1, n, P2, n2, xP, distanceTolerance) && intersectPointSegment(xP, Q1, Q2, distanceTolerance) ) {
1883 P = xP;
1884 return true;
1885 }
1886
1887 return false;
1888}
1889
1902bool intersectPlanePlane( array3D const &P1, array3D const &n1, array3D const &P2, array3D const &n2,
1903 array3D &Pl, array3D &nl, const double coplanarityTolerance)
1904{
1905
1906 assert( validPlane(P1,n1) );
1907 assert( validPlane(P2,n2) );
1908
1909 double n12 = dotProduct(n1, n2);
1910 // check degenerate condition
1911 if( std::abs(n12) > std::cos(coplanarityTolerance)) {
1912 return false;
1913 }
1914
1915
1916 double detCB = 1.0-n12*n12;
1917
1918
1919 nl = crossProduct(n1,n2);
1920 nl /= norm2(nl);
1921
1922 // if planes intersect, determine the closest point
1923 // to P1 and P2 as anchor point. The augmented functional
1924 // I = 0.5*[ (Pl-P1)^2 + (Pl-P2)^2] + lambda1[ n1.(Pl-P1) ] +lambda2[ n2.(Pl-P2) ]
1925 // where lambda1 and lambda2 are Lagrange multipliers.
1926 // The optimality conditions I,Pl I,lambda1 I,lambda2 are
1927 // solved using the Schur complment
1928
1929 array3D dP = P2-P1;
1930 std::array<double,2> rhs = {{ dotProduct(n1,dP) , -dotProduct(n2,dP) }};
1931
1932 double det1 = rhs[0] - n12*rhs[1];
1933 double det2 = rhs[1] - n12*rhs[0];
1934 double lambda1 = det1 /detCB;
1935 double lambda2 = det2 /detCB;
1936
1937 Pl = P1 +P2 -lambda1*n1 -lambda2*n2;
1938 Pl *= 0.5;
1939
1940 return true;
1941
1942}
1943
1954bool intersectPlaneBox( array3D const &P1, array3D const &n1, array3D const &A0, array3D const &A1, int dim, const double distanceTolerance)
1955{
1956 assert( validPlane(P1,n1) );
1957 return _intersectPlaneBox( P1, n1, A0, A1, nullptr, dim, distanceTolerance);
1958}
1959
1971bool intersectPlaneBox( array3D const &P1, array3D const &n1, array3D const &A0, array3D const &A1, std::vector<array3D> &intersects, int dim, const double distanceTolerance)
1972{
1973 assert( validPlane(P1,n1) );
1974 return _intersectPlaneBox( P1, n1, A0, A1, &intersects, dim, distanceTolerance);
1975}
1976
1988bool intersectLineTriangle( array3D const &P, array3D const &n, array3D const &A, array3D const &B, array3D const &C, array3D &Q, const double distanceTolerance)
1989{
1990 assert( validLine(P,n) );
1991 assert( validTriangle(A,B,C) );
1992
1993 array3D nT = crossProduct(B - A, C - A);
1994 nT /= norm2(nT);
1995
1996 array3D xP;
1997 if ( intersectLinePlane(P, n, A, nT, xP, distanceTolerance) && intersectPointTriangle(xP, A, B, C, distanceTolerance) ) {
1998 Q = xP;
1999 return true;
2000 }
2001
2002 return false;
2003}
2004
2016bool intersectSegmentTriangle( array3D const &P0, array3D const &P1, array3D const &A, array3D const &B, array3D const &C, array3D &Q, const double distanceTolerance)
2017{
2018 assert( validSegment(P0,P1) );
2019 assert( validTriangle(A,B,C) );
2020
2021 array3D n = P1 - P0;
2022 n /= norm2(n);
2023
2024 array3D xP;
2025 if ( intersectLineTriangle(P0, n, A, B, C, xP, distanceTolerance) && intersectPointSegment(xP, P0, P1, distanceTolerance) ) {
2026 Q = xP;
2027 return true;
2028 }
2029
2030 return false;
2031}
2032
2042bool intersectLinePolygon( array3D const &P, array3D const &n, std::vector<array3D > const &V, array3D &Q, const double distanceTolerance)
2043{
2044 return intersectLinePolygon( P, n, V.size(), V.data(), Q, distanceTolerance);
2045}
2046
2057bool intersectLinePolygon( array3D const &P, array3D const &n, std::size_t nV, array3D const *V, array3D &Q, const double distanceTolerance)
2058{
2059 assert( validLine(P,n) );
2060
2061 int nTriangles = polygonSubtriangleCount(nV, V);
2062 array3D V0, V1, V2;
2063
2064 for( int i=0; i< nTriangles; ++i){
2065 subtriangleOfPolygon(i, nV, V, V0, V1, V2);
2066
2067 if( intersectLineTriangle(P, n, V0, V1, V2, Q, distanceTolerance) ) {
2068 return true;
2069 }
2070 }
2071
2072 return false;
2073}
2074
2084bool intersectSegmentPolygon( array3D const &P0, array3D const &P1, std::vector<array3D > const &V, array3D &Q, const double distanceTolerance)
2085{
2086 return intersectSegmentPolygon( P0, P1, V.size(), V.data(), Q, distanceTolerance);
2087}
2088
2099bool intersectSegmentPolygon( array3D const &P0, array3D const &P1, std::size_t nV, array3D const *V, array3D &Q, const double distanceTolerance)
2100{
2101 assert( validSegment(P0,P1) );
2102
2103 int nTriangles = polygonSubtriangleCount(nV, V);
2104 array3D V0, V1, V2;
2105
2106 for( int i=0; i< nTriangles; ++i){
2107 subtriangleOfPolygon(i, nV, V, V0, V1, V2);
2108
2109 if( intersectSegmentTriangle(P0, P1, V0, V1, V2, Q, distanceTolerance) ) {
2110 return true;
2111 }
2112 }
2113
2114 return false;
2115}
2116
2138bool intersectPlanePixel(array3D const &Pp, array3D const &nP, array3D const *V,
2139 std::array<array3D, 2> &intersection,
2140 std::array<int, 2> &edges_of_intersection, const double distanceTolerance)
2141{
2142 // Order vertices in counter-clockwise manner
2143 const bitpit::ReferencePixelInfo &pixel = static_cast<ReferencePixelInfo const &>(ReferenceElementInfo::getInfo(ElementType::PIXEL));
2144
2145 const array3D &P0 = V[pixel.getCCWOrderedVertex(0)];
2146 const array3D &P1 = V[pixel.getCCWOrderedVertex(1)];
2147 const array3D &P2 = V[pixel.getCCWOrderedVertex(2)];
2148 const array3D &P3 = V[pixel.getCCWOrderedVertex(3)];
2149
2150 assert( validTriangle(P0,P1,P2) );
2151 assert( validTriangle(P1,P2,P3) );
2152
2153 std::vector<const array3D *> ptrs{&P0, &P1, &P2, &P3};
2154
2155 // Search for intersections at each edge
2156 array3D temp;
2157 std::vector<array3D *> localI{&intersection[0], &intersection[1], &temp};
2158 int temp_2;
2159 std::array<int *, 3> localE{&edges_of_intersection[0], &edges_of_intersection[1], &temp_2};
2160
2161 int count(0);
2162 for (std::size_t i = 0; i < 4; ++i) {
2163 const array3D *v1 = ptrs[i];
2164 const array3D *v2 = ptrs[(i + 1) % 4];
2165 if (intersectSegmentPlane(*v1, *v2, Pp, nP, *(localI[count]), distanceTolerance)) {
2166 int face = pixel.getCCWOrderedFace(i);
2167 *(localE[count]) = face;
2168 ++count;
2169 }
2170 }
2171
2172 if (count > 2) {
2173 // plane is cutting exactly onto a vertex + its opposite edge. So you see 3 apparent intersections, but 2 are the same point.
2174 // take the most significant intersections.
2175 if (norm2(*(localI[2]) - *(localI[0])) > norm2(*(localI[1]) - *(localI[0]))) {
2176 std::swap(intersection[1], temp);
2177 std::swap(edges_of_intersection[1], temp_2);
2178 }
2179 }
2180
2181 // return true if you found at least 2 edges intersecting.
2182 return count >= 2;
2183}
2184
2203bool intersectPlanePixel(array3D const &Pp, array3D const &nP, array3D const *V,
2204 std::array<array3D, 2> &intersection, const double distanceTolerance)
2205{
2206 std::array<int, 2> edges_of_intersection;
2207 return intersectPlanePixel(Pp, nP, V, intersection, edges_of_intersection, distanceTolerance);
2208}
2209
2229bool intersectPlanePixel(array3D const &Pp, array3D const &nP, array3D const *V,
2230 std::array<array3D, 2> &intersection,
2231 std::vector<array3D> &poly, const double distanceTolerance)
2232{
2233 poly.clear();
2234
2235 // Order vertices in counter-clockwise manner
2236 const bitpit::ReferencePixelInfo &pixel = static_cast<ReferencePixelInfo const &>(ReferenceElementInfo::getInfo(ElementType::PIXEL));
2237 const array3D &P0 = V[pixel.getCCWOrderedVertex(0)];
2238 const array3D &P1 = V[pixel.getCCWOrderedVertex(1)];
2239 const array3D &P2 = V[pixel.getCCWOrderedVertex(2)];
2240 const array3D &P3 = V[pixel.getCCWOrderedVertex(3)];
2241
2242 std::vector<const array3D *> ptrs{&P0, &P1, &P2, &P3};
2243
2244 // Compute vertices signed distance from the plane
2245 std::array<double, 4> a;
2246 double aMax = std::numeric_limits<int>::min();
2247 double aMin = std::numeric_limits<int>::max();
2248 for (int i = 0; i < 4; ++ i) {
2249 a[i] = dotProduct(Pp - *(ptrs[i]), nP);
2250 if (a[i] > aMax) {
2251 aMax = a[i];
2252 }
2253 if (a[i] < aMin) {
2254 aMin = a[i];
2255 }
2256 }
2257
2258 // Early return if pixel is not intersected
2259 if (aMax < distanceTolerance) {
2260 return false;
2261 }
2262 if (aMin > -distanceTolerance) {
2263 for (int i = 0; i < 4; ++i) {
2264 poly.push_back(*(ptrs[i]));
2265 }
2266 return false;
2267 }
2268
2269 // Compute intersections
2270 std::array<int, 2> edges_of_intersection;
2271 bool intersected = intersectPlanePixel(Pp, nP, V,
2272 intersection, edges_of_intersection, distanceTolerance);
2273
2274 // Build polygon
2275 int intr = 0;
2276 bool push = (a[0] > distanceTolerance);
2277 for (std::size_t i = 0; i < ptrs.size(); ++i) {
2278 int face = pixel.getCCWOrderedFace(i);
2279 if (intr < 2 && edges_of_intersection[intr] == face) {
2280 poly.push_back(intersection[intr]);
2281 ++intr;
2282 push = !push;
2283 }
2284 if (push) {
2285 int iNext = (int(i) + 1) % 4;
2286 poly.push_back(*(ptrs[iNext]));
2287 }
2288 }
2289 return intersected;
2290}
2291
2309bool intersectPlaneTriangle(array3D const &P0, array3D const &P1, array3D const &P2,
2310 array3D const &Pp, array3D const &nP,
2311 std::array<array3D, 2> &intersection,
2312 std::array<int, 2> &edges_of_intersection,
2313 const double distanceTolerance)
2314{
2315 assert( validTriangle(P0,P1,P2) );
2316
2317 std::vector<const array3D *> ptrs{&P0, &P1, &P2};
2318 array3D temp;
2319 std::vector<array3D *> localI{&intersection[0], &intersection[1], &temp};
2320 int temp_2;
2321 std::array<int *, 3> localE{&edges_of_intersection[0], &edges_of_intersection[1], &temp_2};
2322
2323 int count(0);
2324 for (std::size_t i = 0; i < 3; ++i) {
2325 const array3D *v1 = ptrs[i];
2326 const array3D *v2 = ptrs[(i + 1) % 3];
2327 if (intersectSegmentPlane(*v1, *v2, Pp, nP, *(localI[count]), distanceTolerance)) {
2328 *(localE[count]) = i;
2329 ++count;
2330 }
2331 }
2332
2333 if (count > 2) {
2334 // plane is cutting exactly onto a vertex + its opposite edge. So you see 3 apparent intersections, but 2 are the same point.
2335 // take the most significant intersections.
2336 if (norm2(*(localI[2]) - *(localI[0])) > norm2(*(localI[1]) - *(localI[0]))) {
2337 std::swap(intersection[1], temp);
2338 std::swap(edges_of_intersection[1], temp_2);
2339 }
2340 }
2341
2342 // return true if you found at least 2 edges intersecting.
2343 return count >= 2;
2344}
2345
2359bool intersectPlaneTriangle(array3D const &P0, array3D const &P1, array3D const &P2,
2360 array3D const &Pp, array3D const &nP,
2361 std::array<array3D, 2> &intersection,
2362 const double distanceTolerance)
2363{
2364
2365 std::array<int, 2> edges_of_intersection;
2366 return intersectPlaneTriangle(P0, P1, P2, Pp, nP, intersection,
2367 edges_of_intersection, distanceTolerance);
2368}
2369
2386bool intersectPlaneTriangle(array3D const &P0, array3D const &P1, array3D const &P2,
2387 array3D const &Pp, array3D const &nP,
2388 std::array<array3D, 2> &intersection,
2389 std::vector<array3D> &poly,
2390 const double distanceTolerance)
2391{
2392 poly.clear();
2393
2394 std::vector<const array3D*> ptrs{&P0, &P1, &P2};
2395
2396 // Compute vertices signed distance from the plane
2397 std::array<double, 3> a;
2398 double aMax = std::numeric_limits<int>::min();
2399 double aMin = std::numeric_limits<int>::max();
2400 for (int i = 0; i < 3; ++ i) {
2401 a[i] = dotProduct(Pp - *(ptrs[i]), nP);
2402 if (a[i] > aMax) {
2403 aMax = a[i];
2404 }
2405 if (a[i] < aMin) {
2406 aMin = a[i];
2407 }
2408 }
2409
2410 // Early return if triangle is not intersected
2411 if (aMax < distanceTolerance) {
2412 return false;
2413 }
2414 if (aMin > -distanceTolerance) {
2415 for (int i = 0; i < 3; ++i) {
2416 poly.push_back(*(ptrs[i]));
2417 }
2418 return false;
2419 }
2420
2421 // Compute intersections
2422 std::array<int, 2> edges_of_intersection;
2423 bool intersected = intersectPlaneTriangle(P0, P1, P2, Pp, nP, intersection,
2424 edges_of_intersection, distanceTolerance);
2425
2426 // Build polygon
2427 int intr = 0;
2428 bool push = (a[0] > distanceTolerance);
2429 for (std::size_t i = 0; i < ptrs.size(); ++i) {
2430 if (intr < 2 && edges_of_intersection[intr] == int(i)) {
2431 poly.push_back(intersection[intr]);
2432 ++intr;
2433 push = !push;
2434 }
2435 if (push) {
2436 int iNext = (int(i) + 1) % 3;
2437 poly.push_back(*(ptrs[iNext]));
2438 }
2439 }
2440 return intersected;
2441}
2442
2460bool intersectPlanePolygon(array3D const &P, array3D const &nP, std::size_t nV, array3D const *V,
2461 std::vector<std::array<array3D, 2>> &Qs,
2462 std::vector<std::array<int, 2>> &edges_of_Qs,
2463 const double distanceTolerance)
2464{
2465 // early return if no polygon is provided
2466 if (V == nullptr) {
2467 return false;
2468 }
2469 assert(validPlane(P, nP));
2470
2471 // verify the set of vertices is defining a non-zero area polygon
2472 array3D N = computePolygonNormal(nV, V);
2473 if (norm2(N) <= std::numeric_limits<double>::min()) {
2474 throw std::runtime_error ("List of vertices provided do not describe a polygon with area > 0.0. Cannot perform polygon - plane intersection.");
2475 }
2476
2477 // note for Devs: passing from triangle subdivision proven to be more robust than looping on polygon edges crossing plane
2478 // when detecting multiple separate intersections in concave polygons.
2479
2480 Qs.clear();
2481 edges_of_Qs.clear();
2482
2483 // evaluate the polygon verices mean
2484 // used as an auxiliary point
2485 array3D C = {0.0, 0.0, 0.0};
2486 for (std::size_t i = 0; i < nV; ++i) {
2487 C += V[i];
2488 }
2489 C /= double(nV > 0 ? nV : 1);
2490
2491 std::map<int, array3D> ordered_intersections;
2492
2493 for (int i = 0; i < int(nV); ++i) {
2494
2495 int next = (i + 1) % nV;
2496
2497 std::array<array3D, 2> wSegment;
2498 std::array<int, 2> edges_of_wSegment;
2499
2500 if (!intersectPlaneTriangle(V[i], V[next], C, P, nP, wSegment, edges_of_wSegment, distanceTolerance)) {
2501 continue;
2502 }
2503
2504 // Keep only the intersections of the plane with the polygon excluding the
2505 // intersections between the plane and the edges resulted form the polygon triangulation.
2506 for (int k = 0; k < 2; ++k) {
2507 if (edges_of_wSegment[k] == 0) {
2508 ordered_intersections[i] = wSegment[k];
2509 }
2510 }
2511 }
2512
2513 // The ordered_intersections map should retain only even entries.
2514 std::size_t size = ordered_intersections.size();
2515
2516 // If 2 entries are retained, is the normal segment cutting a regular polygon.
2517 // if 4 or 6 or m= 2*n are found, there are m/2 segment cutting the polygon
2518 // (which can be convex or plane is cutting onto one or multiple polygon vertices)
2519 if (size < 2 || size % 2 != 0) {
2520 return false;
2521 }
2522
2523 Qs.reserve(size / 2);
2524 edges_of_Qs.reserve(size / 2);
2525
2526 int iL(0), iR(1);
2527 std::map<int, array3D>::iterator tup1 = std::next(ordered_intersections.begin(), iL);
2528 std::map<int, array3D>::iterator tup2 = std::next(ordered_intersections.begin(), iR);
2529
2530 if (size == 2) {
2531 // push directly without problems.
2532 Qs.push_back(std::array<array3D, 2>{tup1->second, tup2->second});
2533 edges_of_Qs.push_back(std::array<int, 2>{tup1->first, tup2->first});
2534 } else {
2535 // try to find as representative couple 2 intersection points not coincident.
2536 bool found = norm2(tup1->second - tup2->second) > distanceTolerance;
2537 while (!found && tup2 != ordered_intersections.end()) {
2538 ++iL, ++iR;
2539 tup1 = std::next(ordered_intersections.begin(), iL);
2540 tup2 = std::next(ordered_intersections.begin(), iR);
2541 found = norm2(tup1->second - tup2->second) > distanceTolerance;
2542 }
2543
2544 std::size_t offset = 0;
2545 if (found) {
2546 // check the normal of polygon portion cut by segment has the same normal direction than my original polygon.
2547 // if not alter the offset so that i can visit intersection n-1,0,1,2,... 2 by 2, instead of 0,1,2,...,n-1
2548 array3D polyNormal = computePolygonNormal(nV, V);
2549
2550 std::vector<array3D> pp;
2551 pp.reserve(tup2->first - tup1->first + 2);
2552 pp.push_back(tup1->second);
2553 for (int k = (tup1->first + 1); k <= tup2->first; ++k) {
2554 pp.push_back(V[k]);
2555 }
2556 pp.push_back(tup2->second);
2557
2558 array3D subNormal = computePolygonNormal(pp.size(), pp.data());
2559 offset = (dotProduct(polyNormal, subNormal) < 0) ? size - 1 : 0;
2560 }
2561 for (std::size_t j = 0; j < (size / 2); ++j) {
2562 tup1 = std::next(ordered_intersections.begin(), (2 * j + offset) % size);
2563 tup2 = std::next(ordered_intersections.begin(), (2 * j + 1 + offset) % size);
2564 Qs.push_back(std::array<array3D, 2>{tup1->second, tup2->second});
2565 edges_of_Qs.push_back(std::array<int, 2>{tup1->first, tup2->first});
2566 }
2567 }
2568 return !Qs.empty();
2569}
2570
2582bool intersectPlanePolygon(array3D const &P, array3D const &nP, std::size_t nV, array3D const *V,
2583 std::vector<std::array<array3D, 2>> &Qs, const double distanceTolerance)
2584{
2585 std::vector<std::array<int, 2>> edges_of_Qs;
2586 return intersectPlanePolygon(P, nP, nV, V, Qs, edges_of_Qs, distanceTolerance);
2587}
2588
2602bool intersectPlanePolygon(array3D const &P, array3D const &nP, std::size_t nV, array3D const *V,
2603 std::vector<std::array<array3D, 2>> &Qs,
2604 std::vector< std::vector<array3D> > &polys,
2605 const double distanceTolerance)
2606{
2607 std::vector<std::array<int, 2>> edges_of_Qs;
2608 if (!intersectPlanePolygon(P, nP, nV, V, Qs, edges_of_Qs, distanceTolerance)) {
2609 return false;
2610 }
2611
2612 std::vector< std::vector<array3D> > totalPolys;
2613 reconstructPlaneIntersectedPolygons(nV, V, Qs, edges_of_Qs, totalPolys, distanceTolerance);
2614
2615 // discard polygons placed on the subspace pointed by the normal
2616 for (std::size_t i = 0; i < totalPolys.size(); ++i) {
2617 double dMax = 0.0;
2618 for (std::size_t j = 0; j < totalPolys[i].size(); ++j) {
2619 double d = dotProduct(P - totalPolys[i][j], nP);
2620 if (std::abs(d) > std::abs(dMax)) {
2621 dMax = d;
2622 }
2623 }
2624 if (dMax > -distanceTolerance) {
2625 polys.push_back(totalPolys[i]);
2626 }
2627 }
2628 return (!polys.empty());
2629}
2630
2638array3D computePolygonNormal(std::size_t nV, const array3D *V)
2639{
2640 //Note for Devs : method 2) algorithm of vtk::vtkPolygon.
2641 array3D normal{0., 0., 0.};
2642
2643 if (nV < 3 || V == nullptr) {
2644 //lines or vertices are not a polygon or if the polygon is not defined.
2645 return normal;
2646 }
2647
2648 if (nV == 3) {
2649 //it's a regular triangle, can do it fast, without summation.
2650 normal = crossProduct(V[2] - V[1], V[0] - V[1]);
2651 } else {
2652 //use vtkPolygon algorithm
2653 int iV0(0), iV1(1), iV2(1);
2654 for (std::size_t i = 0; i < nV; ++i) {
2655 //update the vertices
2656 iV0 = iV1;
2657 iV1 = iV2;
2658 iV2 = (i + 2) % nV;
2659 normal += crossProduct(V[iV2] - V[iV1], V[iV0] - V[iV1]);
2660 }
2661 }
2662
2663 double normv = norm2(normal);
2664 normv = normv > std::numeric_limits<double>::min() ? normv : 1.0;
2665
2666 return normal / normv;
2667}
2668
2680void reconstructPlaneIntersectedPolygons(std::size_t nV, array3D const *V,
2681 std::vector<std::array<array3D, 2>> const &Qs,
2682 std::vector<std::array<int, 2>> const &edges_of_Qs,
2683 std::vector< std::vector<array3D> > &polys,
2684 const double distanceTolerance)
2685{
2686 polys.clear();
2687
2688 // Build mother polygons. Each of them is a closed polygonal chain of vertices
2689 // formed by the intersection of the given polygon with the given plane. In case
2690 // of an intersection between a concave polygon and a plane, more than one mother
2691 // polygons may be created.
2692 std::vector<array3D> motherPolygon;
2693 std::size_t motherPos = 0;
2694 int motherInit = -1;
2695 motherPolygon.reserve(nV);
2696
2697 std::size_t size = Qs.size();
2698 for (std::size_t i = 0; i < size; ++i) {
2699 const std::array<array3D, 2> &Q = Qs[i];
2700 const std::array<int, 2> &edges = edges_of_Qs[i];
2701
2702 //skip invalid input data in edges
2703 if (edges[0] < 0 || edges[1] < 0) {
2704 continue;
2705 }
2706
2707 const int &L1 = edges[0];
2708 const int &L2 = edges[1];
2709 const array3D &S1 = Q[0];
2710 const array3D &S2 = Q[1];
2711
2712 //if segment has negligible lenght
2713 if (utils::DoubleFloatingEqual()(norm2(S1 - S2), 0., distanceTolerance )) {
2714 continue;
2715 }
2716
2717 if (motherInit < 0) {
2718 motherInit = L1;
2719 motherPos = motherInit;
2720 }
2721
2722 std::size_t index = motherPos;
2723 while (int(index) != L1) {
2724 motherPolygon.push_back(V[index]);
2725 index = (index + 1) % nV;
2726 }
2727 motherPolygon.push_back(V[L1]);
2728 //ok extract the next cut sub_polygon.
2729 {
2730 std::vector<array3D> newp;
2731 newp.push_back(S1);
2732 index = (L1 + 1) % nV;
2733 while (int(index) != L2) {
2734 newp.push_back(V[index]);
2735 index = (index + 1) % nV;
2736 }
2737 newp.push_back(V[L2]);
2738 newp.push_back(S2);
2739 polys.push_back(newp);
2740 }
2741
2742 // and update the mother polygon with intersections.
2743 motherPolygon.push_back(S1);
2744 motherPolygon.push_back(S2);
2745 motherPos = (L2 + 1) % nV;
2746 }
2747
2748 //if mother polygon is empty means no valid intersection occurred.
2749 if (motherPolygon.empty()) {
2750 return;
2751 }
2752
2753 //otherwise you may need to complete motherPolygon, and push it as valid polys.
2754 std::size_t index = motherPos;
2755 while (int(index) != motherInit) {
2756 motherPolygon.push_back(V[index]);
2757 index = (index + 1) % nV;
2758 }
2759 polys.push_back(motherPolygon);
2760}
2761
2772bool intersectBoxBox(array3D const &A1, array3D const &A2, array3D const &B1, array3D const &B2, int dim, const double distanceTolerance)
2773{
2774 for( int d=0; d<dim; ++d){
2775 if( B1[d] > A2[d] + distanceTolerance || B2[d] < A1[d] - distanceTolerance ){
2776 return false;
2777 }
2778 }
2779
2780 return true;
2781}
2782
2795bool intersectBoxBox(array3D const &A1, array3D const &A2, array3D const &B1, array3D const &B2, array3D &I1, array3D &I2, int dim, const double distanceTolerance )
2796{
2797 for( int d=0; d<dim; ++d){
2798
2799 if( B1[d] > A2[d] + distanceTolerance || B2[d] < A1[d] - distanceTolerance ){
2800 return false;
2801 }
2802
2803 else{
2804 I1[d] = std::max( A1[d], B1[d] );
2805 I2[d] = std::min( A2[d], B2[d] );
2806 }
2807
2808 }
2809
2810 return true;
2811}
2812
2824bool intersectBoxTriangle(array3D const &A0, array3D const &A1, array3D const &V0, array3D const &V1, array3D const &V2, int dim, const double distanceTolerance)
2825{
2826 return _intersectBoxTriangle( A0, A1, V0, V1, V2, false, false, false, nullptr, nullptr, dim, distanceTolerance);
2827}
2828
2844bool intersectBoxTriangle(array3D const &A0, array3D const &A1, array3D const &V0, array3D const &V1, array3D const &V2, bool interiorTriangleVertices, bool triangleEdgeBoxFaceIntersections, bool triangleBoxEdgeIntersections, std::vector<array3D> &P, int dim, const double distanceTolerance)
2845{
2846 return _intersectBoxTriangle( A0, A1, V0, V1, V2, interiorTriangleVertices, triangleEdgeBoxFaceIntersections, triangleBoxEdgeIntersections, &P, nullptr, dim, distanceTolerance);
2847}
2848
2865bool intersectBoxTriangle(array3D const &A0, array3D const &A1, array3D const &V0, array3D const &V1, array3D const &V2, bool interiorTriangleVertices, bool triangleEdgeBoxHullIntersections, bool triangleBoxEdgeIntersections, std::vector<array3D> &P, std::vector<int> &flag, int dim, const double distanceTolerance)
2866{
2867 return _intersectBoxTriangle( A0, A1, V0, V1, V2, interiorTriangleVertices, triangleEdgeBoxHullIntersections, triangleBoxEdgeIntersections, &P, &flag, dim, distanceTolerance);
2868}
2869
2880bool intersectSegmentBox( array3D const &V0, array3D const &V1, array3D const &A0, array3D const &A1, int dim, const double distanceTolerance)
2881{
2882 return _intersectSegmentBox( V0, V1, A0, A1, false, false, nullptr, nullptr, dim, distanceTolerance);
2883}
2884
2898bool intersectSegmentBox( array3D const &V0, array3D const &V1, array3D const &A0, array3D const &A1, bool interiorSegmentVertice, bool segmentBoxHullIntersection, std::vector<array3D> &P, int dim, const double distanceTolerance)
2899{
2900 return _intersectSegmentBox( V0, V1, A0, A1, interiorSegmentVertice, segmentBoxHullIntersection, &P, nullptr, dim, distanceTolerance);
2901}
2902
2917bool intersectSegmentBox( array3D const &V0, array3D const &V1, array3D const &A0, array3D const &A1, bool interiorSegmentVertice, bool segmentBoxHullIntersection, std::vector<array3D> &P, std::vector<int> &flag, int dim, const double distanceTolerance)
2918{
2919 return _intersectSegmentBox( V0, V1, A0, A1, interiorSegmentVertice, segmentBoxHullIntersection, &P, &flag, dim, distanceTolerance);
2920}
2921
2931bool intersectBoxPolygon( array3D const &A0, array3D const &A1, std::vector<array3D> const &VS, int dim, const double distanceTolerance )
2932{
2933 return intersectBoxPolygon( A0, A1, VS.size(), VS.data(), dim, distanceTolerance );
2934}
2935
2945bool intersectBoxPolygon( array3D const &A0, array3D const &A1, std::size_t nVS, array3D const *VS, int dim, const double distanceTolerance )
2946{
2947 return _intersectBoxPolygon(A0, A1, nVS, VS, false, false, false, nullptr, nullptr, dim, distanceTolerance);
2948}
2949
2963bool intersectBoxPolygon( array3D const &A0, array3D const &A1, std::vector<array3D> const &VS, bool innerPolygonPoints, bool polygonEdgeBoxFaceIntersections, bool polygonBoxEdgeIntersections, std::vector<array3D> &P, int dim, const double distanceTolerance)
2964{
2965 return intersectBoxPolygon( A0, A1, VS.size(), VS.data(), innerPolygonPoints, polygonEdgeBoxFaceIntersections, polygonBoxEdgeIntersections, P, dim, distanceTolerance);
2966}
2967
2968
2983bool intersectBoxPolygon( array3D const &A0, array3D const &A1, std::size_t nVS, array3D const *VS, bool innerPolygonPoints, bool polygonEdgeBoxFaceIntersections, bool polygonBoxEdgeIntersections, std::vector<array3D> &P, int dim, const double distanceTolerance)
2984{
2985 return _intersectBoxPolygon(A0, A1, nVS, VS, innerPolygonPoints, polygonEdgeBoxFaceIntersections, polygonBoxEdgeIntersections, &P, nullptr, dim, distanceTolerance);
2986}
2987
3002bool intersectBoxPolygon( array3D const &A0, array3D const &A1, std::vector<array3D> const &VS, bool innerPolygonPoints, bool polygonEdgeBoxFaceIntersections, bool polygonBoxEdgeIntersections, std::vector<array3D> &P, std::vector<int> &flag, int dim, const double distanceTolerance)
3003{
3004 return intersectBoxPolygon( A0, A1, VS.size(), VS.data(), innerPolygonPoints, polygonEdgeBoxFaceIntersections, polygonBoxEdgeIntersections, P, flag, dim, distanceTolerance);
3005}
3006
3022bool intersectBoxPolygon( array3D const &A0, array3D const &A1, std::size_t nVS, array3D const *VS, bool innerPolygonPoints, bool polygonEdgeBoxFaceIntersections, bool polygonBoxEdgeIntersections, std::vector<array3D> &P, std::vector<int> &flag, int dim, const double distanceTolerance)
3023{
3024 return _intersectBoxPolygon(A0, A1, nVS, VS, innerPolygonPoints, polygonEdgeBoxFaceIntersections, polygonBoxEdgeIntersections, &P, &flag, dim, distanceTolerance);
3025}
3026
3037bool intersectBoxCircle( array3D const &A0, array3D const &A1, array3D const &centre, double radius, const double distanceTolerance)
3038{
3039 double minimumDistance = 0.;
3040 for (int i = 0; i < 2; ++i) {
3041 if (centre[i] < A0[i]) {
3042 minimumDistance += (centre[i] - A0[i]) * (centre[i] - A0[i]);
3043 } else if (centre[i] > A1[i]) {
3044 minimumDistance += (centre[i] - A1[i]) * (centre[i] - A1[i]);
3045 }
3046 }
3047
3048 double inflatedRadius = radius + distanceTolerance;
3049
3050 return (minimumDistance <= (inflatedRadius * inflatedRadius));
3051}
3052
3063bool intersectBoxSphere( array3D const &A0, array3D const &A1, array3D const &centre, double radius, const double distanceTolerance)
3064{
3065 double minimumDistance = 0.;
3066 for (int i = 0; i < 3; ++i) {
3067 if (centre[i] < A0[i]) {
3068 minimumDistance += (centre[i] - A0[i]) * (centre[i] - A0[i]);
3069 } else if (centre[i] > A1[i]) {
3070 minimumDistance += (centre[i] - A1[i]) * (centre[i] - A1[i]);
3071 }
3072 }
3073
3074 double inflatedRadius = radius + distanceTolerance;
3075
3076 return (minimumDistance <= (inflatedRadius * inflatedRadius));
3077}
3078
3079//to levelset // -------------------------------------------------------------------------- //
3080//to levelset bool intersectLineSurface(
3081//to levelset array3D const &x1,
3082//to levelset array3D const &n1,
3083//to levelset array3D const &x2,
3084//to levelset array3D const &n2,
3085//to levelset array3D const &xL,
3086//to levelset array3D const &nL,
3087//to levelset array3D &xp,
3088//to levelset array3D &np
3089//to levelset ) {
3090//to levelset
3091//to levelset // ========================================================================== //
3092//to levelset // //
3093//to levelset // Reconstruct Surface given by two points and their normals and computes //
3094//to levelset // intersection of reconstruction with a line given by point and versor ' //
3095//to levelset // ========================================================================== //
3096//to levelset // INPUT //
3097//to levelset // ========================================================================== //
3098//to levelset // ========================================================================== //
3099//to levelset // OUTPUT //
3100//to levelset // ========================================================================== //
3101//to levelset // - none //
3102//to levelset // ========================================================================== //
3103//to levelset
3104//to levelset // ========================================================================== //
3105//to levelset // VARIABLES DECLARATION //
3106//to levelset // ========================================================================== //
3107//to levelset
3108//to levelset double w1(0), w2(0), w(0);
3109//to levelset array3D c1, c2;
3110//to levelset bool s1, s2;
3111//to levelset
3112//to levelset s1 = intersectLinePlane( xL, nL, x1, n1, c1);
3113//to levelset s2 = intersectLinePlane( xL, nL, x2, n2, c2);
3114//to levelset
3115//to levelset if( s1 && s2) {
3116//to levelset w1 = norm2( c2-x2);
3117//to levelset w2 = norm2( c1-x1);
3118//to levelset w = w1+w2;
3119//to levelset
3120//to levelset w1 = w1 /w;
3121//to levelset w2 = w2 /w;
3122//to levelset
3123//to levelset xp = w1*c1 +w2*c2;
3124//to levelset np = w1*n1 +w2*n2;
3125//to levelset
3126//to levelset np = np /norm2(np);
3127//to levelset
3128//to levelset return (true);
3129//to levelset }
3130//to levelset
3131//to levelset else if( s1 ){
3132//to levelset xp = c1;
3133//to levelset np = n1;
3134//to levelset
3135//to levelset return(true);
3136//to levelset }
3137//to levelset
3138//to levelset else if( s2 ){
3139//to levelset xp = c2;
3140//to levelset np = n2;
3141//to levelset
3142//to levelset return(true);
3143//to levelset }
3144//to levelset
3145//to levelset return (false);
3146//to levelset
3147//to levelset }
3148
3157bool intersectPointLine( array3D const &P, array3D const &Q, array3D const &n, const double distanceTolerance)
3158{
3159 assert( validLine(Q,n) );
3160
3161 array3D xP;
3162 if(distancePointLine(P, Q, n, xP) > distanceTolerance){
3163 return false;
3164 }
3165
3166 return true;
3167}
3168
3177bool intersectPointSegment( array3D const &P, array3D const &P1, array3D const &P2, const double distanceTolerance)
3178{
3179 assert( validSegment(P1,P2) );
3180
3181 array3D xP = projectPointSegment( P, P1, P2 );
3182 array3D offset = xP - P;
3183
3184 return (dotProduct(offset, offset) <= distanceTolerance * distanceTolerance);
3185}
3186
3196bool intersectPointTriangle( array3D const &P, array3D const &A, array3D const &B, array3D const &C, const double distanceTolerance)
3197{
3198
3199 if(distancePointTriangle(P, A, B, C) > distanceTolerance){
3200 return false;
3201 }
3202
3203 return true;
3204}
3205
3215bool intersectPointBox( array3D const &P, array3D const &B1, array3D const &B2, int dim, const double distanceTolerance)
3216{
3217
3218 for( int d=0; d<dim; ++d){
3219 if( P[d]< (B1[d] - distanceTolerance) || P[d] > (B2[d] + distanceTolerance)){
3220 return false;
3221 }
3222 }
3223
3224 return true;
3225}
3226
3234void computeAABBSegment(array3D const &A, array3D const &B, array3D &P0, array3D &P1)
3235{
3236
3237 P0 = A;
3238 P1 = A;
3239
3240 for(int i=0; i<3; ++i){
3241 P0[i] = std::min( P0[i], B[i] );
3242 P1[i] = std::max( P1[i], B[i] );
3243 }
3244
3245 return;
3246}
3247
3256void computeAABBTriangle(array3D const &A, array3D const &B, array3D const &C, array3D &P0, array3D &P1)
3257{
3258 P0 = A;
3259 P1 = A;
3260
3261 for(int i=0; i<3; ++i){
3262 P0[i] = std::min( P0[i], B[i] );
3263 P0[i] = std::min( P0[i], C[i] );
3264
3265 P1[i] = std::max( P1[i], B[i] );
3266 P1[i] = std::max( P1[i], C[i] );
3267 }
3268
3269 return;
3270}
3271
3278void computeAABBPolygon(std::vector<array3D> const &VS, array3D &P0, array3D &P1)
3279{
3280 computeAABBPolygon(VS.size(), VS.data(), P0, P1);
3281}
3282
3290void computeAABBPolygon(std::size_t nVS, array3D const *VS, array3D &P0, array3D &P1)
3291{
3292 P0 = VS[0];
3293 P1 = VS[0];
3294
3295 for( std::size_t j=1; j<nVS; ++j){
3296 for( int i=0; i<3; ++i){
3297 P0[i] = std::min( P0[i], VS[j][i] );
3298 P1[i] = std::max( P1[i], VS[j][i] );
3299 }
3300 }
3301
3302 return;
3303}
3304
3314void unionAABB( array3D const &A0, array3D const &A1, array3D const &B0, array3D const &B1, array3D &C0, array3D &C1)
3315{
3316 for( int i=0; i<3; ++i){
3317 C0[i] = std::min( A0[i], B0[i]);
3318 C1[i] = std::max( A1[i], B1[i]);
3319 }
3320
3321 return;
3322}
3323
3331void unionAABB(std::vector<array3D> const &A0, std::vector<array3D> const &A1, array3D &C0, array3D &C1)
3332{
3333
3334 int n( std::min(A0.size(), A1.size() ) );
3335
3336 if( n > 0 ){
3337 C0 = A0[0];
3338 C1 = A1[0];
3339
3340 for( int i=1; i<n; ++i){
3341 unionAABB( A0[i], A1[i], C0, C1, C0, C1);
3342 }
3343 }
3344
3345 return;
3346}
3347
3357void intersectionAABB(array3D const &A0, array3D const &A1, array3D const &B0, array3D const &B1, array3D &C0, array3D &C1)
3358{
3359 intersectBoxBox( A0, A1, B0, B1, C0, C1 );
3360 return;
3361}
3362
3372void subtractionAABB(array3D const &A0, array3D const &A1, array3D const &B0, array3D const &B1, array3D &C0, array3D &C1)
3373{
3374 // X direction
3375 if( B0[1]<=A0[1] && B0[2]<=A0[2] && B1[1]>=A1[1] && B1[2]>=A1[2] ){
3376 C0[0] = ( B0[0]<=A0[0] && B1[0]>=A0[0] ) ? B1[0] : A0[0];
3377 C1[0] = ( B0[0]<=A1[0] && B1[0]>=A1[0] ) ? B0[0] : A1[0];
3378 }
3379
3380 // Y direction
3381 if( B0[0]<=A0[0] && B0[2]<=A0[2] && B1[0]>=A1[0] && B1[2]>=A1[2] ){
3382 C0[1] = ( B0[1]<=A0[1] && B1[1]>=A0[1] ) ? B1[1] : A0[2];
3383 C1[1] = ( B0[1]<=A1[1] && B1[1]>=A1[1] ) ? B0[1] : A1[2];
3384 }
3385
3386 // Z direction
3387 if( B0[0]<=A0[0] && B0[1]<=A0[1] && B1[0]>=A1[0] && B1[1]>=A1[1] ){
3388 C0[2] = ( B0[2]<=A0[2] && B1[2]>=A0[2] ) ? B1[2] : A0[2];
3389 C1[2] = ( B0[2]<=A1[2] && B1[2]>=A1[2] ) ? B0[2] : A1[2];
3390 }
3391
3392 return;
3393}
3394
3402void vertexOfSegment(int i, array3D const &V0, array3D const &V1, array3D &P)
3403{
3404 switch(i){
3405
3406 case 0:
3407 P = V0;
3408 break;
3409
3410 case 1:
3411 P = V1;
3412 break;
3413
3414 default:
3415 assert(false);
3416 break;
3417 }
3418
3419 return;
3420}
3421
3430void vertexOfTriangle(int i, array3D const &V0, array3D const &V1, array3D const &V2, array3D &P)
3431{
3432 switch(i){
3433
3434 case 0:
3435 P = V0;
3436 break;
3437
3438 case 1:
3439 P = V1;
3440 break;
3441
3442 case 2:
3443 P = V2;
3444 break;
3445
3446 default:
3447 assert(false);
3448 break;
3449 }
3450
3451 return;
3452}
3453
3463void edgeOfTriangle(int i, array3D const &V0, array3D const &V1, array3D const &V2, array3D &P0, array3D &P1)
3464{
3465 switch(i){
3466
3467 case 0:
3468 P0 = V0;
3469 P1 = V1;
3470 break;
3471
3472 case 1:
3473 P0 = V1;
3474 P1 = V2;
3475 break;
3476
3477 case 2:
3478 P0 = V2;
3479 P1 = V0;
3480 break;
3481
3482 default:
3483 assert(false);
3484 break;
3485 }
3486
3487 return;
3488}
3489
3500void faceOfBox(int i, array3D const &A0, array3D const &A1, array3D &P0, array3D &P1, array3D &P2, array3D &P3)
3501{
3502
3503 assert(i<6);
3504
3505 int v0 = boxFaceVertexConnectivity[i][0];
3506 int v1 = boxFaceVertexConnectivity[i][1];
3507 int v2 = boxFaceVertexConnectivity[i][2];
3508 int v3 = boxFaceVertexConnectivity[i][3];
3509
3510 vertexOfBox(v0, A0, A1, P0 );
3511 vertexOfBox(v1, A0, A1, P1 );
3512 vertexOfBox(v2, A0, A1, P2 );
3513 vertexOfBox(v3, A0, A1, P3 );
3514
3515 return;
3516}
3517
3526void edgeOfBox(int i, array3D const &A0, array3D const &A1, array3D &P0, array3D &P1)
3527{
3528 assert(i<12);
3529
3530 int v0 = boxEdgeVertexConnectivity[i][0];
3531 int v1 = boxEdgeVertexConnectivity[i][1];
3532
3533 vertexOfBox(v0, A0, A1, P0 );
3534 vertexOfBox(v1, A0, A1, P1 );
3535
3536 return;
3537}
3538
3546void vertexOfBox(int i, array3D const &A0, array3D const &A1, array3D &P)
3547{
3548
3549 switch(i){
3550
3551 case 0:
3552 P[0] = A0[0];
3553 P[1] = A0[1];
3554 P[2] = A0[2];
3555 break;
3556
3557 case 1:
3558 P[0] = A1[0];
3559 P[1] = A0[1];
3560 P[2] = A0[2];
3561 break;
3562
3563 case 2:
3564 P[0] = A0[0];
3565 P[1] = A1[1];
3566 P[2] = A0[2];
3567 break;
3568
3569 case 3:
3570 P[0] = A1[0];
3571 P[1] = A1[1];
3572 P[2] = A0[2];
3573 break;
3574
3575 case 4:
3576 P[0] = A0[0];
3577 P[1] = A0[1];
3578 P[2] = A1[2];
3579 break;
3580
3581 case 5:
3582 P[0] = A1[0];
3583 P[1] = A0[1];
3584 P[2] = A1[2];
3585 break;
3586
3587 case 6:
3588 P[0] = A0[0];
3589 P[1] = A1[1];
3590 P[2] = A1[2];
3591 break;
3592
3593 case 7:
3594 P[0] = A1[0];
3595 P[1] = A1[1];
3596 P[2] = A1[2];
3597 break;
3598
3599 default:
3600 assert(false);
3601 break;
3602
3603 }
3604
3605 return;
3606}
3607
3615array3D rotateVector( array3D const &vector, array3D const &axis, double theta)
3616{
3617
3618 array3D rotated;
3619 double cosTheta = cos(theta);
3620
3621 rotated = cosTheta * vector;
3622 rotated += sin(theta) * crossProduct(axis,vector);
3623 rotated += (1.0 - cosTheta) * dotProduct(axis,vector) * axis;
3624
3625 return rotated;
3626}
3627
3634double areaTriangle( array3D const &a, array3D const &b, array3D const &c)
3635{
3636 return 0.5 *norm2(crossProduct(b-a,c-a));
3637}
3638
3643int polygonEdgesCount( std::vector<array3D> const &V)
3644{
3645 return polygonEdgesCount( V.size(), V.data());
3646}
3647
3654int polygonEdgesCount( std::size_t nV, array3D const *V)
3655{
3656 BITPIT_UNUSED(V);
3657
3658 return nV;
3659}
3660
3669int polygonSubtriangleCount( std::vector<array3D> const &V)
3670{
3671 return polygonSubtriangleCount( V.size(), V.data());
3672}
3673
3684int polygonSubtriangleCount( std::size_t nV, array3D const *V)
3685{
3686 BITPIT_UNUSED(V);
3687
3688 return nV;
3689}
3690
3698void edgeOfPolygon( int edge, std::vector<array3D> const &V, array3D &V0, array3D &V1)
3699{
3700 edgeOfPolygon( edge, V.size(), V.data(), V0, V1);
3701}
3702
3711void edgeOfPolygon( int edge, std::size_t nV, array3D const *V, array3D &V0, array3D &V1)
3712{
3713 assert(edge<polygonEdgesCount(nV, V));
3714
3715 V0 = V[edge];
3716 V1 = V[(edge+1) % nV];
3717 return;
3718}
3719
3734void subtriangleOfPolygon( int triangle, std::vector<array3D> const &V, array3D &V0, array3D &V1, array3D &V2)
3735{
3736 subtriangleOfPolygon( triangle, V.size(), V.data(), V0, V1, V2);
3737}
3738
3754void subtriangleOfPolygon( int triangle, std::size_t nV, array3D const *V, array3D &V0, array3D &V1, array3D &V2)
3755{
3756 assert(triangle<polygonSubtriangleCount(nV, V));
3757
3758 V0 = {0., 0., 0.};
3759 for (std::size_t i = 0; i < nV; i++) {
3760 for (int d = 0; d < 3; d++) {
3761 V0[d] += V[i][d];
3762 }
3763 }
3764 for (int d = 0; d < 3; d++) {
3765 V0[d] /= nV;
3766 }
3767 V1 = V[triangle%nV];
3768 V2 = V[(triangle+1)%nV];
3769 return;
3770}
3771
3775
3776}
3777
3778}
static BITPIT_PUBLIC_API const ReferenceElementInfo & getInfo(ElementType type)
The ReferencePixelInfo class defines the information about the reference pixel.
int getCCWOrderedVertex(int n) const override
int getCCWOrderedFace(int n) const override
void edgeOfPolygon(int, std::vector< array3D > const &, array3D &, array3D &)
Definition CG_elem.cpp:3698
std::vector< double > distanceCloudTriangle(std::vector< array3D > const &, array3D const &, array3D const &, array3D const &)
Definition CG_elem.cpp:1454
double distancePointLine(array3D const &, array3D const &, array3D const &, array3D &)
Definition CG_elem.cpp:1356
double distancePointCone(array3D const &, array3D const &, array3D const &, double)
Definition CG_elem.cpp:1440
array3D projectPointLine(array3D const &, array3D const &, array3D const &)
Definition CG_elem.cpp:971
void edgeOfTriangle(int, array3D const &, array3D const &, array3D const &, array3D &, array3D &)
Definition CG_elem.cpp:3463
const std::array< std::array< int, 2 >, 12 > boxEdgeVertexConnectivity
Definition CG.hpp:53
bool intersectPlaneBox(array3D const &, array3D const &, array3D const &, array3D const &, int dim=3, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:1954
void unionAABB(array3D const &, array3D const &, array3D const &, array3D const &, array3D &, array3D &)
Definition CG_elem.cpp:3314
bool intersectPointTriangle(array3D const &, array3D const &, array3D const &, array3D const &, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:3196
array3D computePolygonNormal(std::size_t nV, const array3D *V)
Definition CG_elem.cpp:2638
bool intersectBoxBox(array3D const &, array3D const &, array3D const &, array3D const &, int dim=3, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:2772
array3D projectPointTriangle(array3D const &, array3D const &, array3D const &, array3D const &)
Definition CG_elem.cpp:1050
array3D rotateVector(array3D const &, array3D const &, double)
Definition CG_elem.cpp:3615
array3D projectPointSegment(array3D const &, array3D const &, array3D const &)
Definition CG_elem.cpp:997
bool intersectPlaneTriangle(array3D const &P0, array3D const &P1, array3D const &P2, array3D const &Pp, array3D const &nP, std::array< array3D, 2 > &intersection, std::array< int, 2 > &edges_of_intersection, const double distanceTolerance=DEFAULT_COPLANARITY_TOLERANCE)
Definition CG_elem.cpp:2309
double distancePointPlane(array3D const &, array3D const &, array3D const &, array3D &)
Definition CG_elem.cpp:1370
bool intersectBoxTriangle(array3D const &, array3D const &, array3D const &, array3D const &, array3D const &, int dim=3, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:2824
int convertBarycentricToFlagSegment(std::array< double, 2 > const &, double tolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:619
void computeAABBTriangle(array3D const &, array3D const &, array3D const &, array3D &, array3D &)
Definition CG_elem.cpp:3256
bool validBarycentric(double const *, int)
Definition CG_elem.cpp:586
void intersectionAABB(array3D const &, array3D const &, array3D const &, array3D const &, array3D &, array3D &)
Definition CG_elem.cpp:3357
double distanceLineLine(array3D const &, array3D const &, array3D const &, array3D const &)
Definition CG_elem.cpp:1729
bool intersectPlanePixel(array3D const &Pp, array3D const &nP, array3D const *V, std::array< array3D, 2 > &intersection, std::array< int, 2 > &edges_of_intersection, const double distanceTolerance=DEFAULT_COPLANARITY_TOLERANCE)
Definition CG_elem.cpp:2138
array3D reconstructPointFromBarycentricTriangle(array3D const &, array3D const &, array3D const &, std::array< double, 3 > const &)
Definition CG_elem.cpp:858
array3D reconstructPointFromBarycentricSegment(array3D const &, array3D const &, std::array< double, 2 > const &)
Definition CG_elem.cpp:829
const std::array< std::array< int, 4 >, 6 > boxFaceVertexConnectivity
Definition CG.hpp:73
std::vector< double > distanceCloudPolygon(std::vector< array3D > const &, std::vector< array3D > const &, std::vector< array3D > &, std::vector< int > &)
Definition CG_elem.cpp:1599
void vertexOfSegment(int, array3D const &, array3D const &, array3D &)
Definition CG_elem.cpp:3402
void vertexOfTriangle(int, array3D const &, array3D const &, array3D const &, array3D &)
Definition CG_elem.cpp:3430
int convertBarycentricToFlagPolygon(std::vector< double > const &, double tolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:687
bool intersectSegmentPlane(array3D const &, array3D const &, array3D const &, array3D const &, array3D &, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:1872
bool intersectLineTriangle(array3D const &, array3D const &, array3D const &, array3D const &, array3D const &, array3D &, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:1988
bool intersectSegmentSegment(array3D const &, array3D const &, array3D const &, array3D const &, array3D &, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:1808
double distancePointTriangle(array3D const &, array3D const &, array3D const &, array3D const &)
Definition CG_elem.cpp:1411
bool intersectPointLine(array3D const &, array3D const &, array3D const &, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:3157
int polygonEdgesCount(std::vector< array3D > const &)
Definition CG_elem.cpp:3643
int polygonSubtriangleCount(std::vector< array3D > const &)
Definition CG_elem.cpp:3669
bool intersectBoxSphere(array3D const &A0, array3D const &A1, array3D const &centre, double radius, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:3063
int convertBarycentricToFlagTriangle(std::array< double, 3 > const &, double tolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:659
double areaTriangle(array3D const &, array3D const &, array3D const &)
Definition CG_elem.cpp:3634
array3D projectPointPlane(array3D const &, array3D const &, array3D const &)
Definition CG_elem.cpp:984
void subtriangleOfPolygon(int, std::vector< array3D > const &, array3D &, array3D &, array3D &)
Definition CG_elem.cpp:3734
bool intersectSegmentBox(array3D const &, array3D const &, array3D const &, array3D const &, int dim=3, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:2880
bool intersectPlanePlane(array3D const &, array3D const &, array3D const &, array3D const &, array3D &, array3D &, const double coplanarityTolerance=DEFAULT_COPLANARITY_TOLERANCE)
Definition CG_elem.cpp:1902
void computeGeneralizedBarycentric(array3D const &, std::vector< array3D > const &, std::vector< double > &)
Definition CG_elem.cpp:751
double distancePointSegment(array3D const &, array3D const &, array3D const &)
Definition CG_elem.cpp:1383
bool intersectLinePlane(array3D const &, array3D const &, array3D const &, array3D const &, array3D &, const double coplanarityTolerance=DEFAULT_COPLANARITY_TOLERANCE)
Definition CG_elem.cpp:1839
bool validPlane(array3D const &, array3D const &)
Definition CG_elem.cpp:541
array3D rotatePoint(const array3D &P, const array3D &n0, const array3D &n1, double angle)
Definition CG_elem.cpp:893
double distancePointPolygon(array3D const &, std::vector< array3D > const &, array3D &, int &)
Definition CG_elem.cpp:1500
bool validLine(array3D const &, array3D const &)
Definition CG_elem.cpp:529
void computeAABBPolygon(std::vector< array3D > const &, array3D &, array3D &)
Definition CG_elem.cpp:3278
bool validTriangle(array3D const &, array3D const &, array3D const &)
Definition CG_elem.cpp:554
array3D reconstructPointFromBarycentricPolygon(std::vector< array3D > const &, std::vector< double > const &)
Definition CG_elem.cpp:928
bool intersectSegmentTriangle(array3D const &, array3D const &, array3D const &, array3D const &, array3D const &, array3D &, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:2016
array3D restrictPointTriangle(array3D const &, array3D const &, array3D const &, array3D &)
Definition CG_elem.cpp:1097
bool intersectBoxPolygon(array3D const &, array3D const &, std::vector< array3D > const &, int dim=3, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:2931
void faceOfBox(int, array3D const &, array3D const &, array3D &, array3D &, array3D &, array3D &)
Definition CG_elem.cpp:3500
bool intersectPlanePolygon(array3D const &P, array3D const &nP, std::size_t nV, array3D const *V, std::vector< std::array< array3D, 2 > > &Qs, std::vector< std::array< int, 2 > > &edges_of_Qs, const double distanceTolerance=DEFAULT_COPLANARITY_TOLERANCE)
Definition CG_elem.cpp:2460
std::vector< array3D > projectCloudTriangle(std::vector< array3D > const &, array3D const &, array3D const &, array3D const &, std::vector< array3D > &)
Definition CG_elem.cpp:1194
void reconstructPlaneIntersectedPolygons(std::size_t nV, array3D const *V, std::vector< std::array< array3D, 2 > > const &Qs, std::vector< std::array< int, 2 > > const &edges_of_Qs, std::vector< std::vector< array3D > > &polys, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:2680
array3D projectPointCone(array3D const &, array3D const &, array3D const &, double)
Definition CG_elem.cpp:1315
void vertexOfBox(int, array3D const &, array3D const &, array3D &)
Definition CG_elem.cpp:3546
void edgeOfBox(int, array3D const &, array3D const &, array3D &, array3D &)
Definition CG_elem.cpp:3526
void subtractionAABB(array3D const &, array3D const &, array3D const &, array3D const &, array3D &, array3D &)
Definition CG_elem.cpp:3372
array3D projectPointPolygon(array3D const &, std::vector< array3D > const &)
Definition CG_elem.cpp:1215
bool validSegment(array3D const &, array3D const &)
Definition CG_elem.cpp:518
void computeAABBSegment(array3D const &, array3D const &, array3D &, array3D &)
Definition CG_elem.cpp:3234
bool intersectPointBox(array3D const &, array3D const &, array3D const &, int dim=3, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:3215
bool intersectPointSegment(array3D const &, array3D const &, array3D const &, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:3177
bool intersectLineLine(array3D const &, array3D const &, array3D const &, array3D const &, array3D &, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:1787
bool intersectBoxCircle(array3D const &A0, array3D const &A1, array3D const &centre, double radius, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:3037
bool intersectLinePolygon(array3D const &, array3D const &, std::vector< array3D > const &, array3D &, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:2042
bool intersectSegmentPolygon(array3D const &, array3D const &, std::vector< array3D > const &, array3D &, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:2084
void sum(const std::array< T, d > &x, T1 &s)
std::array< T, 3 > crossProduct(const std::array< T, 3 > &x, const std::array< T, 3 > &y)
T dotProduct(const std::array< T, d > &x, const std::array< T, d > &y)
double norm2(const std::array< T, d > &x)
std::array< T, d > min(const std::array< T, d > &x, const std::array< T, d > &y)
#define BITPIT_UNREACHABLE(str)
Definition compiler.hpp:53
#define BITPIT_UNUSED(variable)
Definition compiler.hpp:63
#define BITPIT_CREATE_WORKSPACE(workspace, item_type, size, stack_size)