Salome HOME
To compute mesh in SALOME_TESTS/Grids/geom/bugs_15/R7
authoreap <eap@opencascade.com>
Wed, 12 Nov 2014 15:35:28 +0000 (18:35 +0300)
committereap <eap@opencascade.com>
Wed, 12 Nov 2014 15:35:28 +0000 (18:35 +0300)
and other tests of "Extrusion 3D" mesher

src/SMESH/SMESH_MesherHelper.cxx
src/SMESH/SMESH_MesherHelper.hxx
src/StdMeshers/StdMeshers_Prism_3D.cxx
src/StdMeshers/StdMeshers_Prism_3D.hxx
src/StdMeshers/StdMeshers_ProjectionUtils.cxx
src/StdMeshers/StdMeshers_Projection_2D.cxx

index 0d4173c..eac6686 100644 (file)
@@ -941,7 +941,7 @@ bool SMESH_MesherHelper::CheckNodeU(const TopoDS_Edge&   E,
   int  shapeID = n->getshapeId();
   bool infinit = Precision::IsInfinite( u );
   bool zero    = ( u == 0. );
-  if ( force || toCheckPosOnShape( shapeID ) || infinit || zero )
+  if ( force || infinit || zero || toCheckPosOnShape( shapeID ))
   {
     TopLoc_Location loc; double f,l;
     Handle(Geom_Curve) curve = BRep_Tool::Curve( E,loc,f,l );
@@ -958,7 +958,7 @@ bool SMESH_MesherHelper::CheckNodeU(const TopoDS_Edge&   E,
       gp_Pnt nodePnt = SMESH_TNodeXYZ( n );
       if ( !loc.IsIdentity() ) nodePnt.Transform( loc.Transformation().Inverted() );
       gp_Pnt curvPnt;
-      double dist = u;
+      double dist = 2*tol;
       if ( !infinit )
       {
         curvPnt = curve->Value( u );
@@ -2559,7 +2559,8 @@ bool SMESH_MesherHelper::IsStructured( SMESH_subMesh* faceSM )
 //purpose  : Return true if 2D mesh on FACE is ditorted
 //=======================================================================
 
-bool SMESH_MesherHelper::IsDistorted2D( SMESH_subMesh* faceSM )
+bool SMESH_MesherHelper::IsDistorted2D( SMESH_subMesh* faceSM,
+                                        bool           checkUV)
 {
   if ( !faceSM || faceSM->GetSubShape().ShapeType() != TopAbs_FACE )
     return false;
@@ -2577,6 +2578,7 @@ bool SMESH_MesherHelper::IsDistorted2D( SMESH_subMesh* faceSM )
   double prevArea2D = 0;
   vector< const SMDS_MeshNode* > nodes;
   vector< gp_XY >                uv;
+  bool* toCheckUV = checkUV ? & checkUV : 0;
   while ( faceIt->more() && !haveBadFaces )
   {
     const SMDS_MeshElement* face = faceIt->next();
@@ -2608,7 +2610,7 @@ bool SMESH_MesherHelper::IsDistorted2D( SMESH_subMesh* faceSM )
     // get UVs
     uv.resize( nodes.size() );
     for ( size_t i = 0; i < nodes.size(); ++i )
-      uv[ i ] = helper.GetNodeUV( F, nodes[ i ], inFaceNode );
+      uv[ i ] = helper.GetNodeUV( F, nodes[ i ], inFaceNode, toCheckUV );
 
     // compare orientation of triangles
     for ( int iT = 0, nbT = nodes.size()-2; iT < nbT; ++iT )
index ae6767d..164861c 100644 (file)
@@ -120,7 +120,7 @@ class SMESH_EXPORT SMESH_MesherHelper
   /*!
    * \brief Return true if 2D mesh on FACE is distored
    */
-  static bool IsDistorted2D( SMESH_subMesh* faceSM );
+  static bool IsDistorted2D( SMESH_subMesh* faceSM, bool checkUV=false );
 
   /*!
    * \brief Returns true if given node is medium
index 62f538d..8681b78 100644 (file)
@@ -689,6 +689,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
   list< Prism_3D::TPrismTopo > meshedPrism;
   list< TopoDS_Face > suspectSourceFaces;
   TopTools_ListIteratorOfListOfShape solidIt;
+  bool selectBottom = false;
 
   while ( meshedSolids.Extent() < nbSolids )
   {
@@ -709,7 +710,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
         {
           prism.Clear();
           prism.myBottom = face;
-          if ( !initPrism( prism, solid ) ||
+          if ( !initPrism( prism, solid, selectBottom ) ||
                !compute( prism ))
             return false;
 
@@ -762,15 +763,24 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
             while ( const TopoDS_Shape* f = faceIt->next() )
             {
               const TopoDS_Face& candidateF = TopoDS::Face( *f );
+              if ( candidateF.IsSame( wFace )) continue;
+              // select a source FACE: prismIt->myBottom or prismIt->myTop
+              TopoDS_Face sourceF = prismIt->myBottom;
+              for ( TopExp_Explorer v( prismIt->myTop, TopAbs_VERTEX ); v.More(); v.Next() )
+                if ( myHelper->IsSubShape( v.Current(), candidateF )) {
+                  sourceF = prismIt->myTop;
+                  break;
+                }
               prism.Clear();
-              prism.myBottom  = candidateF;
+              prism.myBottom = candidateF;
               mySetErrorToSM = false;
               if ( !myHelper->IsSubShape( candidateF, prismIt->myShape3D ) &&
-                   myHelper->IsSubShape( candidateF, solid ) &&
+                   myHelper ->IsSubShape( candidateF, solid ) &&
                    !myHelper->GetMesh()->GetSubMesh( candidateF )->IsMeshComputed() &&
-                   initPrism( prism, solid ) &&
+                   initPrism( prism, solid, /*selectBottom=*/false ) &&
                    !myHelper->GetMesh()->GetSubMesh( prism.myTop )->IsMeshComputed() &&
-                   project2dMesh( prismIt->myBottom, candidateF))
+                   !myHelper->GetMesh()->GetSubMesh( prism.myBottom )->IsMeshComputed() &&
+                   project2dMesh( sourceF, prism.myBottom ))
               {
                 mySetErrorToSM = true;
                 if ( !compute( prism ))
@@ -780,6 +790,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
                 {
                   meshedFaces.push_front( prism.myTop );
                   meshedFaces.push_front( prism.myBottom );
+                  selectBottom = false;
                 }
                 meshedPrism.push_back( prism );
                 meshedSolids.Add( solid );
@@ -802,6 +813,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
     if ( meshedFaces.empty() )
     {
       meshedFaces.splice( meshedFaces.end(), suspectSourceFaces );
+      selectBottom = true;
     }
 
     // find FACEs with local 1D hyps, which has to be computed by now,
@@ -822,6 +834,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
           {
             if ( !meshedFaces.empty() ) meshedFaces.pop_back();
             meshedFaces.push_back( face ); // lower priority
+            selectBottom = true;
             prevNbFaces = nbFaces;
           }
         }
@@ -836,6 +849,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
             faceSM->ComputeStateEngine( SMESH_subMesh::COMPUTE );
             if ( !faceSM->IsEmpty() ) {
               meshedFaces.push_front( face ); // higher priority
+              selectBottom = true;
               break;
             }
             else {
@@ -867,6 +881,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
           meshedFaces.push_front( prism.myBottom );
           meshedPrism.push_back( prism );
           meshedSolids.Add( solid.Current() );
+          selectBottom = true;
         }
         mySetErrorToSM = true;
       }
@@ -1071,7 +1086,7 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism,
     StdMeshers_FaceSidePtr topSide = thePrism.myWallQuads[i].back()->side[ QUAD_TOP_SIDE ];
     const TopoDS_Edge &       topE = topSide->Edge( 0 );
     if ( !myHelper->IsSubShape( topE, thePrism.myTop ))
-      return toSM( error( TCom("Wrong source face (#") << shapeID( thePrism.myBottom )));
+      return toSM( error( TCom("Wrong source face#") << shapeID( thePrism.myBottom )));
   }
 
   return true;
@@ -1088,13 +1103,21 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism)
   if ( _computeCanceled )
     return toSM( error( SMESH_ComputeError::New(COMPERR_CANCELED)));
 
