Salome HOME
22612: [CEA 1189] sauv2med should not change faces orientation
[tools/medcoupling.git] / src / MEDLoader / SauvMedConvertor.cxx
index 8578ffb7a8e755379cfcc4a8b41f6942aa15b988..a8fb6db55e41d3a29d97ffa8d72c7f047a9b6a9a 100644 (file)
@@ -1,9 +1,9 @@
-// Copyright (C) 2007-2013  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2014  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 // License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -2302,15 +2302,85 @@ void IntermediateMED::checkDataAvailability() const
     THROW_IK_EXCEPTION("Nodes and coordinates mismatch");
 }
 
+//================================================================================
+/*!
+ * \brief Safely adds a new Group
+ */
+//================================================================================
+
+Group* IntermediateMED::addNewGroup(std::vector<SauvUtilities::Group*>* groupsToFix)
+{
+  if ( _groups.size() == _groups.capacity() ) // re-allocation would occure
+    {
+      std::vector<Group> newGroups( _groups.size() );
+      newGroups.push_back( Group() );
+
+      for ( size_t i = 0; i < _groups.size(); ++i )
+        {
+          // avoid copying _cells
+          std::vector<const Cell*> cells;
+          cells.swap( _groups[i]._cells );
+          newGroups[i] = _groups[i];
+          newGroups[i]._cells.swap( cells );
+
+          // correct pointers to sub-groups
+          for ( size_t j = 0; j < _groups[i]._groups.size(); ++j )
+            {
+              int iG = _groups[i]._groups[j] - &_groups[0];
+              newGroups[i]._groups[j] = & newGroups[ iG ];
+            }
+        }
+
+      // fix given groups
+      if ( groupsToFix )
+        for ( size_t i = 0; i < groupsToFix->size(); ++i )
+          if ( (*groupsToFix)[i] )
+            {
+              int iG = (*groupsToFix)[i] - &_groups[0];
+              (*groupsToFix)[i] = & newGroups[ iG ];
+            }
+
+      // fix field supports
+      for ( int isNode = 0; isNode < 2; ++isNode )
+        {
+          std::vector<DoubleField* >& fields = isNode ? _nodeFields : _cellFields;
+          for ( size_t i = 0; i < fields.size(); ++i )
+            {
+              if ( !fields[i] ) continue;
+              for ( size_t j = 0; j < fields[i]->_sub.size(); ++j )
+                if ( fields[i]->_sub[j]._support )
+                  {
+                    int iG = fields[i]->_sub[j]._support - &_groups[0];
+                    fields[i]->_sub[j]._support = & newGroups[ iG ];
+                  }
+              if ( fields[i]->_group )
+                {
+                  int iG = fields[i]->_group - &_groups[0];
+                  fields[i]->_group = & newGroups[ iG ];
+                }
+            }
+        }
+
+      _groups.swap( newGroups );
+    }
+  else
+    {
+      _groups.push_back( Group() );
+    }
+  return &_groups.back();
+}
+
 //================================================================================
 /*!
  * \brief Makes ParaMEDMEM::MEDFileData from self
+ *  \param [in] fix2DOri - to fix or not orientation of faces in 3D space
+ *  \return ParaMEDMEM::MEDFileData* - conversion result
  */
 //================================================================================
 
