Salome HOME
Merge from V6_5_BR 05/06/2012
[modules/smesh.git] / src / StdMeshers / StdMeshers_Projection_1D2D.cxx
index 6053964286192d1c4198a7b0e5d7b08020b71582..efe6bf034819dd7a5c7a696f65812988343d9b55 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 
 using namespace std;
 
-//#define RETURN_BAD_RESULT(msg) { MESSAGE(")-: Error: " << msg); return false; }
+namespace
+{
+  // --------------------------------------------------------------------------------
+  /*!
+   * \brief an event listener updating submehses of EDGEs according to
+   *        events on the target FACE submesh
+   */
+  struct EventProparatorToEdges : public SMESH_subMeshEventListener
+  {
+    EventProparatorToEdges(): SMESH_subMeshEventListener(/*isDeletable=*/false,
+                                                         "Projection_1D2D::EventProparatorToEdges")
+    {}
+    static EventProparatorToEdges* Instance() { static EventProparatorToEdges E; return &E; }
+
+    static void Set(SMESH_subMesh* faceSubMesh)
+    {
+      SMESH_subMeshEventListenerData* edgeSubMeshes =
+        new SMESH_subMeshEventListenerData(/*isDeletable=*/true);
+      SMESH_Mesh* mesh = faceSubMesh->GetFather();
+      TopExp_Explorer eExp( faceSubMesh->GetSubShape(), TopAbs_EDGE );
+      for ( ; eExp.More(); eExp.Next() )
+        edgeSubMeshes->mySubMeshes.push_back( mesh->GetSubMesh( eExp.Current() ));
+
+      // set a listener
+      faceSubMesh->SetEventListener( Instance(), edgeSubMeshes, faceSubMesh );
+    }
+  };
+  // --------------------------------------------------------------------------------
+  /*!
+   * \brief Structure used to temporary remove EventProparatorToEdges from faceSubMesh
+   *  in order to prevent propagation of CLEAN event from FACE to EDGEs during 
+   *  StdMeshers_Projection_1D2D::Compute(). The CLEAN event is emmited by Pattern mapper
+   * and causes removal of faces generated on adjacent FACEs.
+   */
+  struct UnsetterOfEventProparatorToEdges
+  {
+    SMESH_subMesh* _faceSubMesh;
+    UnsetterOfEventProparatorToEdges( SMESH_subMesh* faceSubMesh ):_faceSubMesh(faceSubMesh)
+    {
+      faceSubMesh->DeleteEventListener( EventProparatorToEdges::Instance() );
+    }
+    ~UnsetterOfEventProparatorToEdges()
+    {
+      EventProparatorToEdges::Set(_faceSubMesh);
+    }
+  };
+}
 
 //=======================================================================
 //function : StdMeshers_Projection_1D2D
