X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FStdMeshers%2FStdMeshers_Prism_3D.cxx;h=212ea62b8b6cc88a18b905f6c7e749d476998409;hp=62f538d84d72e927508e3add571619d4ba4d557f;hb=b9986eb294440b54b4d95e24af5b86bb0478de26;hpb=b905bf1432be723426745721b4afde568d54d459 diff --git a/src/StdMeshers/StdMeshers_Prism_3D.cxx b/src/StdMeshers/StdMeshers_Prism_3D.cxx index 62f538d84..212ea62b8 100644 --- a/src/StdMeshers/StdMeshers_Prism_3D.cxx +++ b/src/StdMeshers/StdMeshers_Prism_3D.cxx @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -661,12 +662,14 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh Prism_3D::TPrismTopo prism; myPropagChains = 0; + bool selectBottom = meshedFaces.empty(); if ( nbSolids == 1 ) { + TopoDS_Shape solid = TopExp_Explorer( theShape, TopAbs_SOLID ).Current(); if ( !meshedFaces.empty() ) prism.myBottom = meshedFaces.front(); - return ( initPrism( prism, TopExp_Explorer( theShape, TopAbs_SOLID ).Current() ) && + return ( initPrism( prism, solid, selectBottom ) && compute( prism )); } @@ -709,7 +712,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 +765,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 +792,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 +815,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 +836,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 +851,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 +883,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 +1088,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 +1105,23 @@ 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 (( botSM->IsEmpty() ) && + ( ! botSM->GetAlgo() || + ! _gen->Compute( *botSM->GetFather(), botSM->GetSubShape(), /*shapeOnly=*/true ))) + 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 +1150,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 +1160,33 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism) // use transformation (issue 0020680, IPAL0052499) StdMeshers_Sweeper sweeper; + double tol; + bool allowHighBndError; - // 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 - ( 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 + ( 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 ); + allowHighBndError = !isSimpleBottom( thePrism ); + } - if ( sweeper.ComputeNodes( *myHelper, tol )) + if ( !myUseBlock && sweeper.ComputeNodes( *myHelper, tol, allowHighBndError )) { } else // use block approach @@ -1528,7 +1562,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 +1972,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 +1985,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 +2003,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 +2014,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 +2024,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 +2048,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 +2072,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 +2086,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 +2164,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))); } @@ -2168,11 +2215,11 @@ bool StdMeshers_Prism_3D::projectBottomToTop( const gp_Trsf & bottom case 3: { newFace = myHelper->AddFace(nodes[0], nodes[1], nodes[2]); break; - } + } case 4: { newFace = myHelper->AddFace( nodes[0], nodes[1], nodes[2], nodes[3] ); break; - } + } default: newFace = meshDS->AddPolygonalFace( nodes ); } @@ -2180,7 +2227,42 @@ bool StdMeshers_Prism_3D::projectBottomToTop( const gp_Trsf & bottom meshDS->SetMeshElementOnShape( newFace, topFaceID ); } - myHelper->SetElementsOnShape( oldSetElemsOnShape ); + myHelper->SetElementsOnShape( oldSetElemsOnShape ); + + // Check the projected mesh + + if ( thePrism.myNbEdgesInWires.size() > 1 && // there are holes + topHelper.IsDistorted2D( topSM, /*checkUV=*/false )) + { + SMESH_MeshEditor editor( topHelper.GetMesh() ); + + // smooth in 2D or 3D? + TopLoc_Location loc; + Handle(Geom_Surface) surface = BRep_Tool::Surface( topFace, loc ); + bool isPlanar = GeomLib_IsPlanarSurface( surface ).IsPlanar(); + + bool isFixed = false; + set fixedNodes; + for ( int iAttemp = 0; !isFixed && iAttemp < 10; ++iAttemp ) + { + TIDSortedElemSet faces; + for ( faceIt = topSMDS->GetElements(); faceIt->more(); ) + faces.insert( faces.end(), faceIt->next() ); + + SMESH_MeshEditor::SmoothMethod algo = + iAttemp ? SMESH_MeshEditor::CENTROIDAL : SMESH_MeshEditor::LAPLACIAN; + + // smoothing + editor.Smooth( faces, fixedNodes, algo, /*nbIterations=*/ 10, + /*theTgtAspectRatio=*/1.0, /*the2D=*/!isPlanar); + + isFixed = !topHelper.IsDistorted2D( topSM, /*checkUV=*/true ); + } + if ( !isFixed ) + return toSM( error( TCom("Projection from face #") << botSM->GetId() + << " to face #" << topSM->GetId() + << " failed: inverted elements created")); + } return true; } @@ -2256,6 +2338,44 @@ double StdMeshers_Prism_3D::getSweepTolerance( const Prism_3D::TPrismTopo& thePr return 0.1 * Sqrt ( minDist ); } +//======================================================================= +//function : isSimpleQuad +//purpose : check if the bottom FACE is meshable with nice qudrangles, +// if so the block aproach can work rather fast. +// This is a temporary mean caused by problems in StdMeshers_Sweeper +//======================================================================= + +bool StdMeshers_Prism_3D::isSimpleBottom( const Prism_3D::TPrismTopo& thePrism ) +{ + // analyse angles between edges + double nbConcaveAng = 0, nbConvexAng = 0; + TopoDS_Face reverseBottom = TopoDS::Face( thePrism.myBottom.Reversed() ); // see initPrism() + TopoDS_Vertex commonV; + const list< TopoDS_Edge >& botEdges = thePrism.myBottomEdges; + list< TopoDS_Edge >::const_iterator edge = botEdges.begin(); + while ( edge != botEdges.end() ) + { + if ( SMESH_Algo::isDegenerated( *edge )) + return false; + TopoDS_Edge e1 = *edge++; + TopoDS_Edge e2 = ( edge == botEdges.end() ? botEdges.front() : *edge ); + if ( ! TopExp::CommonVertex( e1, e2, commonV )) + { + e2 = botEdges.front(); + if ( ! TopExp::CommonVertex( e1, e2, commonV )) + break; + } + double angle = myHelper->GetAngle( e1, e2, reverseBottom, commonV ); + if ( angle < -5 * M_PI/180 ) + if ( ++nbConcaveAng > 1 ) + return false; + if ( angle > 85 * M_PI/180 ) + if ( ++nbConvexAng > 4 ) + return false; + } + return true; +} + //======================================================================= //function : project2dMesh //purpose : Project mesh faces from a source FACE of one prism (theSrcFace) @@ -2270,6 +2390,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,16 +2914,18 @@ void StdMeshers_PrismAsBlock::Clear() //======================================================================= bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism, - const TopoDS_Shape& shape3D) + const TopoDS_Shape& theShape3D, + const bool selectBottom) { - myHelper->SetSubShape( shape3D ); + myHelper->SetSubShape( theShape3D ); - SMESH_subMesh* mainSubMesh = myHelper->GetMesh()->GetSubMeshContaining( shape3D ); + SMESH_subMesh* mainSubMesh = myHelper->GetMesh()->GetSubMeshContaining( theShape3D ); if ( !mainSubMesh ) return toSM( error(COMPERR_BAD_INPUT_MESH,"Null submesh of shape3D")); // detect not-quad FACE sub-meshes of the 3D SHAPE list< SMESH_subMesh* > notQuadGeomSubMesh; list< SMESH_subMesh* > notQuadElemSubMesh; + list< SMESH_subMesh* > meshedSubMesh; int nbFaces = 0; // SMESH_subMesh* anyFaceSM = 0; @@ -2816,10 +2947,14 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism, if ( nbWires != 1 || nbEdgesInWires.front() != 4 ) notQuadGeomSubMesh.push_back( sm ); - // look for not quadrangle mesh elements - if ( SMESHDS_SubMesh* smDS = sm->GetSubMeshDS() ) - if ( !myHelper->IsSameElemGeometry( smDS, SMDSGeom_QUADRANGLE )) + // look for a not structured sub-mesh + if ( !sm->IsEmpty() ) + { + meshedSubMesh.push_back( sm ); + if ( !myHelper->IsSameElemGeometry( sm->GetSubMeshDS(), SMDSGeom_QUADRANGLE ) || + !myHelper->IsStructured ( sm )) notQuadElemSubMesh.push_back( sm ); + } } int nbNotQuadMeshed = notQuadElemSubMesh.size(); @@ -2884,33 +3019,50 @@ 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() ) + bool savedSetErrorToSM = mySetErrorToSM; + mySetErrorToSM = false; // ingore errors in initPrism() + + // search among meshed FACEs + list< SMESH_subMesh* >::iterator sm = meshedSubMesh.begin(); + for ( ; !botSM && sm != meshedSubMesh.end(); ++sm ) + { + thePrism.Clear(); + botSM = *sm; + thePrism.myBottom = TopoDS::Face( botSM->GetSubShape() ); + if ( !initPrism( thePrism, theShape3D, /*selectBottom=*/false )) + botSM = NULL; + } + // search among all FACEs + for ( TopExp_Explorer f( theShape3D, TopAbs_FACE ); !botSM && f.More(); f.Next() ) { int minNbFaces = 2 + myHelper->Count( f.Current(), TopAbs_EDGE, false); - if ( nbFaces >= minNbFaces) - { - thePrism.Clear(); - thePrism.myBottom = TopoDS::Face( f.Current() ); - if ( initPrism( thePrism, shape3D )) - return true; - } - return toSM( error( COMPERR_BAD_SHAPE )); + if ( nbFaces < minNbFaces) continue; + thePrism.Clear(); + thePrism.myBottom = TopoDS::Face( f.Current() ); + botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom ); + if ( !initPrism( thePrism, theShape3D, /*selectBottom=*/false )) + botSM = NULL; } + mySetErrorToSM = savedSetErrorToSM; + return botSM ? true : toSM( error( COMPERR_BAD_SHAPE )); } // find vertex 000 - the one with smallest coordinates (for easy DEBUG :-) @@ -2929,11 +3081,11 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism, } } - thePrism.myShape3D = shape3D; + thePrism.myShape3D = theShape3D; if ( thePrism.myBottom.IsNull() ) thePrism.myBottom = TopoDS::Face( botSM->GetSubShape() ); - thePrism.myBottom.Orientation( myHelper->GetSubShapeOri( shape3D, thePrism.myBottom )); - thePrism.myTop. Orientation( myHelper->GetSubShapeOri( shape3D, thePrism.myTop )); + thePrism.myBottom.Orientation( myHelper->GetSubShapeOri( theShape3D, thePrism.myBottom )); + thePrism.myTop. Orientation( myHelper->GetSubShapeOri( theShape3D, thePrism.myTop )); // Get ordered bottom edges TopoDS_Face reverseBottom = // to have order of top EDGEs as in the top FACE @@ -2943,7 +3095,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 +4039,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() ) @@ -4430,7 +4582,8 @@ void StdMeshers_Sweeper::applyBoundaryError(const vector< gp_XYZ >& bndPoints, //================================================================================ bool StdMeshers_Sweeper::ComputeNodes( SMESH_MesherHelper& helper, - const double tol) + const double tol, + const bool allowHighBndError) { const size_t zSize = myBndColumns[0]->size(); const size_t zSrc = 0, zTgt = zSize-1; @@ -4549,6 +4702,9 @@ bool StdMeshers_Sweeper::ComputeNodes( SMESH_MesherHelper& helper, bndErrorIsSmall = ( sumError < tol ); } + if ( !bndErrorIsSmall && !allowHighBndError ) + return false; + // compute final points on the central layer std::vector< double > int2BndDist( myBndColumns.size() ); // work array of applyBoundaryError() double r = zS / ( zSize - 1.);