From: eap Date: Mon, 7 Jul 2014 15:41:18 +0000 (+0400) Subject: IPAL52444: Viscous Layers and Projection fail X-Git-Tag: V7_5_0a1~67 X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=commitdiff_plain;h=69f064e1222d71a85b8ac1e11d82e0480b6d6cea;hp=7a9f9e2e462984087fe10a558a1f22366617cb4f IPAL52444: Viscous Layers and Projection fail --- diff --git a/src/SMESH/SMESH_Algo.cxx b/src/SMESH/SMESH_Algo.cxx index 8f071e783..95c81e419 100644 --- a/src/SMESH/SMESH_Algo.cxx +++ b/src/SMESH/SMESH_Algo.cxx @@ -410,7 +410,7 @@ bool SMESH_Algo::GetSortedNodesOnEdge(const SMESHDS_Mesh* theM return false; SMESHDS_SubMesh * eSubMesh = theMesh->MeshElements( theEdge ); - if ( !eSubMesh || ( eSubMesh->NbElements()==0 && eSubMesh->NbNodes() == 0)) + if ( !eSubMesh || ( /*eSubMesh->NbElements()==0 && */ eSubMesh->NbNodes() == 0)) return false; // edge is not meshed int nbNodes = 0; diff --git a/src/SMESH/SMESH_Pattern.cxx b/src/SMESH/SMESH_Pattern.cxx index 0ae35919a..75d26244d 100644 --- a/src/SMESH/SMESH_Pattern.cxx +++ b/src/SMESH/SMESH_Pattern.cxx @@ -86,20 +86,15 @@ typedef map< const SMDS_MeshElement*, int > TNodePointIDMap; #define smdsNode( elem ) static_cast( elem ) -//======================================================================= -//function : SMESH_Pattern -//purpose : -//======================================================================= - -SMESH_Pattern::SMESH_Pattern () +namespace { -} + //======================================================================= //function : getInt //purpose : //======================================================================= -static inline int getInt( const char * theSring ) +inline int getInt( const char * theSring ) { if ( *theSring < '0' || *theSring > '9' ) return -1; @@ -119,7 +114,7 @@ static inline int getInt( const char * theSring ) //purpose : //======================================================================= -static inline double getDouble( const char * theSring ) +inline double getDouble( const char * theSring ) { char *ptr; return strtod( theSring, &ptr ); @@ -131,9 +126,9 @@ static inline double getDouble( const char * theSring ) // Return the number of the found tokens //======================================================================= -static int readLine (list & theFields, - const char* & theLineBeg, - const bool theClearFields ) +int readLine (list & theFields, + const char* & theLineBeg, + const bool theClearFields ) { if ( theClearFields ) theFields.clear(); @@ -206,6 +201,65 @@ static int readLine (list & theFields, return nbRead; } +//======================================================================= +//function : isRealSeam +//purpose : return true if an EDGE encounters twice in a FACE +//======================================================================= + +// bool isRealSeam( const TopoDS_Edge& e, const TopoDS_Face& f ) +// { +// if ( BRep_Tool::IsClosed( e, f )) +// { +// int nb = 0; +// for (TopExp_Explorer exp( f, TopAbs_EDGE ); exp.More(); exp.Next()) +// if ( exp.Current().IsSame( e )) +// if ( ++nb == 2 ) +// return true; +// } +// return false; +// } + +//======================================================================= +//function : loadVE +//purpose : load VERTEXes and EDGEs in a map. Return nb loaded VERTEXes +//======================================================================= + +int loadVE( const list< TopoDS_Edge > & eList, + TopTools_IndexedMapOfOrientedShape & map ) +{ + list< TopoDS_Edge >::const_iterator eIt = eList.begin(); + // vertices + int nbV; + for ( eIt = eList.begin(); eIt != eList.end(); eIt++ ) + { + nbV = map.Extent(); + map.Add( TopExp::FirstVertex( *eIt, true )); + bool added = ( nbV < map.Extent() ); + if ( !added ) { // vertex encountered twice + // a seam vertex have two corresponding key points + map.Add( TopExp::FirstVertex( *eIt, true ).Reversed()); + } + } + nbV = map.Extent(); + + // edges + for ( eIt = eList.begin(); eIt != eList.end(); eIt++ ) + map.Add( *eIt ); + + return nbV; +} + +} // namespace + +//======================================================================= +//function : SMESH_Pattern +//purpose : +//======================================================================= + +SMESH_Pattern::SMESH_Pattern () +{ +} + //======================================================================= //function : Load //purpose : Load a pattern from @@ -647,31 +701,34 @@ bool SMESH_Pattern::Load (SMESH_Mesh* theMesh, // Load shapes in the consequent order and count nb of points - // vertices - for ( elIt = eList.begin(); elIt != eList.end(); elIt++ ) { - int nbV = myShapeIDMap.Extent(); - myShapeIDMap.Add( TopExp::FirstVertex( *elIt, true )); - bool added = ( nbV < myShapeIDMap.Extent() ); - if ( !added ) { // vertex encountered twice - // a seam vertex have two corresponding key points - myShapeIDMap.Add( TopExp::FirstVertex( *elIt, true ).Reversed()); - ++nbNodes; - } + loadVE( eList, myShapeIDMap ); + myShapeIDMap.Add( face ); + + nbNodes += myShapeIDMap.Extent() - 1; + + for ( elIt = eList.begin(); elIt != eList.end(); elIt++ ) if ( SMESHDS_SubMesh * eSubMesh = aMeshDS->MeshElements( *elIt )) nbNodes += eSubMesh->NbNodes() + 1; - } - // edges - for ( elIt = eList.begin(); elIt != eList.end(); elIt++ ) - myShapeIDMap.Add( *elIt ); - // the face - myShapeIDMap.Add( face ); myPoints.resize( nbNodes ); // Load U of points on edges - for ( elIt = eList.begin(); elIt != eList.end(); elIt++ ) + list::iterator nbEinW = myNbKeyPntInBoundary.begin(); + int iE = 0; + vector< TopoDS_Edge > eVec; + for ( elIt = eList.begin(); elIt != eList.end(); elIt++, iE++ ) { + if ( isClosed && ( iE == 0 || iE == *nbEinW )) + { + // new wire begins; put EDGEs in eVec + list::iterator eEnd = elIt; + std::advance( eEnd, *nbEinW ); + eVec.assign( elIt, eEnd ); + if ( iE > 0 ) + ++nbEinW; + iE = 0; + } TopoDS_Edge & edge = *elIt; list< TPoint* > & ePoints = getShapePoints( edge ); double f, l; @@ -698,13 +755,8 @@ bool SMESH_Pattern::Load (SMESH_Mesh* theMesh, TopoDS_Shape & v = is2 ? v2 : v1; if ( helper.IsRealSeam( v ) ) { // reverse or not depending on orientation of adjacent seam - TopoDS_Edge seam; - list::iterator eIt2 = elIt; - if ( is2 ) - seam = ( ++eIt2 == eList.end() ? eList.front() : *eIt2 ); - else - seam = ( eIt2 == eList.begin() ? eList.back() : *(--eIt2) ); - if ( seam.Orientation() == TopAbs_REVERSED ) + int iSeam = helper.WrapIndex( iE + ( is2 ? +1 : -1 ), eVec.size() ); + if ( eVec[ iSeam ].Orientation() == TopAbs_REVERSED ) v.Reverse(); } } @@ -999,6 +1051,7 @@ void SMESH_Pattern::computeUVOnEdge (const TopoDS_Edge& theEdge, BRep_Tool::CurveOnSurface( theEdge, TopoDS::Face( myShape ), f, l ); ePoints.back()->myInitU = 1.0; + //ePoints.front()->myInitU = 0.0; //myUV = C2d->Value( isForward ? f : l ).XY(); list< TPoint* >::const_iterator pIt = ePoints.begin(); for ( pIt++; pIt != ePoints.end(); pIt++ ) { @@ -2387,33 +2440,7 @@ bool SMESH_Pattern::Apply (const TopoDS_Face& theFace, } // here shapes get IDs, for the outer wire IDs are OK - list::iterator elIt = eList.begin(); - for ( ; elIt != eList.end(); elIt++ ) { - myShapeIDMap.Add( TopExp::FirstVertex( *elIt, true )); - bool isClosed1 = BRep_Tool::IsClosed( *elIt, theFace ); - // BEGIN: jfa for bug 0019943 - if (isClosed1) { - isClosed1 = false; - for (TopExp_Explorer expw (theFace, TopAbs_WIRE); expw.More() && !isClosed1; expw.Next()) { - const TopoDS_Wire& wire = TopoDS::Wire(expw.Current()); - int nbe = 0; - for (BRepTools_WireExplorer we (wire, theFace); we.More() && !isClosed1; we.Next()) { - if (we.Current().IsSame(*elIt)) { - nbe++; - if (nbe == 2) isClosed1 = true; - } - } - } - } - // END: jfa for bug 0019943 - if (isClosed1) - myShapeIDMap.Add( TopExp::LastVertex( *elIt, true ));// vertex orienation is REVERSED - } - int nbVertices = myShapeIDMap.Extent(); - - for ( elIt = eList.begin(); elIt != eList.end(); elIt++ ) - myShapeIDMap.Add( *elIt ); - + int nbVertices = loadVE( eList, myShapeIDMap ); myShapeIDMap.Add( face ); if ( myShapeIDToPointsMap.size() != myShapeIDMap.Extent() ) { @@ -2425,10 +2452,11 @@ bool SMESH_Pattern::Apply (const TopoDS_Face& theFace, list< list< TPoint* > > edgesPointsList; edgesPointsList.push_back( list< TPoint* >() ); list< TPoint* > * edgesPoints = & edgesPointsList.back(); - list< TPoint* >::iterator pIt; + list< TPoint* >::iterator pIt, pEnd; // compute UV of points on the outer wire int iE, nbEdgesInOuterWire = nbVertexInWires.front(); + list< TopoDS_Edge >::iterator elIt; for (iE = 0, elIt = eList.begin(); iE < nbEdgesInOuterWire && elIt != eList.end(); iE++, elIt++ ) @@ -2543,14 +2571,24 @@ bool SMESH_Pattern::Apply (const TopoDS_Face& theFace, // re-fill myShapeIDMap - all shapes get good IDs myShapeIDMap.Clear(); - for ( elIt = eList.begin(); elIt != eList.end(); elIt++ ) - myShapeIDMap.Add( TopExp::FirstVertex( *elIt, true )); - for ( elIt = eList.begin(); elIt != eList.end(); elIt++ ) - myShapeIDMap.Add( *elIt ); + nbVertices = loadVE( eList, myShapeIDMap ); myShapeIDMap.Add( face ); } // there are inner wires + // Set XYZ of on-vertex points + + // for ( int iV = 1; iV <= nbVertices; ++iV ) + // { + // const TopoDS_Vertex& V = TopoDS::Vertex( myShapeIDMap( iV )); + // list< TPoint* > & vPoints = getShapePoints( iV ); + // if ( !vPoints.empty() ) + // { + // //vPoints.front()->myUV = BRep_Tool::Parameters( V, theFace ).XY(); + // vPoints.front()->myXYZ = BRep_Tool::Pnt( V ); + // } + // } + // Compute XYZ of on-edge points TopLoc_Location loc; @@ -2558,8 +2596,7 @@ bool SMESH_Pattern::Apply (const TopoDS_Face& theFace, { BRepAdaptor_Curve C3d( *elIt ); list< TPoint* > & ePoints = getShapePoints( iE++ ); - pIt = ePoints.begin(); - for ( pIt++; pIt != ePoints.end(); pIt++ ) + for ( pIt = ++ePoints.begin(), pEnd = ePoints.end(); pIt != pEnd; pIt++ ) { TPoint* point = *pIt; point->myXYZ = C3d.Value( point->myU ); @@ -3881,13 +3918,97 @@ void SMESH_Pattern::clearMesh(SMESH_Mesh* theMesh) const } } +//======================================================================= +//function : findExistingNodes +//purpose : fills nodes vector with nodes existing on a given shape (IMP 22368) +// Returns true if all nodes for all points on S are found +//======================================================================= + +bool SMESH_Pattern::findExistingNodes( SMESH_Mesh* mesh, + const TopoDS_Shape& S, + const std::list< TPoint* > & points, + vector< const SMDS_MeshNode* > & nodesVector) +{ + if ( S.IsNull() || points.empty() ) + return false; + + SMESHDS_Mesh* aMeshDS = mesh->GetMeshDS(); + + switch ( S.ShapeType() ) + { + case TopAbs_VERTEX: + { + int pIndex = points.back() - &myPoints[0]; + if ( !nodesVector[ pIndex ] ) + nodesVector[ pIndex ] = SMESH_Algo::VertexNode( TopoDS::Vertex( S ), aMeshDS ); + return nodesVector[ pIndex ]; + } + case TopAbs_EDGE: + { + const TopoDS_Edge& edge = TopoDS::Edge( S ); + map< double, const SMDS_MeshNode* > paramsOfNodes; + if ( !SMESH_Algo::GetSortedNodesOnEdge( aMeshDS, edge, + /*ignoreMediumNodes=*/false, + paramsOfNodes ) + || paramsOfNodes.size() < 3 ) + break; + // points on VERTEXes are included with wrong myU + list< TPoint* >::const_reverse_iterator pItR = ++points.rbegin(); + list< TPoint* >::const_iterator pItF = ++points.begin(); + const bool isForward = ( (*pItF)->myU < (*pItR)->myU ); + map< double, const SMDS_MeshNode* >::iterator u2n = ++paramsOfNodes.begin(); + map< double, const SMDS_MeshNode* >::iterator u2nEnd = --paramsOfNodes.end(); + TPoint* p; + if ( paramsOfNodes.size() == points.size() ) + { + for ( ; u2n != u2nEnd; ++u2n ) + { + p = ( isForward ? *pItF : *pItR ); + int pIndex = p - &myPoints[0]; + if ( !nodesVector [ pIndex ] ) + nodesVector [ pIndex ] = u2n->second; + ++pItF; + ++pItR; + } + return true; + } + else + { + const double tolFact = 0.05; + while ( u2n != u2nEnd && pItF != points.end() ) + { + const double u = u2n->first; + const SMDS_MeshNode* n = u2n->second; + const double tol = ( (++u2n)->first - u ) * tolFact; + do + { + p = ( isForward ? *pItF : *pItR ); + if ( Abs( u - p->myU ) < tol ) + { + int pIndex = p - &myPoints[0]; + if ( !nodesVector [ pIndex ] ) + nodesVector [ pIndex ] = n; + ++pItF; + ++pItR; + break; + } + } + while ( p->myU < u && ( ++pItF, ++pItR != points.rend() )); + } + } + break; + } // case TopAbs_EDGE: + + default:; + } // switch ( S.ShapeType() ) + + return false; +} + //======================================================================= //function : MakeMesh //purpose : Create nodes and elements in using nodes // coordinates computed by either of Apply...() methods -// WARNING : StdMeshers_Projection_... relies on MakeMesh() behavior: that -// it does not care of nodes and elements already existing on -// sub-shapes. DO NOT MERGE them or modify also StdMeshers_Projection_.. //======================================================================= bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh, @@ -3982,98 +4103,23 @@ bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh, { nodesVector.resize( myPoints.size(), 0 ); - // find existing nodes on EDGEs and VERTEXes (IMP 22368) - map< int, list< TPoint* > >::iterator idPointIt = myShapeIDToPointsMap.begin(); - if ( !myShapeIDMap.IsEmpty() && aMeshDS->NbNodes() > 0 ) - - for ( ; idPointIt != myShapeIDToPointsMap.end(); idPointIt++ ) - { - const TopoDS_Shape& S = myShapeIDMap( idPointIt->first ); - list< TPoint* > & points = idPointIt->second; - if ( points.empty() ) - continue; - - switch ( S.ShapeType() ) - { - case TopAbs_VERTEX: - { - int pIndex = points.back() - &myPoints[0]; - if ( !nodesVector[ pIndex ] ) - nodesVector[ pIndex ] = SMESH_Algo::VertexNode( TopoDS::Vertex( S ), aMeshDS ); - break; - } - case TopAbs_EDGE: - { - const TopoDS_Edge& edge = TopoDS::Edge( S ); - map< double, const SMDS_MeshNode* > paramsOfNodes; - if ( !SMESH_Algo::GetSortedNodesOnEdge( aMeshDS, edge, - /*ignoreMediumNodes=*/false, - paramsOfNodes ) - || paramsOfNodes.size() < 3 ) - break; - // points on VERTEXes are included with wrong myU - list< TPoint* >::reverse_iterator pItR = ++points.rbegin(); - list< TPoint* >::iterator pItF = ++points.begin(); - const bool isForward = ( (*pItF)->myU < (*pItR)->myU ); - map< double, const SMDS_MeshNode* >::iterator u2n = ++paramsOfNodes.begin(); - map< double, const SMDS_MeshNode* >::iterator u2nEnd = --paramsOfNodes.end(); - TPoint* p; - if ( paramsOfNodes.size() == points.size() ) - { - for ( ; u2n != u2nEnd; ++u2n ) - { - p = ( isForward ? *pItF : *pItR ); - int pIndex = p - &myPoints[0]; - if ( !nodesVector [ pIndex ] ) - nodesVector [ pIndex ] = u2n->second; - ++pItF; - ++pItR; - } - } - else - { - const double tolFact = 0.05; - while ( u2n != u2nEnd && pItF != points.end() ) - { - const double u = u2n->first; - const SMDS_MeshNode* n = u2n->second; - const double tol = ( (++u2n)->first - u ) * tolFact; - do - { - p = ( isForward ? *pItF : *pItR ); - if ( Abs( u - p->myU ) < tol ) - { - int pIndex = p - &myPoints[0]; - if ( !nodesVector [ pIndex ] ) - nodesVector [ pIndex ] = n; - ++pItF; - ++pItR; - break; - } - } - while ( p->myU < u && ( ++pItF, ++pItR != points.rend() )); - } - } - break; - } - default:; - } - } // end of "find existing nodes on EDGEs and VERTEXes" - // loop on sub-shapes of myShape: create nodes - idPointIt = myShapeIDToPointsMap.begin(); + map< int, list< TPoint* > >::iterator idPointIt = myShapeIDToPointsMap.begin(); for ( ; idPointIt != myShapeIDToPointsMap.end(); idPointIt++ ) { + list< TPoint* > & points = idPointIt->second; TopoDS_Shape S; - if ( !myShapeIDMap.IsEmpty() ) { + if ( !myShapeIDMap.IsEmpty() ) S = myShapeIDMap( idPointIt->first ); - } - list< TPoint* > & points = idPointIt->second; + + // find existing nodes on EDGEs and VERTEXes + if ( findExistingNodes( theMesh, S, points, nodesVector )) + continue; + list< TPoint* >::iterator pIt = points.begin(); for ( ; pIt != points.end(); pIt++ ) { TPoint* point = *pIt; - //int pIndex = pointIndex[ point ]; int pIndex = point - &myPoints[0]; if ( nodesVector [ pIndex ] ) continue; @@ -4082,8 +4128,8 @@ bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh, point->myXYZ.Z()); nodesVector [ pIndex ] = node; - if ( !S.IsNull() /*subMeshDS*/ ) { - // !!!!! do not merge new nodes with ones existing on submeshes (see method comment) + if ( !S.IsNull() ) { + switch ( S.ShapeType() ) { case TopAbs_VERTEX: { aMeshDS->SetNodeOnVertex( node, TopoDS::Vertex( S )); break; @@ -4755,7 +4801,7 @@ bool SMESH_Pattern::setShapeToMesh(const TopoDS_Shape& theShape) TopTools_MapOfShape seamVertices; TopoDS_Face face = TopoDS::Face( theShape ); TopExp_Explorer eExp( theShape, TopAbs_EDGE ); - for ( ; eExp.More() && nbNodeOnSeamEdge == 0; eExp.Next() ) { + for ( ; eExp.More() /*&& nbNodeOnSeamEdge == 0*/; eExp.Next() ) { const TopoDS_Edge& ee = TopoDS::Edge(eExp.Current()); if ( BRep_Tool::IsClosed(ee, face) ) { // seam edge and vertices encounter twice in theFace diff --git a/src/SMESH/SMESH_Pattern.hxx b/src/SMESH/SMESH_Pattern.hxx index cbe677493..225e5abaa 100644 --- a/src/SMESH/SMESH_Pattern.hxx +++ b/src/SMESH/SMESH_Pattern.hxx @@ -334,6 +334,12 @@ private: void clearMesh(SMESH_Mesh* theMesh) const; // clear mesh elements existing on myShape in theMesh + bool findExistingNodes( SMESH_Mesh* mesh, + const TopoDS_Shape& S, + const std::list< TPoint* > & points, + std::vector< const SMDS_MeshNode* > & nodes); + // fills nodes vector with nodes existing on a given shape + static SMESHDS_SubMesh * getSubmeshWithElements(SMESH_Mesh* theMesh, const TopoDS_Shape& theShape); // return submesh containing elements bound to theShape in theMesh diff --git a/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx b/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx index 15b9487bc..1bf5e5c8b 100644 --- a/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx @@ -916,7 +916,7 @@ void SMESHGUI_BaseComputeOp::computeMesh() long nbElements = 0; if ( !memoryLack ) { - // List of objects that will be updated automatically + // List of objects that will be updated automatically QList< QPair< SMESH::SMESH_IDSource_var, _PTR(SObject) > > aListToUpdate; SMESH::SMESH_IDSource_var aMeshObj = SMESH::SObjectToInterface( aMeshSObj ); // put Mesh into list @@ -949,60 +949,60 @@ void SMESHGUI_BaseComputeOp::computeMesh() // update mesh, sub-mesh and groups, if it's possible QList< QPair< SMESH::SMESH_IDSource_var, _PTR(SObject) > >::iterator anIter; for( anIter = aListToUpdate.begin(); anIter != aListToUpdate.end(); anIter++ ) { - SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow( SMESH::SObjectToObject( (*anIter).second )); - if ( getSMESHGUI()->automaticUpdate( (*anIter).first, &entities, &limitExceeded, &hidden, &nbElements ) ) - { - try { + SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow( SMESH::SObjectToObject( (*anIter).second )); + if ( getSMESHGUI()->automaticUpdate( (*anIter).first, &entities, &limitExceeded, &hidden, &nbElements ) ) + { + try { #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 - OCC_CATCH_SIGNALS; + OCC_CATCH_SIGNALS; #endif - bool toDisplay = false; - - if ( !aMesh->_is_nil() ) { // display a mesh only - toDisplay = true; - SMESH_Actor *anActor = SMESH::FindActorByObject( aMesh ); - if ( !anActor ) anActor = SMESH::CreateActor( (*anIter).second->GetStudy(), (*anIter).second->GetID().c_str(), true ); - if ( anActor ) // actor is not created for an empty mesh - { - anActor->SetEntityMode( entities ); - SMESH::DisplayActor( SMESH::GetActiveWindow(), anActor ); - } - } - Handle(SALOME_InteractiveObject) anIO = new SALOME_InteractiveObject - ( (*anIter).second->GetID().c_str(), "SMESH", (*anIter).second->GetName().c_str() ); - SMESH::Update(anIO, toDisplay); - - if ( limitExceeded && !aMesh->_is_nil() ) - { - QStringList hiddenMsg; - if ( hidden & SMESH_Actor::e0DElements ) hiddenMsg << tr( "SMESH_ELEMS0D" ); - if ( hidden & SMESH_Actor::eEdges ) hiddenMsg << tr( "SMESH_EDGES" ); - if ( hidden & SMESH_Actor::eFaces ) hiddenMsg << tr( "SMESH_FACES" ); - if ( hidden & SMESH_Actor::eVolumes ) hiddenMsg << tr( "SMESH_VOLUMES" ); - if ( hidden & SMESH_Actor::eBallElem ) hiddenMsg << tr( "SMESH_BALLS" ); - SUIT_MessageBox::warning( desktop(), - tr( "SMESH_WRN_WARNING" ), - tr( "SMESH_WRN_SIZE_INC_LIMIT_EXCEEDED" ).arg( nbElements ).arg( limitSize ).arg( hiddenMsg.join(", ") ) ); - } - } - catch (...) { + bool toDisplay = false; + + if ( !aMesh->_is_nil() ) { // display a mesh only + toDisplay = true; + SMESH_Actor *anActor = SMESH::FindActorByObject( aMesh ); + if ( !anActor ) anActor = SMESH::CreateActor( (*anIter).second->GetStudy(), (*anIter).second->GetID().c_str(), true ); + if ( anActor ) // actor is not created for an empty mesh + { + anActor->SetEntityMode( entities ); + SMESH::DisplayActor( SMESH::GetActiveWindow(), anActor ); + } + } + Handle(SALOME_InteractiveObject) anIO = new SALOME_InteractiveObject + ( (*anIter).second->GetID().c_str(), "SMESH", (*anIter).second->GetName().c_str() ); + SMESH::Update(anIO, toDisplay); + + if ( limitExceeded && !aMesh->_is_nil() ) + { + QStringList hiddenMsg; + if ( hidden & SMESH_Actor::e0DElements ) hiddenMsg << tr( "SMESH_ELEMS0D" ); + if ( hidden & SMESH_Actor::eEdges ) hiddenMsg << tr( "SMESH_EDGES" ); + if ( hidden & SMESH_Actor::eFaces ) hiddenMsg << tr( "SMESH_FACES" ); + if ( hidden & SMESH_Actor::eVolumes ) hiddenMsg << tr( "SMESH_VOLUMES" ); + if ( hidden & SMESH_Actor::eBallElem ) hiddenMsg << tr( "SMESH_BALLS" ); + SUIT_MessageBox::warning( desktop(), + tr( "SMESH_WRN_WARNING" ), + tr( "SMESH_WRN_SIZE_INC_LIMIT_EXCEEDED" ).arg( nbElements ).arg( limitSize ).arg( hiddenMsg.join(", ") ) ); + } + } + catch (...) { #ifdef _DEBUG_ - MESSAGE ( "Exception thrown during mesh visualization" ); + MESSAGE ( "Exception thrown during mesh visualization" ); #endif - if ( SMDS_Mesh::CheckMemory(true) ) { // has memory to show warning? - SMESH::OnVisuException(); - } - else { - memoryLack = true; - } - } - } - else if ( limitExceeded && !aMesh->_is_nil() ) - { - SUIT_MessageBox::warning( desktop(), - tr( "SMESH_WRN_WARNING" ), - tr( "SMESH_WRN_SIZE_LIMIT_EXCEEDED" ).arg( nbElements ).arg( limitSize ) ); - } + if ( SMDS_Mesh::CheckMemory(true) ) { // has memory to show warning? + SMESH::OnVisuException(); + } + else { + memoryLack = true; + } + } + } + else if ( limitExceeded && !aMesh->_is_nil() ) + { + SUIT_MessageBox::warning( desktop(), + tr( "SMESH_WRN_WARNING" ), + tr( "SMESH_WRN_SIZE_LIMIT_EXCEEDED" ).arg( nbElements ).arg( limitSize ) ); + } } } LightApp_SelectionMgr *Sel = selectionMgr(); diff --git a/src/SMESHUtils/SMESH_Block.cxx b/src/SMESHUtils/SMESH_Block.cxx index 472061d24..1b519201b 100644 --- a/src/SMESHUtils/SMESH_Block.cxx +++ b/src/SMESHUtils/SMESH_Block.cxx @@ -1464,7 +1464,7 @@ int SMESH_Block::GetShapeIDByParams ( const gp_XYZ& theCoord ) /*! * \brief Return number of wires and a list of oredered edges. * \param theFace - the face to process - * \param theEdges - all ordered edges of theFace (outer edges goes first). + * \param theEdges - all ordered edges of theFace (outer edges go first). * \param theNbEdgesInWires - nb of edges (== nb of vertices in closed wire) in each wire * \param theFirstVertex - the vertex of the outer wire to set first in the returned * list ( theFirstVertex may be NULL ) diff --git a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx index 18c6f27d2..9739fcb3e 100644 --- a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx +++ b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx @@ -529,6 +529,8 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the TShapePairsList::iterator s1_s2 = shapesQueue.begin(); for ( ; s1_s2 != shapesQueue.end(); ++s1_s2 ) { + if ( theMap.IsBound( s1_s2->first )) // avoid re-binding for a seam edge + continue; // to avoid this: Forward seam -> Reversed seam InsertAssociation( s1_s2->first, s1_s2->second, theMap ); TopoDS_Iterator s1It( s1_s2->first), s2It( s1_s2->second ); for ( ; s1It.More(); s1It.Next(), s2It.Next() ) diff --git a/src/StdMeshers/StdMeshers_Projection_2D.cxx b/src/StdMeshers/StdMeshers_Projection_2D.cxx index c4bbc0c68..0e3d183f2 100644 --- a/src/StdMeshers/StdMeshers_Projection_2D.cxx +++ b/src/StdMeshers/StdMeshers_Projection_2D.cxx @@ -381,8 +381,10 @@ namespace { SMESH_Mesh * srcMesh, const TAssocTool::TShapeShapeMap& shape2ShapeMap) { - MESSAGE("projectPartner"); - const double tol = 1.e-7*srcMesh->GetMeshDS()->getMaxDim(); + SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS(); + SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS(); + + const double tol = 1.e-7 * srcMeshDS->getMaxDim(); gp_Trsf trsf; // transformation to get location of target nodes from source ones if ( tgtFace.IsPartner( srcFace )) @@ -441,11 +443,11 @@ namespace { else pOK = (( tgtP.Distance( tgtPP[0] ) > tol*tol ) && ( tgtPP.size() == 1 || tgtP.Distance( tgtPP[1] ) > tol*tol )); - //cout << "V - nS " << p._node->GetID() << " - nT " << SMESH_Algo::VertexNode(TopoDS::Vertex( tgtShape),tgtMesh->GetMeshDS())->GetID() << endl; + //cout << "V - nS " << p._node->GetID() << " - nT " << SMESH_Algo::VertexNode(TopoDS::Vertex( tgtShape),tgtMeshDS)->GetID() << endl; } else if ( tgtPP.size() > 0 ) { - if ( SMESHDS_SubMesh* tgtSmds = tgtMesh->GetMeshDS()->MeshElements( tgtShape )) + if ( SMESHDS_SubMesh* tgtSmds = tgtMeshDS->MeshElements( tgtShape )) { double srcDist = srcPP[0].Distance( p ); double eTol = BRep_Tool::Tolerance( TopoDS::Edge( tgtShape )); @@ -486,26 +488,33 @@ namespace { map src2tgtNodes; map::iterator srcN_tgtN; - for ( TopExp_Explorer srcEdge( srcFace, TopAbs_EDGE); srcEdge.More(); srcEdge.Next() ) + for ( TopExp_Explorer srcExp( srcFace, TopAbs_EDGE); srcExp.More(); srcExp.Next() ) { - const TopoDS_Shape& tgtEdge = shape2ShapeMap( srcEdge.Current(), /*isSrc=*/true ); + const TopoDS_Shape& srcEdge = srcExp.Current(); + const TopoDS_Shape& tgtEdge = shape2ShapeMap( srcEdge, /*isSrc=*/true ); + if ( srcMesh->GetSubMesh( srcEdge )->IsEmpty() || + tgtMesh->GetSubMesh( tgtEdge )->IsEmpty() ) + continue; map< double, const SMDS_MeshNode* > srcNodes, tgtNodes; - if ( !SMESH_Algo::GetSortedNodesOnEdge( srcMesh->GetMeshDS(), - TopoDS::Edge( srcEdge.Current() ), - /*ignoreMediumNodes = */true, - srcNodes ) + if (( ! SMESH_Algo::GetSortedNodesOnEdge( srcMeshDS, + TopoDS::Edge( srcEdge ), + /*ignoreMediumNodes = */true, + srcNodes )) || - !SMESH_Algo::GetSortedNodesOnEdge( tgtMesh->GetMeshDS(), - TopoDS::Edge( tgtEdge ), - /*ignoreMediumNodes = */true, - tgtNodes ) + ( ! SMESH_Algo::GetSortedNodesOnEdge( tgtMeshDS, + TopoDS::Edge( tgtEdge ), + /*ignoreMediumNodes = */true, + tgtNodes )) || - srcNodes.size() != tgtNodes.size()) + (( srcNodes.size() != tgtNodes.size() ) && tgtNodes.size() > 0 ) + ) return false; - if ( !tgtEdge.IsPartner( srcEdge.Current() )) + if ( !tgtEdge.IsPartner( srcEdge )) { + if ( tgtNodes.empty() ) + return false; // check that transformation is OK by three nodes gp_Pnt p0S = SMESH_TNodeXYZ( (srcNodes.begin()) ->second); gp_Pnt p1S = SMESH_TNodeXYZ( (srcNodes.rbegin()) ->second); @@ -527,11 +536,13 @@ namespace { return false; } } - - map< double, const SMDS_MeshNode* >::iterator u_tn = tgtNodes.begin(); - map< double, const SMDS_MeshNode* >::iterator u_sn = srcNodes.begin(); - for ( ; u_tn != tgtNodes.end(); ++u_tn, ++u_sn) - src2tgtNodes.insert( make_pair( u_sn->second, u_tn->second )); + if ( !tgtNodes.empty() ) + { + map< double, const SMDS_MeshNode* >::iterator u_tn = tgtNodes.begin(); + map< double, const SMDS_MeshNode* >::iterator u_sn = srcNodes.begin(); + for ( ; u_tn != tgtNodes.end(); ++u_tn, ++u_sn) + src2tgtNodes.insert( make_pair( u_sn->second, u_tn->second )); + } } // Make new faces @@ -540,7 +551,6 @@ namespace { SMESH_MesherHelper helper( *tgtMesh ); helper.SetSubShape( tgtFace ); helper.IsQuadraticSubMesh( tgtFace ); - helper.SetElementsOnShape( true ); SMESH_MesherHelper srcHelper( *srcMesh ); srcHelper.SetSubShape( srcFace ); @@ -548,11 +558,12 @@ namespace { const SMDS_MeshNode* nullNode = 0; // indices of nodes to create properly oriented faces + bool isReverse = ( trsf.Form() != gp_Identity ); int tri1 = 1, tri2 = 2, quad1 = 1, quad3 = 3; - if ( trsf.Form() != gp_Identity ) + if ( isReverse ) std::swap( tri1, tri2 ), std::swap( quad1, quad3 ); - SMESHDS_SubMesh* srcSubDS = srcMesh->GetMeshDS()->MeshElements( srcFace ); + SMESHDS_SubMesh* srcSubDS = srcMeshDS->MeshElements( srcFace ); SMDS_ElemIteratorPtr elemIt = srcSubDS->GetElements(); vector< const SMDS_MeshNode* > tgtNodes; while ( elemIt->more() ) // loop on all mesh faces on srcFace @@ -560,6 +571,7 @@ namespace { const SMDS_MeshElement* elem = elemIt->next(); const int nbN = elem->NbCornerNodes(); tgtNodes.resize( nbN ); + helper.SetElementsOnShape( false ); for ( int i = 0; i < nbN; ++i ) // loop on nodes of the source element { const SMDS_MeshNode* srcNode = elem->GetNode(i); @@ -567,27 +579,117 @@ namespace { if ( srcN_tgtN->second == nullNode ) { // create a new node - gp_Pnt tgtP = gp_Pnt(srcNode->X(),srcNode->Y(),srcNode->Z()).Transformed( trsf ); + gp_Pnt tgtP = gp_Pnt( SMESH_TNodeXYZ( srcNode )).Transformed( trsf ); SMDS_MeshNode* n = helper.AddNode( tgtP.X(), tgtP.Y(), tgtP.Z() ); srcN_tgtN->second = n; - - gp_Pnt2d srcUV = srcHelper.GetNodeUV( srcFace, srcNode, - elem->GetNode( helper.WrapIndex(i+1,nbN))); - n->SetPosition( new SMDS_FacePosition( srcUV.X(), srcUV.Y() )); + switch ( srcNode->GetPosition()->GetTypeOfPosition() ) + { + case SMDS_TOP_FACE: + { + gp_Pnt2d srcUV = srcHelper.GetNodeUV( srcFace, srcNode ); + tgtMeshDS->SetNodeOnFace( n, helper.GetSubShapeID(), srcUV.X(), srcUV.Y() ); + break; + } + case SMDS_TOP_EDGE: + { + const TopoDS_Shape & srcE = srcMeshDS->IndexToShape( srcNode->getshapeId() ); + const TopoDS_Shape & tgtE = shape2ShapeMap( srcE, /*isSrc=*/true ); + double srcU = srcHelper.GetNodeU( TopoDS::Edge( srcE ), srcNode ); + tgtMeshDS->SetNodeOnEdge( n, TopoDS::Edge( tgtE ), srcU ); + break; + } + case SMDS_TOP_VERTEX: + { + const TopoDS_Shape & srcV = srcMeshDS->IndexToShape( srcNode->getshapeId() ); + const TopoDS_Shape & tgtV = shape2ShapeMap( srcV, /*isSrc=*/true ); + tgtMeshDS->SetNodeOnVertex( n, TopoDS::Vertex( tgtV )); + break; + } + default:; + } } tgtNodes[i] = srcN_tgtN->second; } // create a new face + helper.SetElementsOnShape( true ); switch ( nbN ) { case 3: helper.AddFace(tgtNodes[0], tgtNodes[tri1], tgtNodes[tri2]); break; case 4: helper.AddFace(tgtNodes[0], tgtNodes[quad1], tgtNodes[2], tgtNodes[quad3]); break; + default: + if ( isReverse ) std::reverse( tgtNodes.begin(), tgtNodes.end() ); + helper.AddPolygonalFace( tgtNodes ); + } + } + + // check node positions + + if ( !tgtFace.IsPartner( srcFace ) ) + { + int nbOkPos = 0; + const double tol2d = 1e-12; + srcN_tgtN = src2tgtNodes.begin(); + for ( ; srcN_tgtN != src2tgtNodes.end(); ++srcN_tgtN ) + { + const SMDS_MeshNode* n = srcN_tgtN->second; + switch ( n->GetPosition()->GetTypeOfPosition() ) + { + case SMDS_TOP_FACE: + { + gp_XY uv = helper.GetNodeUV( tgtFace, n ), uvBis = uv; + if (( helper.CheckNodeUV( tgtFace, n, uv, tol )) && + (( uv - uvBis ).SquareModulus() < tol2d ) && + ( ++nbOkPos > 10 )) + return true; + else + nbOkPos = 0; + break; + } + case SMDS_TOP_EDGE: + { + const TopoDS_Edge & tgtE = TopoDS::Edge( tgtMeshDS->IndexToShape( n->getshapeId() )); + double u = helper.GetNodeU( tgtE, n ), uBis = u; + if (( !helper.CheckNodeU( tgtE, n, u, tol )) || + (( u - uBis ) < tol2d )) + nbOkPos = 0; + break; + } + default:; + } } } + return true; } // bool projectPartner() + //================================================================================ + /*! + * \brief Check if two consecutive EDGEs are connected in 2D + * \param [in] E1 - a well oriented non-seam EDGE + * \param [in] E2 - a possibly well oriented seam EDGE + * \param [in] F - a FACE + * \return bool - result + */ + //================================================================================ + + bool are2dConnected( const TopoDS_Edge & E1, + const TopoDS_Edge & E2, + const TopoDS_Face & F ) + { + double f,l; + Handle(Geom2d_Curve) c1 = BRep_Tool::CurveOnSurface( E1, F, f, l ); + gp_Pnt2d uvLast1 = c1->Value( E1.Orientation() == TopAbs_REVERSED ? f : l ); + + Handle(Geom2d_Curve) c2 = BRep_Tool::CurveOnSurface( E2, F, f, l ); + gp_Pnt2d uvFirst2 = c2->Value( f ); + gp_Pnt2d uvLast2 = c2->Value( l ); + double tol2 = 1e-5 * uvLast2.SquareDistance( uvFirst2 ); + + return (( uvLast1.SquareDistance( uvFirst2 ) < tol2 ) || + ( uvLast1.SquareDistance( uvLast2 ) < tol2 )); + } + //================================================================================ /*! * \brief Preform projection in case if the faces are similar in 2D space @@ -612,19 +714,31 @@ namespace { // make corresponding sequence of tgt EDGEs TSideVector tgtWires( srcWires.size() ); - for ( unsigned iW = 0; iW < srcWires.size(); ++iW ) + for ( size_t iW = 0; iW < srcWires.size(); ++iW ) { list< TopoDS_Edge > tgtEdges; StdMeshers_FaceSidePtr srcWire = srcWires[iW]; TopTools_IndexedMapOfShape edgeMap; // to detect seam edges for ( int iE = 0; iE < srcWire->NbEdges(); ++iE ) { - tgtEdges.push_back( TopoDS::Edge( shape2ShapeMap( srcWire->Edge( iE ), /*isSrc=*/true))); + TopoDS_Edge E = TopoDS::Edge( shape2ShapeMap( srcWire->Edge( iE ), /*isSrc=*/true)); // reverse a seam edge encountered for the second time - const int oldExtent = edgeMap.Extent(); - edgeMap.Add( tgtEdges.back() ); - if ( oldExtent == edgeMap.Extent() ) - tgtEdges.back().Reverse(); + const int index = edgeMap.Add( E ); + if ( index < edgeMap.Extent() ) // E is a seam + { + // check which of edges to reverse, E or one already being in tgtEdges + if ( are2dConnected( tgtEdges.back(), E, tgtFace )) + { + list< TopoDS_Edge >::iterator eIt = tgtEdges.begin(); + std::advance( eIt, index-1 ); + eIt->Reverse(); + } + else + { + E.Reverse(); + } + } + tgtEdges.push_back( E ); } tgtWires[ iW ].reset( new StdMeshers_FaceSide( tgtFace, tgtEdges, tgtMesh, /*theIsForward = */ true, diff --git a/src/StdMeshers/StdMeshers_ViscousLayers.cxx b/src/StdMeshers/StdMeshers_ViscousLayers.cxx index 685b141fe..10006f481 100644 --- a/src/StdMeshers/StdMeshers_ViscousLayers.cxx +++ b/src/StdMeshers/StdMeshers_ViscousLayers.cxx @@ -897,12 +897,12 @@ namespace if ( SMESH_Algo::isDegenerated( e )) continue; TopExp::Vertices( e, VV[0], VV[1], /*CumOri=*/true ); if ( VV[1].IsSame( fromV )) { + nbEdges += edges[ 0 ].IsNull(); edges[ 0 ] = e; - nbEdges++; } else if ( VV[0].IsSame( fromV )) { + nbEdges += edges[ 1 ].IsNull(); edges[ 1 ] = e; - nbEdges++; } } } @@ -940,7 +940,7 @@ namespace } else if ( nbEdges == 1 ) { - dir = getFaceDir( faceFrw, edges[0], node, helper, ok ); + dir = getFaceDir( faceFrw, edges[ edges[0].IsNull() ], node, helper, ok ); if ( cosin ) *cosin = 1.; } else