]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
*** empty log message ***
authorageay <ageay>
Tue, 3 Aug 2010 08:29:48 +0000 (08:29 +0000)
committerageay <ageay>
Tue, 3 Aug 2010 08:29:48 +0000 (08:29 +0000)
src/MEDCoupling/MEDCouplingExtrudedMesh.cxx
src/MEDCoupling/MEDCouplingExtrudedMesh.hxx
src/MEDCoupling/MEDCouplingUMesh.cxx
src/MEDCoupling/MEDCouplingUMesh.hxx
src/MEDCoupling/Test/MEDCouplingBasicsTest.hxx
src/MEDCoupling/Test/MEDCouplingBasicsTest1.cxx
src/MEDCoupling/Test/MEDCouplingBasicsTest2.cxx
src/MEDCoupling_Swig/MEDCouplingBasicsTest.py
src/MEDCoupling_Swig/libMEDCoupling_Swig.i

index 928edc0c34bb9a1aa68a7fd6dbd11f6c0a546817..bfa591c18b0ad1a1927c7d5a3e31e0146e945b42 100644 (file)
@@ -67,9 +67,17 @@ try:_mesh2D(mesh2D),_mesh1D(MEDCouplingUMesh::New()),_mesh3D_ids(0),_cell_2D_id(
   if(_mesh2D!=0)
     _mesh2D->incrRef();
   computeExtrusion(mesh3D);
+  setName(mesh3D->getName());
 }
-catch(INTERP_KERNEL::Exception&)
+catch(INTERP_KERNEL::Exception& e)
   {
+    if(_mesh2D)
+      _mesh2D->decrRef();
+    if(_mesh1D)
+      _mesh1D->decrRef();
+    if(_mesh3D_ids)
+      _mesh3D_ids->decrRef();
+    throw e;
   }
 
 MEDCouplingExtrudedMesh::MEDCouplingExtrudedMesh():_mesh2D(0),_mesh1D(0),_mesh3D_ids(0),_cell_2D_id(-1)
@@ -148,8 +156,13 @@ bool MEDCouplingExtrudedMesh::isEqual(const MEDCouplingMesh *other, double prec)
 
 INTERP_KERNEL::NormalizedCellType MEDCouplingExtrudedMesh::getTypeOfCell(int cellId) const
 {
+  const int *ids=_mesh3D_ids->getConstPointer();
+  int nbOf3DCells=_mesh3D_ids->getNumberOfTuples();
+  const int *where=std::find(ids,ids+nbOf3DCells,cellId);
+  if(where==ids+nbOf3DCells)
+    throw INTERP_KERNEL::Exception("Invalid cellId specified >= getNumberOfCells() !");
   int nbOfCells2D=_mesh2D->getNumberOfCells();
-  int locId=cellId%nbOfCells2D;
+  int locId=std::distance(ids,where)%nbOfCells2D;
   INTERP_KERNEL::NormalizedCellType tmp=_mesh2D->getTypeOfCell(locId);
   return INTERP_KERNEL::CellModel::getCellModel(tmp).getExtrudedType();
 }
@@ -236,13 +249,45 @@ void MEDCouplingExtrudedMesh::updateTime()
     }
 }
 
+MEDCouplingUMesh *MEDCouplingExtrudedMesh::build3DUnstructuredMesh() const
+{
+  MEDCouplingUMesh *ret=_mesh2D->buildExtrudedMeshFromThis(_mesh1D,0);
+  const int *renum=_mesh3D_ids->getConstPointer();
+  int nbOf3DCells=_mesh3D_ids->getNumberOfTuples();
+  ret->renumberCells(renum,renum+nbOf3DCells,false);
+  ret->setName(getName());
+  return ret;
+}
+
 MEDCouplingFieldDouble *MEDCouplingExtrudedMesh::getMeasureField(bool) const
 {
-  //not implemented yet
-  return 0;
+  std::string name="MeasureOfMesh_";
+  name+=getName();
+  MEDCouplingFieldDouble *ret2D=_mesh2D->getMeasureField(true);
+  MEDCouplingFieldDouble *ret1D=_mesh1D->getMeasureField(true);
+  const double *ret2DPtr=ret2D->getArray()->getConstPointer();
+  const double *ret1DPtr=ret1D->getArray()->getConstPointer();
+  int nbOf2DCells=_mesh2D->getNumberOfCells();
+  int nbOf1DCells=_mesh1D->getNumberOfCells();
+  int nbOf3DCells=nbOf2DCells*nbOf1DCells;
+  const int *renum=_mesh3D_ids->getConstPointer();
+  MEDCouplingFieldDouble *ret=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
+  ret->setMesh(this);
+  DataArrayDouble *da=DataArrayDouble::New();
+  da->alloc(nbOf3DCells,1);
+  double *retPtr=da->getPointer();
+  for(int i=0;i<nbOf1DCells;i++)
+    for(int j=0;j<nbOf2DCells;j++)
+      retPtr[renum[i*nbOf2DCells+j]]=ret2DPtr[j]*ret1DPtr[i];
+  ret->setArray(da);
+  da->decrRef();
+  ret->setName(name.c_str());
+  ret2D->decrRef();
+  ret1D->decrRef();
+  return ret;
 }
 
