Salome HOME
Regression of SALOME_TESTS/Grids/smesh/imps_09/K2
[modules/smesh.git] / src / StdMeshers / StdMeshers_ProjectionUtils.cxx
index 25bc38a4a08b9f16f1c3e434ffa18f74980eced6..ae6f38419e465580eafdaad0461a7a1eaa107224 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2014  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
@@ -6,7 +6,7 @@
 // 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
@@ -41,6 +41,7 @@
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_subMesh.hxx"
 #include "SMESH_subMeshEventListener.hxx"
+#include "SMESH_MeshAlgos.hxx"
 
 #include "utilities.h"
 
@@ -437,8 +438,8 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the
                                                          TShapeShapeMap &    theMap)
 {
   // Structure of this long function is following
-  // 1) Group->group projection: theShape1 is a group member,
-  //    theShape2 is a group. We find a group theShape1 is in and recall self.
+  // 1) Group -> Group projection: theShape1 is a group member,
+  //    theShape2 is another group. We find a group theShape1 is in and recall self.
   // 2) Accosiate same shapes with different location (partners).
   // 3) If vertex association is given, perform accosiation according to shape type:
   //       switch ( ShapeType ) {
@@ -621,7 +622,8 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the
       TopTools_ListIteratorOfListOfShape ancestIt1( edgeToFace1.FindFromKey( edge1 ));
       for ( ; F1.IsNull() && ancestIt1.More(); ancestIt1.Next() )
         if ( ancestIt1.Value().ShapeType() == TopAbs_FACE )
-          F1 = ancestIt1.Value().Oriented( TopAbs_FORWARD );
+          F1 = ancestIt1.Value().Oriented //( TopAbs_FORWARD );
+            ( SMESH_MesherHelper::GetSubShapeOri( theShape1, ancestIt1.Value() ));
       if ( F1.IsNull() )
         RETURN_BAD_RESULT(" Face1 not found");
 
@@ -629,7 +631,8 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the
       TopTools_ListIteratorOfListOfShape ancestIt2( edgeToFace2.FindFromKey( edge2 ));
       for ( int i = 0; FF2[1].IsNull() && ancestIt2.More(); ancestIt2.Next() )
         if ( ancestIt2.Value().ShapeType() == TopAbs_FACE )
-          FF2[ i++ ] = ancestIt2.Value().Oriented( TopAbs_FORWARD );
+          FF2[ i++ ] = ancestIt2.Value().Oriented // ( TopAbs_FORWARD );
+            ( SMESH_MesherHelper::GetSubShapeOri( theShape2, ancestIt2.Value() ));
 
       // get oriented edge1 and edge2 from F1 and FF2[0]
       for ( exp.Init( F1, TopAbs_EDGE ); exp.More(); exp.Next() )
@@ -1329,9 +1332,15 @@ int StdMeshers_ProjectionUtils::FindFaceAssociation(const TopoDS_Face&    face1,
           CONT_BAD_RESULT("GetOrderedEdges() failed");
       }
     }
