Salome HOME
new functionality MEDCouplingUMesh.explodeMeshIntoMicroEdges
authorAnthony Geay <anthony.geay@edf.fr>
Wed, 10 Aug 2016 15:12:12 +0000 (17:12 +0200)
committerAnthony Geay <anthony.geay@edf.fr>
Wed, 10 Aug 2016 15:12:12 +0000 (17:12 +0200)
src/INTERP_KERNEL/CellModel.cxx
src/INTERP_KERNEL/CellModel.hxx
src/MEDCoupling/MEDCouplingUMesh.cxx
src/MEDCoupling/MEDCouplingUMesh.hxx
src/MEDCoupling_Swig/MEDCouplingBasicsTest5.py
src/MEDCoupling_Swig/MEDCouplingCommon.i

index bd676e4248a46314c4e751dade3a960c92101e38..9632fb1ce470ee640398fa0e3b0f6ede5ffb9fda 100644 (file)
@@ -452,6 +452,28 @@ namespace INTERP_KERNEL
       return (lgth-std::count(conn,conn+lgth,-1))/2;
   }
   
+  /*!
+   * \sa fillMicroEdgeNodalConnectivity
+   */
+  unsigned CellModel::getNumberOfMicroEdges() const
+  {
+    unsigned mul(isQuadratic()?2:1);
+    if(!isDynamic())
+      {
+        switch(getDimension())
+          {
+          case 2:
+            return mul*getNumberOfSons();
+          case 3:
+            return mul*_nb_of_little_sons;
+          default:
+            throw INTERP_KERNEL::Exception("CellModel::getNumberOfMacroEdges : only 2D and 3D cells support this !");
+          }
+      }
+    else
+      throw INTERP_KERNEL::Exception("CellModel::getNumberOfMacroEdges : not supported by dynamic type !");
+  }
+  
   NormalizedCellType CellModel::getCorrespondingPolyType() const
   {
     switch(getDimension())
@@ -592,6 +614,50 @@ namespace INTERP_KERNEL
       throw INTERP_KERNEL::Exception("CellModel::fillSonEdgesNodalConnectivity3D : not implemented yet for NORM_POLYHED !");   
   }
 
+  /*!
+   * \sa getNumberOfMicroEdges
+   */
+  unsigned CellModel::fillMicroEdgeNodalConnectivity(int sonId, const int *nodalConn, int *sonNodalConn, NormalizedCellType& typeOfSon) const
+  {
+    if(isQuadratic())
+      {
+        int edgeId(sonId/2),subEdgeId(sonId%2);
+        typeOfSon=NORM_SEG2;
+        const unsigned *sonConn(0);
+        switch(getDimension())
+          {
+          case 2:
+            {
+              sonConn=_sons_con[edgeId];
+              break;
+            }
+          case 3:
+            {
+              sonConn=_little_sons_con[edgeId];
+              break;
+            }
+          default:
+            throw INTERP_KERNEL::Exception("CellModel::fillMicroEdgeNodalConnectivity : only 2D and 3D cells support this !");
+          }
+        const unsigned tmp[3]={sonConn[0],sonConn[2],sonConn[1]};
+        sonNodalConn[0]=nodalConn[tmp[subEdgeId]];
+        sonNodalConn[1]=nodalConn[tmp[subEdgeId+1]];
+        return 2;
+      }
+    else
+      {
+        switch(getDimension())
+          {
+          case 2:
+            return fillSonCellNodalConnectivity2(sonId,nodalConn,0,sonNodalConn,typeOfSon);
+          case 3:
+            return fillSonEdgesNodalConnectivity3D(sonId,nodalConn,0,sonNodalConn,typeOfSon);
+          default:
+            throw INTERP_KERNEL::Exception("CellModel::fillMicroEdgeNodalConnectivity : only 2D and 3D cells support this #2 !");
+          }
+      }
+  }
+
   void CellModel::changeOrientationOf2D(int *nodalConn, unsigned int sz) const
   {
     if(sz<1)
index 59cfb6e4d7960de1d24a1f71cb0c9776bb29d58d..9da0f7d229fe779f1063a9072f558289e90d04ca 100644 (file)
@@ -60,6 +60,7 @@ namespace INTERP_KERNEL
     INTERPKERNEL_EXPORT unsigned getNumberOfSons() const { return _nb_of_sons; }
     INTERPKERNEL_EXPORT unsigned getNumberOfSons2(const int *conn, int lgth) const;
     INTERPKERNEL_EXPORT unsigned getNumberOfEdgesIn3D(const int *conn, int lgth) const;
+    INTERPKERNEL_EXPORT unsigned getNumberOfMicroEdges() const;
     INTERPKERNEL_EXPORT unsigned getNumberOfNodesConstituentTheSon(unsigned sonId) const { return _nb_of_sons_con[sonId]; }
     INTERPKERNEL_EXPORT unsigned getNumberOfNodesConstituentTheSon2(unsigned sonId, const int *nodalConn, int lgth) const;
     INTERPKERNEL_EXPORT NormalizedCellType getExtrudedType() const { return _extruded_type; }
@@ -74,6 +75,7 @@ namespace INTERP_KERNEL
     INTERPKERNEL_EXPORT unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, NormalizedCellType& typeOfSon) const;
     INTERPKERNEL_EXPORT unsigned fillSonCellNodalConnectivity4(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, NormalizedCellType& typeOfSon) const;
     INTERPKERNEL_EXPORT unsigned fillSonEdgesNodalConnectivity3D(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, NormalizedCellType& typeOfSon) const;
