]> SALOME platform Git repositories - modules/smesh.git/blobdiff - src/StdMeshers/StdMeshers_Projection_2D.cxx
Salome HOME
Improvement 0018239: Create subMesh menu item
[modules/smesh.git] / src / StdMeshers / StdMeshers_Projection_2D.cxx
index b7b3ff3e61004ecf2fc68d354e14ee3d2cb644c1..7f193fbf93f32f33010412a992f94c1dc7e4dae5 100644 (file)
 #include "SMESH_Pattern.hxx"
 #include "SMESH_subMesh.hxx"
 #include "SMESH_subMeshEventListener.hxx"
+#include "SMESH_Comment.hxx"
 #include "SMDS_EdgePosition.hxx"
 
 #include "utilities.h"
 
+#include <BRep_Tool.hxx>
+#include <Bnd_B2d.hxx>
 #include <TopExp.hxx>
-#include <TopoDS.hxx>
+#include <TopExp_Explorer.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
-#include <BRep_Tool.hxx>
-
+#include <TopoDS.hxx>
 
 
 using namespace std;
 
-#define RETURN_BAD_RESULT(msg) { MESSAGE(msg); return false; }
+#define RETURN_BAD_RESULT(msg) { MESSAGE(")-: Error: " << msg); return false; }
 
 typedef StdMeshers_ProjectionUtils TAssocTool;
 
@@ -143,13 +145,17 @@ bool StdMeshers_Projection_2D::CheckHypothesis(SMESH_Mesh&
         // target vertices
         edge = TAssocTool::GetEdgeByVertices
           ( tgtMesh, _sourceHypo->GetTargetVertex(1), _sourceHypo->GetTargetVertex(2) );
-        if ( edge.IsNull() ||
-             !TAssocTool::IsSubShape( edge, tgtMesh ) ||
-             !TAssocTool::IsSubShape( edge, theShape ))
+        if ( edge.IsNull() || !TAssocTool::IsSubShape( edge, tgtMesh ))
         {
           theStatus = HYP_BAD_PARAMETER;
           SCRUTE((edge.IsNull()));
           SCRUTE((TAssocTool::IsSubShape( edge, tgtMesh )));
+        }
+        // PAL16203
+        else if ( !_sourceHypo->IsCompoundSource() &&
+                  !TAssocTool::IsSubShape( edge, theShape ))
+        {
+          theStatus = HYP_BAD_PARAMETER;
           SCRUTE((TAssocTool::IsSubShape( edge, theShape )));
         }
       }
