Salome HOME
Join modifications from branch BR_DEBUG_3_2_0b1
[plugins/netgenplugin.git] / src / NETGENPlugin / NETGENPlugin_NETGEN_3D.cxx
index 281e08ee530d762aedaf40059803cc10f018db49..c9031d88c7a75a0af4b065a186f241e37b9bb90b 100644 (file)
@@ -1,3 +1,22 @@
+// Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS, L3S, LJLL, MENSI
+//
+// 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.
+//
+// This library is distributed in the hope that it will be useful
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
 //=============================================================================
 // File      : NETGENPlugin_NETGEN_3D.cxx
 //             Moved here from SMESH_NETGEN_3D.cxx
@@ -17,8 +36,12 @@ using namespace std;
 #include "SMESHDS_Mesh.hxx"
 #include "SMDS_MeshElement.hxx"
 #include "SMDS_MeshNode.hxx"
+#include "SMESH_MesherHelper.hxx"
 
+#include <BRep_Tool.hxx>
 #include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
 
 #include "utilities.h"
 
@@ -30,7 +53,10 @@ using namespace std;
   Netgen include files
 */
 
-#include "nglib.h"
+namespace nglib {
+#include <nglib.h>
+}
+using namespace nglib;
 
 //=============================================================================
 /*!
@@ -44,9 +70,7 @@ NETGENPlugin_NETGEN_3D::NETGENPlugin_NETGEN_3D(int hypId, int studyId,
 {
   MESSAGE("NETGENPlugin_NETGEN_3D::NETGENPlugin_NETGEN_3D");
   _name = "NETGEN_3D";
-//   _shapeType = TopAbs_SOLID;
   _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
-//   MESSAGE("_shapeType octal " << oct << _shapeType);
   _compatibleHypothesis.push_back("MaxElementVolume");
 
   _maxElementVolume = 0.;
@@ -79,6 +103,7 @@ bool NETGENPlugin_NETGEN_3D::CheckHypothesis
   MESSAGE("NETGENPlugin_NETGEN_3D::CheckHypothesis");
 
   _hypMaxElementVolume = NULL;
+  _maxElementVolume = DBL_MAX;
 
   list<const SMESHDS_Hypothesis*>::const_iterator itl;
   const SMESHDS_Hypothesis* theHyp;
@@ -87,8 +112,9 @@ bool NETGENPlugin_NETGEN_3D::CheckHypothesis
   int nbHyp = hyps.size();
   if (!nbHyp)
   {
-    aStatus = SMESH_Hypothesis::HYP_MISSING;
-    return false;  // can't work with no hypothesis
+    aStatus = SMESH_Hypothesis::HYP_OK;
+    //aStatus = SMESH_Hypothesis::HYP_MISSING;
+    return true;  // can work with no hypothesis
   }
 
   itl = hyps.begin();
@@ -125,34 +151,46 @@ bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
 
   SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
 
+  const int invalid_ID = -1;
+
+  SMESH::Controls::Area areaControl;
+  SMESH::Controls::TSequenceOfXYZ nodesCoords;
+
   // -------------------------------------------------------------------
   // get triangles on aShell and make a map of nodes to Netgen node IDs
   // -------------------------------------------------------------------
 
+  SMESH_MesherHelper* myTool = new SMESH_MesherHelper(aMesh);
+  bool _quadraticMesh = myTool->IsQuadraticSubMesh(aShape);
+
   typedef map< const SMDS_MeshNode*, int> TNodeToIDMap;
   TNodeToIDMap nodeToNetgenID;
   list< const SMDS_MeshElement* > triangles;
   list< bool >                    isReversed; // orientation of triangles
 
-  SMESH::Controls::Area areaControl;
-  SMESH::Controls::TSequenceOfXYZ nodesCoords;
+  // for the degeneraged edge: ignore all but one node on it;
+  // map storing ids of degen edges and vertices and their netgen id:
+  map< int, int* > degenShapeIdToPtrNgId;
+  map< int, int* >::iterator shId_ngId;
+  list< int > degenNgIds;
 
   for (TopExp_Explorer exp(aShape,TopAbs_FACE);exp.More();exp.Next())
   {
-    TopoDS_Shape aShapeFace = exp.Current();
-    int faceID = meshDS->ShapeToIndex( aShapeFace );
-    TopoDS_Shape aMeshedFace = meshDS->IndexToShape( faceID );
-    const SMESHDS_SubMesh * aSubMeshDSFace = meshDS->MeshElements( faceID );
+    const TopoDS_Shape& aShapeFace = exp.Current();
+    const SMESHDS_SubMesh * aSubMeshDSFace = meshDS->MeshElements( aShapeFace );
     if ( aSubMeshDSFace )
     {
-      bool isRev = ( aShapeFace.Orientation() != aMeshedFace.Orientation() );
+      bool isRev = SMESH_Algo::IsReversedSubMesh( TopoDS::Face(aShapeFace), meshDS );
+
       SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements();
       while ( iteratorElem->more() ) // loop on elements on a face
       {
         // check element
         const SMDS_MeshElement* elem = iteratorElem->next();
-        if ( !elem || elem->NbNodes() != 3 ) {
+        if ( !elem ||
+             !( elem->NbNodes()==3 || ( _quadraticMesh && elem->NbNodes()==6) ) ) {
           INFOS( "NETGENPlugin_NETGEN_3D::Compute(), bad mesh");
+          delete myTool; myTool = 0;
           return false;
         }
         // keep a triangle
@@ -163,7 +201,9 @@ bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
         while ( triangleNodesIt->more() ) {
          const SMDS_MeshNode * node =
             static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
-          nodeToNetgenID.insert( make_pair( node, 0 ));
+          if(myTool->IsMedium(node))
+            continue;
+          nodeToNetgenID.insert( make_pair( node, invalid_ID ));
         }
 #ifdef _DEBUG_
         // check if a trainge is degenerated
@@ -174,13 +214,29 @@ bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
         }
 #endif
       }
+      // look for degeneraged edges and vetices
+      for (TopExp_Explorer expE(aShapeFace,TopAbs_EDGE);expE.More();expE.Next())
+      {
+        TopoDS_Edge aShapeEdge = TopoDS::Edge( expE.Current() );
+        if ( BRep_Tool::Degenerated( aShapeEdge ))
+        {
+          degenNgIds.push_back( invalid_ID );
+          int* ptrIdOnEdge = & degenNgIds.back();
+          // remember edge id
+          int edgeID = meshDS->ShapeToIndex( aShapeEdge );
+          degenShapeIdToPtrNgId.insert( make_pair( edgeID, ptrIdOnEdge ));
+          // remember vertex id
+          int vertexID = meshDS->ShapeToIndex( TopExp::FirstVertex( aShapeEdge ));
+          degenShapeIdToPtrNgId.insert( make_pair( vertexID, ptrIdOnEdge ));
+        }
+      }
     }
   }
   // ---------------------------------
   // Feed the Netgen with surface mesh
   // ---------------------------------
 
-  int Netgen_NbOfNodes = nodeToNetgenID.size();
+  int Netgen_NbOfNodes = 0;
   int Netgen_param2ndOrder = 0;
   double Netgen_paramFine = 1.;
   double Netgen_paramSize = _maxElementVolume;
@@ -194,16 +250,32 @@ bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
   Ng_Mesh * Netgen_mesh = Ng_NewMesh();
 
   // set nodes and remember thier netgen IDs
+  bool isDegen = false, hasDegen = !degenShapeIdToPtrNgId.empty();
   TNodeToIDMap::iterator n_id = nodeToNetgenID.begin();
-  for ( int id = 0; n_id != nodeToNetgenID.end(); ++n_id )
+  for ( ; n_id != nodeToNetgenID.end(); ++n_id )
   {
     const SMDS_MeshNode* node = n_id->first;
+
+    // ignore nodes on degenerated edge
+    if ( hasDegen ) {
+      int shapeId = node->GetPosition()->GetShapeId();
+      shId_ngId = degenShapeIdToPtrNgId.find( shapeId );
+      isDegen = ( shId_ngId != degenShapeIdToPtrNgId.end() );
+      if ( isDegen && *(shId_ngId->second) != invalid_ID ) {
+        n_id->second = *(shId_ngId->second);
+        continue;
+      }
+    }
     Netgen_point [ 0 ] = node->X();
     Netgen_point [ 1 ] = node->Y();
     Netgen_point [ 2 ] = node->Z();
-    n_id->second = ++id;
     Ng_AddPoint(Netgen_mesh, Netgen_point);
+    n_id->second = ++Netgen_NbOfNodes; // set netgen ID
+
+    if ( isDegen ) // all nodes on a degen edge get one netgen ID
+      *(shId_ngId->second) = n_id->second;
   }
+
   // set triangles
   list< const SMDS_MeshElement* >::iterator tria = triangles.begin();
   list< bool >::iterator                 reverse = isReversed.begin();
@@ -214,10 +286,17 @@ bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
     while ( triangleNodesIt->more() ) {
       const SMDS_MeshNode * node =
         static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
+      if(myTool->IsMedium(node))
+        continue;
       Netgen_triangle[ *reverse ? 2 - i : i ] = nodeToNetgenID[ node ];
       ++i;
     }
-    Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle);
+    if ( !hasDegen ||
+         // ignore degenerated triangles, they have 2 or 3 same ids
+         (Netgen_triangle[0] != Netgen_triangle[1] &&
+          Netgen_triangle[0] != Netgen_triangle[2] &&
+          Netgen_triangle[2] != Netgen_triangle[1] ))
+      Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle);
   }
 
   // -------------------------
@@ -234,7 +313,8 @@ bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
 
   try {
     status = Ng_GenerateVolumeMesh(Netgen_mesh, &Netgen_param);
-  } catch (...) {
+  }
+  catch (...) {
     MESSAGE("An exception has been caught during the Volume Mesh Generation ...");
     status = NG_VOLUME_FAILURE;
   }
@@ -257,8 +337,9 @@ bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
     // vector of nodes in which node index == netgen ID
     vector< const SMDS_MeshNode* > nodeVec ( Netgen_NbOfNodesNew + 1 );
     // insert old nodes into nodeVec
-    for ( n_id = nodeToNetgenID.begin(); n_id != nodeToNetgenID.end(); ++n_id )
-      nodeVec[ n_id->second ] = n_id->first;
+    for ( n_id = nodeToNetgenID.begin(); n_id != nodeToNetgenID.end(); ++n_id ) {
+      nodeVec.at( n_id->second ) = n_id->first;
+    }
     // create and insert new nodes into nodeVec
     int nodeIndex = Netgen_NbOfNodes + 1;
     int shapeID = meshDS->ShapeToIndex( aShape );
@@ -269,17 +350,17 @@ bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
                                              Netgen_point[1],
                                              Netgen_point[2]);
       meshDS->SetNodeInVolume(node, shapeID);
-      nodeVec[nodeIndex] = node;
+      nodeVec.at(nodeIndex) = node;
     }
 
     // create tetrahedrons
     for ( int elemIndex = 1; elemIndex <= Netgen_NbOfTetra; ++elemIndex )
     {
       Ng_GetVolumeElement(Netgen_mesh, elemIndex, Netgen_tetrahedron);
-      SMDS_MeshVolume * elt = meshDS->AddVolume (nodeVec[ Netgen_tetrahedron[0] ],
-                                                 nodeVec[ Netgen_tetrahedron[1] ],
-                                                 nodeVec[ Netgen_tetrahedron[2] ],
-                                                 nodeVec[ Netgen_tetrahedron[3] ]);
+      SMDS_MeshVolume * elt = myTool->AddVolume (nodeVec.at( Netgen_tetrahedron[0] ),
+                                                 nodeVec.at( Netgen_tetrahedron[1] ),
+                                                 nodeVec.at( Netgen_tetrahedron[2] ),
+                                                 nodeVec.at( Netgen_tetrahedron[3] ));
       meshDS->SetMeshElementOnShape(elt, shapeID );
     }
   }
@@ -287,6 +368,8 @@ bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
   Ng_DeleteMesh(Netgen_mesh);
   Ng_Exit();
 
+  delete myTool; myTool = 0;
+
   return isOK;
 }