X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH%2FSMESH_MesherHelper.cxx;h=4d8f9952a0749638ba138ce458ae7f1c2825630c;hp=67df8daebb388f8127ad0e94026a6bcb89fea7ec;hb=4fa5fdbd44a9567a62142d6abd80f663165f3ba2;hpb=922336dfb7873d5449ccd871a22339113c3bd645 diff --git a/src/SMESH/SMESH_MesherHelper.cxx b/src/SMESH/SMESH_MesherHelper.cxx index 67df8daeb..4d8f9952a 100644 --- a/src/SMESH/SMESH_MesherHelper.cxx +++ b/src/SMESH/SMESH_MesherHelper.cxx @@ -139,9 +139,9 @@ SMESHDS_Mesh* SMESH_MesherHelper::GetMeshDS() const //======================================================================= //function : IsQuadraticSubMesh -//purpose : Check submesh for given shape: if all elements on this shape +//purpose : Check sub-meshes of a given shape: if all elements on sub-shapes // are quadratic, quadratic elements will be created. -// Also fill myTLinkNodeMap +// Fill myTLinkNodeMap //======================================================================= bool SMESH_MesherHelper::IsQuadraticSubMesh(const TopoDS_Shape& aSh) @@ -149,7 +149,6 @@ bool SMESH_MesherHelper::IsQuadraticSubMesh(const TopoDS_Shape& aSh) SMESHDS_Mesh* meshDS = GetMeshDS(); // we can create quadratic elements only if all elements // created on sub-shapes of given shape are quadratic - // also we have to fill myTLinkNodeMap myCreateQuadratic = true; mySeamShapeIds.clear(); myDegenShapeIds.clear(); @@ -162,9 +161,6 @@ bool SMESH_MesherHelper::IsQuadraticSubMesh(const TopoDS_Shape& aSh) } SMDSAbs_ElementType elemType( subType==TopAbs_FACE ? SMDSAbs_Face : SMDSAbs_Edge ); - - //int nbOldLinks = myTLinkNodeMap.size(); - if ( !myMesh->HasShapeToMesh() ) { if (( myCreateQuadratic = myMesh->NbFaces( ORDER_QUADRATIC ))) @@ -373,6 +369,27 @@ void SMESH_MesherHelper::SetSubShape(const TopoDS_Shape& aSh) } } +//======================================================================= +/*! + * \brief Copy shape information from another helper. Used to improve performance + * since SetSubShape() can be time consuming if there are many edges + */ +//======================================================================= + +void SMESH_MesherHelper::CopySubShapeInfo(const SMESH_MesherHelper& other) +{ + this->myShape = other.myShape; + this->myShapeID = other.myShapeID; + this->myDegenShapeIds = other.myDegenShapeIds; + this->mySeamShapeIds = other.mySeamShapeIds; + this->myPar1[0] = other.myPar1[0]; + this->myPar1[1] = other.myPar1[1]; + this->myPar2[0] = other.myPar2[0]; + this->myPar2[1] = other.myPar2[1]; + this->myParIndex = other.myParIndex; + this->myFace2Surface = other.myFace2Surface; +} + //======================================================================= //function : ShapeToIndex //purpose : Convert a shape to its index in the SMESHDS_Mesh @@ -807,7 +824,7 @@ bool SMESH_MesherHelper::CheckNodeUV(const TopoDS_Face& F, MESSAGE( "SMESH_MesherHelper::CheckNodeUV() failed to project" ); return false; } - Quantity_Parameter U,V; + Standard_Real U,V; projector.LowerDistanceParameters(U,V); uv.SetCoord( U,V ); surfPnt = surface->Value( U, V ); @@ -1113,7 +1130,7 @@ bool SMESH_MesherHelper::CheckNodeU(const TopoDS_Edge& E, MESSAGE( "SMESH_MesherHelper::CheckNodeU() failed to project" ); return false; } - Quantity_Parameter U = projector->LowerDistanceParameter(); + Standard_Real U = projector->LowerDistanceParameter(); u = double( U ); curvPnt = curve->Value( u ); dist = nodePnt.Distance( curvPnt ); @@ -1889,7 +1906,7 @@ const SMDS_MeshNode* SMESH_MesherHelper::getMediumNodeOnComposedWire(const SMDS_ if ( !bestEdge.IsNull() ) { - // move n12 to position of a successfull projection + // move n12 to position of a successful projection //double tol = BRep_Tool::Tolerance(edges[ iOkEdge ]); if ( !force3d /*&& distMiddleProj > 2*tol*/ ) { @@ -2568,6 +2585,7 @@ bool SMESH_MesherHelper::LoadNodeColumns(TParam2ColumnMap & theParam2 } // get nodes on theBaseEdge sorted by param on edge and initialize theParam2ColumnMap with them + const SMDS_MeshNode* prevEndNodes[2] = { 0, 0 }; edge = theBaseSide.begin(); for ( int iE = 0; edge != theBaseSide.end(); ++edge, ++iE ) { @@ -2635,18 +2653,23 @@ bool SMESH_MesherHelper::LoadNodeColumns(TParam2ColumnMap & theParam2 const double prevPar = theParam2ColumnMap.empty() ? 0 : theParam2ColumnMap.rbegin()->first; for ( u_n = sortedBaseNN.begin(); u_n != sortedBaseNN.end(); u_n++ ) { + if ( u_n->second == prevEndNodes[0] || + u_n->second == prevEndNodes[1] ) + continue; double par = prevPar + coeff * ( u_n->first - f ); TParam2ColumnMap::iterator u2nn = theParam2ColumnMap.insert( theParam2ColumnMap.end(), make_pair( par, TNodeColumn())); u2nn->second.push_back( u_n->second ); } + prevEndNodes[0] = sortedBaseNN.begin()->second; + prevEndNodes[1] = sortedBaseNN.rbegin()->second; } if ( theParam2ColumnMap.size() < 2 ) return false; } // nb rows of nodes - size_t prevNbRows = theParam2ColumnMap.begin()->second.size(); // current, at least 1 here + size_t prevNbRows = theParam2ColumnMap.begin()->second.size(); // current, at least 1 here size_t expectNbRows = faceSubMesh->NbElements() / ( theParam2ColumnMap.size()-1 ); // to be added // fill theParam2ColumnMap column by column by passing from nodes on @@ -2819,8 +2842,9 @@ 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 checkUV) +bool SMESH_MesherHelper::IsDistorted2D( SMESH_subMesh* faceSM, + bool checkUV, + SMESH_MesherHelper* faceHelper) { if ( !faceSM || faceSM->GetSubShape().ShapeType() != TopAbs_FACE ) return false; @@ -2828,12 +2852,26 @@ bool SMESH_MesherHelper::IsDistorted2D( SMESH_subMesh* faceSM, bool haveBadFaces = false; SMESH_MesherHelper helper( *faceSM->GetFather() ); + if ( faceHelper ) + helper.CopySubShapeInfo( *faceHelper ); helper.SetSubShape( faceSM->GetSubShape() ); const TopoDS_Face& F = TopoDS::Face( faceSM->GetSubShape() ); SMESHDS_SubMesh* smDS = helper.GetMeshDS()->MeshElements( F ); if ( !smDS || smDS->NbElements() == 0 ) return false; + bool subIdsValid = true; // shape ID of nodes is OK + if ( helper.HasSeam() ) + { + // check if nodes are bound to seam edges + SMESH_subMeshIteratorPtr smIt = faceSM->getDependsOnIterator(/*includeSelf=*/false); + while ( smIt->more() && subIdsValid ) + { + SMESH_subMesh* sm = smIt->next(); + if ( helper.IsSeamShape( sm->GetId() ) && sm->IsEmpty() ) + subIdsValid = false; + } + } SMDS_ElemIteratorPtr faceIt = smDS->GetElements(); double prevArea = 0; vector< const SMDS_MeshNode* > nodes; @@ -2858,12 +2896,20 @@ bool SMESH_MesherHelper::IsDistorted2D( SMESH_subMesh* faceSM, if ( isOnDegen ) continue; } - // prepare to getting UVs + // prepare for getting UVs const SMDS_MeshNode* inFaceNode = 0; if ( helper.HasSeam() ) { for ( size_t i = 0; ( i < nodes.size() && !inFaceNode ); ++i ) if ( !helper.IsSeamShape( nodes[ i ]->getshapeId() )) + { inFaceNode = nodes[ i ]; + if ( !subIdsValid ) + { + gp_XY uv = helper.GetNodeUV( F, inFaceNode ); + if ( helper.IsOnSeam( uv )) + inFaceNode = NULL; + } + } if ( !inFaceNode ) continue; } @@ -2872,6 +2918,14 @@ bool SMESH_MesherHelper::IsDistorted2D( SMESH_subMesh* faceSM, for ( size_t i = 0; i < nodes.size(); ++i ) uv[ i ] = helper.GetNodeUV( F, nodes[ i ], inFaceNode, toCheckUV ); + if ( !subIdsValid ) // fix uv on seam + { + gp_XY uvInFace = helper.GetNodeUV( F, inFaceNode ); + for ( size_t i = 0; i < uv.size(); ++i ) + if ( helper.IsOnSeam( uv[i] )) + uv[i] = helper.getUVOnSeam( uv[i], uvInFace ).XY(); + } + // compare orientation of triangles double faceArea = 0; for ( int iT = 0, nbT = nodes.size()-2; iT < nbT; ++iT ) @@ -3081,7 +3135,7 @@ TopAbs_Orientation SMESH_MesherHelper::GetSubShapeOri(const TopoDS_Shape& shape, //======================================================================= //function : IsSubShape -//purpose : +//purpose : //======================================================================= bool SMESH_MesherHelper::IsSubShape( const TopoDS_Shape& shape, @@ -3179,7 +3233,7 @@ double SMESH_MesherHelper::getFaceMaxTol( const TopoDS_Shape& face ) const * of the FACE normal * \return double - the angle (between -Pi and Pi), negative if the angle is concave, * 1e100 in case of failure - * \waring Care about order of the EDGEs and their orientation to be as they are + * \warning Care about order of the EDGEs and their orientation to be as they are * within the FACE! Don't pass degenerated EDGEs neither! */ //================================================================================ @@ -3389,6 +3443,25 @@ double SMESH_MesherHelper::GetOtherParam(const double param) const return fabs(param-myPar1[i]) < fabs(param-myPar2[i]) ? myPar2[i] : myPar1[i]; } +//======================================================================= +//function : IsOnSeam +//purpose : Check if UV is on seam. Return 0 if not, 1 for U seam, 2 for V seam +//======================================================================= + +int SMESH_MesherHelper::IsOnSeam(const gp_XY& uv) const +{ + for ( int i = U_periodic; i <= V_periodic ; ++i ) + if ( myParIndex & i ) + { + double p = uv.Coord( i ); + double tol = ( myPar2[i-1] - myPar1[i-1] ) / 100.; + if ( Abs( p - myPar1[i-1] ) < tol || + Abs( p - myPar2[i-1] ) < tol ) + return i; + } + return 0; +} + namespace { //======================================================================= @@ -3402,11 +3475,16 @@ namespace { TopTools_ListIteratorOfListOfShape _ancIter; TopAbs_ShapeEnum _type; TopTools_MapOfShape _encountered; - TAncestorsIterator( const TopTools_ListOfShape& ancestors, TopAbs_ShapeEnum type) + TopTools_IndexedMapOfShape _allowed; + TAncestorsIterator( const TopTools_ListOfShape& ancestors, + TopAbs_ShapeEnum type, + const TopoDS_Shape* container/* = 0*/) : _ancIter( ancestors ), _type( type ) { + if ( container && !container->IsNull() ) + TopExp::MapShapes( *container, type, _allowed); if ( _ancIter.More() ) { - if ( _ancIter.Value().ShapeType() != _type ) next(); + if ( !isCurrentAllowed() ) next(); else _encountered.Add( _ancIter.Value() ); } } @@ -3419,25 +3497,32 @@ namespace { const TopoDS_Shape* s = _ancIter.More() ? & _ancIter.Value() : 0; if ( _ancIter.More() ) for ( _ancIter.Next(); _ancIter.More(); _ancIter.Next()) - if ( _ancIter.Value().ShapeType() == _type && _encountered.Add( _ancIter.Value() )) + if ( isCurrentAllowed() && _encountered.Add( _ancIter.Value() )) break; return s; } + bool isCurrentAllowed() + { + return (( _ancIter.Value().ShapeType() == _type ) && + ( _allowed.IsEmpty() || _allowed.Contains( _ancIter.Value() ))); + } }; } // namespace //======================================================================= /*! - * \brief Return iterator on ancestors of the given type + * \brief Return iterator on ancestors of the given type, included into a container shape */ //======================================================================= PShapeIteratorPtr SMESH_MesherHelper::GetAncestors(const TopoDS_Shape& shape, const SMESH_Mesh& mesh, - TopAbs_ShapeEnum ancestorType) + TopAbs_ShapeEnum ancestorType, + const TopoDS_Shape* container) { - return PShapeIteratorPtr( new TAncestorsIterator( mesh.GetAncestors(shape), ancestorType)); + return PShapeIteratorPtr + ( new TAncestorsIterator( mesh.GetAncestors(shape), ancestorType, container)); } //======================================================================= @@ -3715,7 +3800,7 @@ namespace { // Structures used by FixQuadraticElements() * \brief Make up a chain of links * \param iSide - link to add first * \param chain - chain to fill in - * \param pos - postion of medium nodes the links should have + * \param pos - position of medium nodes the links should have * \param error - out, specifies what is wrong * \retval bool - false if valid chain can't be built; "valid" means that links * of the chain belongs to rectangles bounding hexahedrons @@ -3729,7 +3814,7 @@ namespace { // Structures used by FixQuadraticElements() if ( _sideIsAdded[ iSide ]) // already in chain return true; - if ( _sides.size() != 4 ) { // triangle - visit all my continous faces + if ( _sides.size() != 4 ) { // triangle - visit all my continuous faces MSGBEG( *this ); TLinkSet links; list< const QFace* > faces( 1, this ); @@ -3775,7 +3860,7 @@ namespace { // Structures used by FixQuadraticElements() if ( link->MediumPos() >= pos ) { int nbLinkFaces = link->_faces.size(); if ( nbLinkFaces == 4 || (/*nbLinkFaces < 4 && */link->OnBoundary())) { - // hexahedral mesh or boundary quadrangles - goto a continous face + // hexahedral mesh or boundary quadrangles - goto a continuous face if ( const QFace* f = link->GetContinuesFace( this )) if ( f->_sides.size() == 4 ) return f->GetLinkChain( *chLink, chain, pos, error ); @@ -3903,7 +3988,7 @@ namespace { // Structures used by FixQuadraticElements() * \brief Move medium node of theLink according to its distance from boundary * \param theLink - link to fix * \param theRefVec - movement of boundary - * \param theLinks - all adjacent links of continous triangles + * \param theLinks - all adjacent links of continuous triangles * \param theFaceHelper - helper is not used so far * \param thePrevLen - distance from the boundary * \param theStep - number of steps till movement propagation limit @@ -4634,8 +4719,8 @@ namespace { // Structures used by FixQuadraticElements() < const SMDS_MeshElement*, vector< SMDS_ElemIteratorPtr > > TIterOnIter; SMDS_ElemIteratorPtr faceIter( new TIterOnIter( faceIterVec )); - // a seacher to check if a volume is close to a concave face - std::auto_ptr< SMESH_ElementSearcher > faceSearcher + // search to check if a volume is close to a concave face + SMESHUtils::Deleter< SMESH_ElementSearcher > faceSearcher ( SMESH_MeshAlgos::GetElementSearcher( *theHelper.GetMeshDS(), faceIter )); // classifier @@ -4737,7 +4822,7 @@ namespace { // Structures used by FixQuadraticElements() gp_Pnt pMedium = SMESH_TNodeXYZ( linkIt->second ); double hMedium = faceNorm * gp_Vec( pOnFace0, pMedium ).XYZ(); double hVol = faceNorm * gp_Vec( pOnFace0, pInSolid ).XYZ(); - isDistorted = ( Abs( hMedium ) > Abs( hVol * 0.5 )); + isDistorted = ( Abs( hMedium ) > Abs( hVol * 0.75 )); } } }