-ParaMEDMEM::MEDFileData* IntermediateMED::convertInMEDFileDS()
+ParaMEDMEM::MEDFileData* IntermediateMED::convertInMEDFileDS(bool fix2DOri)
 {
-  MEDCouplingAutoRefCountObjectPtr< MEDFileUMesh >  mesh   = makeMEDFileMesh();
+  MEDCouplingAutoRefCountObjectPtr< MEDFileUMesh >  mesh   = makeMEDFileMesh(fix2DOri);
   MEDCouplingAutoRefCountObjectPtr< MEDFileFields > fields = makeMEDFileFields(mesh);
 
   MEDCouplingAutoRefCountObjectPtr< MEDFileMeshes > meshes = MEDFileMeshes::New();
@@ -2328,7 +2398,7 @@ ParaMEDMEM::MEDFileData* IntermediateMED::convertInMEDFileDS()
  */
 //================================================================================
 
-ParaMEDMEM::MEDFileUMesh* IntermediateMED::makeMEDFileMesh()
+ParaMEDMEM::MEDFileUMesh* IntermediateMED::makeMEDFileMesh(bool fix2DOri)
 {
   // check if all needed piles are present
   checkDataAvailability();
@@ -2340,7 +2410,7 @@ ParaMEDMEM::MEDFileUMesh* IntermediateMED::makeMEDFileMesh()
   if ( _spaceDim == 2 || _spaceDim == 1 )
     orientElements2D();
   else if ( _spaceDim == 3 )
-    orientElements3D();
+    orientElements3D( fix2DOri );
 
   // process groups
   decreaseHierarchicalDepthOfSubgroups();
@@ -2660,10 +2730,11 @@ void IntermediateMED::orientElements2D()
  */
 //================================================================================
 
-void IntermediateMED::orientElements3D()
+void IntermediateMED::orientElements3D(bool fix2DOri)
 {
   // set _reverse flags of faces
-  orientFaces3D();
+  if ( fix2DOri )
+    orientFaces3D();
 
   // -----------------
   // fix connectivity
@@ -3170,10 +3241,10 @@ void IntermediateMED::setGroups( ParaMEDMEM::MEDFileUMesh* mesh )
           grp._medGroup = DataArrayInt::New();
           grp._medGroup->setName( grp._name.c_str() );
           grp._medGroup->alloc( cell2order.size(), /*nbOfCompo=*/1 );
-          int * idsPrt = grp._medGroup->getPointer();
+          int * idsPtr = grp._medGroup->getPointer();
           TCellToOrderMap::iterator cell2orderIt, cell2orderEnd = cell2order.end();
           for ( cell2orderIt = cell2order.begin(); cell2orderIt != cell2orderEnd; ++cell2orderIt )
-            *idsPrt++ = (*cell2orderIt).first->_number - 1;
+            *idsPtr++ = (*cell2orderIt).first->_number - 1;
 
           // try to set the mesh name
           if ( !isMeshNameSet &&
@@ -3217,16 +3288,17 @@ bool IntermediateMED::isOnAll( const Group* grp, int & dimRel ) const
   int dim = getDim( grp );
 
   int nbElems = 0;
-  CellsByDimIterator dimCells( *this, dim );
-  while ( const std::set<Cell > * cells = dimCells.nextType() )
-    nbElems += cells->size();
-
-  const bool onAll = ( nbElems == grp->size() );
-
   if ( dim == 0 )
-    dimRel = 0;
+    {
+      nbElems = _nbNodes;
+      dimRel  = 0;
+    }
   else
     {
+      CellsByDimIterator dimCells( *this, dim );
+      while ( const std::set<Cell > * cells = dimCells.nextType() )
+        nbElems += cells->size();
+
       int meshDim = 3;
       for ( ; meshDim > 0; --meshDim )
         {
@@ -3236,6 +3308,8 @@ bool IntermediateMED::isOnAll( const Group* grp, int & dimRel ) const
         }
       dimRel = dim - meshDim;
     }
+
+  bool onAll = ( nbElems == grp->size() );
   return onAll;
 }
 
@@ -3274,7 +3348,7 @@ void IntermediateMED::setFields( SauvUtilities::DoubleField* fld,
                                  ParaMEDMEM::MEDFileFields*  medFields,
                                  ParaMEDMEM::MEDFileUMesh*   mesh,
                                  const TID                   castemID,
-                                 std::set< std::string >&              usedFieldNames)
+                                 std::set< std::string >&    usedFieldNames)
 {
   bool sameNbGauss = true;
   if ( !fld || !fld->isMedCompatible( sameNbGauss )) return;
@@ -3364,7 +3438,7 @@ void IntermediateMED::setTS( SauvUtilities::DoubleField*  fld,
       DataArrayDouble * coo = mesh->getCoords();
       MEDCouplingAutoRefCountObjectPtr
         <DataArrayDouble> subCoo = coo->selectByTupleId(support->_medGroup->begin(),
-                                                        support->_medGroup->end()); 
+                                                        support->_medGroup->end());
       MEDCouplingAutoRefCountObjectPtr< MEDCouplingUMesh > nodeSubMesh =
         MEDCouplingUMesh::Build0DMeshFromCoords( subCoo );
       timeStamp->setMesh( nodeSubMesh );
@@ -3386,8 +3460,9 @@ void IntermediateMED::setTS( SauvUtilities::DoubleField*  fld,
   // set gauss points
   if ( timeStamp->getTypeOfField() == ParaMEDMEM::ON_GAUSS_PT )
     {
-      TGaussDef gaussDef( support->_cellType, fld->_sub[iSub].nbGauss() );
-      timeStamp->setGaussLocalizationOnType( support->_cellType,
+      TGaussDef gaussDef( fld->_sub[iSub]._support->_cellType,
+                          fld->_sub[iSub].nbGauss() );
+      timeStamp->setGaussLocalizationOnType( fld->_sub[iSub]._support->_cellType,
                                              gaussDef.myRefCoords,
                                              gaussDef.myCoords,
                                              gaussDef.myWeights );