+  // Assure the bottom is meshed
+  SMESH_subMesh * botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
+  if ( ! NSProjUtils::MakeComputed( botSM ))
+    return error( COMPERR_BAD_INPUT_MESH,
+                  TCom( "No mesher defined to compute the face #")
+                  << shapeID( thePrism.myBottom ));
+
   // Make all side FACEs of thePrism meshed with quads
   if ( !computeWalls( thePrism ))
     return false;
 
   // Analyse mesh and geometry to find all block sub-shapes and submeshes
-  // (after fixing IPAL52499 myBlock is used only as a holder of boundary nodes
-  // and location of internal nodes is computed by StdMeshers_Sweeper)
+  // (after fixing IPAL52499 myBlock is used as a holder of boundary nodes
+  // and for 2D projection in hard cases where StdMeshers_Projection_2D fails;
+  // location of internal nodes is usually computed by StdMeshers_Sweeper)
   if ( !myBlock.Init( myHelper, thePrism ))
     return toSM( error( myBlock.GetError()));
 
@@ -1123,6 +1146,7 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism)
 
   // Projections on the top and bottom faces are taken from nodes existing
   // on these faces; find correspondence between bottom and top nodes
+  myUseBlock = false;
   myBotToColumnMap.clear();
   if ( !assocOrProjBottom2Top( bottomToTopTrsf, thePrism ) ) // it also fills myBotToColumnMap
     return false;
@@ -1132,27 +1156,31 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism)
 
   // use transformation (issue 0020680, IPAL0052499)
   StdMeshers_Sweeper sweeper;
+  double tol;
 