+    INTERPKERNEL_EXPORT unsigned fillMicroEdgeNodalConnectivity(int sonId, const int *nodalConn, int *sonNodalConn, NormalizedCellType& typeOfSon) const;
     INTERPKERNEL_EXPORT void changeOrientationOf2D(int *nodalConn, unsigned int sz) const;
     INTERPKERNEL_EXPORT void changeOrientationOf1D(int *nodalConn, unsigned int sz) const;
     INTERPKERNEL_EXPORT DiameterCalculator *buildInstanceOfDiameterCalulator(int spaceDim) const;
index e41149f6b451024f80c09aaa3e4aa160c26c17dd..f7f960ceca62cfb34d9772b3fb22bed94030e73a 100644 (file)
@@ -674,6 +674,28 @@ private:
   const INTERP_KERNEL::CellModel& _cm;
 };
 
+class MicroEdgesGenerator2D
+{
+public:
+  MicroEdgesGenerator2D(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
+  unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfMicroEdges(); }
+  unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillMicroEdgeNodalConnectivity(sonId,nodalConn,sonNodalConn,typeOfSon); }
+  static const int DELTA=1;
+private:
+  const INTERP_KERNEL::CellModel& _cm;
+};
+
+class MicroEdgesGenerator3D
+{
+public:
+  MicroEdgesGenerator3D(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
+  unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfMicroEdges(); }
+  unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillMicroEdgeNodalConnectivity(sonId,nodalConn,sonNodalConn,typeOfSon); }
+  static const int DELTA=2;
+private:
+  const INTERP_KERNEL::CellModel& _cm;
+};
+
 /// @endcond
 
 /*!
@@ -740,6 +762,26 @@ MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataAr
   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
 }
 
+/*!
+ * This method computes the micro edges constituting each cell in \a this. Micro edge is an edge for non quadratic cells. Micro edge is an half edge for quadratic cells.
+ * This method works for both meshes with mesh dimenstion equal to 2 or 3. Dynamical cells are not supported (polygons, polyhedrons...)
+ * 
+ * \sa explode3DMeshTo1D, buildDescendingConnectiviy
+ */
+MEDCouplingUMesh *MEDCouplingUMesh::explodeMeshIntoMicroEdges(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
+{
+   checkFullyDefined();
+   switch(getMeshDimension())
+     {
+     case 2:
+       return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
+     case 3:
+       return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
+     default:
+       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explodeMeshIntoMicroEdges : Only 2D and 3D supported !");
+     }
+}
+
 /*!
  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
  * this->getMeshDimension(), that bound cells of \a this mesh. In
index e4320302886c197ce1219e4748b986437c15e010..68093553c692c5c99f0ff89dd03e9e57765f1b2d 100644 (file)
@@ -123,6 +123,7 @@ namespace MEDCoupling
     MEDCOUPLING_EXPORT MEDCouplingUMesh *explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const;
     MEDCOUPLING_EXPORT MEDCouplingUMesh *buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const;
     MEDCOUPLING_EXPORT MEDCouplingUMesh *buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const;
+    MEDCOUPLING_EXPORT MEDCouplingUMesh *explodeMeshIntoMicroEdges(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const;
     MEDCOUPLING_EXPORT void computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const;
     MEDCOUPLING_EXPORT static void ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI,
                                                               DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx);
index 5722fee79ddb5426be0edc37988dae04533bc49d..534079086aeee643dc0defff43c7217f01d0be97 100644 (file)
@@ -4307,7 +4307,32 @@ class MEDCouplingBasicsTest5(unittest.TestCase):
         m.setNodalConnectivity(DataArrayInt([]),DataArrayInt([0]))
         m=m.buildUnstructured()
         pass
-    
+
+    def testExplodeMeshIntoMicroEdges1(self):
+        """ test for new functionality MEDCouplingUMesh.explodeMeshIntoMicroEdges"""
+        m=MEDCouplingUMesh("mesh",2)
+        coo=DataArrayDouble([2,0,10,0,12,0,0,3,4,5,10,5,12,7,3,2.5,7,2.5,6,0,10,2.5,11,2.5,11,0,7,5],14,2)
+        m.setCoords(coo)
+        m.allocateCells()
+        # here a mix of quadratic, linear cells. Non conform but conform considering micro edges
+        m.insertNextCell(NORM_TRI6,[0,4,1,7,8,9])
+        m.insertNextCell(NORM_TRI6,[1,5,2,10,11,12])
+        m.insertNextCell(NORM_TRI6,[5,1,4,10,8,13])
+        m.insertNextCell(NORM_TRI3,[3,4,7])
+        m.insertNextCell(NORM_TRI3,[3,7,0])
+        m.insertNextCell(NORM_TRI3,[6,2,11])
+        m.insertNextCell(NORM_TRI3,[6,11,5])
+        m.insertNextCell(NORM_TRI3,[6,5,13])
+        m.insertNextCell(NORM_TRI3,[6,13,4])
+        edges,d,di,rd,rdi=m.explodeMeshIntoMicroEdges() # <- new method
+        self.assertTrue(MEDCoupling1SGTUMesh(edges).getNodalConnectivity().isEqual(DataArrayInt([0,7,7,4,4,8,8,1,1,9,9,0,1,10,10,5,5,11,11,2,2,12,12,1,4,13,13,5,3,4,7,3,0,3,6,2,11,6,5,6,13,6,4,6])))
+        self.assertEqual(edges.getCoords().getHiddenCppPointer(),coo.getHiddenCppPointer())
+        self.assertTrue(d.isEqual(DataArrayInt([0,1,2,3,4,5,6,7,8,9,10,11,7,6,3,2,12,13,14,1,15,15,0,16,17,9,18,18,8,19,19,13,20,20,12,21])))
+        self.assertTrue(di.isEqual(DataArrayInt([0,6,12,18,21,24,27,30,33,36])))
+        self.assertTrue(rd.isEqual(DataArrayInt([0,4,0,3,0,2,0,2,0,0,1,2,1,2,1,6,1,5,1,1,2,8,2,7,3,3,4,4,5,5,6,6,7,7,8,8])))
+        self.assertTrue(rdi.isEqual(DataArrayInt([0,2,4,6,8,9,10,12,14,16,18,19,20,22,24,25,27,28,29,31,33,35,36])))
+        pass
+        
     pass
 
 if __name__ == '__main__':
index eaaa5eb64a0b231a85eb6c4dd57c49281cf1af08..bcd4781126662fac6ba9938edf3265ec966710fe 100644 (file)
@@ -279,6 +279,7 @@ using namespace INTERP_KERNEL;
 %newobject MEDCoupling::MEDCouplingUMesh::buildDescendingConnectivity;
 %newobject MEDCoupling::MEDCouplingUMesh::buildDescendingConnectivity2;
 %newobject MEDCoupling::MEDCouplingUMesh::explode3DMeshTo1D;
+%newobject MEDCoupling::MEDCouplingUMesh::explodeMeshIntoMicroEdges;
 %newobject MEDCoupling::MEDCouplingUMesh::buildExtrudedMesh;
 %newobject MEDCoupling::MEDCouplingUMesh::buildSpreadZonesWithPoly;
 %newobject MEDCoupling::MEDCouplingUMesh::MergeUMeshes;
@@ -1788,6 +1789,7 @@ namespace MEDCoupling
     MEDCouplingUMesh *buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception);
     MEDCouplingUMesh *buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception);
     MEDCouplingUMesh *explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception);
+    MEDCouplingUMesh *explodeMeshIntoMicroEdges(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception);
     void orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception);
     bool isPresenceOfQuadratic() const throw(INTERP_KERNEL::Exception);
     bool isFullyQuadratic() const throw(INTERP_KERNEL::Exception);
@@ -2540,6 +2542,22 @@ namespace MEDCoupling
         return ret;
       }
 
+      PyObject *explodeMeshIntoMicroEdges() const throw(INTERP_KERNEL::Exception)
+      {
+        MCAuto<DataArrayInt> d0=DataArrayInt::New();
+        MCAuto<DataArrayInt> d1=DataArrayInt::New();
+        MCAuto<DataArrayInt> d2=DataArrayInt::New();
+        MCAuto<DataArrayInt> d3=DataArrayInt::New();
+        MEDCouplingUMesh *m=self->explodeMeshIntoMicroEdges(d0,d1,d2,d3);
+        PyObject *ret=PyTuple_New(5);
+        PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(m),SWIGTYPE_p_MEDCoupling__MEDCouplingUMesh, SWIG_POINTER_OWN | 0 ));
+        PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(d0.retn()),SWIGTYPE_p_MEDCoupling__DataArrayInt, SWIG_POINTER_OWN | 0 ));
+        PyTuple_SetItem(ret,2,SWIG_NewPointerObj(SWIG_as_voidptr(d1.retn()),SWIGTYPE_p_MEDCoupling__DataArrayInt, SWIG_POINTER_OWN | 0 ));
+        PyTuple_SetItem(ret,3,SWIG_NewPointerObj(SWIG_as_voidptr(d2.retn()),SWIGTYPE_p_MEDCoupling__DataArrayInt, SWIG_POINTER_OWN | 0 ));
+        PyTuple_SetItem(ret,4,SWIG_NewPointerObj(SWIG_as_voidptr(d3.retn()),SWIGTYPE_p_MEDCoupling__DataArrayInt, SWIG_POINTER_OWN | 0 ));
+        return ret;
+      }
+
       PyObject *buildDescendingConnectivity() const throw(INTERP_KERNEL::Exception)
       {
         MCAuto<DataArrayInt> d0=DataArrayInt::New();