-MEDCouplingFieldDouble *MEDCouplingExtrudedMesh::getMeasureFieldOnNode(bool) const
+MEDCouplingFieldDouble *MEDCouplingExtrudedMesh::getMeasureFieldOnNode(bool isAbs) const
 {
   //not implemented yet
   return 0;
@@ -250,8 +295,7 @@ MEDCouplingFieldDouble *MEDCouplingExtrudedMesh::getMeasureFieldOnNode(bool) con
 
 MEDCouplingFieldDouble *MEDCouplingExtrudedMesh::buildOrthogonalField() const
 {
-  //not implemented yet
-  throw INTERP_KERNEL::Exception("MEDCouplingExtrudedMesh::buildOrthogonalField not implemented yet !");
+  throw INTERP_KERNEL::Exception("MEDCouplingExtrudedMesh::buildOrthogonalField : This method has no sense for MEDCouplingExtrudedMesh that is 3D !");
 }
 
 int MEDCouplingExtrudedMesh::getCellContainingPoint(const double *pos, double eps) const
index 559831fbc80c7aa4146bbf93fc6678fcfa731fbc..566b23616b04cce96779a19511f0e5aa9da3cf6a 100644 (file)
@@ -55,6 +55,7 @@ namespace ParaMEDMEM
     MEDCouplingUMesh *getMesh2D() const { return _mesh2D; }
     MEDCouplingUMesh *getMesh1D() const { return _mesh1D; }
     DataArrayInt *getMesh3DIds() const { return _mesh3D_ids; }
+    MEDCouplingUMesh *build3DUnstructuredMesh() const;
     MEDCouplingFieldDouble *getMeasureField(bool) const;
     MEDCouplingFieldDouble *getMeasureFieldOnNode(bool) const;
     MEDCouplingFieldDouble *buildOrthogonalField() const;
@@ -92,6 +93,7 @@ namespace ParaMEDMEM
   private:
     MEDCouplingUMesh *_mesh2D;
     MEDCouplingUMesh *_mesh1D;
+    //! New to old 3D cell Ids Array
     DataArrayInt *_mesh3D_ids;
     int _cell_2D_id;
   };
index 7c046c06c664b96151190d0dff171717d6edae57..e0bcf76caee57834e7110ce6ce174d9397e981f6 100644 (file)
@@ -36,6 +36,8 @@ using namespace ParaMEDMEM;
 
 const char MEDCouplingUMesh::PART_OF_NAME[]="PartOf_";
 
+double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
+
 MEDCouplingUMesh *MEDCouplingUMesh::New()
 {
   return new MEDCouplingUMesh;
@@ -1271,7 +1273,7 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
         {
           ipt=connec_index[iel];
           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
-          area_vol[iel]=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[iel+1]-ipt-1,coords,dim_space);
+          area_vol[iel]=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[iel+1]-ipt-1,coords,dim_space,isAbs);
         }
       if(isAbs)
         for(int iel=0;iel<nbelem;iel++)
@@ -1754,6 +1756,114 @@ bool MEDCouplingUMesh::isPresenceOfQuadratic() const
   return ret;
 }
 