-  // load boundary nodes
-  bool dummy;
-  list< TopoDS_Edge >::const_iterator edge = thePrism.myBottomEdges.begin();
-  for ( ; edge != thePrism.myBottomEdges.end(); ++edge )
+  if ( !myUseBlock )
   {
-    int edgeID = meshDS->ShapeToIndex( *edge );
-    TParam2ColumnMap* u2col = const_cast<TParam2ColumnMap*>
-      ( myBlock.GetParam2ColumnMap( edgeID, dummy ));
-    TParam2ColumnMap::iterator u2colIt = u2col->begin();
-    for ( ; u2colIt != u2col->end(); ++u2colIt )
-      sweeper.myBndColumns.push_back( & u2colIt->second );
-  }
-  // load node columns inside the bottom face
-  TNode2ColumnMap::iterator bot_column = myBotToColumnMap.begin();
-  for ( ; bot_column != myBotToColumnMap.end(); ++bot_column )
-    sweeper.myIntColumns.push_back( & bot_column->second );
+    // load boundary nodes into sweeper
+    bool dummy;
+    list< TopoDS_Edge >::const_iterator edge = thePrism.myBottomEdges.begin();
+    for ( ; edge != thePrism.myBottomEdges.end(); ++edge )
+    {
+      int edgeID = meshDS->ShapeToIndex( *edge );
+      TParam2ColumnMap* u2col = const_cast<TParam2ColumnMap*>
+        ( myBlock.GetParam2ColumnMap( edgeID, dummy ));
+      TParam2ColumnMap::iterator u2colIt = u2col->begin();
+      for ( ; u2colIt != u2col->end(); ++u2colIt )
+        sweeper.myBndColumns.push_back( & u2colIt->second );
+    }
+    // load node columns inside the bottom face
+    TNode2ColumnMap::iterator bot_column = myBotToColumnMap.begin();
+    for ( ; bot_column != myBotToColumnMap.end(); ++bot_column )
+      sweeper.myIntColumns.push_back( & bot_column->second );
 
-  const double tol = getSweepTolerance( thePrism );
+    tol = getSweepTolerance( thePrism );
+  }
 
-  if ( sweeper.ComputeNodes( *myHelper, tol ))
+  if ( !myUseBlock && sweeper.ComputeNodes( *myHelper, tol ))
   {
   }
   else // use block approach
@@ -1528,7 +1556,7 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
     for ( ; quad != thePrism.myWallQuads[iW].end(); ++quad )
     {
       const TopoDS_Face& face = (*quad)->face;
-      SMESH_subMesh* fSM = mesh->GetSubMesh( face );
+      SMESH_subMesh*      fSM = mesh->GetSubMesh( face );
       if ( ! fSM->IsMeshComputed() )
       {
         // Top EDGEs must be projections from the bottom ones
@@ -1938,8 +1966,8 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
     NSProjUtils::TShapeShapeMap shape2ShapeMap;
     const bool sameTopo =
       NSProjUtils::FindSubShapeAssociation( thePrism.myBottom, myHelper->GetMesh(),
-                                           thePrism.myTop,    myHelper->GetMesh(),
-                                           shape2ShapeMap);
+                                            thePrism.myTop,    myHelper->GetMesh(),
+                                            shape2ShapeMap);
     if ( !sameTopo )
       for ( size_t iQ = 0; iQ < thePrism.myWallQuads.size(); ++iQ )
       {
@@ -1951,10 +1979,10 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
           for ( int iE = 0; iE < botSide->NbEdges(); ++iE )
           {
             NSProjUtils::InsertAssociation( botSide->Edge( iE ),
-                                           topSide->Edge( iE ), shape2ShapeMap );
+                                            topSide->Edge( iE ), shape2ShapeMap );
             NSProjUtils::InsertAssociation( myHelper->IthVertex( 0, botSide->Edge( iE )),
-                                           myHelper->IthVertex( 0, topSide->Edge( iE )),
-                                           shape2ShapeMap );
+                                            myHelper->IthVertex( 0, topSide->Edge( iE )),
+                                            shape2ShapeMap );
           }
         }
         else
@@ -1969,7 +1997,7 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
                vt.IsSame( sideT->LastVertex() ))
           {
             NSProjUtils::InsertAssociation( botSide->Edge( 0 ),
-                                           topSide->Edge( 0 ), shape2ShapeMap );
+                                            topSide->Edge( 0 ), shape2ShapeMap );
             NSProjUtils::InsertAssociation( vb, vt, shape2ShapeMap );
           }
           vb = myHelper->IthVertex( 1, botSide->Edge( botSide->NbEdges()-1 ));
@@ -1980,8 +2008,8 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
                vt.IsSame( sideT->LastVertex() ))
           {
             NSProjUtils::InsertAssociation( botSide->Edge( botSide->NbEdges()-1 ),
-                                           topSide->Edge( topSide->NbEdges()-1 ),
-                                           shape2ShapeMap );
+                                            topSide->Edge( topSide->NbEdges()-1 ),
+                                            shape2ShapeMap );
             NSProjUtils::InsertAssociation( vb, vt, shape2ShapeMap );
           }
         }
