]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
2D PointLocator remapping now works properly on non-convex polygons.
authorabn <adrien.bruneton@cea.fr>
Tue, 12 Jan 2021 14:17:16 +0000 (15:17 +0100)
committerabn <adrien.bruneton@cea.fr>
Thu, 21 Jan 2021 20:09:35 +0000 (21:09 +0100)
+ unified PointLocator logic (getCell*ContainingPoint* functions are always
using PointLocator algorithms)

src/INTERP_KERNEL/MappedBarycentric2DIntersectorP1P1.txx
src/INTERP_KERNEL/PlanarIntersectorP0P1PL.txx
src/INTERP_KERNEL/PlanarIntersectorP1P0PL.txx
src/INTERP_KERNEL/PlanarIntersectorP1P1PL.txx
src/INTERP_KERNEL/PointLocator2DIntersector.txx
src/INTERP_KERNEL/PointLocatorAlgos.txx
src/MEDCoupling/MEDCouplingUMesh_internal.hxx
src/MEDCoupling_Swig/MEDCouplingRemapperTest.py

index 29c3eda4e72e373c195a6f40a6ad30c2904ffdbf..8031bf1caf7f0f450b82b4df6d6ec723de38f1d8 100644 (file)
@@ -58,7 +58,7 @@ namespace INTERP_KERNEL
         for(ConnType nodeIdT=0;nodeIdT<nbOfNodesT;nodeIdT++)
           {
             typename MyMatrix::value_type& resRow=res[OTT<ConnType,numPol>::ind2C(startOfCellNodeConnT[nodeIdT])];
-            if( PointLocatorAlgos<MyMeshType>::isElementContainsPointAlg2D(&CoordsTTmp[nodeIdT*SPACEDIM],&CoordsS[0],4,PlanarIntersector<MyMeshType,MyMatrix>::_precision) )
+            if( PointLocatorAlgos<MyMeshType>::isElementContainsPointAlg2DSimple(&CoordsTTmp[nodeIdT*SPACEDIM],&CoordsS[0],4,PlanarIntersector<MyMeshType,MyMatrix>::_precision) )
               {
                 double mco[2];  // mapped coordinates in the quad4
                 std::vector<const double*> coo(4);
index cb0ea5ce012017e9a58d6e494b4d3b726fccf3ce..4ca0e022c4d8410d746cba06e3fca9fd4f2857d8 100644 (file)
@@ -56,7 +56,7 @@ namespace INTERP_KERNEL
           PlanarIntersector<MyMeshType,MyMatrix>::projectionThis(&tmpSource[0],&tmpTarget[0],ToConnType(tmpSource.size())/SPACEDIM,nbNodesT);
         for(ConnType nodeIdT=0;nodeIdT<nbNodesT;nodeIdT++)
           {
-            if(PointLocatorAlgos<MyMeshType>::isElementContainsPointAlg2D(&tmpTarget[0]+nodeIdT*SPACEDIM,&tmpSource[0],ToConnType(tmpSource.size())/SPACEDIM,PlanarIntersector<MyMeshType,MyMatrix>::_precision))
+            if(PointLocatorAlgos<MyMeshType>::isElementContainsPointAlg2DSimple(&tmpTarget[0]+nodeIdT*SPACEDIM,&tmpSource[0],ToConnType(tmpSource.size())/SPACEDIM,PlanarIntersector<MyMeshType,MyMatrix>::_precision))
               {
                 ConnType curNodeTInCmode=OTT<ConnType,numPol>::coo2C(startOfCellNodeConnT[nodeIdT]);
                 typename MyMatrix::value_type& resRow=res[curNodeTInCmode];
index e5a06c599f535f98a40c04d9c848acb24ffa60fa..279dbdbaf3e936db7c8dcec0fbbd11e53c0074fb 100644 (file)
@@ -67,7 +67,7 @@ namespace INTERP_KERNEL
             PlanarIntersector<MyMeshType,MyMatrix>::projectionThis(&CoordsS[0],littleTargetCell,3,3);
             std::copy(littleTargetCell,littleTargetCell+3,baryTTmp);
           }
-        if(PointLocatorAlgos<MyMeshType>::isElementContainsPointAlg2D(baryTTmp,&CoordsS[0],3,PlanarIntersector<MyMeshType,MyMatrix>::_precision))
+        if(PointLocatorAlgos<MyMeshType>::isElementContainsPointAlg2DSimple(baryTTmp,&CoordsS[0],3,PlanarIntersector<MyMeshType,MyMatrix>::_precision))
           {
             double resLoc[3];
             barycentric_coords<SPACEDIM>(&CoordsS[0],baryTTmp,resLoc);
index e80b6f191bb8a403abe7cca88ddac7d6e7c5eae3..1b2fddf09cf4b7655130756d798f173a30200619 100644 (file)
@@ -57,7 +57,7 @@ namespace INTERP_KERNEL
         for(int nodeIdT=0;nodeIdT<nbOfNodesT;nodeIdT++)
           {
             typename MyMatrix::value_type& resRow=res[OTT<ConnType,numPol>::ind2C(startOfCellNodeConnT[nodeIdT])];
-            if( PointLocatorAlgos<MyMeshType>::isElementContainsPointAlg2D(CoordsTTmp.data()+nodeIdT*SPACEDIM,CoordsS.data(),3,this->_precision) )
+            if( PointLocatorAlgos<MyMeshType>::isElementContainsPointAlg2DSimple(CoordsTTmp.data()+nodeIdT*SPACEDIM,CoordsS.data(),3,this->_precision) )
               {
                 double resLoc[3];
                 barycentric_coords<SPACEDIM>(&CoordsS[0],&CoordsTTmp[nodeIdT*SPACEDIM],resLoc);
index e6b4b4c5c8bdb396a255b627cad5964607da66a5..bc54cbe4aac831e09c1e973eeee3263a504543d1 100644 (file)
@@ -53,13 +53,22 @@ namespace INTERP_KERNEL
     std::vector<double> CoordsS;
     PlanarIntersector<MyMeshType,MyMatrix>::getRealCoordinates(icellT,icellS,nbNodesT,nbNodesS,CoordsT,CoordsS,orientation);
     NormalizedCellType tT=PlanarIntersector<MyMeshType,MyMatrix>::_meshT.getTypeOfElement(icellT);
+    NormalizedCellType tS=PlanarIntersector<MyMeshType,MyMatrix>::_meshS.getTypeOfElement(icellS);
     QuadraticPolygon *pT=buildPolygonFrom(CoordsT,tT);
     double baryT[SPACEDIM];
     pT->getBarycenterGeneral(baryT);
     delete pT;
-    if(PointLocatorAlgos<MyMeshType>::isElementContainsPointAlg2D(baryT,&CoordsS[0],nbNodesS,InterpType<MyMeshType,MyMatrix,PTLOC2D_INTERSECTOR >::_precision))
-      return 1.;
-    return 0.;
+    bool ret;
+    double eps = InterpType<MyMeshType,MyMatrix,PTLOC2D_INTERSECTOR >::_precision;
+    if (tS != INTERP_KERNEL::NORM_POLYGON && !CellModel::GetCellModel(tS).isQuadratic())
+      ret = PointLocatorAlgos<MyMeshType>::isElementContainsPointAlg2DSimple(baryT,&CoordsS[0],nbNodesS,eps);
+    else
+      {
+        std::vector<ConnType> conn_elem(nbNodesS);
+        std::iota(conn_elem.begin(), conn_elem.end(), 0);
+        ret = PointLocatorAlgos<MyMeshType>::isElementContainsPointAlgo2DPolygon(baryT, tS, &CoordsS[0], &conn_elem[0], nbNodesS, eps);
+      }
+    return (ret ? 1. : 0.);
   }
 
   INTERSECTOR_TEMPLATE
index a0aba9d06db7f2432e1242683c01859059411001..5a87fcf10707cc44335c581d41e0ad60f5a691e1 100644 (file)
 #include "CellModel.hxx"
 #include "BBTree.txx"
 
+#include "InterpKernelGeo2DNode.hxx"
+#include "InterpKernelGeo2DQuadraticPolygon.hxx"
+
 #include <list>
+#include <vector>
 #include <set>
 #include <limits>
 
@@ -102,7 +106,7 @@ namespace INTERP_KERNEL
       return retlist;
     }
 
-    static bool isElementContainsPointAlg2D(const double *ptToTest, const double *cellPts, mcIdType nbEdges, double eps)
+    static bool isElementContainsPointAlg2DSimple(const double *ptToTest, const double *cellPts, mcIdType nbEdges, double eps)
     {
       /* with dimension 2, it suffices to check all the edges
          and see if the sign of double products from the point
@@ -133,6 +137,60 @@ namespace INTERP_KERNEL
       return ret;
     }
 
+    // Same as isElementContainsPointAlg2DSimple() with a different input format ...
+    static bool isElementContainsPointAlgo2DSimple2(const double *ptToTest, NormalizedCellType type,
+                                                    const double *coords, const typename MyMeshType::MyConnType *conn_elem,
+                                                    typename MyMeshType::MyConnType conn_elem_sz, double eps)
+    {
+      const int SPACEDIM=MyMeshType::MY_SPACEDIM;
+      typedef typename MyMeshType::MyConnType ConnType;
+      const NumberingPolicy numPol=MyMeshType::My_numPol;
+
+      const CellModel& cmType=CellModel::GetCellModel(type);
+      bool ret=false;
+
+      int nbEdges=cmType.getNumberOfSons();
+      double *pts = new double[nbEdges*SPACEDIM];
+      for (int iedge=0; iedge<nbEdges; iedge++)
+        {
+          const double* a=coords+SPACEDIM*(OTT<ConnType,numPol>::ind2C(conn_elem[iedge]));
+          std::copy(a,a+SPACEDIM,pts+iedge*SPACEDIM);
+        }
+      ret=isElementContainsPointAlg2DSimple(ptToTest,pts,nbEdges,eps);
+      delete [] pts;
+      return ret;
+    }
+
+    static bool isElementContainsPointAlgo2DPolygon(const double *ptToTest, NormalizedCellType type,
+                                                    const double *coords, const typename MyMeshType::MyConnType *conn_elem,
+                                                    typename MyMeshType::MyConnType conn_elem_sz, double eps)
+    {
+      // Override precision for this method only:
+      INTERP_KERNEL::QuadraticPlanarPrecision prec(eps);
+
+      const int SPACEDIM=MyMeshType::MY_SPACEDIM;
+      typedef typename MyMeshType::MyConnType ConnType;
+      const NumberingPolicy numPol=MyMeshType::My_numPol;
+
+      std::vector<INTERP_KERNEL::Node *> nodes(conn_elem_sz);
+      INTERP_KERNEL::QuadraticPolygon *pol(0);
+      for(mcIdType j=0;j<conn_elem_sz;j++)
+        {
+          mcIdType nodeId(OTT<ConnType,numPol>::ind2C(conn_elem[j]));
+          nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
+        }
+      if(!INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic())
+        pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
+      else
+        pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
+      INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(ptToTest[0],ptToTest[1]));
+      double a(0.),b(0.),c(0.);
+      a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
+      bool ret=pol->isInOrOut2(n);
+      delete pol; n->decrRef();
+      return ret;
+    }
+
     static bool isElementContainsPointAlg3D(const double *ptToTest, const typename MyMeshType::MyConnType *conn_elem, typename MyMeshType::MyConnType conn_elem_sz, const double *coords, const CellModel& cmType, double eps)
     {
       const int SPACEDIM=MyMeshType::MY_SPACEDIM;
@@ -166,7 +224,9 @@ namespace INTERP_KERNEL
     /*!
      * Precondition : spacedim==meshdim. To be checked upstream to this call.
      */
-    static bool isElementContainsPoint(const double *ptToTest, NormalizedCellType type, const double *coords, const typename MyMeshType::MyConnType *conn_elem, typename MyMeshType::MyConnType conn_elem_sz, double eps)
+    static bool isElementContainsPoint(const double *ptToTest, NormalizedCellType type, const double *coords,
+                                       const typename MyMeshType::MyConnType *conn_elem,
+                                       typename MyMeshType::MyConnType conn_elem_sz, double eps)
     {
       const int SPACEDIM=MyMeshType::MY_SPACEDIM;
       typedef typename MyMeshType::MyConnType ConnType;
@@ -176,18 +236,11 @@ namespace INTERP_KERNEL
       //
       if (SPACEDIM==2)
         {
-          int nbEdges=cmType.getNumberOfSons();
-          double *pts = new double[nbEdges*SPACEDIM];
-          for (int iedge=0; iedge<nbEdges; iedge++)
-            {
-              const double* a=coords+SPACEDIM*(OTT<ConnType,numPol>::ind2C(conn_elem[iedge]));
-              std::copy(a,a+SPACEDIM,pts+iedge*SPACEDIM);
-            }
-          bool ret=isElementContainsPointAlg2D(ptToTest,pts,nbEdges,eps);
-          delete [] pts;
-          return ret;
+          if(type != INTERP_KERNEL::NORM_POLYGON && !cmType.isQuadratic())
+            return isElementContainsPointAlgo2DSimple2(ptToTest, type, coords, conn_elem, conn_elem_sz, eps);
+          else
+            return isElementContainsPointAlgo2DPolygon(ptToTest, type, coords, conn_elem, conn_elem_sz, eps);
         }
-                        
       if (SPACEDIM==3)
         {
           return isElementContainsPointAlg3D(ptToTest,conn_elem,conn_elem_sz,coords,cmType,eps);
index ae8f17bab1484456d7aba12185846d4f516dc79d..7835309f89cf700070f10bc13cdaff2947d948ed 100644 (file)
@@ -129,30 +129,15 @@ void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const d
           mcIdType sz(connI[(*iter)+1]-connI[*iter]-1);
           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
           bool status(false);
-          // [ABN] : point locator algorithms are only properly working for linear cells.
-          if(ct!=INTERP_KERNEL::NORM_POLYGON && !sensibilityTo2DQuadraticLinearCellsFunc(ct,_mesh_dim))
-            status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
+          // [ABN] : point locator algorithms are not impl. for POLY or QPOLY in spaceDim3
+          if(  SPACEDIM!=2 &&
+              (ct == INTERP_KERNEL::NORM_POLYGON || sensibilityTo2DQuadraticLinearCellsFunc(ct,_mesh_dim)))
+            throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
+          // Keep calling simple algorithm when this is desired and simple for speed reasons:
+          if (SPACEDIM == 2 && ct != INTERP_KERNEL::NORM_POLYGON && !sensibilityTo2DQuadraticLinearCellsFunc(ct,_mesh_dim))
+            status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<2> >::isElementContainsPointAlgo2DSimple2(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
           else
-            {
-              if(SPACEDIM!=2)
-                throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
-              std::vector<INTERP_KERNEL::Node *> nodes(sz);
-              INTERP_KERNEL::QuadraticPolygon *pol(0);
-              for(mcIdType j=0;j<sz;j++)
-                {
-                  mcIdType nodeId(conn[connI[*iter]+1+j]);
-                  nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
-                }
-              if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
-                pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
-              else
-                pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
-              INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
-              double a(0.),b(0.),c(0.);
-              a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
-              status=pol->isInOrOut2(n);
-              delete pol; n->decrRef();
-            }
+            status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
           if(status)
             {
               eltsIndexPtr[i+1]++;
index f45ae66ce5e835bc00309ab4aa3e7d3f3672bbbc..49ff6b9e305735d66cce4f8d88f80ce4bca12602 100644 (file)
@@ -1084,6 +1084,52 @@ class MEDCouplingBasicsTest(unittest.TestCase):
         self.assertTrue(ftrg.isEqual(ftrg2,1e-12,1e-12))
         pass
 
+    def testPointLocator2D2DNonConvexPolygons(self):
+        """ PointLocator remapper now correclty support non-convex polygons
+        """
+        src = MEDCouplingUMesh('src', 2)
+        coo = DataArrayDouble([(6,1),(6,2),(4,2),(4,3),(3,3),(3,4),(2,4),(2,6),(1,6),(1,8),(2,8),(2,9),(3,9),(3,8),(4,8),(4,9),(5,9),(5,8),
+          (6,8),(6,9),(7,9),(7,8),(8,8),(8,9),(9,9),(9,8),(10,8),(10,9),(11,9),(11,8),(12,8),(12,9),(13,9),(13,8),
+          (14,8),(14,9),(15,9),(15,8),(16,8),(16,6),(15,6),(15,4),(14,4),(14,3),(13,3),(13,2),(11,2),(11,1),(16,11),
+          (15,11),(15,13),(14,13),(14,14),(13,14),(13,15),(11,15),(11,16),(6,16),(6,15),(4,15),(4,14),(3,14),(3,13),(2,13),
+          (2,11),(1,11)])
+        src.setCoords(coo)
+        c = DataArrayInt([5, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+         31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 5, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+         21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+         60, 61, 62, 63, 64, 65])
+        cI = DataArrayInt([0, 49, 98])
+        src.setConnectivity(c, cI)
+        src.checkConsistency()
+        tgt = MEDCouplingCMesh('tgt')
+        da = DataArrayDouble(18, 1); da.iota();
+        tgt.setCoords(da, da)
+        tgt = tgt.buildUnstructured()
+        srcF = MEDCouplingFieldDouble(ON_CELLS, ONE_TIME)
+        srcF.setArray(DataArrayDouble([25.,50.]))
+        srcF.setMesh(src)
+        srcF.setNature(IntensiveConservation)
+        remap = MEDCouplingRemapper()
+        remap.setIntersectionType(PointLocator)
+        remap.prepare(src, tgt, "P0P0")
+        tgtF = remap.transferField(srcF, 0.0)
+        ids1 = [137, 139, 141, 143, 145, 147, 149, 151, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 171, 172,
+        173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200,
+        201, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 242,
+        243, 244, 245, 246, 247, 248, 249, 250, 261, 262, 263, 264, 265]
+        ids2 = [23, 24, 25, 26, 27, 38, 39, 40, 41, 42, 43, 44, 45, 46, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 70, 71, 72, 73, 74, 75, 76,
+           77, 78, 79, 80, 81, 82, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+           114, 115, 116, 117, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 138, 140, 142, 144, 146, 148, 150]
+        ids3 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 47, 48,
+                49, 50, 51, 52, 53, 65, 66, 67, 68, 69, 83, 84, 85, 86, 100, 101, 102, 118, 119, 135, 136, 152, 153, 169, 170, 186, 187, 188, 202, 203,
+                204, 205, 219, 220, 221, 222, 223, 235, 236, 237, 238, 239, 240, 241, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 266, 267, 268,
+                269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288]
+        a = tgtF.getArray()
+        self.assertTrue(a[ids1].isUniform(50.0, 1e-12))
+        self.assertTrue(a[ids2].isUniform(25.0, 1e-12))
+        self.assertTrue(a[ids3].isUniform(0.0, 1e-12))
+        pass
+
     def testExtrudedOnDiffZLev1(self):
         """Non regression bug : This test is base on P0P0 ExtrudedExtruded. This test checks that if the input meshes are not based on a same plane // OXY the interpolation works"""
         arrX=DataArrayDouble([0,1]) ; arrY=DataArrayDouble([0,1]) ; arrZ=DataArrayDouble([0,1,2])
@@ -1335,7 +1381,7 @@ class MEDCouplingBasicsTest(unittest.TestCase):
         rem.prepare(src,trg,"P0P0")
         self.checkMatrix(rem.getCrudeMatrix(),[{0:1.0}],src.getNumberOfCells(),1e-12)
         pass
-    
+
     def test2D0DPointLocator(self):
         """
         For pointlocator fans, Remapper support following intersection