+/*!
+ * This method checks that all or only polygons (depending 'polyOnly' parameter) 2D cells are correctly oriented relative to 'vec' vector.
+ * The 'vec' vector has to have a non nul norm.
+ * If not 'cells' parameter will be appended with cellIds of incorrect cells.
+ * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
+ */
+void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
+{
+  if(getMeshDimension()!=2 || getSpaceDimension()!=3)
+    throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
+  int nbOfCells=getNumberOfCells();
+  const int *conn=_nodal_connec->getConstPointer();
+  const int *connI=_nodal_connec_index->getConstPointer();
+  const double *coordsPtr=_coords->getConstPointer();
+  for(int i=0;i<nbOfCells;i++)
+    {
+      INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
+      if(!polyOnly || type==INTERP_KERNEL::NORM_POLYGON)
+        {
+          if(!isPolygonWellOriented(vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
+            cells.push_back(i);
+        }
+    }
+}
+
+/*!
+ * This method orient correctly (if needed) all or only polygons (depending 'polyOnly' parameter)  2D cells are correctly oriented relative to 'vec' vector.
+ * The 'vec' vector has to have a non nul norm.
+ * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
+ */
+void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
+{
+  if(getMeshDimension()!=2 || getSpaceDimension()!=3)
+    throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
+  int nbOfCells=getNumberOfCells();
+  int *conn=_nodal_connec->getPointer();
+  const int *connI=_nodal_connec_index->getConstPointer();
+  const double *coordsPtr=_coords->getConstPointer();
+  bool isModified=false;
+  for(int i=0;i<nbOfCells;i++)
+    {
+      INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
+      if(!polyOnly || type==INTERP_KERNEL::NORM_POLYGON)
+        if(!isPolygonWellOriented(vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
+          {
+            isModified=true;
+            std::vector<int> tmp(connI[i+1]-connI[i]-2);
+            std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
+            std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
+          }
+    }
+  if(isModified)
+    _nodal_connec->declareAsNew();
+  updateTime();
+}
+
+/*!
+ * This method checks that all polyhedrons cells have correctly oriented faces.
+ * If not, 'cells' parameter will be appended with cellIds of incorrect cells.
+ * @throw when 'this' is not a mesh with meshdim==3 and spacedim==3
+ */
+void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
+{
+  if(getMeshDimension()!=3 || getSpaceDimension()!=3)
+    throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
+  int nbOfCells=getNumberOfCells();
+  const int *conn=_nodal_connec->getConstPointer();
+  const int *connI=_nodal_connec_index->getConstPointer();
+  const double *coordsPtr=_coords->getConstPointer();
+  for(int i=0;i<nbOfCells;i++)
+    {
+      INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
+      if(type==INTERP_KERNEL::NORM_POLYHED)
+        {
+          if(!isPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
+            cells.push_back(i);
+        }
+    }
+}
+
+/*!
+ * This method tries to orient correctly polhedrons cells.
+ * @throw when 'this' is not a mesh with meshdim==3 and spacedim==3. An exception is also thrown when the attempt of reparation fails.
+ */
+void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
+{
+  if(getMeshDimension()!=3 || getSpaceDimension()!=3)
+    throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
+  int nbOfCells=getNumberOfCells();
+  int *conn=_nodal_connec->getPointer();
+  const int *connI=_nodal_connec_index->getConstPointer();
+  const double *coordsPtr=_coords->getConstPointer();
+  bool isModified=false;
+  for(int i=0;i<nbOfCells;i++)
+    {
+      INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
+      if(type==INTERP_KERNEL::NORM_POLYHED)
+        if(!isPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
+          {
+            tryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
+            isModified=true;
+          }
+    }
+  if(isModified)
+    _nodal_connec->declareAsNew();
+  updateTime();
+}
+
 /*!
  * This method aggregate the bbox of each cell and put it into bbox parameter.
  * @param bbox out parameter of size 2*spacedim*nbOfcells.
@@ -2186,12 +2296,14 @@ void MEDCouplingUMesh::appendExtrudedCell(const int *connBg, const int *connEnd,
         std::back_insert_iterator< std::vector<int> > ii(ret);
         std::copy(connBg+1,connEnd,ii);
         *ii++=-1;
-        std::transform(connBg+1,connEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
+        std::reverse_iterator<const int *> rConnBg(connEnd);
+        std::reverse_iterator<const int *> rConnEnd(connBg+1);
+        std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
         int nbOfRadFaces=std::distance(connBg+1,connEnd);
         for(int i=0;i<nbOfRadFaces;i++)
           {
             *ii++=-1;
-            int conn[4]={connBg[i+1],connBg[(i+1)%nbOfRadFaces+1],connBg[(i+1)%nbOfRadFaces+1]+deltaz,connBg[i+1]+deltaz};
+            int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
             std::copy(conn,conn+4,ii);
           }
         break;
@@ -2200,3 +2312,100 @@ void MEDCouplingUMesh::appendExtrudedCell(const int *connBg, const int *connEnd,
       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
     }
 }
+
+/*!
+ * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [begin,end).
+ */
+bool MEDCouplingUMesh::isPolygonWellOriented(const double *vec, const int *begin, const int *end, const double *coords)
+{
+  double v[3]={0.,0.,0.};
+  int sz=std::distance(begin,end);
+  for(int i=0;i<sz;i++)
+    {
+      v[0]+=coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]+2]-coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]+1];
+      v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
+      v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
+    }
+  return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]<0.;
+}
+
+/*!
+ * The polyhedron is specfied by its connectivity nodes in [begin,end).
+ */
+bool MEDCouplingUMesh::isPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
+{
+  std::vector<std::pair<int,int> > edges;
+  int nbOfFaces=std::count(begin,end,-1)+1;
+  const int *bgFace=begin;
+  for(int i=0;i<nbOfFaces;i++)
+    {
+      const int *endFace=std::find(bgFace+1,end,-1);
+      int nbOfEdgesInFace=std::distance(bgFace,endFace);
+      for(int j=0;j<nbOfEdgesInFace;j++)
+        {
+          std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
+          if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
+            return false;
+          edges.push_back(p1);
+        }
+      bgFace=endFace+1;
+    }
+  return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
+}
+
+/*!
+ * This method tries to obtain a well oriented polyhedron.
+ * If the algorithm fails, an exception will be thrown.
+ */
+void MEDCouplingUMesh::tryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
+{
+  std::vector<std::pair<int,int> > edges;
+  int nbOfFaces=std::count(begin,end,-1)+1;
+  int *bgFace=begin;
+  std::vector<bool> isPerm(nbOfFaces);
+  for(int i=0;i<nbOfFaces;i++)
+    {
+      int *endFace=std::find(bgFace+1,end,-1);
+      int nbOfEdgesInFace=std::distance(bgFace,endFace);
+      for(int l=0;l<nbOfEdgesInFace;l++)
+        {
+          std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]);
+          edges.push_back(p1);
+        }
+      int *bgFace2=endFace+1;
+      for(int k=i+1;k<nbOfFaces;k++)
+        {
+          int *endFace2=std::find(bgFace2+1,end,-1);
+          int nbOfEdgesInFace2=std::distance(bgFace2,endFace2);
+          for(int j=0;j<nbOfEdgesInFace2;j++)
+            {
+              std::pair<int,int> p2(bgFace2[j],bgFace2[(j+1)%nbOfEdgesInFace2]);
+              if(std::find(edges.begin(),edges.end(),p2)!=edges.end())
+                {
+                  if(isPerm[k])
+                    throw INTERP_KERNEL::Exception("Fail to repare polyhedron ! Polyedron looks bad !");
+                  std::vector<int> tmp(nbOfEdgesInFace2-1);
+                  std::copy(bgFace2+1,endFace2,tmp.rbegin());
+                  std::copy(tmp.begin(),tmp.end(),bgFace2+1);
+                  isPerm[k]=true;
+                  continue;
+                }
+            }
+          bgFace2=endFace2+1;
+        }
+      bgFace=endFace+1;
+    }
+  if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
+    {//not lucky ! The first face was not correctly oriented : reorient all faces...
+      bgFace=begin;
+      for(int i=0;i<nbOfFaces;i++)
+        {
+          int *endFace=std::find(bgFace+1,end,-1);
+          int nbOfEdgesInFace=std::distance(bgFace,endFace);
+          std::vector<int> tmp(nbOfEdgesInFace-1);
+          std::copy(bgFace+1,endFace,tmp.rbegin());
+          std::copy(tmp.begin(),tmp.end(),bgFace+1);
+          bgFace=endFace+1;
+        }
+    }
+}
index 04d4bb6910b58f696ecd33777b791ce0e476966e..1ae0fdc74ff2871af27912b3250d272230b76943 100644 (file)
@@ -93,6 +93,10 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT MEDCouplingUMesh *buildExtrudedMeshFromThis(const MEDCouplingUMesh *mesh1D, int policy);
     MEDCOUPLING_EXPORT bool isFullyQuadratic() const;
     MEDCOUPLING_EXPORT bool isPresenceOfQuadratic() const;
