BasicShapes.cpp
1 /*---------------------------------------------------------------------------*\
2  *
3  * mimmo
4  *
5  * Copyright (C) 2015-2021 OPTIMAD engineering Srl
6  *
7  * -------------------------------------------------------------------------
8  * License
9  * This file is part of mimmo.
10  *
11  * mimmo 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  * mimmo 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 mimmo. If not, see <http://www.gnu.org/licenses/>.
22  *
23  \ *---------------------------------------------------------------------------*/
24 #include "BasicShapes.hpp"
25 #include "customOperators.hpp"
26 #include <CG.hpp>
27 #include <bitpit_common.hpp>
28 #include <algorithm>
29 
30 
38 {
39  buffer << static_cast<int> (var);
40  return buffer;
41 }
42 
43 
51 {
52  int val;
53  buffer >> val;
54  var = static_cast<mimmo::ShapeType> (val);
55  return buffer;
56 }
57 
65 {
66  buffer << static_cast<int> (var);
67  return buffer;
68 }
69 
70 
78 {
79  int val;
80  buffer >> val;
81  var = static_cast<mimmo::CoordType> (val);
82  return buffer;
83 }
84 
85 
86 namespace mimmo{
87 
92 
94  m_origin.fill(0.0);
95  m_span.fill(0.0);
96  m_infLimits.fill(0.0);
97  m_sdr[0] = m_sdr_inverse[0] = {{1.0,0.0,0.0}};
98  m_sdr[1] = m_sdr_inverse[1] = {{0.0,1.0,0.0}};
99  m_sdr[2] = m_sdr_inverse[2] = {{0.0,0.0,1.0}};
101  m_scaling.fill(1.0);
102 };
103 
106 
113 void BasicShape::swap(BasicShape & x) noexcept
114 {
115  std::swap(m_shape, x.m_shape);
116  std::swap(m_origin, x.m_origin);
117  std::swap(m_span, x.m_span);
118  std::swap(m_infLimits, x.m_infLimits);
119  std::swap(m_sdr, x.m_sdr);
120  std::swap(m_sdr_inverse, x.m_sdr_inverse);
121  std::swap(m_scaling, x.m_scaling);
122  std::swap(m_typeCoord, x.m_typeCoord);
123 }
124 
131  m_origin = origin;
132 }
133 
140 void BasicShape::setSpan(double s0, double s1, double s2){
141  checkSpan(s0,s1,s2);
142  setScaling(s0,s1,s2);
143 }
144 
150  checkSpan(span[0],span[1],span[2]);
151  setScaling(span[0],span[1],span[2]);
152 }
153 
163 void BasicShape::setInfLimits(double orig, int dir){
164  if(dir<0 || dir>2) return;
165 
166  darray3E span = getSpan();
167  bool check = checkInfLimits(orig,dir);
168  if(check){
169  m_infLimits[dir] = orig;
170  setSpan(span[0],span[1],span[2]);
171  }
172 }
173 
183  for (int dir=0; dir<3; dir++){
184  setInfLimits(val[dir], dir);
185  }
186 }
187 
197 
198  double a = norm2(axis0);
199  double b = norm2(axis1);
200  double c = norm2(axis2);
201 
202  bool check = ( a>0.0 && b >0.0 && c > 0.0);
203  if (! check){
204  assert(false && "one or more 0-vector passed as arguments in BasicShape::SetRefSystem method");
205  return;
206  }
207 
208  axis0 /= a;
209  axis1 /= b;
210  axis2 /= c;
211 
212  double tol = 1.0e-3, val;
213  val = std::abs(dotProduct(axis0,axis1)) + std::abs(dotProduct(axis1,axis2)) + std::abs(dotProduct(axis0,axis2));
214 
215  if(val > tol) {
216  assert(false && "not orthogonal axes passed as arguments in BasicShape::SetRefSystem method");
217  return;
218  }
219 
220  m_sdr[0] = axis0;
221  m_sdr[1] = axis1;
222  m_sdr[2] = axis2;
223 
225 }
226 
232 void BasicShape::setRefSystem(int label, darray3E axis){
233 
234  if(label <0 || label >2 ){
235  assert(false && "no correct label passed as argument in BasicShape::setRefSystem");
236  return;
237  }
238 
239  double a = norm2(axis);
240  if (!(a > 0.0) ){
241  assert(false && "0-vector passed as axis argument in BasicShape::SetRefSystem method");
242  return;
243  }
244 
245  m_sdr[label] = axis/a;
246  dvecarr3E point_mat(3,darray3E{0,0,0});
247  point_mat[0][0] = point_mat[1][1]= point_mat[2][2]=1.0;
248 
249  int next_label = (label + 1)%3;
250  int fin_label = (label + 2)%3;
251 
252  double pj = dotProduct(point_mat[next_label], m_sdr[label]);
253  m_sdr[next_label] = point_mat[next_label] - pj*m_sdr[label];
254  m_sdr[next_label] = m_sdr[next_label]/norm2(m_sdr[next_label]);
255 
256  m_sdr[fin_label] = crossProduct(m_sdr[label],m_sdr[next_label]);
257  m_sdr[fin_label] = m_sdr[fin_label]/norm2(m_sdr[fin_label]);
258 
260 }
261 
267  setRefSystem(axes[0], axes[1], axes[2]);
268 }
269 
276  m_typeCoord[dir] = type;
277 }
278 
283  return(m_origin);
284 }
285 
291  darray3E result = getLocalSpan();
292  darray3E scale = getScaling();
293  for(int i=0; i<3; ++i){
294  result[i] = scale[i]*result[i];
295  }
296  return(result);
297 }
298 
303  return(m_infLimits);
304 }
305 
310  return(m_sdr);
311 }
312 
318  return(m_typeCoord[dir]);
319 }
324  return(m_shape);
325 };
326 
331  return(m_shape);
332 };
333 
338  return(m_scaling);
339 }
340 
345  return(m_span);
346 }
347 
356  if(geo == nullptr) return livector1D(0);
357  if(!(geo->isSkdTreeSupported())) return livector1D(0);
358 
359  //create BvTree and fill it w/ cell list
360  if(geo->getSkdTreeSyncStatus() != SyncStatus::SYNC) geo->buildSkdTree();
361  //get recursively all the list element in the shape
362  livector1D elements;
363  searchBvTreeMatches(*(geo->getSkdTree()), geo->getPatch(), elements);
364 
365  return(elements);
366 };
367 
377 
378  if(geo == nullptr) return livector1D(0);
379  livector1D internals = includeGeometry(geo);
380  std::sort(internals.begin(), internals.end());
381 
382  livector1D originals = geo->getCellsIds();
383  std::sort(originals.begin(), originals.end());
384 
385  livector1D result(originals.size() - internals.size());
386  int counter = 0;
387  auto internal_itr = internals.begin();
388  auto original_itr = originals.begin();
389  while (original_itr != originals.end()) {
390  long origval = *original_itr;
391  if (internal_itr == internals.end() || origval != *internal_itr) {
392  result[counter] = origval;
393  ++counter;
394  } else {
395  ++internal_itr;
396  }
397  ++original_itr;
398  }
399  return result;
400 };
401 
408 livector1D BasicShape::includeGeometry(bitpit::PatchKernel * tri ){
409 
410  if(tri == nullptr) return livector1D(0);
411  livector1D result(tri->getCellCount());
412  long id;
413  int counter = 0;
414  for(auto & cell : tri->getCells()){
415  id = cell.getId();
416  if(isSimplexIncluded(tri,id)){
417  result[counter] = id;
418  ++counter;
419  }
420  }
421  result.resize(counter);
422  return(result);
423 
424 };
425 
432 livector1D BasicShape::excludeGeometry(bitpit::PatchKernel * tri){
433 
434  if(tri == nullptr) return livector1D(0);
435  livector1D result(tri->getCellCount());
436  long id;
437  int counter = 0;
438  for(auto & cell : tri->getCells()){
439  id = cell.getId();
440  if(!isSimplexIncluded(tri,id)){
441  result[counter] = id;
442  ++counter;
443  }
444  }
445  result.resize(counter);
446  return(result);
447 
448 };
449 
457 
458  if(list.empty()) return livector1D(0);
459  livector1D result(list.size());
460  int counter = 0;
461  long real = 0;
462  for(const auto & vert : list){
463  if(isPointIncluded(vert)){
464  result[counter] = real;
465  ++counter;
466  }
467  ++real;
468  }
469  result.resize(counter);
470  return(result);
471 };
472 
480  if(list.empty()) return livector1D(0);
481  livector1D result(list.size());
482  long real = 0;
483  int counter = 0;
484  for(const auto & vert : list){
485  if(!isPointIncluded(vert)){
486  result[counter] = real;
487  ++counter;
488  }
489  ++real;
490  }
491  result.resize(counter);
492  return(result);
493 
494 };
495 
502 livector1D BasicShape::includeCloudPoints(bitpit::PatchKernel * tri){
503 
504  if(tri == nullptr) return livector1D(0);
505  livector1D result(tri->getVertexCount());
506  int counter = 0;
507  long id;
508  for(auto & vert : tri->getVertices()){
509  id = vert.getId();
510  if(isPointIncluded(tri, id)){
511  result[counter] = id;
512  ++counter;
513  }
514  }
515  result.resize(counter);
516  return(result);
517 };
518 
525 livector1D BasicShape::excludeCloudPoints(bitpit::PatchKernel * tri){
526 
527  if(tri == nullptr) return livector1D(0);
528  livector1D result(tri->getVertexCount());
529  int counter = 0;
530  long id;
531  for(auto & vert : tri->getVertices()){
532  id = vert.getId();
533  if(!isPointIncluded(tri, id)){
534  result[counter] = id;
535  ++counter;
536  }
537  }
538  result.resize(counter);
539  return(result);
540 
541 };
542 
552  if(geo == nullptr) return livector1D(0);
553  if(geo->isEmpty()) return livector1D(0);
554 
555  livector1D elements;
556  //create BvTree and fill it w/ cell list
557  if(geo->getKdTreeSyncStatus() != SyncStatus::SYNC) geo->buildKdTree();
558 
559  getTempBBox();
560  //get recursively all the list element in the shape
561  searchKdTreeMatches(*(geo->getKdTree()), elements);
562 
563  return(elements);
564 };
565 
573 
574  if(geo == nullptr) return livector1D(0);
575  if(geo->isEmpty()) return livector1D(0);
576 
577  livector1D internals = includeCloudPoints(geo);
578  std::sort(internals.begin(), internals.end());
579 
580  livector1D originals = geo->getCellsIds();
581  std::sort(originals.begin(), originals.end());
582 
583  livector1D result(originals.size() - internals.size());
584  int counter = 0;
585  auto internal_itr = internals.begin();
586  auto original_itr = originals.begin();
587  while (original_itr != originals.end()) {
588  long origval = *original_itr;
589  if (internal_itr == internals.end() || origval != *internal_itr) {
590  result[counter] = origval;
591  ++counter;
592  } else {
593  ++internal_itr;
594  }
595  ++original_itr;
596  }
597  return result;
598 };
599 
604 bool BasicShape::isSimplexIncluded(const dvecarr3E & simplexVert){
605 
606  bool check = true;
607  for(const auto & val : simplexVert){
608  check = check && isPointIncluded(val);
609  }
610  return(check);
611 };
612 
618 bool BasicShape::isSimplexIncluded(bitpit::PatchKernel * tri, const long int &indexT){
619 
620  bitpit::Cell & cell = tri->getCell(indexT);
621  bitpit::ConstProxyVector<long> vIds = cell.getVertexIds();
622  bool check = true;
623  for(const auto & val: vIds){
624  //recover vertex index
625  check = check && isPointIncluded(tri,val);
626  }
627  return(check);
628 };
629 
635 
636  bool check = true;
637  darray3E temp2 = localToBasic(toLocalCoord(point));
638  double tol = 1.0E-12;
639 
640  for(int i=0; i<3; ++i){
641  check = check && ((temp2[i] > -1.0*tol) && (temp2[i]< (1.0+tol)));
642  }
643 
644  return(check);
645 };
646 
652 bool BasicShape::isPointIncluded(bitpit::PatchKernel * tri, const long int & indexV){
653 
654  return(isPointIncluded(tri->getVertex(indexV).getCoords()));
655 };
656 
657 
658 
667 
668  darray3E result = {{0,0,0}};
669  int counter=0;
670  for (auto && val: point){
671  result[counter] = std::fmin(bMax[counter], std::fmax(val,bMin[counter]));
672  ++counter;
673  }
674  return result;
675 };
676 
685 void BasicShape::searchKdTreeMatches(bitpit::KdTree<3,bitpit::Vertex,long> & tree, livector1D & result, bool squeeze ){
686 
687  //1st step get data
688  std::vector<int> candidates;
689  std::vector< std::pair<int, int> > nodeStackLoc; //cointains touple with kdNode id and level label.
690 
691  nodeStackLoc.push_back(std::make_pair(0, 0));
692  while(!nodeStackLoc.empty()){
693  std::pair<int, int> toupleId = nodeStackLoc.back();
694  bitpit::KdNode<bitpit::Vertex, long> & target = tree.nodes[toupleId.first];
695  nodeStackLoc.pop_back();
696 
697  //add children to the stack, if node has any of them.
698  uint32_t check = intersectShapePlane((toupleId.second)%3, target.object_->getCoords());
699  if((check%2 == 0) && (target.lchild_ >= 0)){
700  nodeStackLoc.push_back(std::make_pair(target.lchild_, (toupleId.second) + 1));
701  }
702  if((check > 0) && (target.rchild_ >= 0)){
703  nodeStackLoc.push_back(std::make_pair(target.rchild_, (toupleId.second) + 1));
704  }
705 
706  //push node as candidate if is in the raw bounding box of the shape
707  if (bitpit::CGElem::intersectPointBox(target.object_->getCoords(), m_bbox[0], m_bbox[1], 3)){
708  candidates.push_back(toupleId.first);
709  }
710  }
711 
712  result.clear();
713  result.reserve(candidates.size());
714  for (const auto & idCand : candidates){
715  bitpit::KdNode<bitpit::Vertex, long> & target = tree.nodes[idCand];
716  if(isPointIncluded(target.object_->getCoords())){
717  result.push_back(target.label);
718  }
719  }
720  if (squeeze)
721  result.shrink_to_fit();
722 };
723 
734 void BasicShape::searchBvTreeMatches(bitpit::PatchSkdTree & tree, bitpit::PatchKernel * geo, livector1D & result, bool squeeze){
735 
736  std::size_t rootId = 0;
737 
738  std::vector<std::size_t> toBeCandidates;
739  toBeCandidates.reserve(geo->getCellCount());
740 
741  std::vector<size_t> nodeStack;
742  nodeStack.push_back(rootId);
743  while(!nodeStack.empty()){
744  std::size_t nodeId = nodeStack.back();
745  const bitpit::SkdNode & node = tree.getNode(nodeId);
746  nodeStack.pop_back();
747 
748  //second step: if the current node AABB does not intersect or does not completely contains the Shape, then thrown it away and continue.
749  if(!intersectShapeAABBox(node.getBoxMin(), node.getBoxMax()) ){
750  continue;
751  }
752 
753  //now the only option is to visit node's children. If node is not leaf, add children to the stack,
754  //otherwise add current node as a possible candidate in shape inclusion.
755  bool isLeaf = true;
756  for (int i = bitpit::SkdNode::CHILD_BEGIN; i != bitpit::SkdNode::CHILD_END; ++i) {
757  bitpit::SkdNode::ChildLocation childLocation = static_cast<bitpit::SkdNode::ChildLocation>(i);
758  std::size_t childId = node.getChildId(childLocation);
759  if (childId != bitpit::SkdNode::NULL_ID) {
760  isLeaf = false;
761  nodeStack.push_back(childId);
762  }
763  }
764  if (isLeaf) {
765  toBeCandidates.push_back(nodeId);
766  }
767  }
768 
769  result.clear();
770  result.reserve(toBeCandidates.size());
771  for (const auto & idCand : toBeCandidates){
772  const bitpit::SkdNode &node = tree.getNode(idCand);
773  std::vector<long> cellids = node.getCells();
774  for(long id : cellids){
775  if(isSimplexIncluded(geo, id)){
776  result.push_back(id);
777  }
778  }
779  }
780  if (squeeze)
781  result.shrink_to_fit();
782 };
783 
784 
798 uint32_t BasicShape::intersectShapePlane(int level, const darray3E &target) {
799 
800  if(target[level] < m_bbox[0][level]) return 1; //shape is on the right
801  if(target[level] > m_bbox[1][level]) return 0; //shape is on the left
802  return 2; // in the middle of something
803 
804 }
805 
813  dmatrix33E out;
814 
815  for(std::size_t i=0; i<3; ++i){
816  for(std::size_t j=0; j<3; ++j){
817  out[j][i] = mat[i][j];
818  }
819  }
820  return out;
821 }
822 
830  dmatrix33E out;
831 
832  double det = mat[0][0] * (mat[1][1]*mat[2][2] - mat[2][1]*mat[1][2]) -
833  mat[0][1] * (mat[1][0]*mat[2][2] - mat[2][0]*mat[1][2]) +
834  mat[0][2] * (mat[1][0]*mat[2][1] - mat[2][0]*mat[1][1]);
835 
836  out[0][0] = (mat[1][1]*mat[2][2] - mat[2][1]*mat[1][2])/det;
837  out[0][1] = (mat[0][2]*mat[2][1] - mat[2][2]*mat[0][1])/det;
838  out[0][2] = (mat[0][1]*mat[1][2] - mat[1][1]*mat[0][2])/det;
839  out[1][0] = (mat[1][2]*mat[2][0] - mat[2][2]*mat[1][0])/det;
840  out[1][1] = (mat[0][0]*mat[2][2] - mat[2][0]*mat[0][2])/det;
841  out[1][2] = (mat[0][2]*mat[1][0] - mat[1][2]*mat[0][0])/det;
842  out[2][0] = (mat[1][0]*mat[2][1] - mat[2][0]*mat[1][1])/det;
843  out[2][1] = (mat[0][1]*mat[2][0] - mat[2][1]*mat[0][0])/det;
844  out[2][2] = (mat[0][0]*mat[1][1] - mat[1][0]*mat[0][1])/det;
845 
846  return out;
847 }
848 
849 
856 darray3E BasicShape::matmul(const darray3E & vec, const dmatrix33E & mat){
857 
858  darray3E out;
859  for (std::size_t i = 0; i < 3; i++) {
860  out[i] = 0.0;
861  for (std::size_t j = 0; j <3; j++) {
862  out[i] += vec[j]*mat[j][i];
863  } //next j
864  } //next i
865 
866  return out;
867 }
868 
875 darray3E BasicShape::matmul(const dmatrix33E & mat, const darray3E & vec){
876 
877  darray3E out;
878  for (std::size_t i = 0; i < 3; i++) {
879  out[i] = 0.0;
880  for (std::size_t j = 0; j <3; j++) {
881  out[i] += vec[j]*mat[i][j];
882  } //next j
883  } //next i
884 
885  return out;
886 }
887 
889 //Cube IMPLEMENTATION
890 
896  m_span = {{1.0, 1.0, 1.0}};
897 };
898 
905  Cube::Cube(const darray3E &origin, const darray3E & span): Cube(){
906 
907  setOrigin(origin);
908  setSpan(span[0], span[1], span[2]);
909 };
910 
913 
914 
919 Cube::Cube(const Cube & other):BasicShape(other){};
920 
921 
929 
930  darray3E work, work2;
931 
932  //unscale your local point
933  for(int i =0; i<3; ++i){
934  work[i] = point[i]*m_scaling[i];
935  }
936 
937  //return to local xyz system
938  // -> cube, doing nothing
939 
940  //unapply change to local sdr transformation
941  for(int i=0; i<3; ++i){
942  work2[i] = dotProduct(work, m_sdr_inverse[i]);
943  }
944 
945  //unapply origin translation
946  return(work2 + m_origin);
947 };
948 
956 
957  darray3E work, work2;
958 
959  //unapply origin translation
960  work = point - m_origin;
961 
962  //apply change to local sdr transformation
963  for(int i=0; i<3; ++i){
964  work2[i] = dotProduct(work, m_sdr[i]);
965  }
966 
967  //get to proper local system
968  // -> cube, doing nothing
969 
970  //scale your local point
971  for(int i =0; i<3; ++i){
972  work[i] = work2[i]/m_scaling[i];
973  }
974 
975  return(work);
976 
977 };
978 
983  return(darray3E{-0.5,-0.5,-0.5});
984 };
985 
992 darray3E Cube::basicToLocal(const darray3E &point){
993  return(point + getLocalOrigin());
994 };
995 
1002 darray3E Cube::localToBasic(const darray3E &point){
1003  return(point - getLocalOrigin());
1004 };
1005 
1013 void Cube::checkSpan(double &s0, double &s1,double &s2){
1014  s0 = std::abs(s0);
1015  s1 = std::abs(s1);
1016  s2 = std::abs(s2);
1017 };
1018 
1026 bool Cube::checkInfLimits(double &o0, int &dir){
1027  BITPIT_UNUSED(o0);
1028  BITPIT_UNUSED(dir);
1029  //really doing nothing here.
1030  //whatever origin for whatever coordinate must return always 0 for cubic/cuboidal shape
1031  return(false);
1032 };
1033 
1040 void Cube::setScaling( const double &s0, const double &s1, const double &s2){
1041  m_span.fill(1.0);
1042  m_scaling[0] = s0;
1043  m_scaling[1] = s1;
1044  m_scaling[2] = s2;
1045 };
1046 
1051 void Cube::getTempBBox(){
1052 
1053  m_bbox.clear();
1054  m_bbox.resize(2);
1055  m_bbox[0].fill(1.e18);
1056  m_bbox[1].fill(-1.e18);
1057 
1058  dvecarr3E locals(8,darray3E{{0.0,0.0,0.0}});
1059  darray3E temp;
1060  locals[1].fill(1.0);
1061  locals[2][0]= locals[2][1]=1.0;
1062  locals[3][2]=1.0;
1063  locals[4][0]= 1.0;
1064  locals[5][1]= locals[5][2] = 1.0;
1065  locals[6][1] = 1.0;
1066  locals[7][0] = locals[7][2] = 1.0;
1067 
1068  for(auto &vv : locals){
1069  temp = toWorldCoord(basicToLocal(vv));
1070  for(int i=0; i<3; ++i) {
1071  m_bbox[0][i] = std::fmin(m_bbox[0][i], temp[i]);
1072  m_bbox[1][i] = std::fmax(m_bbox[1][i], temp[i]);
1073  }
1074  }
1075 }
1076 
1085 bool Cube::intersectShapeAABBox(const darray3E &bMin, const darray3E &bMax){
1086 
1087  dvecarr3E points(8, bMin);
1088  points[1][0] = points[2][0] = points[5][0]=points[6][0]= bMax[0];
1089  points[2][1] = points[3][1] = points[6][1]=points[7][1]= bMax[1];
1090  points[4][2] = points[5][2] = points[6][2]=points[7][2]= bMax[2];
1091 
1092  for(auto &val:points) val += -1.0*m_origin;
1093 
1094  for(int j=0; j<3; ++j){
1095  double ref1 = -0.5*m_scaling[j];
1096  double ref2 = 0.5*m_scaling[j];
1097 
1098  double tmin, tmax, t;
1099  t= dotProduct(points[0],m_sdr[j]);
1100  tmax=tmin=t;
1101 
1102  for(int i=1; i<8; ++i){
1103  t= dotProduct(points[i],m_sdr[j]);
1104  if(t<tmin){
1105  tmin=t;
1106  }else if(t>tmax){
1107  tmax=t;
1108  }
1109  }
1110 
1111  //check height dimension if overlaps;
1112  if(tmin>ref2 || tmax<ref1) return false;
1113  }
1114 
1115  return true;
1116 };
1117 
1118 
1120 //Cylinder IMPLEMENTATION
1121 
1127  m_span = {{1.0, 2*BITPIT_PI, 1.0}};
1129 };
1130 
1137 Cylinder::Cylinder(const darray3E &origin, const darray3E & span): Cylinder(){
1138  setOrigin(origin);
1139  setSpan(span[0], span[1], span[2]);
1140 };
1141 
1144 
1149 Cylinder::Cylinder(const Cylinder & other):BasicShape(other){};
1150 
1158 
1159  darray3E work, work2;
1160  //unscale your local point
1161  for(int i =0; i<3; ++i){
1162  work[i] = point[i]*m_scaling[i];
1163  }
1164 
1165  //return to local xyz system
1166  work2[0] = (work[0]+m_infLimits[0])*std::cos(work[1] + m_infLimits[1]);
1167  work2[1] = (work[0]+m_infLimits[0])*std::sin(work[1] + m_infLimits[1]);
1168  work2[2] = work[2];
1169 
1170  //unapply change to local sdr transformation
1171  for(int i=0; i<3; ++i){
1172  work[i] = dotProduct(work2, m_sdr_inverse[i]);
1173  }
1174 
1175  //unapply origin translation
1176  return(work + m_origin);
1177 };
1178 
1186  darray3E work, work2;
1187 
1188  //unapply origin translation
1189  work = point - m_origin;
1190 
1191  //apply change to local sdr transformation
1192  for(int i=0; i<3; ++i){
1193  work2[i] = dotProduct(work, m_sdr[i]);
1194  }
1195 
1196  //get to proper local system
1197  if(work2[0] ==0.0 && work2[1] ==0.0){work[0] = 0.0; work[1] = 0.0;}
1198  else{
1199  work[0] = pow(work2[0]*work2[0] + work2[1]*work2[1],0.5);
1200  double pdum = std::atan2(work2[1],work2[0]);
1201  work[1] = pdum - (getSign(pdum)-1.0)*BITPIT_PI;
1202  }
1203  //get to the correct m_thetaOrigin mark
1204  double param = 2*BITPIT_PI;
1205  work[1] = work[1] - m_infLimits[1];
1206  if(work[1] < 0) work[1] = param + work[1];
1207  if(work[1] > param) work[1] = work[1] - param;
1208 
1209  work[2] = work2[2];
1210  //get the correct origin for radius
1211  work[0] = work[0] - m_infLimits[0];
1212 
1213  //scale your local point
1214  for(int i =0; i<3; ++i){
1215  work2[i] = work[i]/m_scaling[i];
1216  }
1217  return(work2);
1218 };
1219 
1224  return(darray3E{0.0,0.0,-0.5});
1225 };
1226 
1233 darray3E Cylinder::basicToLocal(const darray3E &point){
1234  darray3E result = point;
1235  result[1] *= m_span[1];
1236  result += getLocalOrigin();
1237  return(result);
1238 };
1239 
1246 darray3E Cylinder::localToBasic(const darray3E &point){
1247  darray3E result = point;
1248  result += -1.0*getLocalOrigin();
1249  result[1] /= m_span[1];
1250  return(result);
1251 };
1252 
1260 void Cylinder::checkSpan(double &s0, double &s1, double &s2){
1261  s0 = std::abs(s0);
1262  s1 = std::abs(s1);
1263  s2 = std::abs(s2);
1264 
1265  double thetalim = 8.0* std::atan(1.0);
1266  s1 = std::min(s1, thetalim);
1267  //check closedLoops;
1268  if(!(s1 < thetalim)){setCoordinateType(CoordType::PERIODIC,1);}
1269 };
1270 
1278 bool Cylinder::checkInfLimits(double &orig, int &dir){
1279  double thetalim = 2.0*BITPIT_PI;
1280  bool check = false;
1281  switch(dir){
1282  case 0:
1283  orig = std::max(0.0, orig);
1284  check = true;
1285  break;
1286  case 1:
1287  orig = std::min(thetalim, std::max(0.0, orig));
1288  check = true;
1289  break;
1290  default: // doing nothing
1291  break;
1292  }
1293  return(check);
1294 };
1295 
1302 void Cylinder::setScaling(const double &s0, const double &s1, const double &s2){
1303  m_span.fill(1.0);
1304  m_scaling.fill(1.0);
1305  m_span[1] = s1;
1306  m_scaling[0] = s0;
1307  m_scaling[2] = s2;
1308 };
1309 
1310 
1315 void Cylinder::getTempBBox(){
1316 
1317  m_bbox.clear();
1318  m_bbox.resize(2);
1319  m_bbox[0].fill(1.e18);
1320  m_bbox[1].fill(-1.e18);
1321 
1322  dvecarr3E locals(20,darray3E{{0.0,0.0,0.0}});
1323  darray3E temp;
1324  int counter = 0;
1325  for(int i=0; i<2; ++i){
1326  for(int j=0; j<5; ++j){
1327  for(int k=0; k<2; ++k){
1328  locals[counter][0] = double(i)*1.0;
1329  locals[counter][1] = double(j)*0.25;
1330  locals[counter][2] = double(k)*1.0;
1331  ++counter;
1332  }
1333  }
1334  }
1335  for(auto &vv : locals){
1336  temp = toWorldCoord(basicToLocal(vv));
1337  for(int i=0; i<3; ++i) {
1338  m_bbox[0][i] = std::fmin(m_bbox[0][i], temp[i]);
1339  m_bbox[1][i] = std::fmax(m_bbox[1][i], temp[i]);
1340  }
1341  }
1342 }
1343 
1352 bool Cylinder::intersectShapeAABBox(const darray3E &bMin, const darray3E &bMax){
1353  dvecarr3E points(8, bMin);
1354  points[1][0] = points[2][0] = points[5][0]=points[6][0]= bMax[0];
1355  points[2][1] = points[3][1] = points[6][1]=points[7][1]= bMax[1];
1356  points[4][2] = points[5][2] = points[6][2]=points[7][2]= bMax[2];
1357 
1358  for(auto &point : points){
1359  point = localToBasic(toLocalCoord(point));
1360  }
1361 
1362  for(int j=0; j<3; ++j){
1363  double tmin = 1.E18, tmax= -1.E18;
1364 
1365  for(int i=0; i<8; ++i){
1366  tmin=std::min(tmin,points[i][j]);
1367  tmax=std::max(tmax,points[i][j]);
1368  }
1369 
1370  if(j == 0){
1371  if(tmax< 0.0 ) return false;
1372  }else{
1373  if(tmin> 1.0 || tmax< 0.0) return false;
1374  }
1375  }
1376  return true;
1377 };
1378 
1379 
1380 
1382 //Sphere IMPLEMENTATION
1383 
1389  m_span = {{1.0, 2*BITPIT_PI, BITPIT_PI}};
1392 };
1393 
1400 Sphere::Sphere(const darray3E &origin, const darray3E & span): Sphere(){
1401 
1402  setOrigin(origin);
1403  setSpan(span[0], span[1], span[2]);
1404 };
1405 
1408 
1413 Sphere::Sphere(const Sphere & other):BasicShape(other){};
1414 
1422 
1423  darray3E work, work2;
1424  //unscale your local point
1425  for(int i =0; i<3; ++i){
1426  work[i] = point[i]*m_scaling[i];
1427  }
1428 
1429  //return to local xyz system
1430  work2[0] = (work[0]+m_infLimits[0])*std::cos(work[1] + m_infLimits[1])*std::sin(work[2] + m_infLimits[2]);
1431  work2[1] = (work[0]+m_infLimits[0])*std::sin(work[1] + m_infLimits[1])*std::sin(work[2] + m_infLimits[2]);
1432  work2[2] = (work[0]+m_infLimits[0])*std::cos(work[2] + m_infLimits[2]);
1433 
1434  //unapply change to local sdr transformation
1435  for(int i=0; i<3; ++i){
1436  work[i] = dotProduct(work2, m_sdr_inverse[i]);
1437  }
1438 
1439  //unapply origin translation
1440  work2 = work + m_origin;
1441  return(work2);
1442 };
1443 
1451 
1452  darray3E work, work2;
1453  //unapply origin translation
1454  work = point - m_origin;
1455 
1456  //apply change to local sdr transformation
1457  for(int i=0; i<3; ++i){
1458  work2[i] = dotProduct(work, m_sdr[i]);
1459  }
1460 
1461  //get to proper local system
1462  work[0] = norm2(work2);
1463 
1464  if(work[0]>0.0){
1465  if(work2[0] ==0.0 && work2[1] ==0.0){
1466  work[1] = 0.0;
1467  }else{
1468  double pdum = std::atan2(work2[1],work2[0]);
1469  work[1] = pdum - (getSign(pdum)-1.0)*BITPIT_PI;
1470  }
1471  //get to the correct m_thetaOrigin mark
1472  double param = 2.0*BITPIT_PI;
1473  work[1] = work[1] - m_infLimits[1];
1474  if(work[1] < 0) work[1] = param + work[1];
1475  if(work[1] > param) work[1] = work[1] - param;
1476 
1477  work[2] = std::acos(work2[2]/work[0]);
1478  work[2] = work[2] - m_infLimits[2];
1479  }
1480 
1481  work[0] = work[0] - m_infLimits[0];
1482 
1483  //scale your local point
1484  for(int i =0; i<3; ++i){
1485  work2[i] = work[i]/m_scaling[i];
1486  }
1487  return(work2);
1488 };
1489 
1494  return(darray3E{0.0,0.0,0.0});
1495 };
1496 
1503 darray3E Sphere::basicToLocal(const darray3E & point){
1504  darray3E result = point;
1505  result[1] *= m_span[1];
1506  result[2] *= m_span[2];
1507  result += getLocalOrigin();
1508  return(result);
1509 };
1510 
1517 darray3E Sphere::localToBasic(const darray3E & point){
1518  darray3E result = point;
1519  result += -1.0*getLocalOrigin();
1520  result[1] /= m_span[1];
1521  result[2] /= m_span[2];
1522  return(result);
1523 };
1524 
1532 void Sphere::checkSpan( double &s0, double &s1, double &s2){
1533  s0 = std::abs(s0);
1534  s1 = std::abs(s1);
1535  s2 = std::abs(s2);
1536 
1537  double thetalim = 2.0*BITPIT_PI;
1538  s1 = std::min(s1, thetalim);
1539 
1540  double maxS2 = 0.5*thetalim - m_infLimits[2];
1541  s2 = std::min(s2, maxS2);
1542 
1543  //check closedLoops;
1544  if(!(s1 < thetalim)){setCoordinateType(CoordType::PERIODIC,1);}
1545 
1546 };
1547 
1556 bool Sphere::checkInfLimits( double &orig, int &dir){
1557 
1558  double thetalim = 2.0*BITPIT_PI;
1559  double tol = 1.e-12;
1560  bool check = false;
1561  switch(dir){
1562  case 0:
1563  orig = std::max(0.0, orig);
1564  check = true;
1565  break;
1566  case 1:
1567  orig = std::min(thetalim, std::max(0.0, orig));
1568  check = true;
1569  break;
1570  case 2:
1571  orig = std::min((0.5-tol)*thetalim, std::max(0.0, orig));
1572  check = true;
1573  break;
1574  default: // doing nothing
1575  break;
1576  }
1577  return(check);
1578 };
1579 
1586 void Sphere::setScaling(const double &s0, const double &s1, const double &s2){
1587  m_span.fill(1.0);
1588  m_scaling.fill(1.0);
1589 
1590  m_scaling[0] = s0;
1591  m_span[1] = s1;
1592  m_span[2] = s2;
1593 };
1594 
1599 void Sphere::getTempBBox(){
1600 
1601  m_bbox.clear();
1602  m_bbox.resize(2);
1603  m_bbox[0].fill(1.e18);
1604  m_bbox[1].fill(-1.e18);
1605 
1606  dvecarr3E locals(30,darray3E{{0.0,0.0,0.0}});
1607  darray3E temp;
1608  int counter = 0;
1609  for(int i=0; i<2; ++i){
1610  for(int j=0; j<5; ++j){
1611  for(int k=0; k<3; ++k){
1612  locals[counter][0] = double(i)*1.0;
1613  locals[counter][1] = double(j)*0.25;
1614  locals[counter][2] = double(k)*0.5;
1615  ++counter;
1616  }
1617  }
1618  }
1619 
1620  for(auto &vv : locals){
1621  temp = toWorldCoord(basicToLocal(vv));
1622  for(int i=0; i<3; ++i) {
1623  m_bbox[0][i] = std::fmin(m_bbox[0][i], temp[i]);
1624  m_bbox[1][i] = std::fmax(m_bbox[1][i], temp[i]);
1625  }
1626  }
1627 }
1628 
1635 bool Sphere::intersectShapeAABBox(const darray3E &bMin, const darray3E &bMax){
1636 
1637  dvecarr3E points(8, bMin);
1638  points[1][0] = points[2][0] = points[5][0]=points[6][0]= bMax[0];
1639  points[2][1] = points[3][1] = points[6][1]=points[7][1]= bMax[1];
1640  points[4][2] = points[5][2] = points[6][2]=points[7][2]= bMax[2];
1641 
1642  for(auto &point : points){
1643  point = localToBasic(toLocalCoord(point));
1644  }
1645 
1646  for(int j=0; j<3; ++j){
1647  double tmin = 1.E18, tmax= -1.E18;
1648 
1649  for(int i=0; i<8; ++i){
1650  tmin=std::min(tmin,points[i][j]);
1651  tmax=std::max(tmax,points[i][j]);
1652  }
1653 
1654  if(j == 0){
1655  if(tmax< 0.0 ) return false;
1656  }else{
1657  if(tmin> 1.0 || tmax< 0.0) return false;
1658  }
1659  }
1660 
1661  return true;
1662 
1663 };
1664 
1666 //Wedge IMPLEMENTATION
1667 
1673  m_span = {{1.0, 1.0, 1.0}};
1674 };
1675 
1682 Wedge::Wedge(const darray3E &origin, const darray3E & span): Wedge(){
1683 
1684  setOrigin(origin);
1685  setSpan(span[0], span[1], span[2]);
1686 };
1687 
1690 
1691 
1696 Wedge::Wedge(const Wedge & other):BasicShape(other){};
1697 
1698 
1706 
1707  darray3E work, work2;
1708 
1709  //Duffy transformation
1710  work2 = point;
1711  work2[1] *= (1.0-work2[0]);
1712 
1713  //unscale your local point
1714  for(int i =0; i<3; ++i){
1715  work[i] = work2[i]*m_scaling[i];
1716  }
1717 
1718  //return to local xyz system
1719  // -> wedge, doing nothing
1720 
1721  //unapply change to local sdr transformation
1722  for(int i=0; i<3; ++i){
1723  work2[i] = dotProduct(work, m_sdr_inverse[i]);
1724  }
1725 
1726  //unapply origin translation
1727  return(work2 + m_origin);
1728 };
1729 
1737 
1738  darray3E work, work2 ;
1739 
1740  //unapply origin translation
1741  work = point - m_origin;
1742 
1743  //apply change to local sdr transformation
1744  for(int i=0; i<3; ++i){
1745  work2[i] = dotProduct(work, m_sdr[i]);
1746  }
1747 
1748  //get to proper local system
1749  // -> wedge, doing nothing
1750 
1751  //scale your local point
1752  for(int i =0; i<3; ++i){
1753  work[i] = work2[i]/m_scaling[i];
1754  }
1755 
1756  //reverse Duffy Transformation;
1757  work2 = work;
1758  if(std::abs(1.0-work2[0]) > 0.0){
1759  work2[1] /= (1.0 - work2[0]);
1760  }else{
1761  if(std::abs(work2[1]) > 0.0 ) work2[1] = std::numeric_limits<double>::max();
1762  else work2[1] = 0.0;
1763  }
1764 
1765  return(work2);
1766 
1767 };
1768 
1773  return(darray3E{0.0,0.0,-0.5});
1774 };
1775 
1782 darray3E Wedge::basicToLocal(const darray3E &point){
1783  return point + getLocalOrigin();
1784 };
1785 
1792 darray3E Wedge::localToBasic(const darray3E &point){
1793  return point - getLocalOrigin();
1794 };
1795 
1803 void Wedge::checkSpan(double &s0, double &s1, double &s2){
1804  s0 = std::abs(s0);
1805  s1 = std::abs(s1);
1806  s2 = std::abs(s2);
1807 };
1808 
1816 bool Wedge::checkInfLimits( double &o0, int &dir){
1817  BITPIT_UNUSED(o0);
1818  BITPIT_UNUSED(dir);
1819  //really doing nothing here.
1820  //whatever origin for whatever coordinate must return always 0 for cubic/cuboidal/wedge shape
1821  return(false);
1822 };
1823 
1830 void Wedge::setScaling( const double &s0, const double &s1, const double &s2){
1831  m_span.fill(1.0);
1832  m_scaling[0] = s0;
1833  m_scaling[1] = s1;
1834  m_scaling[2] = s2;
1835 };
1836 
1841 void Wedge::getTempBBox(){
1842 
1843  m_bbox.clear();
1844  m_bbox.resize(2);
1845  m_bbox[0].fill(1.e18);
1846  m_bbox[1].fill(-1.e18);
1847 
1848  dvecarr3E locals(8,darray3E{{0.0,0.0,0.0}});
1849  darray3E temp;
1850  locals[1].fill(1.0);
1851  locals[2][0]= locals[2][1]=1.0;
1852  locals[3][2]=1.0;
1853  locals[4][0]= 1.0;
1854  locals[5][1]= locals[5][2] = 1.0;
1855  locals[6][1] = 1.0;
1856  locals[7][0] = locals[7][2] = 1.0;
1857 
1858  for(auto &vv : locals){
1859  temp = toWorldCoord(basicToLocal(vv));
1860  for(int i=0; i<3; ++i) {
1861  m_bbox[0][i] = std::fmin(m_bbox[0][i], temp[i]);
1862  m_bbox[1][i] = std::fmax(m_bbox[1][i], temp[i]);
1863  }
1864  }
1865 }
1866 
1875 bool Wedge::intersectShapeAABBox(const darray3E &bMin, const darray3E &bMax){
1876 
1877  dvecarr3E points(8, bMin);
1878  points[1][0] = points[2][0] = points[5][0]=points[6][0]= bMax[0];
1879  points[2][1] = points[3][1] = points[6][1]=points[7][1]= bMax[1];
1880  points[4][2] = points[5][2] = points[6][2]=points[7][2]= bMax[2];
1881 
1882  for(auto &val:points) val += -1.0*m_origin;
1883 
1884  double ref1, ref2;
1885  ref1 = -0.5*m_scaling[2];
1886  ref2 = 0.5*m_scaling[2];
1887 
1888  double tmin, tmax, t;
1889  t= dotProduct(points[0],m_sdr[2]);
1890  tmax=tmin=t;
1891  points[0] += -1.0*t*m_sdr[2]; //project point on plane
1892 
1893  for(int i=1; i<8; ++i){
1894  t= dotProduct(points[i],m_sdr[2]);
1895  points[i] += -1.0*t*m_sdr[2];
1896 
1897  if(t<tmin){
1898  tmin=t;
1899  }else if(t>tmax){
1900  tmax=t;
1901  }
1902 
1903  }
1904 
1905  //check height dimension if overlaps;
1906  if(tmin>ref2 || tmax<ref1) return false;
1907  darray3E bMin2, bMax2;
1908  bMin2 = points[0]; bMax2=points[0];
1909  for(int i=1; i<8; ++i){
1910  for(int j=0; j<3; ++j){
1911  bMin2[j] = std::fmin(bMin2[j], points[i][j]);
1912  bMax2[j] = std::fmax(bMax2[j], points[i][j]);
1913  }
1914  }
1915 
1916  return(isPointIncluded(checkNearestPointToAABBox({{0.0,0.0,0.0}},bMin2,bMax2) + m_origin));
1917 };
1918 
1919 }
darray3E getInfLimits()
livector1D includeGeometry(MimmoSharedPointer< MimmoObject >)
void setOrigin(darray3E)
Abstract Interface class for Elementary Shape Representation.
Definition: BasicShapes.hpp:91
void setInfLimits(double val, int dir)
bool intersectShapeAABBox(const darray3E &bMin, const darray3E &bMax)
darray3E m_infLimits
Definition: BasicShapes.hpp:97
static dmatrix33E inverse(const dmatrix33E &mat)
darray3E getLocalOrigin()
CoordType
Specify type of conditions to distribute NURBS nodes in a given coordinate of the shape.
Definition: BasicShapes.hpp:49
bool intersectShapeAABBox(const darray3E &bMin, const darray3E &bMax)
Elementary Shape Representation of a Prism with triangular basis.
darray3E getLocalSpan()
bool isSimplexIncluded(const dvecarr3E &)
std::vector< darray3E > dvecarr3E
std::vector< long > livector1D
mimmo custom derivation of bitpit OBinaryStream (see relative doc)
virtual bool intersectShapeAABBox(const darray3E &bMin, const darray3E &bMax)=0
std::array< CoordType, 3 > m_typeCoord
mimmo::OBinaryStream & operator<<(mimmo::OBinaryStream &buf, const std::string &element)
bool intersectShapeAABBox(const darray3E &bMin, const darray3E &bMax)
ShapeType getShapeType()
mimmo::IBinaryStream & operator>>(mimmo::IBinaryStream &buffer, mimmo::CoordType &var)
Definition: BasicShapes.cpp:77
Elementary Shape Representation of a Sphere or portion of it.
darray3E toLocalCoord(const darray3E &point)
virtual darray3E toLocalCoord(const darray3E &point)=0
darray3E toWorldCoord(const darray3E &point)
Elementary Shape Representation of a Cylinder or portion of it.
darray3E toWorldCoord(const darray3E &point)
dmatrix33E m_sdr
Definition: BasicShapes.hpp:98
static darray3E matmul(const darray3E &vec, const dmatrix33E &mat)
static dmatrix33E transpose(const dmatrix33E &mat)
darray3E getLocalOrigin()
livector1D includeCloudPoints(const dvecarr3E &)
darray3E checkNearestPointToAABBox(const darray3E &point, const darray3E &bMin, const darray3E &bMax)
darray3E toLocalCoord(const darray3E &point)
virtual ~BasicShape()
void setRefSystem(darray3E, darray3E, darray3E)
void swap(BasicShape &) noexcept
Elementary Shape Representation of a Cube.
std::array< darray3E, 3 > dmatrix33E
bool isPointIncluded(const darray3E &)
darray3E getOrigin()
uint32_t intersectShapePlane(int level, const darray3E &target)
bool intersectShapeAABBox(const darray3E &bMin, const darray3E &bMax)
ShapeType
Identifies the type of elemental shape supported by BasicShape class.
Definition: BasicShapes.hpp:38
darray3E toWorldCoord(const darray3E &point)
livector1D excludeGeometry(MimmoSharedPointer< MimmoObject >)
darray3E getLocalOrigin()
darray3E getSpan()
mimmo custom derivation of bitpit IBinaryStream (see relative doc)
darray3E getScaling()
std::array< double, 3 > darray3E
dmatrix33E m_sdr_inverse
Definition: BasicShapes.hpp:99
dmatrix33E getRefSystem()
void setSpan(double, double, double)
MimmoSharedPointer is a custom implementation of shared pointer.
livector1D excludeCloudPoints(const dvecarr3E &)
void setCoordinateType(CoordType, int dir)
darray3E getLocalOrigin()
darray3E toLocalCoord(const darray3E &point)
darray3E toWorldCoord(const darray3E &point)
T getSign(T &t)
CoordType getCoordinateType(int dir)
darray3E toLocalCoord(const darray3E &point)