Salome HOME
IPAL52444: Viscous Layers and Projection fail
authoreap <eap@opencascade.com>
Mon, 7 Jul 2014 15:41:18 +0000 (19:41 +0400)
committereap <eap@opencascade.com>
Mon, 7 Jul 2014 15:41:18 +0000 (19:41 +0400)
src/SMESH/SMESH_Algo.cxx
src/SMESH/SMESH_Pattern.cxx
src/SMESH/SMESH_Pattern.hxx
src/SMESHGUI/SMESHGUI_ComputeDlg.cxx
src/SMESHUtils/SMESH_Block.cxx
src/StdMeshers/StdMeshers_ProjectionUtils.cxx
src/StdMeshers/StdMeshers_Projection_2D.cxx
src/StdMeshers/StdMeshers_ViscousLayers.cxx

index 8f071e7..95c81e4 100644 (file)
@@ -410,7 +410,7 @@ bool SMESH_Algo::GetSortedNodesOnEdge(const SMESHDS_Mesh*                   theM
     return false;
 
   SMESHDS_SubMesh * eSubMesh = theMesh->MeshElements( theEdge );
-  if ( !eSubMesh || ( eSubMesh->NbElements()==0 && eSubMesh->NbNodes() == 0))
+  if ( !eSubMesh || ( /*eSubMesh->NbElements()==0 && */ eSubMesh->NbNodes() == 0))
     return false; // edge is not meshed
 
   int nbNodes = 0;
index 0ae3591..75d2624 100644 (file)
@@ -86,20 +86,15 @@ typedef map< const SMDS_MeshElement*, int > TNodePointIDMap;
 
 #define smdsNode( elem ) static_cast<const SMDS_MeshNode*>( elem )
 
-//=======================================================================
-//function : SMESH_Pattern
-//purpose  : 
-//=======================================================================
-
-SMESH_Pattern::SMESH_Pattern ()
+namespace
 {
-}
+  
 //=======================================================================
 //function : getInt
 //purpose  : 
 //=======================================================================
 
-static inline int getInt( const char * theSring )
+inline int getInt( const char * theSring )
 {
   if ( *theSring < '0' || *theSring > '9' )
     return -1;
@@ -119,7 +114,7 @@ static inline int getInt( const char * theSring )
 //purpose  : 
 //=======================================================================
 
-static inline double getDouble( const char * theSring )
+inline double getDouble( const char * theSring )
 {
   char *ptr;
   return strtod( theSring, &ptr );
@@ -131,9 +126,9 @@ static inline double getDouble( const char * theSring )
 //           Return the number of the found tokens
 //=======================================================================
 
-static int readLine (list <const char*> & theFields,
-                     const char*        & theLineBeg,
-                     const bool           theClearFields )
+int readLine (list <const char*> & theFields,
+              const char*        & theLineBeg,
+              const bool           theClearFields )
 {
   if ( theClearFields )
     theFields.clear();
@@ -207,6 +202,65 @@ static int readLine (list <const char*> & theFields,
 }
 
 //=======================================================================
+//function : isRealSeam
+//purpose  : return true if an EDGE encounters twice in a FACE
+//=======================================================================
+
+// bool isRealSeam( const TopoDS_Edge& e, const TopoDS_Face& f )
+// {
+//   if ( BRep_Tool::IsClosed( e, f ))
+//   {
+//     int nb = 0;
+//     for (TopExp_Explorer exp( f, TopAbs_EDGE ); exp.More(); exp.Next())
+//       if ( exp.Current().IsSame( e ))
+//         if ( ++nb == 2 )
+//           return true;
+//   }
+//   return false;
+// }
+
+//=======================================================================
+//function : loadVE
+//purpose  : load VERTEXes and EDGEs in a map. Return nb loaded VERTEXes
+//=======================================================================
+
+int loadVE( const list< TopoDS_Edge > &          eList,
+            TopTools_IndexedMapOfOrientedShape & map )
+{
+  list< TopoDS_Edge >::const_iterator eIt = eList.begin();
+  // vertices
+  int nbV;
+  for ( eIt = eList.begin(); eIt != eList.end(); eIt++ )
+  {
+    nbV = map.Extent();
+    map.Add( TopExp::FirstVertex( *eIt, true ));
+    bool added = ( nbV < map.Extent() );
+    if ( !added ) { // vertex encountered twice
+      // a seam vertex have two corresponding key points
+      map.Add( TopExp::FirstVertex( *eIt, true ).Reversed());
+    }
+  }
+  nbV = map.Extent();
+
+  // edges
+  for ( eIt = eList.begin(); eIt != eList.end(); eIt++ )
+    map.Add( *eIt );
+
+  return nbV;
+}
+
+} // namespace
+
+//=======================================================================
+//function : SMESH_Pattern
+//purpose  :
+//=======================================================================
+
+SMESH_Pattern::SMESH_Pattern ()
+{
+}
+
+//=======================================================================
 //function : Load
 //purpose  : Load a pattern from <theFile>
 //=======================================================================
@@ -647,31 +701,34 @@ bool SMESH_Pattern::Load (SMESH_Mesh*        theMesh,
 
     // Load shapes in the consequent order and count nb of points
 
-    // vertices
-    for ( elIt = eList.begin(); elIt != eList.end(); elIt++ ) {
-      int nbV = myShapeIDMap.Extent();
-      myShapeIDMap.Add( TopExp::FirstVertex( *elIt, true ));
-      bool added = ( nbV < myShapeIDMap.Extent() );
-      if ( !added ) { // vertex encountered twice
-        // a seam vertex have two corresponding key points
-        myShapeIDMap.Add( TopExp::FirstVertex( *elIt, true ).Reversed());
-        ++nbNodes;
-      }
+    loadVE( eList, myShapeIDMap );
+    myShapeIDMap.Add( face );
+
+    nbNodes += myShapeIDMap.Extent() - 1;
+
+    for ( elIt = eList.begin(); elIt != eList.end(); elIt++ )
       if ( SMESHDS_SubMesh * eSubMesh = aMeshDS->MeshElements( *elIt ))
         nbNodes += eSubMesh->NbNodes() + 1;
-    }
-    // edges
-    for ( elIt = eList.begin(); elIt != eList.end(); elIt++ )
-      myShapeIDMap.Add( *elIt );
-    // the face
-    myShapeIDMap.Add( face );
 
     myPoints.resize( nbNodes );
 
     // Load U of points on edges
 
-    for ( elIt = eList.begin(); elIt != eList.end(); elIt++ )
+    list<int>::iterator nbEinW = myNbKeyPntInBoundary.begin();
+    int iE = 0;
+    vector< TopoDS_Edge > eVec;
+    for ( elIt = eList.begin(); elIt != eList.end(); elIt++, iE++ )
     {
+      if ( isClosed && ( iE == 0 || iE == *nbEinW ))
+      {
+        // new wire begins; put EDGEs in eVec
+        list<TopoDS_Edge>::iterator eEnd = elIt;
+        std::advance( eEnd, *nbEinW );
+        eVec.assign( elIt, eEnd );
+        if ( iE > 0 )
+          ++nbEinW;
+        iE = 0;
+      }
       TopoDS_Edge & edge = *elIt;
       list< TPoint* > & ePoints = getShapePoints( edge );
       double f, l;
@@ -698,13 +755,8 @@ bool SMESH_Pattern::Load (SMESH_Mesh*        theMesh,
             TopoDS_Shape & v = is2 ? v2 : v1;
             if ( helper.IsRealSeam( v ) ) {
               // reverse or not depending on orientation of adjacent seam
-              TopoDS_Edge seam;
-              list<TopoDS_Edge>::iterator eIt2 = elIt;
-              if ( is2 )
-                seam = ( ++eIt2 == eList.end() ? eList.front() : *eIt2 );
-              else
-                seam = ( eIt2 == eList.begin() ? eList.back() : *(--eIt2) );
-              if ( seam.Orientation() == TopAbs_REVERSED )
+              int iSeam = helper.WrapIndex( iE + ( is2 ? +1 : -1 ), eVec.size() );
+              if ( eVec[ iSeam ].Orientation() == TopAbs_REVERSED )
                 v.Reverse();
             }
           }
@@ -999,6 +1051,7 @@ void SMESH_Pattern::computeUVOnEdge (const TopoDS_Edge&      theEdge,
     BRep_Tool::CurveOnSurface( theEdge, TopoDS::Face( myShape ), f, l );
 
   ePoints.back()->myInitU = 1.0;
+  //ePoints.front()->myInitU = 0.0; //myUV = C2d->Value( isForward ? f : l ).XY();
   list< TPoint* >::const_iterator pIt = ePoints.begin();
   for ( pIt++; pIt != ePoints.end(); pIt++ )
   {
@@ -2387,33 +2440,7 @@ bool SMESH_Pattern::Apply (const TopoDS_Face&   theFace,
   }
 
   // here shapes get IDs, for the outer wire IDs are OK
-  list<TopoDS_Edge>::iterator elIt = eList.begin();
-  for ( ; elIt != eList.end(); elIt++ ) {
-    myShapeIDMap.Add( TopExp::FirstVertex( *elIt, true ));
-    bool isClosed1 = BRep_Tool::IsClosed( *elIt, theFace );
-    // BEGIN: jfa for bug 0019943
-    if (isClosed1) {
-      isClosed1 = false;
-      for (TopExp_Explorer expw (theFace, TopAbs_WIRE); expw.More() && !isClosed1; expw.Next()) {
-        const TopoDS_Wire& wire = TopoDS::Wire(expw.Current());
-        int nbe = 0;
-        for (BRepTools_WireExplorer we (wire, theFace); we.More() && !isClosed1; we.Next()) {
-          if (we.Current().IsSame(*elIt)) {
-            nbe++;
-            if (nbe == 2) isClosed1 = true;
-          }
-        }
-      }
-    }
-    // END: jfa for bug 0019943
-    if (isClosed1)
-      myShapeIDMap.Add( TopExp::LastVertex( *elIt, true ));// vertex orienation is REVERSED
-  }
-  int nbVertices = myShapeIDMap.Extent();
-
-  for ( elIt = eList.begin(); elIt != eList.end(); elIt++ )
-    myShapeIDMap.Add( *elIt );
-
+  int nbVertices = loadVE( eList, myShapeIDMap );
   myShapeIDMap.Add( face );
 
   if ( myShapeIDToPointsMap.size() != myShapeIDMap.Extent() ) {
@@ -2425,10 +2452,11 @@ bool SMESH_Pattern::Apply (const TopoDS_Face&   theFace,
   list< list< TPoint* > > edgesPointsList;
   edgesPointsList.push_back( list< TPoint* >() );
   list< TPoint* > * edgesPoints = & edgesPointsList.back();
-  list< TPoint* >::iterator pIt;
+  list< TPoint* >::iterator pIt, pEnd;
 
   // compute UV of points on the outer wire
   int iE, nbEdgesInOuterWire = nbVertexInWires.front();
+  list< TopoDS_Edge >::iterator elIt;
   for (iE = 0, elIt = eList.begin();
        iE < nbEdgesInOuterWire && elIt != eList.end();
        iE++, elIt++ )
@@ -2543,14 +2571,24 @@ bool SMESH_Pattern::Apply (const TopoDS_Face&   theFace,
     // re-fill myShapeIDMap - all shapes get good IDs
 
     myShapeIDMap.Clear();
-    for ( elIt = eList.begin(); elIt != eList.end(); elIt++ )
-      myShapeIDMap.Add( TopExp::FirstVertex( *elIt, true ));
-    for ( elIt = eList.begin(); elIt != eList.end(); elIt++ )
-      myShapeIDMap.Add( *elIt );
+    nbVertices = loadVE( eList, myShapeIDMap );
     myShapeIDMap.Add( face );
 
   } // there are inner wires
 
+  // Set XYZ of on-vertex points
+
+  // for ( int iV = 1; iV <= nbVertices; ++iV )
+  // {
+  //   const TopoDS_Vertex&    V = TopoDS::Vertex( myShapeIDMap( iV ));
+  //   list< TPoint* > & vPoints = getShapePoints( iV );
+  //   if ( !vPoints.empty() )
+  //   {
+  //     //vPoints.front()->myUV  = BRep_Tool::Parameters( V, theFace ).XY();
+  //     vPoints.front()->myXYZ = BRep_Tool::Pnt( V );
+  //   }
+  // }
+
   // Compute XYZ of on-edge points
 
   TopLoc_Location loc;
@@ -2558,8 +2596,7 @@ bool SMESH_Pattern::Apply (const TopoDS_Face&   theFace,
   {
     BRepAdaptor_Curve C3d( *elIt );
     list< TPoint* > & ePoints = getShapePoints( iE++ );
-    pIt = ePoints.begin();
-    for ( pIt++; pIt != ePoints.end(); pIt++ )
+    for ( pIt = ++ePoints.begin(), pEnd = ePoints.end(); pIt != pEnd; pIt++ )
     {
       TPoint* point = *pIt;
       point->myXYZ = C3d.Value( point->myU );
@@ -3882,12 +3919,96 @@ void SMESH_Pattern::clearMesh(SMESH_Mesh* theMesh) const
 }
 
 //=======================================================================
+//function : findExistingNodes
+//purpose  : fills nodes vector with nodes existing on a given shape (IMP 22368)
+//           Returns true if all nodes for all points on S are found
+//=======================================================================
+
+bool SMESH_Pattern::findExistingNodes( SMESH_Mesh*                      mesh,
+                                       const TopoDS_Shape&              S,
+                                       const std::list< TPoint* > &     points,
+                                       vector< const SMDS_MeshNode* > & nodesVector)
+{
+  if ( S.IsNull() || points.empty() )
+    return false;
+
+  SMESHDS_Mesh* aMeshDS = mesh->GetMeshDS();
+
+  switch ( S.ShapeType() )
+  {
+  case TopAbs_VERTEX:
+  {
+    int pIndex = points.back() - &myPoints[0];
+    if ( !nodesVector[ pIndex ] )
+      nodesVector[ pIndex ] = SMESH_Algo::VertexNode( TopoDS::Vertex( S ), aMeshDS );
+    return nodesVector[ pIndex ];
+  }
+  case TopAbs_EDGE:
+  {
+    const TopoDS_Edge& edge = TopoDS::Edge( S );
+    map< double, const SMDS_MeshNode* > paramsOfNodes;
+    if ( !SMESH_Algo::GetSortedNodesOnEdge( aMeshDS, edge,
+                                            /*ignoreMediumNodes=*/false,
+                                            paramsOfNodes )
+         || paramsOfNodes.size() < 3 )
+      break;
+    // points on VERTEXes are included with wrong myU
+    list< TPoint* >::const_reverse_iterator pItR = ++points.rbegin();
+    list< TPoint* >::const_iterator         pItF = ++points.begin();
+    const bool isForward = ( (*pItF)->myU < (*pItR)->myU );
+    map< double, const SMDS_MeshNode* >::iterator u2n    = ++paramsOfNodes.begin();
+    map< double, const SMDS_MeshNode* >::iterator u2nEnd = --paramsOfNodes.end();
+    TPoint* p;
+    if ( paramsOfNodes.size() == points.size() )
+    {
+      for ( ; u2n != u2nEnd; ++u2n )
+      {
+        p = ( isForward ? *pItF : *pItR );
+        int pIndex = p - &myPoints[0];
+        if ( !nodesVector [ pIndex ] )
+          nodesVector [ pIndex ] = u2n->second;
+        ++pItF;
+        ++pItR;
+      }
+      return true;
+    }
+    else
+    {
+      const double tolFact = 0.05;
+      while ( u2n != u2nEnd && pItF != points.end() )
+      {
+        const double         u = u2n->first;
+        const SMDS_MeshNode* n = u2n->second;
+        const double       tol = ( (++u2n)->first - u ) * tolFact;
+        do
+        {
+          p = ( isForward ? *pItF : *pItR );
+          if ( Abs( u - p->myU ) < tol )
+          {
+            int pIndex = p - &myPoints[0];
+            if ( !nodesVector [ pIndex ] )
+              nodesVector [ pIndex ] = n;
+            ++pItF;
+            ++pItR;
+            break;
+          }
+        }
+        while ( p->myU < u && ( ++pItF, ++pItR != points.rend() ));
+      }
+    }
+    break;
+  } // case TopAbs_EDGE:
+
+  default:;
+  } // switch ( S.ShapeType() )
+
+  return false;
+}
+
+//=======================================================================
 //function : MakeMesh
 //purpose  : Create nodes and elements in <theMesh> using nodes
 //           coordinates computed by either of Apply...() methods
-// WARNING : StdMeshers_Projection_... relies on MakeMesh() behavior: that
-//           it does not care of nodes and elements already existing on
-//           sub-shapes. DO NOT MERGE them or modify also StdMeshers_Projection_..
 //=======================================================================
 
 bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh,
@@ -3982,98 +4103,23 @@ bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh,
   {
     nodesVector.resize( myPoints.size(), 0 );
 
-    // find existing nodes on EDGEs and VERTEXes (IMP 22368)
-    map< int, list< TPoint* > >::iterator idPointIt = myShapeIDToPointsMap.begin();
-    if ( !myShapeIDMap.IsEmpty() && aMeshDS->NbNodes() > 0 )
-
-      for ( ; idPointIt != myShapeIDToPointsMap.end(); idPointIt++ )
-      {
-        const TopoDS_Shape&    S = myShapeIDMap( idPointIt->first );
-        list< TPoint* > & points = idPointIt->second;
-        if ( points.empty() )
-          continue;
-
-        switch ( S.ShapeType() )
-        {
-        case TopAbs_VERTEX:
-        {
-          int pIndex = points.back() - &myPoints[0];
-          if ( !nodesVector[ pIndex ] )
-            nodesVector[ pIndex ] = SMESH_Algo::VertexNode( TopoDS::Vertex( S ), aMeshDS );
-          break;
-        }
-        case TopAbs_EDGE:
-        {
-          const TopoDS_Edge& edge = TopoDS::Edge( S );
-          map< double, const SMDS_MeshNode* > paramsOfNodes;
-          if ( !SMESH_Algo::GetSortedNodesOnEdge( aMeshDS, edge,
-                                                  /*ignoreMediumNodes=*/false,
-                                                  paramsOfNodes )
-               || paramsOfNodes.size() < 3 )
-            break;
-          // points on VERTEXes are included with wrong myU
-          list< TPoint* >::reverse_iterator pItR = ++points.rbegin();
-          list< TPoint* >::iterator         pItF = ++points.begin();
-          const bool isForward = ( (*pItF)->myU < (*pItR)->myU );
-          map< double, const SMDS_MeshNode* >::iterator u2n    = ++paramsOfNodes.begin();
-          map< double, const SMDS_MeshNode* >::iterator u2nEnd = --paramsOfNodes.end();
-          TPoint* p;
-          if ( paramsOfNodes.size() == points.size() )
-          {
-            for ( ; u2n != u2nEnd; ++u2n )
-            {
-              p = ( isForward ? *pItF : *pItR );
-              int pIndex = p - &myPoints[0];
-              if ( !nodesVector [ pIndex ] )
-                nodesVector [ pIndex ] = u2n->second;
-              ++pItF;
-              ++pItR;
-            }
-          }
-          else
-          {
-            const double tolFact = 0.05;
-            while ( u2n != u2nEnd && pItF != points.end() )
-            {
-              const double         u = u2n->first;
-              const SMDS_MeshNode* n = u2n->second;
-              const double       tol = ( (++u2n)->first - u ) * tolFact;
-              do
-              {
-                p = ( isForward ? *pItF : *pItR );
-                if ( Abs( u - p->myU ) < tol )
-                {
-                  int pIndex = p - &myPoints[0];
-                  if ( !nodesVector [ pIndex ] )
-                    nodesVector [ pIndex ] = n;
-                  ++pItF;
-                  ++pItR;
-                  break;
-                }
-              }
-              while ( p->myU < u && ( ++pItF, ++pItR != points.rend() ));
-            }
-          }
-          break;
-        }
-        default:;
-        }
-      } // end of "find existing nodes on EDGEs and VERTEXes"
-
     // loop on sub-shapes of myShape: create nodes
-    idPointIt = myShapeIDToPointsMap.begin();
+    map< int, list< TPoint* > >::iterator idPointIt = myShapeIDToPointsMap.begin();
     for ( ; idPointIt != myShapeIDToPointsMap.end(); idPointIt++ )
     {
+      list< TPoint* > & points = idPointIt->second;
       TopoDS_Shape S;
-      if ( !myShapeIDMap.IsEmpty() ) {
+      if ( !myShapeIDMap.IsEmpty() )
         S = myShapeIDMap( idPointIt->first );
-      }
-      list< TPoint* > & points = idPointIt->second;
+
+      // find existing nodes on EDGEs and VERTEXes
+      if ( findExistingNodes( theMesh, S, points, nodesVector ))
+        continue;
+
       list< TPoint* >::iterator pIt = points.begin();
       for ( ; pIt != points.end(); pIt++ )
       {
         TPoint* point = *pIt;
-        //int pIndex = pointIndex[ point ];
         int pIndex = point - &myPoints[0];
         if ( nodesVector [ pIndex ] )
           continue;
@@ -4082,8 +4128,8 @@ bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh,
                                                 point->myXYZ.Z());
         nodesVector [ pIndex ] = node;
 
-        if ( !S.IsNull() /*subMeshDS*/ ) {
-          // !!!!! do not merge new nodes with ones existing on submeshes (see method comment)
+        if ( !S.IsNull() ) {
+
           switch ( S.ShapeType() ) {
           case TopAbs_VERTEX: {
             aMeshDS->SetNodeOnVertex( node, TopoDS::Vertex( S )); break;
@@ -4755,7 +4801,7 @@ bool SMESH_Pattern::setShapeToMesh(const TopoDS_Shape& theShape)
     TopTools_MapOfShape seamVertices;
     TopoDS_Face face = TopoDS::Face( theShape );
     TopExp_Explorer eExp( theShape, TopAbs_EDGE );
-    for ( ; eExp.More() && nbNodeOnSeamEdge == 0; eExp.Next() ) {
+    for ( ; eExp.More() /*&& nbNodeOnSeamEdge == 0*/; eExp.Next() ) {
       const TopoDS_Edge& ee = TopoDS::Edge(eExp.Current());
       if ( BRep_Tool::IsClosed(ee, face) ) {
         // seam edge and vertices encounter twice in theFace
index cbe6774..225e5ab 100644 (file)
@@ -334,6 +334,12 @@ private:
   void clearMesh(SMESH_Mesh* theMesh) const;
   // clear mesh elements existing on myShape in theMesh
 
+  bool findExistingNodes( SMESH_Mesh*                           mesh,
+                          const TopoDS_Shape&                   S,
+                          const std::list< TPoint* > &          points,
+                          std::vector< const SMDS_MeshNode* > & nodes);
+  // fills nodes vector with nodes existing on a given shape
+
   static SMESHDS_SubMesh * getSubmeshWithElements(SMESH_Mesh*         theMesh,
                                                   const TopoDS_Shape& theShape);
   // return submesh containing elements bound to theShape in theMesh
index 15b9487..1bf5e5c 100644 (file)
@@ -916,7 +916,7 @@ void SMESHGUI_BaseComputeOp::computeMesh()
       long nbElements = 0;
       if ( !memoryLack )
       {
-       // List of objects that will be updated automatically
+        // List of objects that will be updated automatically
         QList< QPair< SMESH::SMESH_IDSource_var, _PTR(SObject) > > aListToUpdate;
         SMESH::SMESH_IDSource_var aMeshObj = SMESH::SObjectToInterface<SMESH::SMESH_IDSource>( aMeshSObj );
         // put Mesh into list
@@ -949,60 +949,60 @@ void SMESHGUI_BaseComputeOp::computeMesh()
         // update mesh, sub-mesh and groups, if it's possible
         QList< QPair< SMESH::SMESH_IDSource_var, _PTR(SObject) > >::iterator anIter;
         for( anIter = aListToUpdate.begin(); anIter != aListToUpdate.end(); anIter++ ) {
-         SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow( SMESH::SObjectToObject( (*anIter).second ));
-         if ( getSMESHGUI()->automaticUpdate( (*anIter).first, &entities, &limitExceeded, &hidden, &nbElements ) )
-         {
-           try {
+          SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow( SMESH::SObjectToObject( (*anIter).second ));
+          if ( getSMESHGUI()->automaticUpdate( (*anIter).first, &entities, &limitExceeded, &hidden, &nbElements ) )
+          {
+            try {
 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
-             OCC_CATCH_SIGNALS;
+              OCC_CATCH_SIGNALS;
 #endif
-             bool toDisplay = false;
-
-             if ( !aMesh->_is_nil() ) { // display a mesh only
-               toDisplay = true;
-               SMESH_Actor *anActor = SMESH::FindActorByObject( aMesh );
-               if ( !anActor ) anActor = SMESH::CreateActor( (*anIter).second->GetStudy(), (*anIter).second->GetID().c_str(), true );    
-               if ( anActor ) // actor is not created for an empty mesh
-               {
-                 anActor->SetEntityMode( entities );
-                 SMESH::DisplayActor( SMESH::GetActiveWindow(), anActor );
-               }
-             }
-             Handle(SALOME_InteractiveObject) anIO = new SALOME_InteractiveObject
-               ( (*anIter).second->GetID().c_str(), "SMESH", (*anIter).second->GetName().c_str() );
-             SMESH::Update(anIO, toDisplay);
-
-             if ( limitExceeded && !aMesh->_is_nil() )
-             {
-               QStringList hiddenMsg;
-               if ( hidden & SMESH_Actor::e0DElements ) hiddenMsg << tr( "SMESH_ELEMS0D" );
-               if ( hidden & SMESH_Actor::eEdges )      hiddenMsg << tr( "SMESH_EDGES" );
-               if ( hidden & SMESH_Actor::eFaces )      hiddenMsg << tr( "SMESH_FACES" );
-               if ( hidden & SMESH_Actor::eVolumes )    hiddenMsg << tr( "SMESH_VOLUMES" );
-               if ( hidden & SMESH_Actor::eBallElem )   hiddenMsg << tr( "SMESH_BALLS" );
-               SUIT_MessageBox::warning( desktop(),
-                                         tr( "SMESH_WRN_WARNING" ),
-                                         tr( "SMESH_WRN_SIZE_INC_LIMIT_EXCEEDED" ).arg( nbElements ).arg( limitSize ).arg( hiddenMsg.join(", ") ) );
-             }
-           }
-           catch (...) {
+              bool toDisplay = false;
+
+              if ( !aMesh->_is_nil() ) { // display a mesh only
+                toDisplay = true;
+                SMESH_Actor *anActor = SMESH::FindActorByObject( aMesh );
+                if ( !anActor ) anActor = SMESH::CreateActor( (*anIter).second->GetStudy(), (*anIter).second->GetID().c_str(), true );    
+                if ( anActor ) // actor is not created for an empty mesh
+                {
+                  anActor->SetEntityMode( entities );
+                  SMESH::DisplayActor( SMESH::GetActiveWindow(), anActor );
+                }
+              }
+              Handle(SALOME_InteractiveObject) anIO = new SALOME_InteractiveObject
+                ( (*anIter).second->GetID().c_str(), "SMESH", (*anIter).second->GetName().c_str() );
+              SMESH::Update(anIO, toDisplay);
+
+              if ( limitExceeded && !aMesh->_is_nil() )
+              {
+                QStringList hiddenMsg;
+                if ( hidden & SMESH_Actor::e0DElements ) hiddenMsg << tr( "SMESH_ELEMS0D" );
+                if ( hidden & SMESH_Actor::eEdges )      hiddenMsg << tr( "SMESH_EDGES" );
+                if ( hidden & SMESH_Actor::eFaces )      hiddenMsg << tr( "SMESH_FACES" );
+                if ( hidden & SMESH_Actor::eVolumes )    hiddenMsg << tr( "SMESH_VOLUMES" );
+                if ( hidden & SMESH_Actor::eBallElem )   hiddenMsg << tr( "SMESH_BALLS" );
+                SUIT_MessageBox::warning( desktop(),
+                                          tr( "SMESH_WRN_WARNING" ),
+                                          tr( "SMESH_WRN_SIZE_INC_LIMIT_EXCEEDED" ).arg( nbElements ).arg( limitSize ).arg( hiddenMsg.join(", ") ) );
+              }
+            }
+            catch (...) {
 #ifdef _DEBUG_
-             MESSAGE ( "Exception thrown during mesh visualization" );
+              MESSAGE ( "Exception thrown during mesh visualization" );
 #endif
-             if ( SMDS_Mesh::CheckMemory(true) ) { // has memory to show warning?
-               SMESH::OnVisuException();
-             }
-             else {
-               memoryLack = true;
-             }
-           }
-         }
-         else if ( limitExceeded && !aMesh->_is_nil() )
-         {
-           SUIT_MessageBox::warning( desktop(),
-                                     tr( "SMESH_WRN_WARNING" ),
-                                     tr( "SMESH_WRN_SIZE_LIMIT_EXCEEDED" ).arg( nbElements ).arg( limitSize ) );
-         }
+              if ( SMDS_Mesh::CheckMemory(true) ) { // has memory to show warning?
+                SMESH::OnVisuException();
+              }
+              else {
+                memoryLack = true;
+              }
+            }
+          }
+          else if ( limitExceeded && !aMesh->_is_nil() )
+          {
+            SUIT_MessageBox::warning( desktop(),
+                                      tr( "SMESH_WRN_WARNING" ),
+                                      tr( "SMESH_WRN_SIZE_LIMIT_EXCEEDED" ).arg( nbElements ).arg( limitSize ) );
+          }
         }
       }
       LightApp_SelectionMgr *Sel = selectionMgr();
index 472061d..1b51920 100644 (file)
@@ -1464,7 +1464,7 @@ int SMESH_Block::GetShapeIDByParams ( const gp_XYZ& theCoord )
 /*!
  * \brief Return number of wires and a list of oredered edges.
  *  \param theFace - the face to process
- *  \param theEdges - all ordered edges of theFace (outer edges goes first).
+ *  \param theEdges - all ordered edges of theFace (outer edges go first).
  *  \param theNbEdgesInWires - nb of edges (== nb of vertices in closed wire) in each wire
  *  \param theFirstVertex - the vertex of the outer wire to set first in the returned
  *         list ( theFirstVertex may be NULL )
index 18c6f27..9739fcb 100644 (file)
@@ -529,6 +529,8 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the
     TShapePairsList::iterator s1_s2 = shapesQueue.begin();
     for ( ; s1_s2 != shapesQueue.end(); ++s1_s2 )
     {
+      if ( theMap.IsBound( s1_s2->first )) // avoid re-binding for a seam edge
+        continue; // to avoid this:           Forward seam -> Reversed seam
       InsertAssociation( s1_s2->first, s1_s2->second, theMap );
       TopoDS_Iterator s1It( s1_s2->first), s2It( s1_s2->second );
       for ( ; s1It.More(); s1It.Next(), s2It.Next() )
index c4bbc0c..0e3d183 100644 (file)
@@ -381,8 +381,10 @@ namespace {
                       SMESH_Mesh *                      srcMesh,
                       const TAssocTool::TShapeShapeMap& shape2ShapeMap)
   {
-    MESSAGE("projectPartner");
-    const double tol = 1.e-7*srcMesh->GetMeshDS()->getMaxDim();
+    SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
+    SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
+
+    const double tol = 1.e-7 * srcMeshDS->getMaxDim();
 
     gp_Trsf trsf; // transformation to get location of target nodes from source ones
     if ( tgtFace.IsPartner( srcFace ))
@@ -441,11 +443,11 @@ namespace {
             else
               pOK = (( tgtP.Distance( tgtPP[0] ) > tol*tol ) &&
                      ( tgtPP.size() == 1 || tgtP.Distance( tgtPP[1] ) > tol*tol ));
-            //cout << "V - nS " << p._node->GetID() << " - nT " << SMESH_Algo::VertexNode(TopoDS::Vertex( tgtShape),tgtMesh->GetMeshDS())->GetID() << endl;
+            //cout << "V - nS " << p._node->GetID() << " - nT " << SMESH_Algo::VertexNode(TopoDS::Vertex( tgtShape),tgtMeshDS)->GetID() << endl;
           }
           else if ( tgtPP.size() > 0 )
           {
-            if ( SMESHDS_SubMesh* tgtSmds = tgtMesh->GetMeshDS()->MeshElements( tgtShape ))
+            if ( SMESHDS_SubMesh* tgtSmds = tgtMeshDS->MeshElements( tgtShape ))
             {
               double srcDist = srcPP[0].Distance( p );
               double eTol = BRep_Tool::Tolerance( TopoDS::Edge( tgtShape ));
@@ -486,26 +488,33 @@ namespace {
     map<const SMDS_MeshNode* , const SMDS_MeshNode*> src2tgtNodes;
     map<const SMDS_MeshNode* , const SMDS_MeshNode*>::iterator srcN_tgtN;
 
-    for ( TopExp_Explorer srcEdge( srcFace, TopAbs_EDGE); srcEdge.More(); srcEdge.Next() )
+    for ( TopExp_Explorer srcExp( srcFace, TopAbs_EDGE); srcExp.More(); srcExp.Next() )
     {
-      const TopoDS_Shape& tgtEdge = shape2ShapeMap( srcEdge.Current(), /*isSrc=*/true );
+      const TopoDS_Shape& srcEdge = srcExp.Current();
+      const TopoDS_Shape& tgtEdge = shape2ShapeMap( srcEdge, /*isSrc=*/true );
+      if ( srcMesh->GetSubMesh( srcEdge )->IsEmpty() ||
+           tgtMesh->GetSubMesh( tgtEdge )->IsEmpty() )
+        continue;
 
       map< double, const SMDS_MeshNode* > srcNodes, tgtNodes;
-      if ( !SMESH_Algo::GetSortedNodesOnEdge( srcMesh->GetMeshDS(),
-                                              TopoDS::Edge( srcEdge.Current() ),
-                                              /*ignoreMediumNodes = */true,
-                                              srcNodes )
+      if (( ! SMESH_Algo::GetSortedNodesOnEdge( srcMeshDS,
+                                                TopoDS::Edge( srcEdge ),
+                                                /*ignoreMediumNodes = */true,
+                                                srcNodes ))
            ||
-           !SMESH_Algo::GetSortedNodesOnEdge( tgtMesh->GetMeshDS(),
-                                              TopoDS::Edge( tgtEdge ),
-                                              /*ignoreMediumNodes = */true,
-                                              tgtNodes )
+          ( ! SMESH_Algo::GetSortedNodesOnEdge( tgtMeshDS,
+                                                TopoDS::Edge( tgtEdge ),
+                                                /*ignoreMediumNodes = */true,
+                                                tgtNodes ))
            ||
-           srcNodes.size() != tgtNodes.size())
+          (( srcNodes.size() != tgtNodes.size() ) && tgtNodes.size() > 0 )
+          )
         return false;
 
-      if ( !tgtEdge.IsPartner( srcEdge.Current() ))
+      if ( !tgtEdge.IsPartner( srcEdge ))
       {
+        if ( tgtNodes.empty() )
+          return false;
         // check that transformation is OK by three nodes
         gp_Pnt p0S = SMESH_TNodeXYZ( (srcNodes.begin())  ->second);
         gp_Pnt p1S = SMESH_TNodeXYZ( (srcNodes.rbegin()) ->second);
@@ -527,11 +536,13 @@ namespace {
           return false;
         }
       }
-
-      map< double, const SMDS_MeshNode* >::iterator u_tn = tgtNodes.begin();
-      map< double, const SMDS_MeshNode* >::iterator u_sn = srcNodes.begin();
-      for ( ; u_tn != tgtNodes.end(); ++u_tn, ++u_sn)
-        src2tgtNodes.insert( make_pair( u_sn->second, u_tn->second ));
+      if ( !tgtNodes.empty() )
+      {
+        map< double, const SMDS_MeshNode* >::iterator u_tn = tgtNodes.begin();
+        map< double, const SMDS_MeshNode* >::iterator u_sn = srcNodes.begin();
+        for ( ; u_tn != tgtNodes.end(); ++u_tn, ++u_sn)
+          src2tgtNodes.insert( make_pair( u_sn->second, u_tn->second ));
+      }
     }
 
     // Make new faces
@@ -540,7 +551,6 @@ namespace {
     SMESH_MesherHelper helper( *tgtMesh );
     helper.SetSubShape( tgtFace );
     helper.IsQuadraticSubMesh( tgtFace );
-    helper.SetElementsOnShape( true );
 
     SMESH_MesherHelper srcHelper( *srcMesh );
     srcHelper.SetSubShape( srcFace );
@@ -548,11 +558,12 @@ namespace {
     const SMDS_MeshNode* nullNode = 0;
 
     // indices of nodes to create properly oriented faces
+    bool isReverse = ( trsf.Form() != gp_Identity );
     int tri1 = 1, tri2 = 2, quad1 = 1, quad3 = 3;
-    if ( trsf.Form() != gp_Identity )
+    if ( isReverse )
       std::swap( tri1, tri2 ), std::swap( quad1, quad3 );
 
-    SMESHDS_SubMesh* srcSubDS = srcMesh->GetMeshDS()->MeshElements( srcFace );
+    SMESHDS_SubMesh*   srcSubDS = srcMeshDS->MeshElements( srcFace );
     SMDS_ElemIteratorPtr elemIt = srcSubDS->GetElements();
     vector< const SMDS_MeshNode* > tgtNodes;
     while ( elemIt->more() ) // loop on all mesh faces on srcFace
@@ -560,6 +571,7 @@ namespace {
       const SMDS_MeshElement* elem = elemIt->next();
       const int nbN = elem->NbCornerNodes(); 
       tgtNodes.resize( nbN );
+      helper.SetElementsOnShape( false );
       for ( int i = 0; i < nbN; ++i ) // loop on nodes of the source element
       {
         const SMDS_MeshNode* srcNode = elem->GetNode(i);
@@ -567,29 +579,119 @@ namespace {
         if ( srcN_tgtN->second == nullNode )
         {
           // create a new node
-          gp_Pnt tgtP = gp_Pnt(srcNode->X(),srcNode->Y(),srcNode->Z()).Transformed( trsf );
+          gp_Pnt tgtP = gp_Pnt( SMESH_TNodeXYZ( srcNode )).Transformed( trsf );
           SMDS_MeshNode* n = helper.AddNode( tgtP.X(), tgtP.Y(), tgtP.Z() );
           srcN_tgtN->second = n;
-
-          gp_Pnt2d srcUV = srcHelper.GetNodeUV( srcFace, srcNode,
-                                                elem->GetNode( helper.WrapIndex(i+1,nbN)));
-          n->SetPosition( new SMDS_FacePosition( srcUV.X(), srcUV.Y() ));
+          switch ( srcNode->GetPosition()->GetTypeOfPosition() )
+          {
+          case SMDS_TOP_FACE:
+          {
+            gp_Pnt2d srcUV = srcHelper.GetNodeUV( srcFace, srcNode );
+            tgtMeshDS->SetNodeOnFace( n, helper.GetSubShapeID(), srcUV.X(), srcUV.Y() );
+            break;
+          }
+          case SMDS_TOP_EDGE:
+          {
+            const TopoDS_Shape & srcE = srcMeshDS->IndexToShape( srcNode->getshapeId() );
+            const TopoDS_Shape & tgtE = shape2ShapeMap( srcE, /*isSrc=*/true );
+            double srcU = srcHelper.GetNodeU( TopoDS::Edge( srcE ), srcNode );
+            tgtMeshDS->SetNodeOnEdge( n, TopoDS::Edge( tgtE ), srcU );
+            break;
+          }
+          case SMDS_TOP_VERTEX:
+          {
+            const TopoDS_Shape & srcV = srcMeshDS->IndexToShape( srcNode->getshapeId() );
+            const TopoDS_Shape & tgtV = shape2ShapeMap( srcV, /*isSrc=*/true );
+            tgtMeshDS->SetNodeOnVertex( n, TopoDS::Vertex( tgtV ));
+            break;
+          }
+          default:;
+          }
         }
         tgtNodes[i] = srcN_tgtN->second;
       }
       // create a new face
+      helper.SetElementsOnShape( true );
       switch ( nbN )
       {
       case 3: helper.AddFace(tgtNodes[0], tgtNodes[tri1], tgtNodes[tri2]); break;
       case 4: helper.AddFace(tgtNodes[0], tgtNodes[quad1], tgtNodes[2], tgtNodes[quad3]); break;
+      default:
+        if ( isReverse ) std::reverse( tgtNodes.begin(), tgtNodes.end() );
+        helper.AddPolygonalFace( tgtNodes );
+      }
+    }
+
+    // check node positions
+
+    if ( !tgtFace.IsPartner( srcFace ) )
+    {
+      int nbOkPos = 0;
+      const double tol2d = 1e-12;
+      srcN_tgtN = src2tgtNodes.begin();
+      for ( ; srcN_tgtN != src2tgtNodes.end(); ++srcN_tgtN )
+      {
+        const SMDS_MeshNode* n = srcN_tgtN->second;
+        switch ( n->GetPosition()->GetTypeOfPosition() )
+        {
+        case SMDS_TOP_FACE:
+        {
+          gp_XY uv = helper.GetNodeUV( tgtFace, n ), uvBis = uv;
+          if (( helper.CheckNodeUV( tgtFace, n, uv, tol )) &&
+              (( uv - uvBis ).SquareModulus() < tol2d )    &&
+              ( ++nbOkPos > 10 ))
+            return true;
+          else
+            nbOkPos = 0;
+          break;
+        }
+        case SMDS_TOP_EDGE:
+        {
+          const TopoDS_Edge & tgtE = TopoDS::Edge( tgtMeshDS->IndexToShape( n->getshapeId() ));
+          double u = helper.GetNodeU( tgtE, n ), uBis = u;
+          if (( !helper.CheckNodeU( tgtE, n, u, tol )) ||
+              (( u - uBis ) < tol2d ))
+            nbOkPos = 0;
+          break;
+        }
+        default:;
+        }
       }
     }
+
     return true;
 
   } //   bool projectPartner()
 
   //================================================================================
   /*!
+   * \brief Check if two consecutive EDGEs are connected in 2D
+   *  \param [in] E1 - a well oriented non-seam EDGE
+   *  \param [in] E2 - a possibly well oriented seam EDGE
+   *  \param [in] F - a FACE
+   *  \return bool - result
+   */
+  //================================================================================
+
+  bool are2dConnected( const TopoDS_Edge & E1,
+                       const TopoDS_Edge & E2,
+                       const TopoDS_Face & F )
+  {
+    double f,l;
+    Handle(Geom2d_Curve) c1 = BRep_Tool::CurveOnSurface( E1, F, f, l );
+    gp_Pnt2d uvLast1 = c1->Value( E1.Orientation() == TopAbs_REVERSED ? f : l );
+
+    Handle(Geom2d_Curve) c2 = BRep_Tool::CurveOnSurface( E2, F, f, l );
+    gp_Pnt2d uvFirst2 = c2->Value( f );
+    gp_Pnt2d uvLast2  = c2->Value( l );
+    double tol2 = 1e-5 * uvLast2.SquareDistance( uvFirst2 );
+
+    return (( uvLast1.SquareDistance( uvFirst2 ) < tol2 ) ||
+            ( uvLast1.SquareDistance( uvLast2 ) < tol2 ));
+  }
+
+  //================================================================================
+  /*!
    * \brief Preform projection in case if the faces are similar in 2D space
    */
   //================================================================================
@@ -612,19 +714,31 @@ namespace {
 
     // make corresponding sequence of tgt EDGEs
     TSideVector tgtWires( srcWires.size() );
-    for ( unsigned iW = 0; iW < srcWires.size(); ++iW )
+    for ( size_t iW = 0; iW < srcWires.size(); ++iW )
     {
       list< TopoDS_Edge > tgtEdges;
       StdMeshers_FaceSidePtr srcWire = srcWires[iW];
       TopTools_IndexedMapOfShape edgeMap; // to detect seam edges
       for ( int iE = 0; iE < srcWire->NbEdges(); ++iE )
       {
-        tgtEdges.push_back( TopoDS::Edge( shape2ShapeMap( srcWire->Edge( iE ), /*isSrc=*/true)));
+        TopoDS_Edge E = TopoDS::Edge( shape2ShapeMap( srcWire->Edge( iE ), /*isSrc=*/true));
         // reverse a seam edge encountered for the second time
-        const int oldExtent = edgeMap.Extent();
-        edgeMap.Add( tgtEdges.back() );
-        if ( oldExtent == edgeMap.Extent() )
-          tgtEdges.back().Reverse();
+        const int index = edgeMap.Add( E );
+        if ( index < edgeMap.Extent() ) // E is a seam
+        {
+          // check which of edges to reverse, E or one already being in tgtEdges
+          if ( are2dConnected( tgtEdges.back(), E, tgtFace ))
+          {
+            list< TopoDS_Edge >::iterator eIt = tgtEdges.begin();
+            std::advance( eIt, index-1 );
+            eIt->Reverse();
+          }
+          else
+          {
+            E.Reverse();
+          }
+        }
+        tgtEdges.push_back( E );
       }
       tgtWires[ iW ].reset( new StdMeshers_FaceSide( tgtFace, tgtEdges, tgtMesh,
                                                      /*theIsForward = */ true,
index 685b141..10006f4 100644 (file)
@@ -897,12 +897,12 @@ namespace
         if ( SMESH_Algo::isDegenerated( e )) continue;
         TopExp::Vertices( e, VV[0], VV[1], /*CumOri=*/true );
         if ( VV[1].IsSame( fromV )) {
+          nbEdges += edges[ 0 ].IsNull();
           edges[ 0 ] = e;
-          nbEdges++;
         }
         else if ( VV[0].IsSame( fromV )) {
+          nbEdges += edges[ 1 ].IsNull();
           edges[ 1 ] = e;
-          nbEdges++;
         }
       }
     }
@@ -940,7 +940,7 @@ namespace
     }
     else if ( nbEdges == 1 )
     {
-      dir = getFaceDir( faceFrw, edges[0], node, helper, ok );
+      dir = getFaceDir( faceFrw, edges[ edges[0].IsNull() ], node, helper, ok );
       if ( cosin ) *cosin = 1.;
     }
     else