+    MEDCOUPLING_EXPORT void are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception);
     //utilities for MED File RW
     MEDCOUPLING_EXPORT bool checkConsecutiveCellTypes() const;
     MEDCOUPLING_EXPORT DataArrayInt *rearrange2ConsecutiveCellTypes();
@@ -105,6 +109,9 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT static MEDCouplingUMesh *mergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2);
     MEDCOUPLING_EXPORT static MEDCouplingUMesh *mergeUMeshesOnSameCoords(const std::vector<MEDCouplingUMesh *>& meshes);
     MEDCOUPLING_EXPORT static MEDCouplingUMesh *fuseUMeshesOnSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr);
+    MEDCOUPLING_EXPORT static bool isPolygonWellOriented(const double *vec, const int *begin, const int *end, const double *coords);
+    MEDCOUPLING_EXPORT static bool isPolyhedronWellOriented(const int *begin, const int *end, const double *coords);
+    MEDCOUPLING_EXPORT static void tryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception);
   private:
     MEDCouplingUMesh();
     MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCpy);
@@ -131,6 +138,8 @@ namespace ParaMEDMEM
     std::set<INTERP_KERNEL::NormalizedCellType> _types;
   private:
     static const char PART_OF_NAME[];
+  public:
+    static double EPS_FOR_POLYH_ORIENTATION;
   };
 }
 
index ce8d1b8c41afa9ee9148cb555a669c3a7579a26d..7fb1d01feb8725eb4e2f09f4647b48f0f8f4af5c 100644 (file)
@@ -57,6 +57,7 @@ namespace ParaMEDMEM
     CPPUNIT_TEST( testExtrudedMesh1 );
     CPPUNIT_TEST( testExtrudedMesh2 );
     CPPUNIT_TEST( testExtrudedMesh3 );
+    CPPUNIT_TEST( testExtrudedMesh4 );
     CPPUNIT_TEST( testFindCommonNodes );
     CPPUNIT_TEST( testCheckButterflyCells );
     CPPUNIT_TEST( testMergeMesh1 );