@@ -186,10 +192,8 @@ namespace {
   {
     // old nodes are shared by edges and new ones are shared
     // only by faces created by mapper
-    bool isOld = false;
-    SMDS_ElemIteratorPtr invElem = node->GetInverseElementIterator();
-    while ( !isOld && invElem->more() )
-      isOld = ( invElem->next()->GetType() == SMDSAbs_Edge );
+    SMDS_ElemIteratorPtr invEdge = node->GetInverseElementIterator(SMDSAbs_Edge);
+    bool isOld = invEdge->more();
     return isOld;
   }
 
@@ -207,12 +211,13 @@ namespace {
     MeshCleaner( SMESH_subMesh* faceSubMesh ): sm(faceSubMesh) {}
     ~MeshCleaner() { Clean(sm); }
     void Release() { sm = 0; } // mesh will not be removed
-    static void Clean( SMESH_subMesh* sm )
+    static void Clean( SMESH_subMesh* sm, bool withSub=true )
     {
       if ( !sm ) return;
-      switch ( sm->GetSubShape().ShapeType() ) {
-      case TopAbs_VERTEX:
-      case TopAbs_EDGE: {
+      // PAL16567, 18920. Remove face nodes as well
+//       switch ( sm->GetSubShape().ShapeType() ) {
+//       case TopAbs_VERTEX:
+//       case TopAbs_EDGE: {
         SMDS_NodeIteratorPtr nIt = sm->GetSubMeshDS()->GetNodes();
         SMESHDS_Mesh* mesh = sm->GetFather()->GetMeshDS();
         while ( nIt->more() ) {
@@ -221,13 +226,13 @@ namespace {
             mesh->RemoveNode( node );
         }
         // do not break but iterate over DependsOn()
-      }
-      default:
-        const map< int, SMESH_subMesh * >& subSM = sm->DependsOn();
-        map< int, SMESH_subMesh * >::const_iterator i_sm = subSM.begin();
-        for ( ; i_sm != subSM.end(); ++i_sm )
-          Clean( i_sm->second );
-      }
+//       }
+//       default:
+        if ( !withSub ) return;
+        SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(false,false);
+        while ( smIt->more() )
+          Clean( smIt->next(), false );
+//       }
     }
   };
 
@@ -290,16 +295,14 @@ namespace {
       // Find a new node connected to nV1 and belonging to edge submesh;
       const SMDS_MeshNode* nE = 0;
       SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
-      SMDS_ElemIteratorPtr vElems = nV1->GetInverseElementIterator();
+      SMDS_ElemIteratorPtr vElems = nV1->GetInverseElementIterator(SMDSAbs_Face);
       while ( vElems->more() && !nE ) {
         const SMDS_MeshElement* elem = vElems->next();
-        if ( elem->GetType() != SMDSAbs_Face )
-          continue; // new nodes are shared by faces
         int nbNodes = elem->NbNodes();
         if ( elem->IsQuadratic() )
           nbNodes /= 2;
         int iV1 = elem->GetNodeIndex( nV1 );
-        // try next aftre nV1
+        // try next after nV1
         int iE = SMESH_MesherHelper::WrapIndex( iV1 + 1, nbNodes );
         if ( smDS->Contains( elem->GetNode( iE ) ))
           nE = elem->GetNode( iE );
@@ -365,28 +368,28 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
   if ( !_sourceHypo )
     return false;
 
-  TopoDS_Face tgtFace = TopoDS::Face( theShape.Oriented(TopAbs_FORWARD));
-  TopoDS_Face srcFace = TopoDS::Face( _sourceHypo->GetSourceFace().Oriented(TopAbs_FORWARD));
-
-  SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh(); 
+  SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh();
   SMESH_Mesh * tgtMesh = & theMesh;
   if ( !srcMesh )
     srcMesh = tgtMesh;
 
   SMESHDS_Mesh * meshDS = theMesh.GetMeshDS();
 
-  SMESH_MesherHelper helper( theMesh );
-  helper.SetSubShape( tgtFace );
-
   // ---------------------------
   // Make subshapes association
   // ---------------------------
 
+  TopoDS_Face tgtFace = TopoDS::Face( theShape.Oriented(TopAbs_FORWARD));
+  TopoDS_Shape srcShape = _sourceHypo->GetSourceFace().Oriented(TopAbs_FORWARD);
+
   TAssocTool::TShapeShapeMap shape2ShapeMap;
-  TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap );
-  if ( !TAssocTool::FindSubShapeAssociation( tgtFace, tgtMesh, srcFace, srcMesh,
-                                             shape2ShapeMap) )
-    RETURN_BAD_RESULT("FindSubShapeAssociation failed");
+  TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap, tgtFace );
+  if ( !TAssocTool::FindSubShapeAssociation( tgtFace, tgtMesh, srcShape, srcMesh,
+                                             shape2ShapeMap)  ||
+       !shape2ShapeMap.IsBound( tgtFace ))
+    return error(COMPERR_BAD_SHAPE,"Topology of source and target faces seems different" );
+
+  TopoDS_Face srcFace = TopoDS::Face( shape2ShapeMap( tgtFace ).Oriented(TopAbs_FORWARD));
 
   // ----------------------------------------------
   // Assure that mesh on a source Face is computed
@@ -397,22 +400,41 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
 
   if ( tgtMesh == srcMesh ) {
     if ( !TAssocTool::MakeComputed( srcSubMesh ))
-      RETURN_BAD_RESULT("Impossible to compute the source mesh");
+      return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed");
   }
   else {
     if ( !srcSubMesh->IsMeshComputed() )
-      RETURN_BAD_RESULT("Source mesh is not computed");
+      return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed");
   }
 
   // --------------------
   // Prepare to mapping 
   // --------------------
 
+  SMESH_MesherHelper helper( theMesh );
+  helper.SetSubShape( tgtFace );
+
+  // Check if node projection to a face is needed
+  Bnd_B2d uvBox;
+  SMDS_ElemIteratorPtr faceIt = srcSubMesh->GetSubMeshDS()->GetElements();
+  for ( int nbN = 0; nbN < 3 && faceIt->more();  ) {
+    const SMDS_MeshElement* face = faceIt->next();
+    SMDS_ElemIteratorPtr nodeIt = face->nodesIterator();
+    while ( nodeIt->more() ) {
+      const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+      if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ) {
+        nbN++;
+        uvBox.Add( helper.GetNodeUV( srcFace, node ));
+      }
+    }
+  }
+  const bool toProjectNodes = ( uvBox.IsVoid() || uvBox.SquareExtent() < DBL_MIN );
+
   // Load pattern from the source face
   SMESH_Pattern mapper;
-  mapper.Load( srcMesh, srcFace );
+  mapper.Load( srcMesh, srcFace, toProjectNodes );
   if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
-    RETURN_BAD_RESULT("SMESH_Pattern::Load() failed");
+    return error(COMPERR_BAD_INPUT_MESH,"Can't load mesh pattern from the source face");
 
   // Find the first target vertex corresponding to first vertex of the <mapper>
   // and <theReverse> flag needed to call mapper.Apply()
@@ -438,12 +460,8 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
   if ( nbEdgesInWires.front() > 1 ) // possible to find out
   {
     TopoDS_Edge srcE1 = srcEdges.front(), tgtE1 = tgtEdges.front();
-    reverse = ( ! srcE1.IsSame( shape2ShapeMap( tgtE1 )));
-    if ( BRep_Tool::IsClosed( tgtE1, tgtFace )) {
-      reverse = ( srcE1.Orientation() == tgtE1.Orientation() );
-      if ( _sourceHypo->GetSourceFace().Orientation() != theShape.Orientation() )
-        reverse = !reverse;
-    }
+    TopoDS_Shape srcE1bis = shape2ShapeMap( tgtE1 );
+    reverse = ( ! srcE1.IsSame( srcE1bis ));
   }
   else if ( nbEdgesInWires.front() == 1 )
   {
@@ -463,14 +481,14 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
 
   mapper.Apply( tgtFace, tgtV1, reverse );
   if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
-    RETURN_BAD_RESULT("SMESH_Pattern::Apply() failed");
+    return error("Can't apply source mesh pattern to the face");
 
   // Create the mesh
 
   const bool toCreatePolygons = false, toCreatePolyedrs = false;
   mapper.MakeMesh( tgtMesh, toCreatePolygons, toCreatePolyedrs );
   if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
-    RETURN_BAD_RESULT("SMESH_Pattern::MakeMesh() failed");
+    return error("Can't make mesh by source mesh pattern");
 
   // it will remove mesh built by pattern mapper on edges and vertices
   // in failure case
@@ -487,18 +505,17 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
   // Make groups of nodes to merge
 
   // loop on edge and vertex submeshes of a target face
-  const map< int, SMESH_subMesh * >& subSM = tgtSubMesh->DependsOn();
-  map< int, SMESH_subMesh * >::const_iterator i_subSM = subSM.begin();
-  for ( ; i_subSM != subSM.end(); ++i_subSM )
+  SMESH_subMeshIteratorPtr smIt = tgtSubMesh->getDependsOnIterator(false,false);
+  while ( smIt->more() )
   {
-    SMESH_subMesh*     sm = i_subSM->second;
+    SMESH_subMesh*     sm = smIt->next();
     SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
 
     // Sort new and old nodes of a submesh separately
 
-    bool isSeam = helper.IsSeamShape( sm->GetId() );
+    bool isSeam = helper.IsRealSeam( sm->GetId() );
 
-    enum { NEW_NODES, OLD_NODES };
+    enum { NEW_NODES = 0, OLD_NODES };
     map< double, const SMDS_MeshNode* > u2nodesMaps[2], u2nodesOnSeam;
     map< double, const SMDS_MeshNode* >::iterator u_oldNode, u_newNode, u_newOnSeam, newEnd;
     set< const SMDS_MeshNode* > seamNodes;
@@ -518,8 +535,8 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
           continue; // node is already in the map
       }
 
-      // sort nodes on edges by its position
-      map< double, const SMDS_MeshNode* > & pos2nodes = u2nodesMaps[ isOld ];
+      // sort nodes on edges by their position
+      map< double, const SMDS_MeshNode* > & pos2nodes = u2nodesMaps[isOld ? OLD_NODES : NEW_NODES];
       switch ( node->GetPosition()->GetTypeOfPosition() )
       {
       case  SMDS_TOP_VERTEX: {
@@ -537,14 +554,23 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
                           node->GetPosition()->GetTypeOfPosition());
       }
     }
-    if ( u2nodesMaps[ OLD_NODES ].size() != u2nodesMaps[ NEW_NODES ].size() )
-      RETURN_BAD_RESULT("Different nb of old and new nodes " <<
+    if ( u2nodesMaps[ NEW_NODES ].size() != u2nodesMaps[ OLD_NODES ].size() )
+    {
+      if ( u2nodesMaps[ NEW_NODES ].size() == 0         &&
+           sm->GetSubShape().ShapeType() == TopAbs_EDGE &&
+           helper.IsDegenShape( sm->GetId() )             )
+        // NPAL15894 (tt88bis.py) - project mesh built by NETGEN_1d_2D that
+        // does not make segments/nodes on degenerated edges
+        continue;
+
+      RETURN_BAD_RESULT("Different nb of old and new nodes on shape #"<< sm->GetId() <<" "<<
                         u2nodesMaps[ OLD_NODES ].size() << " != " <<
                         u2nodesMaps[ NEW_NODES ].size());
-    if ( isSeam && u2nodesMaps[ OLD_NODES ].size() != u2nodesOnSeam.size() )
+    }
+    if ( isSeam && u2nodesMaps[ OLD_NODES ].size() != u2nodesOnSeam.size() ) {
       RETURN_BAD_RESULT("Different nb of old and seam nodes " <<
                         u2nodesMaps[ OLD_NODES ].size() << " != " << u2nodesOnSeam.size());
-
+    }
     // Make groups of nodes to merge
     u_oldNode = u2nodesMaps[ OLD_NODES ].begin(); 
     u_newNode = u2nodesMaps[ NEW_NODES ].begin();
@@ -561,7 +587,11 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
 
   // Merge
 
+  int nbFaceBeforeMerge = tgtSubMesh->GetSubMeshDS()->NbElements();
   editor.MergeNodes( groupsOfNodes );
+  int nbFaceAtferMerge = tgtSubMesh->GetSubMeshDS()->NbElements();
+  if ( nbFaceBeforeMerge != nbFaceAtferMerge )
+    return error(COMPERR_BAD_INPUT_MESH, "Probably invalid node parameters on geom faces");
 
   // ---------------------------
   // Check elements orientation
@@ -626,17 +656,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
 
 void StdMeshers_Projection_2D::SetEventListener(SMESH_subMesh* subMesh)
 {
-  if ( _sourceHypo && ! _sourceHypo->GetSourceFace().IsNull() )
-  {
-    SMESH_Mesh* srcMesh = _sourceHypo->GetSourceMesh();
-    if ( !srcMesh )
-      srcMesh = subMesh->GetFather();
-
-    SMESH_subMesh* srcFaceSM =
-      srcMesh->GetSubMesh( _sourceHypo->GetSourceFace() );
-
-    subMesh->SetEventListener( new SMESH_subMeshEventListener(true),
-                               SMESH_subMeshEventListenerData::MakeData( subMesh ),
-                               srcFaceSM );
-  }
+  TAssocTool::SetEventListener( subMesh,
+                                _sourceHypo->GetSourceFace(),
+                                _sourceHypo->GetSourceMesh() );
 }