X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FStdMeshers%2FStdMeshers_Prism_3D.cxx;h=07666af9fbde8cfe620e684c4137b86668c60622;hp=4dd948be3fb334511a0ec02dc5ccc5890635eb59;hb=db6f1785f59eaa5f2d813dc89a83f9739fcf60ef;hpb=85f0b9ca1604fd6f50e91388d3ce04769c5b03e4 diff --git a/src/StdMeshers/StdMeshers_Prism_3D.cxx b/src/StdMeshers/StdMeshers_Prism_3D.cxx index 4dd948be3..07666af9f 100644 --- a/src/StdMeshers/StdMeshers_Prism_3D.cxx +++ b/src/StdMeshers/StdMeshers_Prism_3D.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2019 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 @@ -33,6 +33,7 @@ #include "SMESH_Comment.hxx" #include "SMESH_Gen.hxx" #include "SMESH_HypoFilter.hxx" +#include "SMESH_MeshEditor.hxx" #include "SMESH_MesherHelper.hxx" #include "StdMeshers_FaceSide.hxx" #include "StdMeshers_ProjectionSource1D.hxx" @@ -96,15 +97,14 @@ namespace { */ struct TQuadrangleAlgo : public StdMeshers_Quadrangle_2D { - TQuadrangleAlgo(int studyId, SMESH_Gen* gen) - : StdMeshers_Quadrangle_2D( gen->GetANewId(), studyId, gen) + TQuadrangleAlgo(SMESH_Gen* gen) + : StdMeshers_Quadrangle_2D( gen->GetANewId(), gen) { } static StdMeshers_Quadrangle_2D* instance( SMESH_Algo* fatherAlgo, SMESH_MesherHelper* helper=0) { - static TQuadrangleAlgo* algo = new TQuadrangleAlgo( fatherAlgo->GetStudyId(), - fatherAlgo->GetGen() ); + static TQuadrangleAlgo* algo = new TQuadrangleAlgo( fatherAlgo->GetGen() ); if ( helper && algo->myProxyMesh && algo->myProxyMesh->GetMesh() != helper->GetMesh() ) @@ -127,16 +127,15 @@ namespace { { StdMeshers_ProjectionSource1D myHyp; - TProjction1dAlgo(int studyId, SMESH_Gen* gen) - : StdMeshers_Projection_1D( gen->GetANewId(), studyId, gen), - myHyp( gen->GetANewId(), studyId, gen) + TProjction1dAlgo(SMESH_Gen* gen) + : StdMeshers_Projection_1D( gen->GetANewId(), gen), + myHyp( gen->GetANewId(), gen) { StdMeshers_Projection_1D::_sourceHypo = & myHyp; } static TProjction1dAlgo* instance( SMESH_Algo* fatherAlgo ) { - static TProjction1dAlgo* algo = new TProjction1dAlgo( fatherAlgo->GetStudyId(), - fatherAlgo->GetGen() ); + static TProjction1dAlgo* algo = new TProjction1dAlgo( fatherAlgo->GetGen() ); return algo; } }; @@ -148,16 +147,15 @@ namespace { { StdMeshers_ProjectionSource2D myHyp; - TProjction2dAlgo(int studyId, SMESH_Gen* gen) - : StdMeshers_Projection_1D2D( gen->GetANewId(), studyId, gen), - myHyp( gen->GetANewId(), studyId, gen) + TProjction2dAlgo(SMESH_Gen* gen) + : StdMeshers_Projection_1D2D( gen->GetANewId(), gen), + myHyp( gen->GetANewId(), gen) { StdMeshers_Projection_2D::_sourceHypo = & myHyp; } static TProjction2dAlgo* instance( SMESH_Algo* fatherAlgo ) { - static TProjction2dAlgo* algo = new TProjction2dAlgo( fatherAlgo->GetStudyId(), - fatherAlgo->GetGen() ); + static TProjction2dAlgo* algo = new TProjction2dAlgo( fatherAlgo->GetGen() ); return algo; } const NSProjUtils::TNodeNodeMap& GetNodesMap() @@ -458,7 +456,7 @@ namespace { int nbEdges = thePrism.myNbEdgesInWires.front(); // nb outer edges int nbSides = nbEdges; - + list< TopoDS_Edge >::const_iterator edgeIt = thePrism.myBottomEdges.begin(); std::advance( edgeIt, nbEdges-1 ); TopoDS_Edge prevE = *edgeIt; @@ -526,7 +524,7 @@ namespace { // isPrevStraight = isCurStraight; // iPrev = iE; // } - + return nbSides; } @@ -565,11 +563,11 @@ namespace { //======================================================================= //function : StdMeshers_Prism_3D -//purpose : +//purpose : //======================================================================= -StdMeshers_Prism_3D::StdMeshers_Prism_3D(int hypId, int studyId, SMESH_Gen* gen) - :SMESH_3D_Algo(hypId, studyId, gen) +StdMeshers_Prism_3D::StdMeshers_Prism_3D(int hypId, SMESH_Gen* gen) + :SMESH_3D_Algo(hypId, gen) { _name = "Prism_3D"; _shapeType = (1 << TopAbs_SOLID); // 1 bit per shape type @@ -597,7 +595,7 @@ StdMeshers_Prism_3D::~StdMeshers_Prism_3D() //======================================================================= //function : CheckHypothesis -//purpose : +//purpose : //======================================================================= bool StdMeshers_Prism_3D::CheckHypothesis(SMESH_Mesh& aMesh, @@ -924,7 +922,7 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism, StdMeshers_Quadrangle_2D* quadAlgo = TQuadrangleAlgo::instance( this, myHelper ); TopTools_MapOfShape faceMap; - TopTools_IndexedDataMapOfShapeListOfShape edgeToFaces; + TopTools_IndexedDataMapOfShapeListOfShape edgeToFaces; TopExp::MapShapesAndAncestors( thePrism.myShape3D, TopAbs_EDGE, TopAbs_FACE, edgeToFaces ); @@ -1170,6 +1168,11 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism) if ( !assocOrProjBottom2Top( bottomToTopTrsf, thePrism ) ) // it also fills myBotToColumnMap return false; + // If all "vertical" EDGEs are straight, then all nodes of an internal node column + // are located on a line connecting the top node and the bottom node. + bool isStrightColunm = allVerticalEdgesStraight( thePrism ); + if ( isStrightColunm ) + myUseBlock = false; // Create nodes inside the block @@ -1208,9 +1211,6 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism) myHelper->SetElementsOnShape( true ); - // If all "vertical" EDGEs are straight, then all nodes of an internal node column - // are located on a line connecting the top node and the bottom node. - bool isStrightColunm = allVerticalEdgesStraight( thePrism ); if ( !isStrightColunm ) { double tol = getSweepTolerance( thePrism ); @@ -1653,7 +1653,7 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism) for ( size_t iN = 1; iN < srcNodeStr.size(); ++iN ) // add segments { // find an EDGE to set a new segment - std::pair id2type = + std::pair id2type = myHelper->GetMediumPos( newNodes[ iN-1 ], newNodes[ iN ] ); if ( id2type.second != TopAbs_EDGE ) { @@ -1673,7 +1673,7 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism) { SMESH_MeshEditor::TListOfListOfNodes lln( 1, list< const SMDS_MeshNode* >() ); lln.back().push_back ( vn ); - lln.back().push_front( newNodes[ iN-isPrev ] ); // to keep + lln.back().push_front( newNodes[ iN-isPrev ] ); // to keep SMESH_MeshEditor( mesh ).MergeNodes( lln ); } } @@ -1798,9 +1798,8 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism) if ( myHelper->GetIsQuadratic() ) { // fill myHelper with medium nodes built by quadAlgo - SMDS_ElemIteratorPtr fIt = fSM->GetSubMeshDS()->GetElements(); - while ( fIt->more() ) - myHelper->AddTLinks( dynamic_cast( fIt->next() )); + for ( SMDS_ElemIteratorPtr fIt = fSM->GetSubMeshDS()->GetElements(); fIt->more(); ) + myHelper->AddTLinks( SMDS_Mesh::DownCast( fIt->next() )); } } } @@ -1999,7 +1998,7 @@ bool StdMeshers_Prism_3D::Evaluate(SMESH_Mesh& theMesh, std::vector aVec = (*anIt).second; nb2d += Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]); } - + MapShapeNbElemsItr anIt = aResMap.find( meshFaces[NumBase-1] ); std::vector aVec = (*anIt).second; bool IsQuadratic = (aVec[SMDSEntity_Quad_Triangle]>aVec[SMDSEntity_Triangle]) || @@ -2312,7 +2311,7 @@ bool StdMeshers_Prism_3D::projectBottomToTop( const gp_Trsf & bottom { return true; } - NSProjUtils::TNodeNodeMap& n2nMap = + NSProjUtils::TNodeNodeMap& n2nMap = (NSProjUtils::TNodeNodeMap&) TProjction2dAlgo::instance( this )->GetNodesMap(); n2nMap.clear(); @@ -2397,7 +2396,7 @@ bool StdMeshers_Prism_3D::projectBottomToTop( const gp_Trsf & bottom meshDS->MoveNode( topNode, distXYZ[1], distXYZ[2], distXYZ[3] ); // transform can be inaccurate } // create node column - TNode2ColumnMap::iterator bN_col = + TNode2ColumnMap::iterator bN_col = myBotToColumnMap.insert( make_pair ( bN, TNodeColumn() )).first; TNodeColumn & column = bN_col->second; column.resize( zSize ); @@ -2545,7 +2544,7 @@ double StdMeshers_Prism_3D::getSweepTolerance( const Prism_3D::TPrismTopo& thePr for ( int iN = 0; iN < nbNodes; ++iN ) nodes[ iN ] = nIt->next(); nodes.back() = nodes[0]; - + // loop on links double dist2; for ( int iN = 0; iN < nbNodes; ++iN ) @@ -2591,7 +2590,7 @@ double StdMeshers_Prism_3D::getSweepTolerance( const Prism_3D::TPrismTopo& thePr //======================================================================= //function : isSimpleQuad //purpose : check if the bottom FACE is meshable with nice quadrangles, -// if so the block aproach can work rather fast. +// if so the block approach can work rather fast. // This is a temporary mean caused by problems in StdMeshers_Sweeper //======================================================================= @@ -2772,22 +2771,53 @@ namespace // utils used by StdMeshers_Prism_3D::IsApplicable() { struct EdgeWithNeighbors { - TopoDS_Edge _edge; - int _iBase; /* index in a WIRE with non-base EDGEs excluded */ - int _iL, _iR; /* used to connect edges in a base FACE */ - bool _isBase; /* is used in a base FACE */ - EdgeWithNeighbors(const TopoDS_Edge& E, int iE, int nbE, int shift, bool isBase ): - _edge( E ), _iBase( iE + shift ), - _iL( SMESH_MesherHelper::WrapIndex( iE-1, Max( 1, nbE )) + shift ), - _iR( SMESH_MesherHelper::WrapIndex( iE+1, Max( 1, nbE )) + shift ), + TopoDS_Edge _edge; + int _iBase; // index in a WIRE with non-base EDGEs excluded + int _iL, _iR; // used to connect PrismSide's + int _iE; // index in a WIRE + int _iLE, _iRE; // used to connect EdgeWithNeighbors's + bool _isBase; // is used in a base FACE + TopoDS_Vertex _vv[2]; // end VERTEXes + EdgeWithNeighbors(const TopoDS_Edge& E, + int iE, int nbE, int shift, + int iEE, int nbEE, int shiftE, + bool isBase, bool setVV ): + _edge( E ), + _iBase( iE + shift ), + _iL ( SMESH_MesherHelper::WrapIndex( iE-1, Max( 1, nbE )) + shift ), + _iR ( SMESH_MesherHelper::WrapIndex( iE+1, Max( 1, nbE )) + shift ), + _iE ( iEE + shiftE ), + _iLE( SMESH_MesherHelper::WrapIndex( iEE-1, Max( 1, nbEE )) + shiftE ), + _iRE( SMESH_MesherHelper::WrapIndex( iEE+1, Max( 1, nbEE )) + shiftE ), _isBase( isBase ) { + if ( setVV ) + { + Vertex( 0 ); + Vertex( 1 ); + } } EdgeWithNeighbors() {} bool IsInternal() const { return !_edge.IsNull() && _edge.Orientation() == TopAbs_INTERNAL; } + bool IsConnected( const EdgeWithNeighbors& edge, int iEnd ) const + { + return (( _vv[ iEnd ].IsSame( edge._vv[ 1 - iEnd ])) || + ( IsInternal() && _vv[ iEnd ].IsSame( edge._vv[ iEnd ]))); + } + bool IsConnected( const std::vector< EdgeWithNeighbors > & edges, int iEnd ) const + { + int iEdge = iEnd ? _iRE : _iLE; + return iEdge == _iE ? false : IsConnected( edges[ iEdge ], iEnd ); + } + const TopoDS_Vertex& Vertex( int iEnd ) + { + if ( _vv[ iEnd ].IsNull() ) + _vv[ iEnd ] = SMESH_MesherHelper::IthVertex( iEnd, _edge ); + return _vv[ iEnd ]; + } }; - // PrismSide contains all FACEs linking a bottom EDGE with a top one. - struct PrismSide + // PrismSide contains all FACEs linking a bottom EDGE with a top one. + struct PrismSide { TopoDS_Face _face; // a currently treated upper FACE TopTools_IndexedMapOfShape *_faces; // all FACEs (pointer because of a private copy constructor) @@ -2799,8 +2829,8 @@ namespace // utils used by StdMeshers_Prism_3D::IsApplicable() PrismSide *_leftSide; // neighbor sides PrismSide *_rightSide; bool _isInternal; // whether this side raises from an INTERNAL EDGE - void SetExcluded() { _leftSide = _rightSide = NULL; } - bool IsExcluded() const { return !_leftSide; } + //void SetExcluded() { _leftSide = _rightSide = NULL; } + //bool IsExcluded() const { return !_leftSide; } const TopoDS_Edge& Edge( int i ) const { return (*_edges)[ i ]._edge; @@ -2811,14 +2841,33 @@ namespace // utils used by StdMeshers_Prism_3D::IsApplicable() if ( E.IsSame( Edge( i ))) return i; return -1; } - bool IsSideFace( const TopoDS_Shape& face, const bool checkNeighbors ) const + const TopoDS_Vertex& Vertex( int iE, int iEnd ) const { - if ( _faces->Contains( face )) // avoid returning true for a prism top FACE - return ( !_face.IsNull() || !( face.IsSame( _faces->FindKey( _faces->Extent() )))); - + return (*_edges)[ iE ].Vertex( iEnd ); + } + bool HasVertex( const TopoDS_Vertex& V ) const + { + for ( size_t i = 0; i < _edges->size(); ++i ) + if ( V.IsSame( Vertex( i, 0 ))) return true; + return false; + } + bool IsSideFace( const TopTools_ListOfShape& faces, + const TopoDS_Face& avoidFace, + const bool checkNeighbors ) const + { + TopTools_ListIteratorOfListOfShape faceIt( faces ); + for ( ; faceIt.More(); faceIt.Next() ) + { + const TopoDS_Shape& face = faceIt.Value(); + if ( !face.IsSame( avoidFace )) + { + if ( _faces->Contains( face )) // avoid returning true for a prism top FACE + return ( !_face.IsNull() || !( face.IsSame( _faces->FindKey( _faces->Extent() )))); + } + } if ( checkNeighbors ) - return (( _leftSide && _leftSide->IsSideFace ( face, false )) || - ( _rightSide && _rightSide->IsSideFace( face, false ))); + return (( _leftSide && _leftSide->IsSideFace ( faces, avoidFace, false )) || + ( _rightSide && _rightSide->IsSideFace( faces, avoidFace, false ))); return false; } @@ -2828,20 +2877,39 @@ namespace // utils used by StdMeshers_Prism_3D::IsApplicable() * \brief Return another faces sharing an edge */ const TopoDS_Face & getAnotherFace( const TopoDS_Face& face, - const TopoDS_Edge& edge, - TopTools_IndexedDataMapOfShapeListOfShape& facesOfEdge) + const TopTools_ListOfShape& faces) { - TopTools_ListIteratorOfListOfShape faceIt( facesOfEdge.FindFromKey( edge )); + TopTools_ListIteratorOfListOfShape faceIt( faces ); for ( ; faceIt.More(); faceIt.Next() ) if ( !face.IsSame( faceIt.Value() )) return TopoDS::Face( faceIt.Value() ); return face; } + //-------------------------------------------------------------------------------- + /*! + * \brief Return another faces sharing an edge + */ + const TopoDS_Face & getAnotherFace( const TopoDS_Face& face, + const TopoDS_Edge& edge, + TopTools_IndexedDataMapOfShapeListOfShape& facesOfEdge) + { + return getAnotherFace( face, facesOfEdge.FindFromKey( edge )); + } //-------------------------------------------------------------------------------- /*! * \brief Return ordered edges of a face */ + //================================================================================ + /*! + * \brief Return ordered edges of a face + * \param [in] face - the face + * \param [out] edges - return edge (edges from which no vertical faces raise excluded) + * \param [in] facesOfEdge - faces of each edge + * \param [in] noHolesAllowed - are multiple wires allowed + */ + //================================================================================ + bool getEdges( const TopoDS_Face& face, vector< EdgeWithNeighbors > & edges, TopTools_IndexedDataMapOfShapeListOfShape& facesOfEdge, @@ -2857,11 +2925,10 @@ namespace // utils used by StdMeshers_Prism_3D::IsApplicable() if ( nbW > 1 && noHolesAllowed ) return false; - int iE, nbTot = 0, nbBase, iBase; list< TopoDS_Edge >::iterator e = ee.begin(); list< int >::iterator nbE = nbEdgesInWires.begin(); for ( ; nbE != nbEdgesInWires.end(); ++nbE ) - for ( iE = 0; iE < *nbE; ++e, ++iE ) + for ( int iE = 0; iE < *nbE; ++e, ++iE ) if ( SMESH_Algo::isDegenerated( *e )) // degenerated EDGE is never used { e = --ee.erase( e ); @@ -2869,6 +2936,7 @@ namespace // utils used by StdMeshers_Prism_3D::IsApplicable() --iE; } + int iE, nbTot = 0, iBase, nbBase, nbTotBase = 0; vector isBase; edges.clear(); e = ee.begin(); @@ -2884,40 +2952,51 @@ namespace // utils used by StdMeshers_Prism_3D::IsApplicable() } for ( iBase = 0, iE = 0; iE < *nbE; ++e, ++iE ) { - edges.push_back( EdgeWithNeighbors( *e, iBase, nbBase, nbTot, isBase[ iE ] )); + edges.push_back( EdgeWithNeighbors( *e, + iBase, nbBase, nbTotBase, + iE, *nbE, nbTot, + isBase[ iE ], nbW > 1 )); iBase += isBase[ iE ]; } - nbTot += nbBase; + nbTot += *nbE; + nbTotBase += nbBase; } - if ( nbTot == 0 ) + if ( nbTotBase == 0 ) return false; - // IPAL53099. Set correct neighbors to INTERNAL EDGEs, which can be connected to - // EDGEs of the outer WIRE but this fact can't be detected by their order. + // IPAL53099, 54416. Set correct neighbors to INTERNAL EDGEs if ( nbW > 1 ) { int iFirst = 0, iLast; for ( nbE = nbEdgesInWires.begin(); nbE != nbEdgesInWires.end(); ++nbE ) { iLast = iFirst + *nbE - 1; - TopoDS_Vertex vv[2] = { SMESH_MesherHelper::IthVertex( 0, edges[ iFirst ]._edge ), - SMESH_MesherHelper::IthVertex( 1, edges[ iLast ]._edge ) }; - bool isConnectOk = ( vv[0].IsSame( vv[1] )); + bool isConnectOk = ( edges[ iFirst ].IsConnected( edges, 0 ) && + edges[ iFirst ].IsConnected( edges, 1 )); if ( !isConnectOk ) { - edges[ iFirst ]._iL = edges[ iFirst ]._iBase; // connect to self - edges[ iLast ]._iR = edges[ iLast ]._iBase; - - // look for an EDGE of the outer WIREs connected to vv - TopoDS_Vertex v0, v1; - for ( iE = 0; iE < iFirst; ++iE ) + for ( iE = iFirst; iE <= iLast; ++iE ) { - v0 = SMESH_MesherHelper::IthVertex( 0, edges[ iE ]._edge ); - v1 = SMESH_MesherHelper::IthVertex( 1, edges[ iE ]._edge ); - if ( vv[0].IsSame( v0 ) || vv[0].IsSame( v1 )) - edges[ iFirst ]._iL = edges[ iE ]._iBase; - if ( vv[1].IsSame( v0 ) || vv[1].IsSame( v1 )) - edges[ iLast ]._iR = edges[ iE ]._iBase; + if ( !edges[ iE ]._isBase ) + continue; + int* iNei[] = { & edges[ iE ]._iL, + & edges[ iE ]._iR }; + for ( int iV = 0; iV < 2; ++iV ) + { + if ( edges[ iE ].IsConnected( edges, iV )) + continue; // Ok - connected to a neighbor EDGE + + // look for a connected EDGE + bool found = false; + for ( int iE2 = 0, nbE = edges.size(); iE2 < nbE && !found; ++iE2 ) + if (( iE2 != iE ) && + ( found = edges[ iE ].IsConnected( edges[ iE2 ], iV ))) + { + *iNei[ iV ] = edges[ iE2 ]._iBase; + } + if ( !found ) + *iNei[ iV ] = edges[ iE ]._iBase; // connect to self + } } } iFirst += *nbE; @@ -2925,7 +3004,7 @@ namespace // utils used by StdMeshers_Prism_3D::IsApplicable() } return edges.size(); } - + //-------------------------------------------------------------------------------- /*! * \brief Return number of faces sharing given edges @@ -3050,11 +3129,11 @@ bool StdMeshers_Prism_3D::IsApplicable(const TopoDS_Shape & shape, bool toCheckA } bool isOK = true; // ok for a current botF - bool isAdvanced = true; // is new data found in a current loop + bool hasAdvanced = true; // is new data found in a current loop int nbFoundSideFaces = 0; - for ( int iLoop = 0; isOK && isAdvanced; ++iLoop ) + for ( int iLoop = 0; isOK && hasAdvanced; ++iLoop ) { - isAdvanced = false; + hasAdvanced = false; for ( size_t iS = 0; iS < sides.size() && isOK; ++iS ) { PrismSide& side = sides[ iS ]; @@ -3063,22 +3142,35 @@ bool StdMeshers_Prism_3D::IsApplicable(const TopoDS_Shape & shape, bool toCheckA if ( side._topEdge.IsNull() ) { - // find vertical EDGEs --- EGDEs shared with neighbor side FACEs + // find vertical EDGEs --- EDGEs shared with neighbor side FACEs for ( int is2nd = 0; is2nd < 2 && isOK; ++is2nd ) // 2 adjacent neighbors { - int di = is2nd ? 1 : -1; const PrismSide* adjSide = is2nd ? side._rightSide : side._leftSide; + if ( side._isInternal ) + { + const TopoDS_Vertex& V = side.Vertex( side._iBotEdge, is2nd ); + bool lHasV = side._leftSide ->HasVertex( V ); + bool rHasV = side._rightSide->HasVertex( V ); + if ( lHasV == rHasV ) + adjSide = ( &side == side._leftSide ) ? side._rightSide : side._leftSide; + else + adjSide = ( rHasV ) ? side._rightSide : side._leftSide; + } + int di = is2nd ? 1 : -1; for ( size_t i = 1; i < side._edges->size(); ++i ) { int iE = SMESH_MesherHelper::WrapIndex( i*di + side._iBotEdge, side._edges->size()); if ( side._isCheckedEdge[ iE ] ) continue; - const TopoDS_Edge& vertE = side.Edge( iE ); - const TopoDS_Shape& neighborF = getAnotherFace( side._face, vertE, facesOfEdge ); - bool isEdgeShared = (( adjSide->IsSideFace( neighborF, side._isInternal )) || - ( adjSide == &side && neighborF.IsSame( side._face )) ); + const TopoDS_Edge& vertE = side.Edge( iE ); + const TopTools_ListOfShape& neighborFF = facesOfEdge.FindFromKey( vertE ); + bool isEdgeShared = (( adjSide->IsSideFace( neighborFF, side._face, + side._isInternal )) || + ( adjSide == &side && + side._face.IsSame( getAnotherFace( side._face, + neighborFF )))); if ( isEdgeShared ) // vertE is shared with adjSide { - isAdvanced = true; + hasAdvanced = true; side._isCheckedEdge[ iE ] = true; side._nbCheckedEdges++; int nbNotCheckedE = side._edges->size() - side._nbCheckedEdges; @@ -3146,7 +3238,7 @@ bool StdMeshers_Prism_3D::IsApplicable(const TopoDS_Shape & shape, bool toCheckA const int nbE = side._edges->size(); if ( nbE >= 4 ) { - isAdvanced = true; + hasAdvanced = true; ++nbFoundSideFaces; side._iBotEdge = side.FindEdge( side._topEdge ); side._isCheckedEdge.clear(); @@ -3176,7 +3268,7 @@ bool StdMeshers_Prism_3D::IsApplicable(const TopoDS_Shape & shape, bool toCheckA cerr << "BUG: infinite loop in StdMeshers_Prism_3D::IsApplicable()" << endl; #endif } - } // while isAdvanced + } // while hasAdvanced if ( isOK && sides[0]._faces->Extent() > 1 ) { @@ -3187,12 +3279,20 @@ bool StdMeshers_Prism_3D::IsApplicable(const TopoDS_Shape & shape, bool toCheckA } else { + // check that all face columns end up at the same top face const TopoDS_Shape& topFace = sides[0]._faces->FindKey( nbFaces ); size_t iS; for ( iS = 1; iS < sides.size(); ++iS ) if ( ! sides[ iS ]._faces->Contains( topFace )) break; - prismDetected = ( iS == sides.size() ); + if (( prismDetected = ( iS == sides.size() ))) + { + // check that bottom and top faces has equal nb of edges + TEdgeWithNeighborsVec& topEdges = faceEdgesVec[ allFaces.FindIndex( topFace )]; + if ( topEdges.empty() ) + getEdges( TopoDS::Face( topFace ), topEdges, facesOfEdge, /*noHoles=*/false ); + prismDetected = ( botEdges.size() == topEdges.size() ); + } } } } // loop on allFaces @@ -3424,7 +3524,7 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism, if ( !botSM ) // find a proper bottom { bool savedSetErrorToSM = mySetErrorToSM; - mySetErrorToSM = false; // ingore errors in initPrism() + mySetErrorToSM = false; // ignore errors in initPrism() // search among meshed FACEs list< SMESH_subMesh* >::iterator sm = meshedSubMesh.begin(); @@ -3538,7 +3638,7 @@ bool StdMeshers_PrismAsBlock::Init(SMESH_MesherHelper* helper, SMESH_Block::init(); myShapeIDMap.Clear(); myShapeIndex2ColumnMap.clear(); - + int wallFaceIds[ NB_WALL_FACES ] = { // to walk around a block SMESH_Block::ID_Fx0z, SMESH_Block::ID_F1yz, SMESH_Block::ID_Fx1z, SMESH_Block::ID_F0yz @@ -3981,7 +4081,7 @@ bool StdMeshers_PrismAsBlock::GetLayersTransformation(vector & if ( p0.SquareDistance( pz ) > tol2 ) { t = gp_Trsf(); - return ( z == zSize - 1 ); // OK if fails only botton->top trsf + return ( z == zSize - 1 ); // OK if fails only bottom->top trsf } } } @@ -3990,12 +4090,12 @@ bool StdMeshers_PrismAsBlock::GetLayersTransformation(vector & //================================================================================ /*! - * \brief Check curve orientation of a bootom edge + * \brief Check curve orientation of a bottom edge * \param meshDS - mesh DS * \param columnsMap - node columns map of side face - * \param bottomEdge - the bootom edge + * \param bottomEdge - the bottom edge * \param sideFaceID - side face in-block ID - * \retval bool - true if orientation coinside with in-block forward orientation + * \retval bool - true if orientation coincide with in-block forward orientation */ //================================================================================ @@ -4066,7 +4166,7 @@ void StdMeshers_PrismAsBlock::faceGridToPythonDump(const SMESH_Block::TShapeID f << n << ", " << n+1 << ", " << n+nb+2 << ", " << n+nb+1 << "]) " << endl; } - + #endif } @@ -4218,8 +4318,8 @@ Adaptor3d_Curve* StdMeshers_PrismAsBlock::TSideFace::VertiCurve(const bool isMax //================================================================================ /*! * \brief Return geometry of the top or bottom curve - * \param isTop - - * \retval Adaptor3d_Curve* - + * \param isTop - + * \retval Adaptor3d_Curve* - */ //================================================================================ @@ -4475,7 +4575,7 @@ gp_Pnt StdMeshers_PrismAsBlock::TSideFace::Value(const Standard_Real U, meshDS->IndexToShape( notFaceID2 ), *myHelper.GetMesh(), TopAbs_FACE ); - if ( face.IsNull() ) + if ( face.IsNull() ) throw SALOME_Exception("StdMeshers_PrismAsBlock::TSideFace::Value() face.IsNull()"); int faceID = meshDS->ShapeToIndex( face ); me->mySurface = me->myShapeID2Surf[ faceID ]; @@ -4605,7 +4705,7 @@ int StdMeshers_PrismAsBlock::TSideFace::InsertSubShapes(TBlockShapes& shapeMap) if ( v1.ShapeType() == TopAbs_VERTEX ) { nbInserted += SMESH_Block::Insert( v1, vertIdVec[ 1 ], shapeMap); } - + // from V1 column SMESH_Block::GetEdgeVertexIDs( edgeIdVec[ V1_EDGE ], vertIdVec); GetColumns(1, col1, col2 ); @@ -4653,7 +4753,7 @@ int StdMeshers_PrismAsBlock::TSideFace::InsertSubShapes(TBlockShapes& shapeMap) // if ( edgeID = edgeIdVec[ _v1 ]) edgeID = edgeIdVec[ _v0 ]; // else edgeID = edgeIdVec[ _v1 ]; // SMESH_Block::Insert( sideEdge, edgeID, shapeMap); - + // // top edge // TopoDS_Edge topEdge = GetEdge( TOP_EDGE ); // SMESH_Block::Insert( topEdge, edgeIdVec[ _u1 ], shapeMap); @@ -4691,7 +4791,7 @@ void StdMeshers_PrismAsBlock::TSideFace::dumpNodes(int nbNodes) const //================================================================================ /*! - * \brief Creates TVerticalEdgeAdaptor + * \brief Creates TVerticalEdgeAdaptor * \param columnsMap - node column map * \param parameter - normalized parameter */ @@ -4766,7 +4866,7 @@ void StdMeshers_PrismAsBlock::THorizontalEdgeAdaptor::dumpNodes(int nbNodes) con TParam2ColumnIt col, col2; TParam2ColumnMap* u2cols = side->GetColumns(); side->GetColumns( u , col, col2 ); - + int j, i = myV ? mySide->ColumnHeight()-1 : 0; const SMDS_MeshNode* n = 0; @@ -4795,7 +4895,7 @@ void StdMeshers_PrismAsBlock::THorizontalEdgeAdaptor::dumpNodes(int nbNodes) con //================================================================================ /*! - * \brief Costructor of TPCurveOnHorFaceAdaptor fills its map of + * \brief Constructor of TPCurveOnHorFaceAdaptor fills its map of * normalized parameter to node UV on a horizontal face * \param [in] sideFace - lateral prism side * \param [in] isTop - is \a horFace top or bottom of the prism @@ -4847,7 +4947,7 @@ TPCurveOnHorFaceAdaptor::TPCurveOnHorFaceAdaptor( const TSideFace* sideFace, } if ( !C2d.IsNull() ) { - double u = static_cast< const SMDS_EdgePosition* >( n->GetPosition() )->GetUParameter(); + double u = SMDS_EdgePositionPtr( n->GetPosition() )->GetUParameter(); if ( f <= u && u <= l ) { uv = C2d->Value( u ).XY(); @@ -4959,7 +5059,7 @@ bool StdMeshers_Sweeper::ComputeNodesByTrsf( const double tol, const size_t zSrc = 0, zTgt = zSize-1; if ( zSize < 3 ) return true; - vector< vector< gp_XYZ > > intPntsOfLayer( zSize ); // node coodinates to compute + vector< vector< gp_XYZ > > intPntsOfLayer( zSize ); // node coordinates to compute // set coordinates of src and tgt nodes for ( size_t z = 0; z < intPntsOfLayer.size(); ++z ) intPntsOfLayer[ z ].resize( myIntColumns.size() ); @@ -4973,7 +5073,7 @@ bool StdMeshers_Sweeper::ComputeNodesByTrsf( const double tol, prepareTopBotDelaunay(); bool isErrorCorrectable = findDelaunayTriangles(); - // compute coordinates of internal nodes by projecting (transfroming) src and tgt + // compute coordinates of internal nodes by projecting (transforming) src and tgt // nodes towards the central layer vector< NSProjUtils::TrsfFinder3D > trsfOfLayer( zSize ); @@ -5364,15 +5464,34 @@ void StdMeshers_Sweeper::fillZColumn( TZColumn& zColumn, void StdMeshers_Sweeper::prepareTopBotDelaunay() { + SMESH_MesherHelper* helper[2] = { myHelper, myHelper }; + SMESH_MesherHelper botHelper( *myHelper->GetMesh() ); + SMESH_MesherHelper topHelper( *myHelper->GetMesh() ); + const SMDS_MeshNode* intBotNode = 0; + const SMDS_MeshNode* intTopNode = 0; + if ( myHelper->HasSeam() || myHelper->HasDegeneratedEdges() ) // use individual helpers + { + botHelper.SetSubShape( myBotFace ); + topHelper.SetSubShape( myTopFace ); + helper[0] = & botHelper; + helper[1] = & topHelper; + if ( !myIntColumns.empty() ) + { + TNodeColumn& nodes = *myIntColumns[ myIntColumns.size()/2 ]; + intBotNode = nodes[0]; + intTopNode = nodes.back(); + } + } + UVPtStructVec botUV( myBndColumns.size() ); UVPtStructVec topUV( myBndColumns.size() ); for ( size_t i = 0; i < myBndColumns.size(); ++i ) { TNodeColumn& nodes = *myBndColumns[i]; botUV[i].node = nodes[0]; - botUV[i].SetUV( myHelper->GetNodeUV( myBotFace, nodes[0] )); + botUV[i].SetUV( helper[0]->GetNodeUV( myBotFace, nodes[0], intBotNode )); topUV[i].node = nodes.back(); - topUV[i].SetUV( myHelper->GetNodeUV( myTopFace, nodes.back() )); + topUV[i].SetUV( helper[1]->GetNodeUV( myTopFace, nodes.back(), intTopNode )); botUV[i].node->setIsMarked( true ); } TopoDS_Edge dummyE;