Salome HOME
Merge branch 'occ/24009'
[tools/medcoupling.git] / src / INTERP_KERNEL / Interpolation3D1D.txx
1 // Copyright (C) 2007-2021  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (EDF R&D)
20
21 #pragma once
22
23 #include "Interpolation3D1D.hxx"
24 #include "Interpolation.txx"
25 #include "MeshElement.txx"
26 #include "PointLocator3DIntersectorP0P0.txx"
27 #include "PointLocator3DIntersectorP0P1.txx"
28 #include "PointLocator3DIntersectorP1P0.txx"
29 #include "PointLocator3DIntersectorP1P1.txx"
30 #include "Log.hxx"
31
32 #include "BBTree.txx"
33
34 #include <memory>
35
36 namespace INTERP_KERNEL
37 {
38   /**
39    *  Very similar to Interpolation3D::interpolateMeshes, except for the bounding boxes that can be
40    *  adjusted in a similar fashion as in InterpolationPlanar::performAdjustmentOfBB()
41    **/
42   template<class MyMeshType, class MatrixType>
43   typename MyMeshType::MyConnType Interpolation3D1D::interpolateMeshes(const MyMeshType& srcMesh, const MyMeshType& targetMesh, MatrixType& result, const std::string& method)
44   {
45     if(InterpolationOptions::getIntersectionType() != PointLocator)
46       INTERP_KERNEL::Exception("Invalid 3D/1D-0D intersection type specified : must be PointLocator.");
47
48     typedef typename MyMeshType::MyConnType ConnType;
49     // create MeshElement objects corresponding to each element of the two meshes
50     const ConnType numSrcElems = srcMesh.getNumberOfElements();
51     const ConnType numTargetElems = targetMesh.getNumberOfElements();
52
53     LOG(2, "Source mesh has " << numSrcElems << " elements and target mesh has " << numTargetElems << " elements ");
54
55     std::vector< std::unique_ptr< MeshElement<ConnType> > > srcElems(numSrcElems);
56     std::vector< std::unique_ptr< MeshElement<ConnType> > > targetElems(numTargetElems);
57
58     std::map<MeshElement<ConnType>*, ConnType> indices;
59
60     for(ConnType i = 0 ; i < numSrcElems ; ++i)
61       srcElems[i].reset( new MeshElement<ConnType>(i, srcMesh) );
62
63     for(ConnType i = 0 ; i < numTargetElems ; ++i)
64       targetElems[i].reset( new MeshElement<ConnType>(i, targetMesh) );
65
66     std::unique_ptr< Intersector3D<MyMeshType,MatrixType> > intersector;
67     std::string methC = InterpolationOptions::filterInterpolationMethod(method);
68     if(methC=="P0P0")
69       { intersector.reset( new PointLocator3DIntersectorP0P0<MyMeshType,MatrixType>(targetMesh, srcMesh, getPrecision()) );
70       }
71     else if(methC=="P0P1")
72       {  intersector.reset( new PointLocator3DIntersectorP0P1<MyMeshType,MatrixType>(targetMesh, srcMesh, getPrecision()) );
73       }
74     else if(methC=="P1P0")
75       {  intersector.reset( new PointLocator3DIntersectorP1P0<MyMeshType,MatrixType>(targetMesh, srcMesh, getPrecision()) );
76       }
77     else if(methC=="P1P1")
78       {  intersector.reset( new PointLocator3DIntersectorP1P1<MyMeshType,MatrixType>(targetMesh, srcMesh, getPrecision()) );
79       }
80     else
81       throw Exception("Invalid method chosen must be in \"P0P0\", \"P0P1\", \"P1P0\" or \"P1P1\".");
82     // create empty maps for all source elements
83     result.resize(intersector->getNumberOfRowsOfResMatrix());
84
85     // create BBTree structure
86     // - get bounding boxes
87     std::vector<double> bboxes(6*numSrcElems);
88     std::unique_ptr<ConnType[]> srcElemIdx{ new ConnType[numSrcElems] };
89     for(ConnType i = 0; i < numSrcElems ; ++i)
90       {
91         // get source bboxes in right order
92         const BoundingBox* box = srcElems[i]->getBoundingBox();
93         bboxes[6*i+0] = box->getCoordinate(BoundingBox::XMIN);
94         bboxes[6*i+1] = box->getCoordinate(BoundingBox::XMAX);
95         bboxes[6*i+2] = box->getCoordinate(BoundingBox::YMIN);
96         bboxes[6*i+3] = box->getCoordinate(BoundingBox::YMAX);
97         bboxes[6*i+4] = box->getCoordinate(BoundingBox::ZMIN);
98         bboxes[6*i+5] = box->getCoordinate(BoundingBox::ZMAX);
99
100         srcElemIdx[i] = srcElems[i]->getIndex();
101       }
102
103     adjustBoundingBoxes(bboxes);
104     const double *bboxPtr = nullptr;
105     if(numSrcElems>0)
106       bboxPtr=bboxes.data();
107     BBTree<3,ConnType> tree(bboxPtr, srcElemIdx.get(), 0, numSrcElems);
108
109     // for each target element, get source elements with which to calculate intersection
110     // - calculate intersection by calling intersectCells
111     for(ConnType i = 0; i < numTargetElems; ++i)
112       {
113         const BoundingBox* box = targetElems[i]->getBoundingBox();
114         const ConnType targetIdx = targetElems[i]->getIndex();
115
116         // get target bbox in right order
117         double targetBox[6];
118         targetBox[0] = box->getCoordinate(BoundingBox::XMIN);
119         targetBox[1] = box->getCoordinate(BoundingBox::XMAX);
120         targetBox[2] = box->getCoordinate(BoundingBox::YMIN);
121         targetBox[3] = box->getCoordinate(BoundingBox::YMAX);
122         targetBox[4] = box->getCoordinate(BoundingBox::ZMIN);
123         targetBox[5] = box->getCoordinate(BoundingBox::ZMAX);
124
125         std::vector<ConnType> intersectElems;
126
127         tree.getIntersectingElems(targetBox, intersectElems);
128
129         if ( !intersectElems.empty() )
130           intersector->intersectCells(targetIdx,intersectElems,result);
131       }
132     return intersector->getNumberOfColsOfResMatrix();
133   }
134 }