@@ -88,6 +89,8 @@ namespace ParaMEDMEM
     //MEDCouplingBasicsTest2.cxx
     CPPUNIT_TEST( testGaussPointField1 );
     CPPUNIT_TEST( testGaussPointNEField1 );
+    CPPUNIT_TEST( testCellOrientation1 );
+    CPPUNIT_TEST( testCellOrientation2 );
     //MEDCouplingBasicsTestInterp.cxx
     CPPUNIT_TEST( test2DInterpP0P0_1 );
     CPPUNIT_TEST( test2DInterpP0P0PL_1 );
@@ -173,6 +176,7 @@ namespace ParaMEDMEM
     void testExtrudedMesh1();
     void testExtrudedMesh2();
     void testExtrudedMesh3();
+    void testExtrudedMesh4();
     void testFindCommonNodes();
     void testCheckButterflyCells();
     void testMergeMesh1();
@@ -204,6 +208,8 @@ namespace ParaMEDMEM
     //MEDCouplingBasicsTest2.cxx
     void testGaussPointField1();
     void testGaussPointNEField1();
+    void testCellOrientation1();
+    void testCellOrientation2();
     //MEDCouplingBasicsTestInterp.cxx
     void test2DInterpP0P0_1();
     void test2DInterpP0P0PL_1();
index 09e9401e785ea26e7e75c0052d482e8852ca07c2..ef2f423547842bf233cbd687e6bdf140bab10a15 100644 (file)
@@ -1103,6 +1103,55 @@ void MEDCouplingBasicsTest::testExtrudedMesh3()
   m1->decrRef();
 }
 
+/*!
+ * This test check MEDCouplingUMesh::buildExtrudedMeshFromThis method, but also, MEDCouplingExtrudedMesh following methods :
+ * getCellContainingPoint getMeasureField getNodeIdsOfCell getCoordinateOfNode getTypeOfCell build3DUnstructuredMesh.
+ */
+void MEDCouplingBasicsTest::testExtrudedMesh4()
+{
+  MEDCouplingUMesh *m1=build2DTargetMesh_1();
+  std::vector<int> cells(2); cells[0]=2; cells[1]=4;
+  m1->convertToPolyTypes(cells);
+  m1->changeSpaceDimension(3);
+  MEDCouplingUMesh *m2=buildCU1DMesh_U();
+  m2->changeSpaceDimension(3);
+  double center[3]={0.,0.,0.};
+  double vector[3]={0.,1.,0.};
+  m2->rotate(center,vector,-M_PI/2.);
+  MEDCouplingUMesh *m3=m1->buildExtrudedMeshFromThis(m2,0);
+  const int expected1[15]= {1,3,2,0,6,5,7,10,11,8,12,9,14,13,4};
+  const int rexpected1[15]={3, 0, 2, 1, 14, 5, 4, 6, 9, 11, 7, 8, 10, 13, 12};
+  m3->renumberCells(expected1,expected1+15,false);
+  MEDCouplingExtrudedMesh *m4=MEDCouplingExtrudedMesh::New(m3,m1,0);
+  CPPUNIT_ASSERT_EQUAL(INTERP_KERNEL::NORM_HEXA8,m4->getTypeOfCell(0));
+  CPPUNIT_ASSERT_EQUAL(INTERP_KERNEL::NORM_HEXA8,m4->getTypeOfCell(1));
+  CPPUNIT_ASSERT_EQUAL(INTERP_KERNEL::NORM_POLYHED,m4->getTypeOfCell(2));
+  CPPUNIT_ASSERT_EQUAL(INTERP_KERNEL::NORM_PENTA6,m4->getTypeOfCell(7));
+  MEDCouplingFieldDouble *f=m4->getMeasureField(true);
+  DataArrayDouble *arr=f->getArray();
+  CPPUNIT_ASSERT_EQUAL(15,arr->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,arr->getNumberOfComponents());
+  const double *arrPtr=arr->getConstPointer();
+  const double expected2[15]={0.075,0.0375,0.0375,0.075,0.075,   0.1125,0.05625,0.05625,0.1125,0.1125,   0.0625,0.03125,0.03125,0.0625,0.0625};
+  for(int i=0;i<15;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[rexpected1[i]],arrPtr[i],1e-16);
+  f->decrRef();
+  MEDCouplingUMesh *m5=m4->build3DUnstructuredMesh();
+  CPPUNIT_ASSERT(m5->isEqual(m3,1e-12));
+  f=m5->getMeasureField(true);
+  arr=f->getArray();
+  arrPtr=arr->getConstPointer();
+  for(int i=0;i<15;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[rexpected1[i]],arrPtr[i],1e-16);
+  f->decrRef();
+  m5->decrRef();
+  //
+  m4->decrRef();
+  m3->decrRef();
+  m2->decrRef();
+  m1->decrRef();
+}
+
 void MEDCouplingBasicsTest::testFindCommonNodes()
 {
   DataArrayInt *comm,*commI;
index 81d9eee56ae27be182ddf15469c5cfb6ac2450eb..b3f96a287c465cdbf90224f6a41a3d2845563533 100644 (file)
@@ -142,3 +142,91 @@ void MEDCouplingBasicsTest::testGaussPointNEField1()
   f->decrRef();
   m->decrRef();
 }