@@ -1990,8 +2018,8 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
     // Find matching nodes of top and bottom faces
     n2nMapPtr = & n2nMap;
     if ( ! NSProjUtils::FindMatchingNodesOnFaces( thePrism.myBottom, myHelper->GetMesh(),
-                                                 thePrism.myTop,    myHelper->GetMesh(),
-                                                 shape2ShapeMap, n2nMap ))
+                                                  thePrism.myTop,    myHelper->GetMesh(),
+                                                  shape2ShapeMap, n2nMap ))
     {
       if ( sameTopo )
         return toSM( error(TCom("Mesh on faces #") << botSM->GetId()
@@ -2014,7 +2042,7 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
       continue; // wall columns are contained in myBlock
     // create node column
     Prism_3D::TNode bN( botNode );
-    TNode2ColumnMap::iterator bN_col = 
+    TNode2ColumnMap::iterator bN_col =
       myBotToColumnMap.insert( make_pair ( bN, TNodeColumn() )).first;
     TNodeColumn & column = bN_col->second;
     column.resize( zSize );
@@ -2038,6 +2066,11 @@ bool StdMeshers_Prism_3D::projectBottomToTop( const gp_Trsf &             bottom
   {
     return true;
   }
+  NSProjUtils::TNodeNodeMap& n2nMap = 
+    (NSProjUtils::TNodeNodeMap&) TProjction2dAlgo::instance( this )->GetNodesMap();
+  n2nMap.clear();
+
+  myUseBlock = true;
 
   SMESHDS_Mesh*  meshDS = myHelper->GetMeshDS();
   SMESH_subMesh * botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
@@ -2047,7 +2080,13 @@ bool StdMeshers_Prism_3D::projectBottomToTop( const gp_Trsf &             bottom
   SMESHDS_SubMesh * topSMDS = topSM->GetSubMeshDS();
 
   if ( topSMDS && topSMDS->NbElements() > 0 )
-    topSM->ComputeStateEngine( SMESH_subMesh::CLEAN );
+  {
+    //topSM->ComputeStateEngine( SMESH_subMesh::CLEAN ); -- avoid propagation of events
+    for ( SMDS_ElemIteratorPtr eIt = topSMDS->GetElements(); eIt->more(); )
+      meshDS->RemoveFreeElement( eIt->next(), topSMDS, /*fromGroups=*/false );
+    for ( SMDS_NodeIteratorPtr nIt = topSMDS->GetNodes(); nIt->more(); )
+      meshDS->RemoveFreeNode( nIt->next(), topSMDS, /*fromGroups=*/false );
+  }
 
   const TopoDS_Face& botFace = thePrism.myBottom; // oriented within
   const TopoDS_Face& topFace = thePrism.myTop;    //    the 3D SHAPE
@@ -2119,6 +2158,8 @@ bool StdMeshers_Prism_3D::projectBottomToTop( const gp_Trsf &             bottom
     column.front() = botNode;
     column.back()  = topNode;
 
+    n2nMap.insert( n2nMap.end(), make_pair( botNode, topNode ));
+
     if ( _computeCanceled )
       return toSM( error( SMESH_ComputeError::New(COMPERR_CANCELED)));
   }
@@ -2270,6 +2311,15 @@ bool StdMeshers_Prism_3D::project2dMesh(const TopoDS_Face& theSrcFace,
   bool ok = projector2D->Compute( *myHelper->GetMesh(), theTgtFace );
 
   SMESH_subMesh* tgtSM = myHelper->GetMesh()->GetSubMesh( theTgtFace );
+  if ( !ok && tgtSM->GetSubMeshDS() ) {
+    //tgtSM->ComputeStateEngine( SMESH_subMesh::CLEAN ); -- avoid propagation of events
+    SMESHDS_Mesh*     meshDS = myHelper->GetMeshDS();
+    SMESHDS_SubMesh* tgtSMDS = tgtSM->GetSubMeshDS();
+    for ( SMDS_ElemIteratorPtr eIt = tgtSMDS->GetElements(); eIt->more(); )
+      meshDS->RemoveFreeElement( eIt->next(), tgtSMDS, /*fromGroups=*/false );
+    for ( SMDS_NodeIteratorPtr nIt = tgtSMDS->GetNodes(); nIt->more(); )
+      meshDS->RemoveFreeNode( nIt->next(), tgtSMDS, /*fromGroups=*/false );
+  }
   tgtSM->ComputeStateEngine       ( SMESH_subMesh::CHECK_COMPUTE_STATE );
   tgtSM->ComputeSubMeshStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
 
@@ -2785,7 +2835,8 @@ void StdMeshers_PrismAsBlock::Clear()
 //=======================================================================
 
 bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
-                                    const TopoDS_Shape&   shape3D)
+                                    const TopoDS_Shape&   shape3D,
+                                    const bool            selectBottom)
 {
   myHelper->SetSubShape( shape3D );
 
@@ -2884,19 +2935,23 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
   // use thePrism.myBottom
   if ( !thePrism.myBottom.IsNull() )
   {
-    if ( botSM ) {
+    if ( botSM ) { // <-- not quad geom or mesh on botSM
       if ( ! botSM->GetSubShape().IsSame( thePrism.myBottom )) {
         std::swap( botSM, topSM );
-        if ( !botSM || ! botSM->GetSubShape().IsSame( thePrism.myBottom ))
-          return toSM( error( COMPERR_BAD_INPUT_MESH,
-                              "Incompatible non-structured sub-meshes"));
+        if ( !botSM || ! botSM->GetSubShape().IsSame( thePrism.myBottom )) {
+          if ( !selectBottom )
+            return toSM( error( COMPERR_BAD_INPUT_MESH,
+                                "Incompatible non-structured sub-meshes"));
+          std::swap( botSM, topSM );
+          thePrism.myBottom = TopoDS::Face( botSM->GetSubShape() );
+        }
       }
     }
-    else {
+    else if ( !selectBottom ) {
       botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
     }
   }
-  else if ( !botSM ) // find a proper bottom
+  if ( !botSM ) // find a proper bottom
   {
     // composite walls or not prism shape
     for ( TopExp_Explorer f( shape3D, TopAbs_FACE ); f.More(); f.Next() )
@@ -2906,11 +2961,17 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
       {
         thePrism.Clear();
         thePrism.myBottom = TopoDS::Face( f.Current() );
-        if ( initPrism( thePrism, shape3D ))
+        if ( initPrism( thePrism, shape3D, /*selectBottom=*/false ))
+        {
+          botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
+          topSM = myHelper->GetMesh()->GetSubMesh( thePrism.myTop );
+          if ( botSM->IsEmpty() && !topSM->IsEmpty() )
+            thePrism.SetUpsideDown();
           return true;
+        }
       }
-      return toSM( error( COMPERR_BAD_SHAPE ));
     }
+    return toSM( error( COMPERR_BAD_SHAPE ));
   }
 
   // find vertex 000 - the one with smallest coordinates (for easy DEBUG :-)
@@ -2943,7 +3004,7 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
                                 thePrism.myNbEdgesInWires, V000 );
 
   // Get Wall faces corresponding to the ordered bottom edges and the top FACE
-  if ( !getWallFaces( thePrism, nbFaces ))
+  if ( !getWallFaces( thePrism, nbFaces )) // it also sets thePrism.myTop
     return false; //toSM( error(COMPERR_BAD_SHAPE, "Can't find side faces"));
 
   if ( topSM )
@@ -3887,7 +3948,7 @@ gp_Pnt StdMeshers_PrismAsBlock::TSideFace::Value(const Standard_Real U,
       TopoDS_Shape s = myHelper.GetSubShapeByNode( nn[0], myHelper.GetMeshDS() );
       if ( s.ShapeType() != TopAbs_EDGE )
         s = myHelper.GetSubShapeByNode( nn[2], myHelper.GetMeshDS() );
-      if ( s.ShapeType() == TopAbs_EDGE )
+      if ( !s.IsNull() && s.ShapeType() == TopAbs_EDGE )
         edge = TopoDS::Edge( s );
     }
     if ( !edge.IsNull() )
index 6c7c52f..5d99375 100644 (file)
@@ -482,7 +482,9 @@ public:
    * \brief Analyse shape geometry and mesh.
     * If there are triangles on one of faces, it becomes 'bottom'
    */
-  bool initPrism(Prism_3D::TPrismTopo& thePrism, const TopoDS_Shape& theSolid);
+  bool initPrism(Prism_3D::TPrismTopo& thePrism,
+                 const TopoDS_Shape&   theSolid,
+                 const bool            selectBottom = true);
 
   /*!
    * \brief Fill thePrism.myWallQuads and thePrism.myTopEdges
@@ -556,6 +558,7 @@ private:
 
   bool myProjectTriangles;
   bool mySetErrorToSM;
+  bool myUseBlock;
 
   StdMeshers_PrismAsBlock myBlock;
   SMESH_MesherHelper*     myHelper;
index f4c233e..00c9257 100644 (file)
@@ -1942,97 +1942,109 @@ FindMatchingNodesOnFaces( const TopoDS_Face&     face1,
 
   // 2. face sets
 
-  set<const SMDS_MeshElement*> Elems1, Elems2;
-  for ( int is2 = 0; is2 < 2; ++is2 )
+  int assocRes;
+  for ( int iAttempt = 0; iAttempt < 2; ++iAttempt )
   {
-    set<const SMDS_MeshElement*> & elems = is2 ? Elems2 : Elems1;
-    SMESHDS_SubMesh*                  sm = is2 ? SM2 : SM1;
-    SMESH_MesherHelper*           helper = is2 ? &helper2 : &helper1;
-    const TopoDS_Face &             face = is2 ? face2 : face1;
-    SMDS_ElemIteratorPtr eIt = sm->GetElements();
-
-    if ( !helper->IsRealSeam( is2 ? edge2 : edge1 ))
-    {
-      while ( eIt->more() ) elems.insert( eIt->next() );
-    }
-    else
+    set<const SMDS_MeshElement*> Elems1, Elems2;
+    for ( int is2 = 0; is2 < 2; ++is2 )
     {
-      // the only suitable edge is seam, i.e. it is a sphere.
-      // FindMatchingNodes() will not know which way to go from any edge.
-      // So we ignore all faces having nodes on edges or vertices except
-      // one of faces sharing current start nodes
-
-      // find a face to keep
-      const SMDS_MeshElement* faceToKeep = 0;
-      const SMDS_MeshNode* vNode = is2 ? vNode2 : vNode1;
-      const SMDS_MeshNode* eNode = is2 ? eNode2[0] : eNode1[0];
-      TIDSortedElemSet inSet, notInSet;
-
-      const SMDS_MeshElement* f1 =
-        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_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
-      const SMDS_MeshNode* notSeamNode[2] = {0, 0};
-      for ( int iF = 0; iF < 2; ++iF ) {
-        const SMDS_MeshElement* f = ( iF ? f2 : f1 );
-        for ( int i = 0; !notSeamNode[ iF ] && i < f->NbNodes(); ++i ) {
-          const SMDS_MeshNode* node = f->GetNode( i );
-          if ( !helper->IsSeamShape( node->getshapeId() ))
-            notSeamNode[ iF ] = node;
-        }
+      set<const SMDS_MeshElement*> & elems = is2 ? Elems2 : Elems1;
+      SMESHDS_SubMesh*                  sm = is2 ? SM2 : SM1;
+      SMESH_MesherHelper*           helper = is2 ? &helper2 : &helper1;
+      const TopoDS_Face &             face = is2 ? face2 : face1;
+      SMDS_ElemIteratorPtr eIt = sm->GetElements();
+
+      if ( !helper->IsRealSeam( is2 ? edge2 : edge1 ))
+      {
+        while ( eIt->more() ) elems.insert( elems.end(), eIt->next() );
       }
-      gp_Pnt2d uv1 = helper->GetNodeUV( face, vNode, notSeamNode[0] );
-      gp_Pnt2d uv2 = helper->GetNodeUV( face, vNode, notSeamNode[1] );
-      if ( uv1.X() + uv1.Y() > uv2.X() + uv2.Y() )
-        faceToKeep = f2;
       else
-        faceToKeep = f1;
-
-      // fill elem set
-      elems.insert( faceToKeep );
-      while ( eIt->more() ) {
-        const SMDS_MeshElement* f = eIt->next();
-        int nbNodes = f->NbNodes();
-        if ( f->IsQuadratic() )
-          nbNodes /= 2;
-        bool onBnd = false;
-        for ( int i = 0; !onBnd && i < nbNodes; ++i ) {
-          const SMDS_MeshNode* node = f->GetNode( i );
-          onBnd = ( node->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE);
+      {
+        // the only suitable edge is seam, i.e. it is a sphere.
+        // FindMatchingNodes() will not know which way to go from any edge.
+        // So we ignore all faces having nodes on edges or vertices except
+        // one of faces sharing current start nodes
+
+        // find a face to keep
+        const SMDS_MeshElement* faceToKeep = 0;
+        const SMDS_MeshNode* vNode = is2 ? vNode2 : vNode1;
+        const SMDS_MeshNode* eNode = is2 ? eNode2[0] : eNode1[0];
+        TIDSortedElemSet inSet, notInSet;
+
+        const SMDS_MeshElement* f1 =
+          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_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
+        const SMDS_MeshNode* notSeamNode[2] = {0, 0};
+        for ( int iF = 0; iF < 2; ++iF ) {
+          const SMDS_MeshElement* f = ( iF ? f2 : f1 );
+          for ( int i = 0; !notSeamNode[ iF ] && i < f->NbNodes(); ++i ) {
+            const SMDS_MeshNode* node = f->GetNode( i );
+            if ( !helper->IsSeamShape( node->getshapeId() ))
+              notSeamNode[ iF ] = node;
+          }
         }
-        if ( !onBnd )
-          elems.insert( f );
-      }
-      // add also faces adjacent to faceToKeep
-      int nbNodes = faceToKeep->NbNodes();
-      if ( faceToKeep->IsQuadratic() ) nbNodes /= 2;
-      notInSet.insert( f1 );
-      notInSet.insert( f2 );
-      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_MeshAlgos::FindFaceInSet( n1, n2, inSet, notInSet );
-        if ( f1 )
-          elems.insert( f1 );
-      }
-    } // case on a sphere
-  } // loop on 2 faces
-
-  //  int quadFactor = (*Elems1.begin())->IsQuadratic() ? 2 : 1;
-
-  node1To2Map.clear();
-  int res = SMESH_MeshEditor::FindMatchingNodes( Elems1, Elems2,
-                                                 vNode1, vNode2,
-                                                 eNode1[0], eNode2[0],
-                                                 node1To2Map);
-  if ( res != SMESH_MeshEditor::SEW_OK )
-    RETURN_BAD_RESULT("FindMatchingNodes() result " << res );
+        gp_Pnt2d uv1 = helper->GetNodeUV( face, vNode, notSeamNode[0] );
+        gp_Pnt2d uv2 = helper->GetNodeUV( face, vNode, notSeamNode[1] );
+        if ( uv1.X() + uv1.Y() > uv2.X() + uv2.Y() )
+          faceToKeep = f2;
+        else
+          faceToKeep = f1;
+
+        // fill elem set
+        elems.insert( faceToKeep );
+        while ( eIt->more() ) {
+          const SMDS_MeshElement* f = eIt->next();
+          int nbNodes = f->NbNodes();
+          if ( f->IsQuadratic() )
+            nbNodes /= 2;
+          bool onBnd = false;
+          for ( int i = 0; !onBnd && i < nbNodes; ++i ) {
+            const SMDS_MeshNode* node = f->GetNode( i );
+            onBnd = ( node->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE);
+          }
+          if ( !onBnd )
+            elems.insert( f );
+        }
+        // add also faces adjacent to faceToKeep
+        int nbNodes = faceToKeep->NbNodes();
+        if ( faceToKeep->IsQuadratic() ) nbNodes /= 2;
+        notInSet.insert( f1 );
+        notInSet.insert( f2 );
+        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_MeshAlgos::FindFaceInSet( n1, n2, inSet, notInSet );
+          if ( f1 )
+            elems.insert( f1 );
+        }
+      } // case on a sphere
+    } // loop on 2 faces
+
+    node1To2Map.clear();
+    assocRes = SMESH_MeshEditor::FindMatchingNodes( Elems1, Elems2,
+                                                    vNode1, vNode2,
+                                                    eNode1[0], eNode2[0],
+                                                    node1To2Map);
+    if (( assocRes != SMESH_MeshEditor::SEW_OK ) &&
+        ( eNode1[1] || eNode2[1] )) // there is another node to try (on a closed EDGE)
+    {
+      node1To2Map.clear();
+      if ( eNode1[1] ) std::swap( eNode1[0], eNode1[1] );
+      else             std::swap( eNode2[0], eNode2[1] );
+      continue; // one more attempt
+    }
+
+    break;
+  }
+  if ( assocRes != SMESH_MeshEditor::SEW_OK )
+    RETURN_BAD_RESULT("FindMatchingNodes() result " << assocRes );
 
   // On a sphere, add matching nodes on the edge
 
index f8dd750..23732bd 100644 (file)
@@ -568,6 +568,7 @@ namespace {
       vector< gp_XYZ > srcPnts, tgtPnts;
       srcPnts.reserve( totNbSeg );
       tgtPnts.reserve( totNbSeg );
+      gp_XYZ srcBC( 0,0,0 ), tgtBC( 0,0,0 );
       for ( size_t iW = 0; iW < srcWires.size(); ++iW )
       {
         const double minSegLen = srcWires[iW]->Length() / totNbSeg;
@@ -584,6 +585,8 @@ namespace {
             tgtPnts.push_back( tgtWires[iW]->Value3d( tgtU ).XYZ() );
             srcU += srcDu;
             tgtU += tgtDu;
+            srcBC += srcPnts.back();
+            tgtBC += tgtPnts.back();
           }
         }
       }
@@ -596,6 +599,8 @@ namespace {
       const int nbTestPnt = 20;
       const size_t  iStep = Max( 1, int( srcPnts.size() / nbTestPnt ));
       // check boundary
+      gp_Pnt trsfTgt = trsf.Transform( srcBC / srcPnts.size() );
+      trsfIsOK = ( trsfTgt.SquareDistance( tgtBC / tgtPnts.size() ) < tol*tol );
       for ( size_t i = 0; ( i < srcPnts.size() && trsfIsOK ); i += iStep )
       {
         gp_Pnt trsfTgt = trsf.Transform( srcPnts[i] );
@@ -606,8 +611,8 @@ namespace {
       {
         BRepAdaptor_Surface srcSurf( srcFace );
         gp_Pnt srcP =
-          srcSurf.Value( 0.5 * ( srcSurf.FirstUParameter() + srcSurf.LastUParameter() ),
-                         0.5 * ( srcSurf.FirstVParameter() + srcSurf.LastVParameter() ));
+          srcSurf.Value( 0.321 * ( srcSurf.FirstUParameter() + srcSurf.LastUParameter() ),
+                         0.123 * ( srcSurf.FirstVParameter() + srcSurf.LastVParameter() ));
         gp_Pnt tgtTrsfP = trsf.Transform( srcP );
         TopLoc_Location loc;
         GeomAPI_ProjectPointOnSurf& proj = helper.GetProjector( tgtFace, loc, 0.1*tol );
@@ -888,10 +893,9 @@ namespace {
           case SMDS_TOP_EDGE: {
             TopoDS_Shape srcEdge = srcHelper.GetSubShapeByNode( srcNode, srcHelper.GetMeshDS() );
             TopoDS_Edge  tgtEdge = TopoDS::Edge( shape2ShapeMap( srcEdge, /*isSrc=*/true ));
-            tgtMeshDS->SetNodeOnEdge( n, TopoDS::Edge( tgtEdge ));
-            double U = srcHelper.GetNodeU( TopoDS::Edge( srcEdge ), srcNode );
+            double U = Precision::Infinite();
             helper.CheckNodeU( tgtEdge, n, U, Precision::PConfusion());
-            n->SetPosition(SMDS_PositionPtr(new SMDS_EdgePosition( U )));
+            tgtMeshDS->SetNodeOnEdge( n, TopoDS::Edge( tgtEdge ), U );
             break;
           }
           case SMDS_TOP_VERTEX: {
@@ -922,12 +926,12 @@ namespace {
    */
   //================================================================================
 
-  void fixDistortedFaces( SMESH_MesherHelper& helper,
+  bool fixDistortedFaces( SMESH_MesherHelper& helper,
                           TSideVector&        tgtWires )
   {
     SMESH_subMesh* faceSM = helper.GetMesh()->GetSubMesh( helper.GetSubShape() );
 
-    if ( helper.IsDistorted2D( faceSM ))
+    if ( helper.IsDistorted2D( faceSM, /*checkUV=*/false ))
     {
       SMESH_MeshEditor editor( helper.GetMesh() );
       SMESHDS_SubMesh* smDS = faceSM->GetSubMeshDS();
@@ -965,7 +969,12 @@ namespace {
       set<const SMDS_MeshNode*> fixedNodes;
       editor.Smooth( faces, fixedNodes, algo, /*nbIterations=*/ 10,
                      /*theTgtAspectRatio=*/1.0, /*the2D=*/!isPlanar);
+
+      helper.ToFixNodeParameters( true );
+
+      return !helper.IsDistorted2D( faceSM, /*checkUV=*/true );
     }
+    return true;
   }
 
 } // namespace
@@ -1048,25 +1057,28 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
   if ( err && !err->IsOK() )
     return error( err );
 
-  bool done = false;
+  bool projDone = false;
 
-  if ( !done )
+  if ( !projDone )
   {
     // try to project from the same face with different location
-    done = projectPartner( tgtFace, srcFace, tgtWires, srcWires,
-                           shape2ShapeMap, _src2tgtNodes, is1DComputed );
+    projDone = projectPartner( tgtFace, srcFace, tgtWires, srcWires,
+                               shape2ShapeMap, _src2tgtNodes, is1DComputed );
   }
-  if ( !done )
+  if ( !projDone )
   {
     // projection in case if the faces are similar in 2D space
-    done = projectBy2DSimilarity( tgtFace, srcFace, tgtWires, srcWires,
-                                  shape2ShapeMap, _src2tgtNodes, is1DComputed);
+    projDone = projectBy2DSimilarity( tgtFace, srcFace, tgtWires, srcWires,
+                                      shape2ShapeMap, _src2tgtNodes, is1DComputed);
   }
 
   SMESH_MesherHelper helper( theMesh );
   helper.SetSubShape( tgtFace );
 
-  if ( !done )
+  // it will remove mesh built on edges and vertices in failure case
+  MeshCleaner cleaner( tgtSubMesh );
+
+  if ( !projDone )
   {
     _src2tgtNodes.clear();
     // --------------------
@@ -1166,10 +1178,6 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
     if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
       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
-    MeshCleaner cleaner( tgtSubMesh );
-
     // -------------------------------------------------------------------------
     // mapper doesn't take care of nodes already existing on edges and vertices,
     // so we must merge nodes created by it with existing ones
@@ -1329,14 +1337,6 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
     if ( nbFaceBeforeMerge != nbFaceAtferMerge && !helper.HasDegeneratedEdges() )
       return error(COMPERR_BAD_INPUT_MESH, "Probably invalid node parameters on geom faces");
 
-
-    // ----------------------------------------------------------------
-    // The mapper can create distorted faces by placing nodes out of the FACE
-    // boundary -- fix bad faces by smoothing
-    // ----------------------------------------------------------------
-
-    fixDistortedFaces( helper, tgtWires );
-
     // ----------------------------------------------------------------
     // The mapper can't create quadratic elements, so convert if needed
     // ----------------------------------------------------------------
@@ -1355,11 +1355,18 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
       editor.ConvertToQuadratic(/*theForce3d=*/false, tgtFaces, false);
     }
 
-    cleaner.Release(); // not to remove mesh
-
   } // end of projection using Pattern mapping
 
 
+  if ( !projDone || is1DComputed )
+    // ----------------------------------------------------------------
+    // The mapper can create distorted faces by placing nodes out of the FACE
+    // boundary, also bad face can be created if EDGEs already discretized
+    // --> fix bad faces by smoothing
+    // ----------------------------------------------------------------
+    if ( !fixDistortedFaces( helper, tgtWires ))
+      return error("Invalid mesh generated");
+
   // ---------------------------
   // Check elements orientation
   // ---------------------------
@@ -1405,6 +1412,8 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
     }
   }
 
+  cleaner.Release(); // not to remove mesh
+
   return true;
 }