@@ -48,7 +94,8 @@ StdMeshers_Projection_1D2D::StdMeshers_Projection_1D2D(int hypId, int studyId, S
   :StdMeshers_Projection_2D(hypId, studyId, gen)
 {
   _name = "Projection_1D2D";
-  _requireDescretBoundary = false;
+  _requireDiscreteBoundary = false;
+  _supportSubmeshes = true;
 }
 
 //=======================================================================
@@ -58,6 +105,8 @@ StdMeshers_Projection_1D2D::StdMeshers_Projection_1D2D(int hypId, int studyId, S
 
 bool StdMeshers_Projection_1D2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theShape)
 {
+  UnsetterOfEventProparatorToEdges eventBarrier( theMesh.GetSubMesh( theShape ));
+
   if ( !StdMeshers_Projection_2D::Compute(theMesh, theShape))
     return false;
 
@@ -81,9 +130,20 @@ bool StdMeshers_Projection_1D2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape
   {
     vector<const SMDS_MeshNode*> nodes = wires[ iWire ]->GetOrderedNodes();
     if ( nodes.empty() )
-      return error("No nodes found on a wire");
+      return error("Wrong nodes on a wire");
 
-    const bool checkExisting = wires[ iWire ]->NbSegments();
+    // check that all nodes are shared by faces generated on F
+    for ( size_t i = 0; i < nodes.size(); ++i )
+    {
+      SMDS_ElemIteratorPtr fIt = nodes[i]->GetInverseElementIterator(SMDSAbs_Face);
+      bool faceFound = false;
+      while ( !faceFound && fIt->more() )
+        faceFound = ( helper.GetSubShapeID() == fIt->next()->getshapeId() );
+      if ( !faceFound )
+        return error("The existing 1D mesh mismatches the generated 2D mesh");
+    }
+
+    const bool checkExisting = ( wires[ iWire ]->NbSegments() || helper.HasSeam() );
 
     if ( _quadraticMesh )
     {
@@ -100,8 +160,8 @@ bool StdMeshers_Projection_1D2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape
       int edgeID = meshDS->ShapeToIndex( wires[ iWire ]->Edge(0) );
       for ( size_t i = 1; i < nodes.size(); ++i )
       {
-        if ( checkExisting && meshDS->FindEdge( nodes[i-1], nodes[i])
-             continue;
+        if ( checkExisting && meshDS->FindEdge( nodes[i-1], nodes[i]))
+          continue;
         SMDS_MeshElement* e = meshDS->AddEdge( nodes[i-1], nodes[i] );
         if ( nodes[i-1]->getshapeId() != edgeID &&
              nodes[i  ]->getshapeId() != edgeID )
@@ -136,7 +196,7 @@ bool StdMeshers_Projection_1D2D::Evaluate(SMESH_Mesh&         theMesh,
 
   typedef StdMeshers_ProjectionUtils SPU;
   SPU::TShapeShapeMap shape2ShapeMap;
-  SPU::InitVertexAssociation( _sourceHypo, shape2ShapeMap, theShape );
+  SPU::InitVertexAssociation( _sourceHypo, shape2ShapeMap );
   if ( !SPU::FindSubShapeAssociation( theShape, &theMesh, srcFace, srcMesh, shape2ShapeMap))
     return error(COMPERR_BAD_SHAPE,"Topology of source and target faces seems different" );
 
@@ -172,7 +232,7 @@ bool StdMeshers_Projection_1D2D::Evaluate(SMESH_Mesh&         theMesh,
         if ( aVec.empty() )
           return error(COMPERR_BAD_INPUT_MESH,"Source mesh is wrongly evaluated");
       }
-      TopoDS_Shape tgtEdge = shape2ShapeMap( srcSM->GetSubShape() );
+      TopoDS_Shape tgtEdge = shape2ShapeMap( srcSM->GetSubShape(), /*isSrc=*/true  );
       SMESH_subMesh* tgtSM = theMesh.GetSubMesh( tgtEdge );
       aResMap.insert(std::make_pair(tgtSM,aVec));
     }
@@ -185,32 +245,20 @@ bool StdMeshers_Projection_1D2D::Evaluate(SMESH_Mesh&         theMesh,
 //=======================================================================
 //function : SetEventListener
 //purpose  : Sets a default event listener to submesh of the source face.
-//           whenSetToFaceSubMesh - submesh where algo is set
+//           faceSubMesh - submesh where algo is set
 // After being set, event listener is notified on each event of a submesh.
 // This method is called when a submesh gets HYP_OK algo_state.
 // Arranges that CLEAN event is translated from source submesh to
-// the whenSetToFaceSubMesh submesh.
+// the faceSubMesh submesh.
 //=======================================================================
 
-void StdMeshers_Projection_1D2D::SetEventListener(SMESH_subMesh* whenSetToFaceSubMesh)
+void StdMeshers_Projection_1D2D::SetEventListener(SMESH_subMesh* faceSubMesh)
 {
   // set a listener of events on a source submesh
-  StdMeshers_Projection_2D::SetEventListener(whenSetToFaceSubMesh);
+  StdMeshers_Projection_2D::SetEventListener(faceSubMesh);
 
   // set a listener to the target FACE submesh in order to update submehses
   // of EDGEs according to events on the target FACE submesh
-
-  // fill a listener data with submeshes of EDGEs
-  SMESH_subMeshEventListenerData* data =
-    new SMESH_subMeshEventListenerData(/*isDeletable=*/true);
-  SMESH_Mesh* mesh = whenSetToFaceSubMesh->GetFather();
-  TopExp_Explorer eExp( whenSetToFaceSubMesh->GetSubShape(), TopAbs_EDGE );
-  for ( ; eExp.More(); eExp.Next() )
-    data->mySubMeshes.push_back( mesh->GetSubMesh( eExp.Current() ));
-
-  // set a listener
-  SMESH_subMeshEventListener* listener =
-    new SMESH_subMeshEventListener(/*isDeletable=*/true);
-  whenSetToFaceSubMesh->SetEventListener( listener, data, whenSetToFaceSubMesh );
+  EventProparatorToEdges::Set( faceSubMesh );
 }