+
+void MEDCouplingBasicsTest::testCellOrientation1()
+{
+  MEDCouplingUMesh *m=build2DTargetMesh_1();
+  double vec[3]={0.,0.,1.};
+  std::vector<int> res1;
+  CPPUNIT_ASSERT_THROW(m->are2DCellsNotCorrectlyOriented(vec,false,res1),INTERP_KERNEL::Exception);
+  m->changeSpaceDimension(3);
+  res1.clear();
+  m->are2DCellsNotCorrectlyOriented(vec,false,res1);
+  CPPUNIT_ASSERT(res1.empty());
+  vec[2]=-1;
+  m->are2DCellsNotCorrectlyOriented(vec,false,res1);
+  CPPUNIT_ASSERT_EQUAL(5,(int)res1.size());
+  res1.clear();
+  //
+  vec[2]=1.;
+  // connectivity inversion
+  int *conn=m->getNodalConnectivity()->getPointer();
+  int tmp=conn[11];
+  conn[11]=conn[12];
+  conn[12]=tmp;
+  m->are2DCellsNotCorrectlyOriented(vec,false,res1);
+  CPPUNIT_ASSERT_EQUAL(1,(int)res1.size());
+  CPPUNIT_ASSERT_EQUAL(2,res1[0]);
+  res1.clear();
+  m->orientCorrectly2DCells(vec,false);
+  m->are2DCellsNotCorrectlyOriented(vec,false,res1);
+  CPPUNIT_ASSERT(res1.empty());
+  MEDCouplingUMesh *m2=build2DTargetMesh_1();
+  m2->changeSpaceDimension(3);
+  CPPUNIT_ASSERT(m->isEqual(m2,1e-12));
+  m2->decrRef();
+  //
+  m->decrRef();
+}
+
+void MEDCouplingBasicsTest::testCellOrientation2()
+{
+  MEDCouplingUMesh *m1=0;
+  MEDCouplingUMesh *m2=build3DExtrudedUMesh_1(m1);
+  m1->decrRef();
+  std::vector<int> res1;
+  m2->arePolyhedronsNotCorrectlyOriented(res1);
+  CPPUNIT_ASSERT_EQUAL(6,(int)res1.size());
+  m2->orientCorrectlyPolyhedrons();
+  res1.clear();
+  m2->arePolyhedronsNotCorrectlyOriented(res1);
+  CPPUNIT_ASSERT(res1.empty());
+  m2->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(18,m2->getNumberOfCells());
+  int cellIds[3]={0,6,12};
+  std::vector<int> cellIds2(cellIds,cellIds+3);
+  m2->convertToPolyTypes(cellIds2);
+  m2->orientCorrectlyPolyhedrons();
+  res1.clear();
+  m2->arePolyhedronsNotCorrectlyOriented(res1);
+  CPPUNIT_ASSERT(res1.empty());
+  MEDCouplingFieldDouble *f2=m2->getMeasureField(false);
+  const double *f2Ptr=f2->getArray()->getConstPointer();
+  //Test to check global reverse in MEDCouplingUMesh::tryToCorrectPolyhedronOrientation
+  MEDCouplingUMesh *m3=build2DTargetMesh_1();
+  double vec[3]={0.,0.,-1.};//<- important for the test
+  m3->changeSpaceDimension(3);
+  const int ids1[5]={0,1,2,3,4};
+  std::vector<int> ids2(ids1,ids1+5);
+  m3->convertToPolyTypes(ids2);
+  m3->orientCorrectly2DCells(vec,false);
+  MEDCouplingUMesh *m4=buildCU1DMesh_U();
+  m4->changeSpaceDimension(3);
+  double center[3]={0.,0.,0.};
+  double vector[3]={0.,1.,0.};
+  m4->rotate(center,vector,-M_PI/2.);
+  MEDCouplingUMesh *m5=m3->buildExtrudedMeshFromThis(m4,0);
+  res1.clear();
+  m5->arePolyhedronsNotCorrectlyOriented(res1);
+  CPPUNIT_ASSERT_EQUAL(15,(int)res1.size());
+  m5->orientCorrectlyPolyhedrons();
+  res1.clear();
+  m5->arePolyhedronsNotCorrectlyOriented(res1);
+  CPPUNIT_ASSERT(res1.empty());
+  m5->decrRef();
+  m3->decrRef();
+  m4->decrRef();
+  //
+  f2->decrRef();
+  m2->decrRef();
+}
index dc4568624aea3984dc24a81b45c62d4515b41387..9a06753e0ac4a1451e575a9c98dcfb3f6ccdc775 100644 (file)
@@ -726,6 +726,46 @@ class MEDCouplingBasicsTest(unittest.TestCase):
         self.assertEqual(expected1,m3DIds);
         pass
 