-    edgeIt = --edges2.end();
     if ( !VV2[1].IsSame( TopExp::LastVertex( edges2.front(), true ))) {
       reverse = !reverse;
+      edgeIt = --edges2.end();
+      // move a degenerated edge from back to front
+      // http://www.salome-platform.org/forum/forum_11/173031193
+      if ( TopExp::FirstVertex( *edgeIt ).IsSame( TopExp::LastVertex( *edgeIt ))) {
+        edges2.splice( edges2.begin(), edges2, edgeIt );
+        edgeIt = --edges2.end();
+      }
       // check if the second vertex belongs to the first or last edge in the wire
       if ( !VV2[1].IsSame( TopExp::FirstVertex( *edgeIt, true ))) {
         bool KO = true; // belongs to none
@@ -1419,7 +1428,8 @@ int StdMeshers_ProjectionUtils::FindFaceAssociation(const TopoDS_Face&    face1,
               // move edge2Beg to place before edge2End
               edges2.splice( edge2End, edges2, edge2Beg++ );
 
-            if ( sameVertexUV( *edge2Beg, face2, 0, v0f1UV, vTolUV ))
+            if ( edge2Beg != edges2.end() &&
+                 sameVertexUV( *edge2Beg, face2, 0, v0f1UV, vTolUV ))
             {
               if ( iW1 == 0 ) OK = true; // OK is for the first wire
               // reverse edges2 if needed
@@ -1603,79 +1613,87 @@ TopoDS_Vertex StdMeshers_ProjectionUtils::GetNextVertex(const TopoDS_Edge&   edg
 /*
  * Return a propagation edge
  *  \param aMesh - mesh
- *  \param theEdge - edge to find by propagation
+ *  \param anEdge - edge to find by propagation
  *  \param fromEdge - start edge for propagation
+ *  \param chain - return, if !NULL, a propagation chain passed till
+ *         anEdge; if anEdge.IsNull() then a full propagation chain is returned;
+ *         fromEdge is the 1st in the chain
  *  \retval pair<int,TopoDS_Edge> - propagation step and found edge
  */
 //================================================================================
 
 pair<int,TopoDS_Edge>
-StdMeshers_ProjectionUtils::GetPropagationEdge( SMESH_Mesh*        aMesh,
-                                                const TopoDS_Edge& theEdge,
-                                                const TopoDS_Edge& fromEdge)
+StdMeshers_ProjectionUtils::GetPropagationEdge( SMESH_Mesh*                 aMesh,
+                                                const TopoDS_Edge&          anEdge,
+                                                const TopoDS_Edge&          fromEdge,
+                                                TopTools_IndexedMapOfShape* chain)
 {
-  TopTools_IndexedMapOfShape aChain;
+  TopTools_IndexedMapOfShape locChain;
+  TopTools_IndexedMapOfShape& aChain = chain ? *chain : locChain;
   int step = 0;
 
+  //TopTools_IndexedMapOfShape checkedWires;
+  BRepTools_WireExplorer aWE;
+  TopoDS_Shape fourEdges[4];
+
   // List of edges, added to chain on the previous cycle pass
   TopTools_ListOfShape listPrevEdges;
-  listPrevEdges.Append(fromEdge);
+  listPrevEdges.Append( fromEdge );
+  aChain.Add( fromEdge );
 
   // Collect all edges pass by pass
-  while (listPrevEdges.Extent() > 0) {
+  while (listPrevEdges.Extent() > 0)
+  {
     step++;
     // List of edges, added to chain on this cycle pass
     TopTools_ListOfShape listCurEdges;
 
     // Find the next portion of edges
     TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
-    for (; itE.More(); itE.Next()) {
-      TopoDS_Shape anE = itE.Value();
+    for (; itE.More(); itE.Next())
+    {
+      const TopoDS_Shape& anE = itE.Value();
 
       // Iterate on faces, having edge <anE>
       TopTools_ListIteratorOfListOfShape itA (aMesh->GetAncestors(anE));
-      for (; itA.More(); itA.Next()) {
-        TopoDS_Shape aW = itA.Value();
+      for (; itA.More(); itA.Next())
+      {
+        const TopoDS_Shape& aW = itA.Value();
 
         // There are objects of different type among the ancestors of edge
-        if (aW.ShapeType() == TopAbs_WIRE) {
-          TopoDS_Shape anOppE;
-
-          BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
-          Standard_Integer nb = 1, found = 0;
-          TopTools_Array1OfShape anEdges (1,4);
-          for (; aWE.More(); aWE.Next(), nb++) {
-            if (nb > 4) {
-              found = 0;
+        if ( aW.ShapeType() == TopAbs_WIRE /*&& checkedWires.Add( aW )*/)
+        {
+          Standard_Integer nb = 0, found = -1;
+          for ( aWE.Init( TopoDS::Wire( aW )); aWE.More(); aWE.Next() ) {
+            if (nb+1 > 4) {
+              found = -1;
               break;
             }
-            anEdges(nb) = aWE.Current();
-            if (anEdges(nb).IsSame(anE)) found = nb;
+            fourEdges[ nb ] = aWE.Current();
+            if ( aWE.Current().IsSame( anE )) found = nb;
+            nb++;
           }
-
-          if (nb == 5 && found > 0) {
+          if (nb == 4 && found >= 0) {
             // Quadrangle face found, get an opposite edge
-            Standard_Integer opp = found + 2;
-            if (opp > 4) opp -= 4;
-            anOppE = anEdges(opp);
+            TopoDS_Shape& anOppE = fourEdges[( found + 2 ) % 4 ];
 
             // add anOppE to aChain if ...
-            if (!aChain.Contains(anOppE)) { // ... anOppE is not in aChain
+            int prevChainSize = aChain.Extent();
+            if ( aChain.Add(anOppE) > prevChainSize ) { // ... anOppE is not in aChain
               // Add found edge to the chain oriented so that to
               // have it co-directed with a forward MainEdge
               TopAbs_Orientation ori = anE.Orientation();
-              if ( anEdges(opp).Orientation() == anEdges(found).Orientation() )
+              if ( anOppE.Orientation() == fourEdges[found].Orientation() )
                 ori = TopAbs::Reverse( ori );
               anOppE.Orientation( ori );
-              if ( anOppE.IsSame( theEdge ))
+              if ( anOppE.IsSame( anEdge ))
                 return make_pair( step, TopoDS::Edge( anOppE ));
-              aChain.Add(anOppE);
               listCurEdges.Append(anOppE);
             }
-          } // if (nb == 5 && found > 0)
+          } // if (nb == 4 && found >= 0)
         } // if (aF.ShapeType() == TopAbs_WIRE)
-      } // for (; itF.More(); itF.Next())
-    } // for (; itE.More(); itE.Next())
+      } // loop on ancestors of anE
+    } // loop on listPrevEdges
 
     listPrevEdges = listCurEdges;
   } // while (listPrevEdges.Extent() > 0)
@@ -1876,12 +1894,12 @@ FindMatchingNodesOnFaces( const TopoDS_Face&     face1,
       TIDSortedElemSet inSet, notInSet;
 
       const SMDS_MeshElement* f1 =
-        SMESH_MeshEditor::FindFaceInSet( vNode, eNode, inSet, notInSet );
+        SMESH_MeshAlgos::FindFaceInSet( vNode, eNode, inSet, notInSet );
       if ( !f1 ) RETURN_BAD_RESULT("The first face on seam not found");
       notInSet.insert( f1 );
 
       const SMDS_MeshElement* f2 =
-        SMESH_MeshEditor::FindFaceInSet( vNode, eNode, inSet, notInSet );
+        SMESH_MeshAlgos::FindFaceInSet( vNode, eNode, inSet, notInSet );
       if ( !f2 ) RETURN_BAD_RESULT("The second face on seam not found");
 
       // select a face with less UV of vNode
@@ -1924,7 +1942,7 @@ FindMatchingNodesOnFaces( const TopoDS_Face&     face1,
       for ( int i = 0; i < nbNodes; ++i ) {
         const SMDS_MeshNode* n1 = faceToKeep->GetNode( i );
         const SMDS_MeshNode* n2 = faceToKeep->GetNode(( i+1 ) % nbNodes );
-        f1 = SMESH_MeshEditor::FindFaceInSet( n1, n2, inSet, notInSet );
+        f1 = SMESH_MeshAlgos::FindFaceInSet( n1, n2, inSet, notInSet );
         if ( f1 )
           elems.insert( f1 );
       }
@@ -2030,8 +2048,8 @@ TopoDS_Shape StdMeshers_ProjectionUtils::OuterShape( const TopoDS_Face& face,
 
 //================================================================================
 /*
- * Check that submesh is computed and try to compute it if is not
- *  \param sm - submesh to compute
+ * Check that sub-mesh is computed and try to compute it if is not
+ *  \param sm - sub-mesh to compute
  *  \param iterationNb - int used to stop infinite recursive call
  *  \retval bool - true if computed
  */
@@ -2046,30 +2064,65 @@ bool StdMeshers_ProjectionUtils::MakeComputed(SMESH_subMesh * sm, const int iter
   if ( sm->IsMeshComputed() )
     return true;
 
-  SMESH_Mesh* mesh = sm->GetFather();
-  SMESH_Gen*   gen = mesh->GetGen();
-  SMESH_Algo* algo = sm->GetAlgo();
+  SMESH_Mesh*   mesh = sm->GetFather();
+  SMESH_Gen*     gen = mesh->GetGen();
+  SMESH_Algo*   algo = sm->GetAlgo();
+  TopoDS_Shape shape = sm->GetSubShape();
   if ( !algo )
   {
-    if ( sm->GetSubShape().ShapeType() != TopAbs_COMPOUND )
-      RETURN_BAD_RESULT("No algo assigned to submesh " << sm->GetId());
-    // group
-    bool computed = true;
-    for ( TopoDS_Iterator grMember( sm->GetSubShape() ); grMember.More(); grMember.Next())
-      if ( SMESH_subMesh* grSub = mesh->GetSubMesh( grMember.Value() ))
-        if ( !MakeComputed( grSub, iterationNb + 1 ))
-          computed = false;
-    return computed;
+    if ( shape.ShapeType() != TopAbs_COMPOUND )
+    {
+      // No algo assigned to a non-compound sub-mesh.
+      // Try to find an all-dimensional algo of an upper dimension
+      int dim = gen->GetShapeDim( shape );
+      for ( ++dim; ( dim <= 3 && !algo ); ++dim )
+      {
+        SMESH_HypoFilter hypoFilter( SMESH_HypoFilter::IsAlgo() );
+        hypoFilter.And( SMESH_HypoFilter::HasDim( dim ));
+        list <const SMESHDS_Hypothesis * > hyps;
+        list< TopoDS_Shape >               assignedTo;
+        int nbAlgos =
+          mesh->GetHypotheses( shape, hypoFilter, hyps, true, &assignedTo );
+        if ( nbAlgos > 1 ) // concurrent algos
+        {
+          list<SMESH_subMesh*> smList; // where an algo is assigned
+          list< TopoDS_Shape >::iterator shapeIt = assignedTo.begin();
+          for ( ; shapeIt != assignedTo.end(); ++shapeIt )
+            smList.push_back( mesh->GetSubMesh( *shapeIt ));
+
+          mesh->SortByMeshOrder( smList );
+          algo  = smList.front()->GetAlgo();
+          shape = smList.front()->GetSubShape();
+        }
+        else if ( nbAlgos == 1 )
+        {
+          algo = (SMESH_Algo*) hyps.front();
+          shape = assignedTo.front();
+        }
+      }
+      if ( !algo )
+        return false;
+    }
+    else
+    {
+      // group
+      bool computed = true;
+      for ( TopoDS_Iterator grMember( shape ); grMember.More(); grMember.Next())
+        if ( SMESH_subMesh* grSub = mesh->GetSubMesh( grMember.Value() ))
+          if ( !MakeComputed( grSub, iterationNb + 1 ))
+            computed = false;
+      return computed;
+    }
   }
 
   string algoType = algo->GetName();
   if ( algoType.substr(0, 11) != "Projection_")
-    return gen->Compute( *mesh, sm->GetSubShape() );
+    return gen->Compute( *mesh, shape, /*shapeOnly=*/true );
 
   // try to compute source mesh
 
   const list <const SMESHDS_Hypothesis *> & hyps =
-    algo->GetUsedHypothesis( *mesh, sm->GetSubShape() );
+    algo->GetUsedHypothesis( *mesh, shape );
 
   TopoDS_Shape srcShape;
   SMESH_Mesh* srcMesh = 0;
@@ -2096,16 +2149,16 @@ bool StdMeshers_ProjectionUtils::MakeComputed(SMESH_subMesh * sm, const int iter
     }
   }
   if ( srcShape.IsNull() ) // no projection source defined
-    return gen->Compute( *mesh, sm->GetSubShape() );
+    return gen->Compute( *mesh, shape, /*shapeOnly=*/true );
 
-  if ( srcShape.IsSame( sm->GetSubShape() ))
+  if ( srcShape.IsSame( shape ))
     RETURN_BAD_RESULT("Projection from self");
     
   if ( !srcMesh )
     srcMesh = mesh;
 
   if ( MakeComputed( srcMesh->GetSubMesh( srcShape ), iterationNb + 1 ) &&
-       gen->Compute( *mesh, sm->GetSubShape() ))
+       gen->Compute( *mesh, shape, /*shapeOnly=*/true ))
     return sm->IsMeshComputed();
 
   return false;