+    def testExtrudedMesh4(self):
+        m1=MEDCouplingDataForTest.build2DTargetMesh_1();
+        cells=[2,4];
+        m1.convertToPolyTypes(cells);
+        m1.changeSpaceDimension(3);
+        m2=MEDCouplingDataForTest.buildCU1DMesh_U();
+        m2.changeSpaceDimension(3);
+        center=[0.,0.,0.]
+        vector=[0.,1.,0.]
+        m2.rotate(center,vector,-pi/2.);
+        m3=m1.buildExtrudedMeshFromThis(m2,0);
+        expected1=[1,3,2,0,6,5,7,10,11,8,12,9,14,13,4]
+        rexpected1=[3, 0, 2, 1, 14, 5, 4, 6, 9, 11, 7, 8, 10, 13, 12]
+        m3.renumberCells(expected1,False);
+        m4=MEDCouplingExtrudedMesh.New(m3,m1,0);
+        self.assertEqual(NORM_HEXA8,m4.getTypeOfCell(0));
+        self.assertEqual(NORM_HEXA8,m4.getTypeOfCell(1));
+        self.assertEqual(NORM_POLYHED,m4.getTypeOfCell(2));
+        self.assertEqual(NORM_PENTA6,m4.getTypeOfCell(7));
+        f=m4.getMeasureField(True);
+        arr=f.getArray();
+        self.assertEqual(15,arr.getNumberOfTuples());
+        self.assertEqual(1,arr.getNumberOfComponents());
+        arrPtr=arr.getValues();
+        expected2=[0.075,0.0375,0.0375,0.075,0.075,
+                   0.1125,0.05625,0.05625,0.1125,0.1125,
+                   0.0625,0.03125,0.03125,0.0625,0.0625]
+        for i in xrange(15):
+            self.assertAlmostEqual(expected2[rexpected1[i]],arrPtr[i],16);
+            pass
+        m5=m4.build3DUnstructuredMesh();
+        self.assertTrue(m5.isEqual(m3,1e-12));
+        f=m5.getMeasureField(True);
+        arr=f.getArray();
+        arrPtr=arr.getValues();
+        for i in xrange(15):
+            self.assertAlmostEqual(expected2[rexpected1[i]],arrPtr[i],1e-16);
+            pass
+        pass
+
     def testFindCommonNodes(self):
         targetMesh=MEDCouplingDataForTest.build3DTargetMesh_1();
         comm,commI=targetMesh.findCommonNodes(1e-10);
@@ -1767,6 +1807,71 @@ class MEDCouplingBasicsTest(unittest.TestCase):
         self.assertAlmostEqual(18.,f.getIJK(1,1,1),14);
         pass
 
+    def testCellOrientation1(self):
+        m=MEDCouplingDataForTest.build2DTargetMesh_1();
+        vec=[0.,0.,1.]
+        self.assertRaises(Exception,m.are2DCellsNotCorrectlyOriented,vec,False);
+        m.changeSpaceDimension(3);
+        res1=m.are2DCellsNotCorrectlyOriented(vec,False);
+        self.assertTrue(len(res1)==0);
+        vec[2]=-1.;
+        res1=m.are2DCellsNotCorrectlyOriented(vec,False);
+        self.assertEqual(5,len(res1));
+        #
+        vec[2]=1.;
+        # connectivity inversion
+        conn=m.getNodalConnectivity().getValues();
+        tmp=conn[11];
+        conn[11]=conn[12];
+        conn[12]=tmp;
+        m.getNodalConnectivity().setValues(conn,len(conn),1)
+        res1=m.are2DCellsNotCorrectlyOriented(vec,False);
+        self.assertEqual(1,len(res1));
+        self.assertEqual(2,res1[0]);
+        m.orientCorrectly2DCells(vec,False);
+        res1=m.are2DCellsNotCorrectlyOriented(vec,False);
+        self.assertTrue(len(res1)==0);
+        m2=MEDCouplingDataForTest.build2DTargetMesh_1();
+        m2.changeSpaceDimension(3);
+        self.assertTrue(m.isEqual(m2,1e-12));
+        pass
+
+    def testCellOrientation2(self):
+        m2,m1=MEDCouplingDataForTest.build3DExtrudedUMesh_1();
+        res1=m2.arePolyhedronsNotCorrectlyOriented();
+        self.assertEqual(6,len(res1));
+        m2.orientCorrectlyPolyhedrons();
+        res1=m2.arePolyhedronsNotCorrectlyOriented();
+        self.assertTrue(len(res1)==0);
+        m2.checkCoherency();
+        self.assertEqual(18,m2.getNumberOfCells());
+        cellIds2=[0,6,12]
+        m2.convertToPolyTypes(cellIds2);
+        m2.orientCorrectlyPolyhedrons();
+        res1=m2.arePolyhedronsNotCorrectlyOriented();
+        self.assertTrue(len(res1)==0);
+        f2=m2.getMeasureField(False);
+        f2Ptr=f2.getArray().getValues();
+        #Test to check global reverse in MEDCouplingUMesh::tryToCorrectPolyhedronOrientation
+        m3=MEDCouplingDataForTest.build2DTargetMesh_1();
+        vec=[0.,0.,-1.]
+        m3.changeSpaceDimension(3);
+        ids2=[0,1,2,3,4]
+        m3.convertToPolyTypes(ids2);
+        m3.orientCorrectly2DCells(vec,False);
+        m4=MEDCouplingDataForTest.buildCU1DMesh_U();
+        m4.changeSpaceDimension(3);
+        center=[0.,0.,0.]
+        vector=[0.,1.,0.]
+        m4.rotate(center,vector,-pi/2.);
+        m5=m3.buildExtrudedMeshFromThis(m4,0);
+        res1=m5.arePolyhedronsNotCorrectlyOriented();
+        self.assertEqual(15,len(res1));
+        m5.orientCorrectlyPolyhedrons();
+        res1=m5.arePolyhedronsNotCorrectlyOriented();
+        self.assertTrue(len(res1)==0);
+        pass
+
     def setUp(self):
         pass
     pass
index 8bba623ac222e1c8c3308afcdc868e4beca1c013..42397071b9921afb9a61ebcfe25d365205850382 100644 (file)
@@ -90,6 +90,7 @@ using namespace INTERP_KERNEL;
 %newobject ParaMEDMEM::MEDCouplingUMesh::rearrange2ConsecutiveCellTypes;
 %newobject ParaMEDMEM::MEDCouplingUMesh::convertCellArrayPerGeoType;
 %newobject ParaMEDMEM::MEDCouplingExtrudedMesh::New;
+%newobject ParaMEDMEM::MEDCouplingExtrudedMesh::build3DUnstructuredMesh;
 %newobject ParaMEDMEM::MEDCouplingCMesh::New;
 %feature("unref") DataArrayDouble "$this->decrRef();"
 %feature("unref") MEDCouplingPointSet "$this->decrRef();"
@@ -369,6 +370,7 @@ namespace ParaMEDMEM
     DataArrayInt *zipConnectivityTraducer(int compType);
     void getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const;
     MEDCouplingUMesh *buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const;
+    void orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception);
     %extend {
       int getCellContainingPoint(PyObject *p, double eps) const
       {
@@ -499,6 +501,47 @@ namespace ParaMEDMEM
         PyList_SetItem(ret,1,ret1);
         return ret;
       }
+
+      PyObject *are2DCellsNotCorrectlyOriented(PyObject *vec, bool polyOnly) const throw(INTERP_KERNEL::Exception)
+      {
+        std::vector<int> cells;
+        int sz;
+        double *v=convertPyToNewDblArr2(vec,&sz);
+        try
+          {
+            self->are2DCellsNotCorrectlyOriented(v,polyOnly,cells);
+          }
+        catch(INTERP_KERNEL::Exception& e)
+          {
+            delete [] v;
+            throw e;
+          }
+        delete [] v;
+        return convertIntArrToPyList2(cells);
+      }
+
+      void orientCorrectly2DCells(PyObject *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
+      {
+        int sz;
+        double *v=convertPyToNewDblArr2(vec,&sz);
+        try
+          {
+            self->orientCorrectly2DCells(v,polyOnly);
+          }
+        catch(INTERP_KERNEL::Exception& e)
+          {
+            delete [] v;
+            throw e;
+          }
+        delete [] v;
+      }
+      
+      PyObject *arePolyhedronsNotCorrectlyOriented() const throw(INTERP_KERNEL::Exception)
+      {
+        std::vector<int> cells;
+        self->arePolyhedronsNotCorrectlyOriented(cells);
+        return convertIntArrToPyList2(cells);
+      }
     }
     void convertToPolyTypes(const std::vector<int>& cellIdsToConvert);
     MEDCouplingUMesh *buildExtrudedMeshFromThis(const MEDCouplingUMesh *mesh1D, int policy);
@@ -509,6 +552,7 @@ namespace ParaMEDMEM
   {
   public:
     static MEDCouplingExtrudedMesh *New(const MEDCouplingUMesh *mesh3D, MEDCouplingUMesh *mesh2D, int cell2DId) throw(INTERP_KERNEL::Exception);
+    MEDCouplingUMesh *build3DUnstructuredMesh() const;
     %extend {
       PyObject *getMesh2D() const
       {