X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH%2FSMESH_Pattern.cxx;h=f605a90e65d4b405d09b1ea143b1c8fe7cb8593c;hp=b5d732f5887f79b20e6f59f9185c80a4347292e0;hb=b09372829929f8f561495d6c16527134971a1909;hpb=57b43b4d010e2d0a1529d3c131bbb9d416e63258 diff --git a/src/SMESH/SMESH_Pattern.cxx b/src/SMESH/SMESH_Pattern.cxx index b5d732f58..f605a90e6 100644 --- a/src/SMESH/SMESH_Pattern.cxx +++ b/src/SMESH/SMESH_Pattern.cxx @@ -1,21 +1,24 @@ -// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// Copyright (C) 2007-2021 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 +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// // File : SMESH_Pattern.hxx // Created : Mon Aug 2 10:30:00 2004 @@ -23,22 +26,42 @@ #include "SMESH_Pattern.hxx" +#include "SMDS_EdgePosition.hxx" +#include "SMDS_FacePosition.hxx" +#include "SMDS_MeshElement.hxx" +#include "SMDS_MeshFace.hxx" +#include "SMDS_MeshNode.hxx" +#include "SMDS_VolumeTool.hxx" +#include "SMESHDS_Group.hxx" +#include "SMESHDS_Mesh.hxx" +#include "SMESHDS_SubMesh.hxx" +#include "SMESH_Block.hxx" +#include "SMESH_Mesh.hxx" +#include "SMESH_MeshAlgos.hxx" +#include "SMESH_MeshEditor.hxx" +#include "SMESH_MesherHelper.hxx" +#include "SMESH_subMesh.hxx" + +#include #include #include #include #include #include #include +#include #include #include #include #include #include #include -#include +#include #include #include +#include #include +#include #include #include #include @@ -46,7 +69,6 @@ #include #include #include -#include #include #include #include @@ -54,40 +76,25 @@ #include #include -#include "SMDS_EdgePosition.hxx" -#include "SMDS_FacePosition.hxx" -#include "SMDS_MeshElement.hxx" -#include "SMDS_MeshFace.hxx" -#include "SMDS_MeshNode.hxx" -#include "SMDS_VolumeTool.hxx" -#include "SMESHDS_Group.hxx" -#include "SMESHDS_Mesh.hxx" -#include "SMESHDS_SubMesh.hxx" -#include "SMESH_Block.hxx" -#include "SMESH_Mesh.hxx" -#include "SMESH_MeshEditor.hxx" -#include "SMESH_subMesh.hxx" - +#include #include "utilities.h" using namespace std; -typedef map< const SMDS_MeshElement*, int > TNodePointIDMap; +typedef std::map< const SMDS_MeshElement*, int > TNodePointIDMap; +typedef std::list< TopoDS_Edge > TWire; -//======================================================================= -//function : SMESH_Pattern -//purpose : -//======================================================================= +#define smdsNode( elem ) static_cast( elem ) -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; @@ -96,7 +103,7 @@ static inline int getInt( const char * theSring ) int val = strtol( theSring, &ptr, 10 ); if ( ptr == theSring || // there must not be neither '.' nor ',' nor 'E' ... - (*ptr != ' ' && *ptr != '\n' && *ptr != '\0')) + (*ptr != ' ' && *ptr != '\n' && *ptr != '\0' && *ptr != '\r')) return -1; return val; @@ -107,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 ); @@ -119,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(); @@ -170,7 +177,7 @@ static int readLine (list & theFields, case '-': // real number case '+': case '.': - isNumber = true; + isNumber = true; // fall through default: // data isNumber = isNumber || ( *theLineBeg >= '0' && *theLineBeg <= '9' ); if ( isNumber ) { @@ -194,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 (): myToKeepNodes(false) +{ +} + //======================================================================= //function : Load //purpose : Load a pattern from @@ -201,14 +267,14 @@ static int readLine (list & theFields, bool SMESH_Pattern::Load (const char* theFileContents) { - MESSAGE("Load( file ) "); - + Kernel_Utils::Localizer loc; + // file structure: // ! This is a comment // NB_POINTS ! 1 integer - the number of points in the pattern. // X1 Y1 [Z1] ! 2 or 3 reals - nodes coordinates within 2D or 3D domain: - // X2 Y2 [Z2] ! the pattern dimention is defined by the number of coordinates + // X2 Y2 [Z2] ! the pattern dimension is defined by the number of coordinates // ... // [ ID1 ID2 ... IDn ] ! Indices of key-points for a 2D pattern (only). // ! elements description goes after all @@ -231,7 +297,7 @@ bool SMESH_Pattern::Load (const char* theFileContents) // X1 Y1 [Z1] ! 2 or 3 reals - nodes coordinates within 2D or 3D domain: - // read the first point coordinates to define pattern dimention + // read the first point coordinates to define pattern dimension int dim = readLine( fields, lineBeg, clearFields ); if ( dim == 2 ) myIs2D = true; @@ -245,7 +311,7 @@ bool SMESH_Pattern::Load (const char* theFileContents) MESSAGE(" Too few points "); return setErrorCode( ERR_READ_TOO_FEW_POINTS ); } - + // read the rest points int iPoint; for ( iPoint = 1; iPoint < nbPoints; iPoint++ ) @@ -345,7 +411,8 @@ bool SMESH_Pattern::Load (const char* theFileContents) bool SMESH_Pattern::Save (ostream& theFile) { - MESSAGE(" ::Save(file) " ); + Kernel_Utils::Localizer loc; + if ( !IsLoaded() ) { MESSAGE(" Pattern not loaded "); return setErrorCode( ERR_SAVE_NOT_LOADED ); @@ -392,7 +459,7 @@ bool SMESH_Pattern::Save (ostream& theFile) } theFile << endl; - + return setErrorCode( ERR_OK ); } @@ -414,77 +481,6 @@ template void sortBySize( list< list < T > > & theListOfList ) } } -//======================================================================= -//function : getOrderedEdges -//purpose : return nb wires and a list of oredered edges -//======================================================================= - -static int getOrderedEdges (const TopoDS_Face& theFace, - const TopoDS_Vertex& theFirstVertex, - list< TopoDS_Edge >& theEdges, - list< int > & theNbVertexInWires) -{ - // put wires in a list, so that an outer wire comes first - list aWireList; - TopoDS_Wire anOuterWire = BRepTools::OuterWire( theFace ); - aWireList.push_back( anOuterWire ); - for ( TopoDS_Iterator wIt (theFace); wIt.More(); wIt.Next() ) - if ( !anOuterWire.IsSame( wIt.Value() )) - aWireList.push_back( TopoDS::Wire( wIt.Value() )); - - // loop on edges of wires - theNbVertexInWires.clear(); - list::iterator wlIt = aWireList.begin(); - for ( ; wlIt != aWireList.end(); wlIt++ ) - { - int iE; - BRepTools_WireExplorer wExp( *wlIt, theFace ); - for ( iE = 0; wExp.More(); wExp.Next(), iE++ ) - { - TopoDS_Edge edge = wExp.Current(); - edge = TopoDS::Edge( edge.Oriented( wExp.Orientation() )); - theEdges.push_back( edge ); - } - theNbVertexInWires.push_back( iE ); - iE = 0; - if ( wlIt == aWireList.begin() && theEdges.size() > 1 ) { // the outer wire - // orient closed edges - list< TopoDS_Edge >::iterator eIt, eIt2; - for ( eIt = theEdges.begin(); eIt != theEdges.end(); eIt++ ) - { - TopoDS_Edge& edge = *eIt; - if ( TopExp::FirstVertex( edge ).IsSame( TopExp::LastVertex( edge ) )) - { - eIt2 = eIt; - bool isNext = ( eIt2 == theEdges.begin() ); - TopoDS_Edge edge2 = isNext ? *(++eIt2) : *(--eIt2); - double f1,l1,f2,l2; - Handle(Geom2d_Curve) c1 = BRep_Tool::CurveOnSurface( edge, theFace, f1,l1 ); - Handle(Geom2d_Curve) c2 = BRep_Tool::CurveOnSurface( edge2, theFace, f2,l2 ); - gp_Pnt2d pf = c1->Value( edge.Orientation() == TopAbs_FORWARD ? f1 : l1 ); - gp_Pnt2d pl = c1->Value( edge.Orientation() == TopAbs_FORWARD ? l1 : f1 ); - bool isFirst = ( edge2.Orientation() == TopAbs_FORWARD ? isNext : !isNext ); - gp_Pnt2d p2 = c2->Value( isFirst ? f2 : l2 ); - isFirst = ( p2.SquareDistance( pf ) < p2.SquareDistance( pl )); - if ( isNext ? isFirst : !isFirst ) - edge.Reverse(); - } - } - // rotate theEdges until it begins from theFirstVertex - if ( ! theFirstVertex.IsNull() ) - while ( !theFirstVertex.IsSame( TopExp::FirstVertex( theEdges.front(), true ))) - { - theEdges.splice(theEdges.end(), theEdges, - theEdges.begin(), ++ theEdges.begin()); - if ( iE++ > theNbVertexInWires.back() ) - break; // break infinite loop - } - } - } - - return aWireList.size(); -} - //======================================================================= //function : project //purpose : @@ -499,10 +495,10 @@ static gp_XY project (const SMDS_MeshNode* theNode, MESSAGE( "SMESH_Pattern: point projection FAILED"); return gp_XY(0.,0.); } - double u, v, minVal = DBL_MAX; + double u =0, v =0, minVal = DBL_MAX; for ( int i = theProjectorPS.NbExt(); i > 0; i-- ) - if ( theProjectorPS.Value( i ) < minVal ) { - minVal = theProjectorPS.Value( i ); + if ( theProjectorPS.SquareDistance( i ) < minVal ) { + minVal = theProjectorPS.SquareDistance( i ); theProjectorPS.Point( i ).Parameter( u, v ); } return gp_XY( u, v ); @@ -520,9 +516,8 @@ template bool areNodesBound( TFaceIterator & faceItr ) SMDS_ElemIteratorPtr nIt = faceItr->next()->nodesIterator(); while ( nIt->more() ) { - const SMDS_MeshNode* node = static_cast( nIt->next() ); - SMDS_PositionPtr pos = node->GetPosition(); - if ( !pos || !pos->GetShapeId() ) { + const SMDS_MeshNode* node = smdsNode( nIt->next() ); + if (node->getshapeId() <1) { return false; } } @@ -541,7 +536,7 @@ static bool isMeshBoundToShape(SMESHDS_Mesh * aMeshDS, SMESHDS_SubMesh * aFaceSubmesh, const bool isMainShape) { - if ( isMainShape ) { + if ( isMainShape && aFaceSubmesh ) { // check that all faces are bound to aFaceSubmesh if ( aMeshDS->NbFaces() != aFaceSubmesh->NbElements() ) return false; @@ -565,17 +560,22 @@ static bool isMeshBoundToShape(SMESHDS_Mesh * aMeshDS, bool SMESH_Pattern::Load (SMESH_Mesh* theMesh, const TopoDS_Face& theFace, - bool theProject) + bool theProject, + TopoDS_Vertex the1stVertex, + bool theKeepNodes) { - MESSAGE(" ::Load(face) " ); Clear(); myIs2D = true; + myToKeepNodes = theKeepNodes; SMESHDS_Mesh * aMeshDS = theMesh->GetMeshDS(); SMESHDS_SubMesh * fSubMesh = aMeshDS->MeshElements( theFace ); + const bool isQuadMesh = aMeshDS->GetMeshInfo().NbFaces( ORDER_QUADRATIC ); + SMESH_MesherHelper helper( *theMesh ); + helper.SetSubShape( theFace ); - int nbNodes = ( !fSubMesh ? 0 : fSubMesh->NbNodes() ); - int nbElems = ( !fSubMesh ? 0 : fSubMesh->NbElements() ); + smIdType nbNodes = ( !fSubMesh ? 0 : fSubMesh->NbNodes() ); + smIdType nbElems = ( !fSubMesh ? 0 : fSubMesh->NbElements() ); if ( nbElems == 0 && aMeshDS->NbFaces() == 0 ) { MESSAGE( "No elements bound to the face"); @@ -584,72 +584,57 @@ bool SMESH_Pattern::Load (SMESH_Mesh* theMesh, TopoDS_Face face = TopoDS::Face( theFace.Oriented( TopAbs_FORWARD )); - // check that face is not closed - TopoDS_Vertex bidon; + // check if face is closed + bool isClosed = helper.HasSeam(); list eList; - getOrderedEdges( face, bidon, eList, myNbKeyPntInBoundary ); - list::iterator elIt = eList.begin(); - for ( ; elIt != eList.end() ; elIt++ ) - if ( BRep_Tool::IsClosed( *elIt , face )) - return setErrorCode( ERR_LOADF_CLOSED_FACE ); + list::iterator elIt; + SMESH_Block::GetOrderedEdges( face, eList, myNbKeyPntInBoundary, the1stVertex ); // check that requested or needed projection is possible bool isMainShape = theMesh->IsMainShape( face ); bool needProject = !isMeshBoundToShape( aMeshDS, fSubMesh, isMainShape ); bool canProject = ( nbElems ? true : isMainShape ); + if ( isClosed ) + canProject = false; // so far if ( ( theProject || needProject ) && !canProject ) return setErrorCode( ERR_LOADF_CANT_PROJECT ); Extrema_GenExtPS projector; GeomAdaptor_Surface aSurface( BRep_Tool::Surface( face )); - if ( theProject || needProject ) - projector.Initialize( aSurface, 20,20, 1e-5,1e-5 ); + projector.Initialize( aSurface, 20,20, 1e-5,1e-5 ); int iPoint = 0; TNodePointIDMap nodePointIDMap; + TNodePointIDMap closeNodePointIDMap; // for nodes on seam edges if ( needProject ) { - MESSAGE("Project the submesh"); // --------------------------------------------------------------- // The case where the submesh is projected to theFace // --------------------------------------------------------------- // get all faces - list< const SMDS_MeshElement* > faces; - if ( nbElems > 0 ) { - SMDS_ElemIteratorPtr fIt = fSubMesh->GetElements(); - while ( fIt->more() ) { - const SMDS_MeshElement* f = fIt->next(); - if ( f && f->GetType() == SMDSAbs_Face ) - faces.push_back( f ); - } - } - else { - SMDS_FaceIteratorPtr fIt = aMeshDS->facesIterator(); - while ( fIt->more() ) - faces.push_back( fIt->next() ); - } + SMDS_ElemIteratorPtr fIt; + if ( nbElems > 0 ) + fIt = fSubMesh->GetElements(); + else + fIt = aMeshDS->elementsIterator( SMDSAbs_Face ); // put nodes of all faces into the nodePointIDMap and fill myElemPointIDs - list< const SMDS_MeshElement* >::iterator fIt = faces.begin(); - for ( ; fIt != faces.end(); ++fIt ) + while ( fIt->more() ) { + const SMDS_MeshElement* face = fIt->next(); myElemPointIDs.push_back( TElemDef() ); TElemDef& elemPoints = myElemPointIDs.back(); - SMDS_ElemIteratorPtr nIt = (*fIt)->nodesIterator(); - while ( nIt->more() ) + int nbNodes = face->NbCornerNodes(); + for ( int i = 0;i < nbNodes; ++i ) { - const SMDS_MeshElement* node = nIt->next(); - TNodePointIDMap::iterator nIdIt = nodePointIDMap.find( node ); - if ( nIdIt == nodePointIDMap.end() ) - { - elemPoints.push_back( iPoint ); - nodePointIDMap.insert( make_pair( node, iPoint++ )); - } - else - elemPoints.push_back( (*nIdIt).second ); + const SMDS_MeshElement* node = face->GetNode( i ); + TNodePointIDMap::iterator nIdIt = nodePointIDMap.insert( make_pair( node, -1 )).first; + if ( nIdIt->second == -1 ) + nIdIt->second = iPoint++; + elemPoints.push_back( (*nIdIt).second ); } } myPoints.resize( iPoint ); @@ -658,8 +643,7 @@ bool SMESH_Pattern::Load (SMESH_Mesh* theMesh, TNodePointIDMap::iterator nIdIt = nodePointIDMap.begin(); for ( ; nIdIt != nodePointIDMap.end(); nIdIt++ ) { - const SMDS_MeshNode* node = - static_cast( (*nIdIt).first ); + const SMDS_MeshNode* node = smdsNode( (*nIdIt).first ); TPoint * p = & myPoints[ (*nIdIt).second ]; p->myInitUV = project( node, projector ); p->myInitXYZ.SetCoord( p->myInitUV.X(), p->myInitUV.Y(), 0 ); @@ -671,7 +655,7 @@ bool SMESH_Pattern::Load (SMESH_Mesh* theMesh, const TopoDS_Vertex v = TopoDS::Vertex( vExp.Current() ); gp_Pnt2d uv = BRep_Tool::Parameters( v, face ); double minDist = DBL_MAX; - int index; + int index = 0; vector< TPoint >::const_iterator pVecIt = myPoints.begin(); for ( iPoint = 0; pVecIt != myPoints.end(); pVecIt++, iPoint++ ) { double dist = uv.SquareDistance( (*pVecIt).myInitUV ); @@ -694,56 +678,114 @@ 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++ ) { - myShapeIDMap.Add( TopExp::FirstVertex( *elIt, true )); - SMESHDS_SubMesh * eSubMesh = aMeshDS->MeshElements( *elIt ); - if ( eSubMesh ) - nbNodes += eSubMesh->NbNodes() + 1; - } - // edges - for ( elIt = eList.begin(); elIt != eList.end(); elIt++ ) - myShapeIDMap.Add( *elIt ); - // the face + 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; + myPoints.resize( nbNodes ); + // care of INTERNAL VERTEXes + TopExp_Explorer vExp( face, TopAbs_VERTEX, TopAbs_EDGE ); + for ( ; vExp.More(); vExp.Next() ) + { + const SMDS_MeshNode* node = + SMESH_Algo::VertexNode( TopoDS::Vertex( vExp.Current()), aMeshDS ); + if ( !node || node->NbInverseElements( SMDSAbs_Face ) == 0 ) + continue; + myPoints.resize( ++nbNodes ); + list< TPoint* > & fPoints = getShapePoints( face ); + nodePointIDMap.insert( make_pair( node, iPoint )); + TPoint* p = &myPoints[ iPoint++ ]; + fPoints.push_back( p ); + gp_XY uv = helper.GetNodeUV( face, node ); + p->myInitUV.SetCoord( uv.X(), uv.Y() ); + p->myInitXYZ.SetCoord( p->myInitUV.X(), p->myInitUV.Y(), 0 ); + } + // Load U of points on edges - for ( elIt = eList.begin(); elIt != eList.end(); elIt++ ) + Bnd_Box2d edgesUVBox; + + 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 wire EDGEs in eVec + list::iterator eEnd = elIt; + if ( iE == *nbEinW ) + ++nbEinW; + std::advance( eEnd, *nbEinW ); + eVec.assign( elIt, eEnd ); + iE = 0; + } TopoDS_Edge & edge = *elIt; list< TPoint* > & ePoints = getShapePoints( edge ); double f, l; - Handle(Geom2d_Curve) C2d; - if ( !theProject ) - C2d = BRep_Tool::CurveOnSurface( edge, face, f, l ); + Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface( edge, face, f, l ); bool isForward = ( edge.Orientation() == TopAbs_FORWARD ); + TopoDS_Shape v1 = TopExp::FirstVertex( edge, true ); // always FORWARD + TopoDS_Shape v2 = TopExp::LastVertex( edge, true ); // always REVERSED + // to make adjacent edges share key-point, we make v2 FORWARD too + // (as we have different points for same shape with different orientation) + v2.Reverse(); + + // on closed face we must have REVERSED some of seam vertices + if ( isClosed ) { + if ( helper.IsSeamShape( edge ) ) { + if ( helper.IsRealSeam( edge ) && !isForward ) { + // reverse on reversed SEAM edge + v1.Reverse(); + v2.Reverse(); + } + } + else { // on CLOSED edge (i.e. having one vertex with different orientations) + for ( int is2 = 0; is2 < 2; ++is2 ) { + TopoDS_Shape & v = is2 ? v2 : v1; + if ( helper.IsRealSeam( v ) ) { + // reverse or not depending on orientation of adjacent seam + int iSeam = helper.WrapIndex( iE + ( is2 ? +1 : -1 ), eVec.size() ); + if ( eVec[ iSeam ].Orientation() == TopAbs_REVERSED ) + v.Reverse(); + } + } + } + } + // the forward key-point - TopoDS_Shape v = TopExp::FirstVertex( edge, true ); - list< TPoint* > & vPoint = getShapePoints( v ); - if ( vPoint.empty() ) + list< TPoint* > * vPoint = & getShapePoints( v1 ); + if ( vPoint->empty() ) { - SMESHDS_SubMesh * vSubMesh = aMeshDS->MeshElements( v ); + SMESHDS_SubMesh * vSubMesh = aMeshDS->MeshElements( v1 ); if ( vSubMesh && vSubMesh->NbNodes() ) { myKeyPointIDs.push_back( iPoint ); SMDS_NodeIteratorPtr nIt = vSubMesh->GetNodes(); const SMDS_MeshNode* node = nIt->next(); - nodePointIDMap.insert( make_pair( node, iPoint )); + if ( v1.Orientation() == TopAbs_REVERSED ) + closeNodePointIDMap.insert( make_pair( node, iPoint )); + else + nodePointIDMap.insert( make_pair( node, iPoint )); TPoint* keyPoint = &myPoints[ iPoint++ ]; - vPoint.push_back( keyPoint ); + vPoint->push_back( keyPoint ); if ( theProject ) keyPoint->myInitUV = project( node, projector ); else keyPoint->myInitUV = C2d->Value( isForward ? f : l ).XY(); keyPoint->myInitXYZ.SetCoord (keyPoint->myInitUV.X(), keyPoint->myInitUV.Y(), 0); + edgesUVBox.Add( gp_Pnt2d( keyPoint->myInitUV )); } } - if ( !vPoint.empty() ) - ePoints.push_back( vPoint.front() ); + if ( !vPoint->empty() ) + ePoints.push_back( vPoint->front() ); // on-edge points SMESHDS_SubMesh * eSubMesh = aMeshDS->MeshElements( edge ); @@ -752,17 +794,51 @@ bool SMESH_Pattern::Load (SMESH_Mesh* theMesh, // loop on nodes of an edge: sort them by param on edge typedef map < double, const SMDS_MeshNode* > TParamNodeMap; TParamNodeMap paramNodeMap; + int nbMeduimNodes = 0; SMDS_NodeIteratorPtr nIt = eSubMesh->GetNodes(); while ( nIt->more() ) { - const SMDS_MeshNode* node = - static_cast( nIt->next() ); - const SMDS_EdgePosition* epos = - static_cast(node->GetPosition().get()); + const SMDS_MeshNode* node = nIt->next(); + if ( isQuadMesh && helper.IsMedium( node, SMDSAbs_Face )) { + ++nbMeduimNodes; + continue; + } + SMDS_EdgePositionPtr epos = node->GetPosition(); double u = epos->GetUParameter(); - paramNodeMap.insert( TParamNodeMap::value_type( u, node )); + paramNodeMap.insert( make_pair( u, node )); + } + if ((int) paramNodeMap.size() != eSubMesh->NbNodes() - nbMeduimNodes ) { + // wrong U on edge, project + Extrema_ExtPC proj; + BRepAdaptor_Curve aCurve( edge ); + proj.Initialize( aCurve, f, l ); + paramNodeMap.clear(); + nIt = eSubMesh->GetNodes(); + for ( int iNode = 0; nIt->more(); ++iNode ) { + const SMDS_MeshNode* node = nIt->next(); + if ( isQuadMesh && helper.IsMedium( node, SMDSAbs_Face )) + continue; + proj.Perform( gp_Pnt( node->X(), node->Y(), node->Z())); + double u = 0; + if ( proj.IsDone() ) { + for ( int i = 1, nb = proj.NbExt(); i <= nb; ++i ) + if ( proj.IsMin( i )) { + u = proj.Point( i ).Parameter(); + break; + } + } else { + u = isForward ? iNode : eSubMesh->NbNodes() - iNode; + } + paramNodeMap.insert( make_pair( u, node )); + } + + //rnv : To fix the bug IPAL21999 Pattern Mapping - New - collapse of pattern mesh + if ((int) paramNodeMap.size() != eSubMesh->NbNodes() - nbMeduimNodes ) + return setErrorCode(ERR_UNEXPECTED); } + // put U in [0,1] so that the first key-point has U==0 + bool isSeam = helper.IsRealSeam( edge ); double du = l - f; TParamNodeMap::iterator unIt = paramNodeMap.begin(); TParamNodeMap::reverse_iterator unRIt = paramNodeMap.rbegin(); @@ -771,7 +847,10 @@ bool SMESH_Pattern::Load (SMESH_Mesh* theMesh, TPoint* p = & myPoints[ iPoint ]; ePoints.push_back( p ); const SMDS_MeshNode* node = isForward ? (*unIt).second : (*unRIt).second; - nodePointIDMap.insert ( make_pair( node, iPoint )); + if ( isSeam && !isForward ) + closeNodePointIDMap.insert( make_pair( node, iPoint )); + else + nodePointIDMap.insert ( make_pair( node, iPoint )); if ( theProject ) p->myInitUV = project( node, projector ); @@ -781,33 +860,37 @@ bool SMESH_Pattern::Load (SMESH_Mesh* theMesh, p->myInitUV = C2d->Value( u ).XY(); } p->myInitXYZ.SetCoord( p->myInitUV.X(), p->myInitUV.Y(), 0 ); + edgesUVBox.Add( gp_Pnt2d( p->myInitUV )); unIt++; unRIt++; iPoint++; } } // the reverse key-point - v = TopExp::LastVertex( edge, true ).Reversed(); - list< TPoint* > & vPoint2 = getShapePoints( v ); - if ( vPoint2.empty() ) + vPoint = & getShapePoints( v2 ); + if ( vPoint->empty() ) { - SMESHDS_SubMesh * vSubMesh = aMeshDS->MeshElements( v ); + SMESHDS_SubMesh * vSubMesh = aMeshDS->MeshElements( v2 ); if ( vSubMesh && vSubMesh->NbNodes() ) { myKeyPointIDs.push_back( iPoint ); SMDS_NodeIteratorPtr nIt = vSubMesh->GetNodes(); const SMDS_MeshNode* node = nIt->next(); - nodePointIDMap.insert( make_pair( node, iPoint )); + if ( v2.Orientation() == TopAbs_REVERSED ) + closeNodePointIDMap.insert( make_pair( node, iPoint )); + else + nodePointIDMap.insert( make_pair( node, iPoint )); TPoint* keyPoint = &myPoints[ iPoint++ ]; - vPoint2.push_back( keyPoint ); + vPoint->push_back( keyPoint ); if ( theProject ) keyPoint->myInitUV = project( node, projector ); else keyPoint->myInitUV = C2d->Value( isForward ? l : f ).XY(); keyPoint->myInitXYZ.SetCoord( keyPoint->myInitUV.X(), keyPoint->myInitUV.Y(), 0 ); + edgesUVBox.Add( gp_Pnt2d( keyPoint->myInitUV )); } } - if ( !vPoint2.empty() ) - ePoints.push_back( vPoint2.front() ); + if ( !vPoint->empty() ) + ePoints.push_back( vPoint->front() ); // compute U of edge-points if ( theProject ) @@ -838,34 +921,80 @@ bool SMESH_Pattern::Load (SMESH_Mesh* theMesh, SMDS_NodeIteratorPtr nIt = fSubMesh->GetNodes(); while ( nIt->more() ) { - const SMDS_MeshNode* node = - static_cast( nIt->next() ); + const SMDS_MeshNode* node = nIt->next(); + if ( isQuadMesh && helper.IsMedium( node, SMDSAbs_Face )) + continue; nodePointIDMap.insert( make_pair( node, iPoint )); TPoint* p = &myPoints[ iPoint++ ]; fPoints.push_back( p ); - if ( theProject ) + if ( theProject || edgesUVBox.IsOut( p->myInitUV ) ) p->myInitUV = project( node, projector ); else { - const SMDS_FacePosition* pos = - static_cast(node->GetPosition().get()); + SMDS_FacePositionPtr pos = node->GetPosition(); p->myInitUV.SetCoord( pos->GetUParameter(), pos->GetVParameter() ); } p->myInitXYZ.SetCoord( p->myInitUV.X(), p->myInitUV.Y(), 0 ); } // load elements + TNodePointIDMap::iterator n_id, not_found = closeNodePointIDMap.end(); SMDS_ElemIteratorPtr elemIt = fSubMesh->GetElements(); - while ( elemIt->more() ) { - SMDS_ElemIteratorPtr nIt = elemIt->next()->nodesIterator(); + while ( elemIt->more() ) + { + const SMDS_MeshElement* elem = elemIt->next(); + SMDS_ElemIteratorPtr nIt = elem->nodesIterator(); myElemPointIDs.push_back( TElemDef() ); TElemDef& elemPoints = myElemPointIDs.back(); + // find point indices corresponding to element nodes while ( nIt->more() ) - elemPoints.push_back( nodePointIDMap[ nIt->next() ]); + { + const SMDS_MeshNode* node = smdsNode( nIt->next() ); + n_id = nodePointIDMap.find( node ); + if ( n_id == nodePointIDMap.end() ) + continue; // medium node + iPoint = n_id->second; // point index of interest + // for a node on a seam edge there are two points + if ( helper.IsRealSeam( node->getshapeId() ) && + ( n_id = closeNodePointIDMap.find( node )) != not_found ) + { + TPoint & p1 = myPoints[ iPoint ]; + TPoint & p2 = myPoints[ n_id->second ]; + // Select point closest to the rest nodes of element in UV space + SMDS_ElemIteratorPtr nIt2 = elem->nodesIterator(); + const SMDS_MeshNode* notSeamNode = 0; + // find node not on a seam edge + while ( nIt2->more() && !notSeamNode ) { + const SMDS_MeshNode* n = smdsNode( nIt2->next() ); + if ( !helper.IsSeamShape( n->getshapeId() )) + notSeamNode = n; + } + gp_Pnt2d uv = helper.GetNodeUV( theFace, node, notSeamNode ); + double dist1 = uv.SquareDistance( p1.myInitUV ); + double dist2 = uv.SquareDistance( p2.myInitUV ); + if ( dist2 < dist1 ) + iPoint = n_id->second; + } + elemPoints.push_back( iPoint ); + } } } + myPoints.resize( nodePointIDMap.size() + closeNodePointIDMap.size() ); myIsBoundaryPointsFound = true; } + if ( myToKeepNodes ) + { + myInNodes.resize( nodePointIDMap.size() + closeNodePointIDMap.size() ); + + TNodePointIDMap::iterator nIdIt = nodePointIDMap.begin(); + for ( ; nIdIt != nodePointIDMap.end(); nIdIt++ ) + myInNodes[ nIdIt->second ] = smdsNode( nIdIt->first ); + + nIdIt = closeNodePointIDMap.begin(); + for ( ; nIdIt != closeNodePointIDMap.end(); nIdIt++ ) + myInNodes[ nIdIt->second ] = smdsNode( nIdIt->first ); + } + // Assure that U range is proportional to V range Bnd_Box2d bndBox; @@ -933,6 +1062,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++ ) { @@ -958,13 +1088,20 @@ static bool intersectIsolines(const gp_XY& uv11, const gp_XY& uv12, const double gp_XY loc1 = uv11 * ( 1 - r1 ) + uv12 * r1; gp_XY loc2 = uv21 * ( 1 - r2 ) + uv22 * r2; resUV = 0.5 * ( loc1 + loc2 ); - isDeformed = ( loc1 - loc2 ).SquareModulus() > 1e-8; + //isDeformed = ( loc1 - loc2 ).SquareModulus() > 1e-8; + // SKL 26.07.2007 for NPAL16567 + double d1 = (uv11-uv12).Modulus(); + double d2 = (uv21-uv22).Modulus(); + // double delta = d1*d2*1e-6; PAL17233 + double delta = min( d1, d2 ) / 10.; + isDeformed = ( loc1 - loc2 ).SquareModulus() > delta * delta; + // double len1 = ( uv11 - uv12 ).Modulus(); // double len2 = ( uv21 - uv22 ).Modulus(); // resUV = loc1 * len2 / ( len1 + len2 ) + loc2 * len1 / ( len1 + len2 ); // return true; - + // gp_Lin2d line1( uv11, uv12 - uv11 ); // gp_Lin2d line2( uv21, uv22 - uv21 ); // double angle = Abs( line1.Angle( line2 ) ); @@ -978,9 +1115,13 @@ static bool intersectIsolines(const gp_XY& uv11, const gp_XY& uv12, const double // inter.Perform( line1, line2 ); // interUV = inter.Point(1).Value(); // resUV += interUV.XY(); - + // resUV /= 2.; // } + // if ( isDeformed ) { + // MESSAGE("intersectIsolines(), d1 = " << d1 << ", d2 = " << d2 << ", delta = " << delta << + // ", " << (loc1 - loc2).SquareModulus() << " > " << delta * delta); + // } return true; } @@ -1014,7 +1155,7 @@ bool SMESH_Pattern::compUVByIsoIntersection (const list< list< TPoint* > >& theB const list< TPoint* > & bndPoints = * bndIt; TPoint* prevP = bndPoints.back(); // this is the first point list< TPoint* >::const_iterator pIt = bndPoints.begin(); - bool coincPrev = false; + bool coincPrev = false; // loop on the edge-points for ( ; pIt != bndPoints.end(); pIt++ ) { @@ -1073,7 +1214,7 @@ bool SMESH_Pattern::compUVByIsoIntersection (const list< list< TPoint* > >& theB } if ( !intersectIsolines( uv1[0], uv2[0], ratio[0], uv1[1], uv2[1], ratio[1], theUV, theIsDeformed )) { - MESSAGE(" Cant intersect isolines for a point "<myUV - n[2]->myUV ).SquareModulus() ); } maxLen2 = Max( maxLen2, ( n[2]->myUV - node->myUV ).SquareModulus() ); - minDiag = sqrt( maxLen2 ) * PI / 60.; // ~ maxLen * Sin( 3 deg ) + minDiag = sqrt( maxLen2 ) * M_PI / 60.; // ~ maxLen * Sin( 3 deg ) } // check if newUV is behind 3 dirs: n[0]-n[1], n[1]-n[2] and n[0]-n[2] @@ -1279,7 +1420,7 @@ static bool checkQuads (const TIsoNode* node, gp_XY uv1, uv2 = node->myUV; for ( i = isTriangle ? 2 : 0; i < 3; i++ ) // mark not computed vectors if ( wasOk[i] ) - moveVec[ i ].SetCoord( 1, 2e100); // not use this vector + moveVec[ i ].SetCoord( 1, 2e100); // not use this vector while ( !isOldOk ) { // find the least moveVec int i, iMin = 4; @@ -1343,7 +1484,7 @@ static bool checkQuads (const TIsoNode* node, return false; } else { - //MESSAGE(" Cant improve UV, uv: "< >& theBndPoints, const list< TPoint* >& thePntToCompute) { + return false; // PAL17233 //cout << "============================== KEY POINTS =============================="<::iterator kpIt = myKeyPointIDs.begin(); // for ( ; kpIt != myKeyPointIDs.end(); kpIt++ ) { @@ -1607,6 +1749,11 @@ bool SMESH_Pattern:: // " dir0: "<myDir[0].X()<<" "<myDir[0].Y() << // " dir1: "<myDir[1].X()<<" "<myDir[1].Y() << endl; } + else { + /// WHAT IN THIS CASE ????????????? MAY BE THIS, I AM NOT SURE :( + node->SetBoundaryNode( 0, iDir, 0 ); + node->SetBoundaryNode( 0, iDir, 1 ); + } } nIt++; nPrevIt++; if ( nNextIt != isoLine.end() ) nNextIt++; @@ -1704,7 +1851,7 @@ bool SMESH_Pattern:: aNorm[1-iDir].Normalize(); double r = Abs ( ratio[iDir] - 0.5 ) * 2.0; // [0,1] - distance from the middle r *= r; - + node->myDir[iDir] = //aTgt[iDir]; aNorm[1-iDir] * r + aTgt[iDir] * ( 1. - r ); } @@ -1730,7 +1877,7 @@ bool SMESH_Pattern:: double initAngle = initTgt1.Angle( initTgt2 ); double angle = node->myDir[0].Angle( node->myDir[1] ); if ( reversed ) angle = -angle; - if ( initAngle > angle && initAngle - angle > PI / 2.1 ) { + if ( initAngle > angle && initAngle - angle > M_PI / 2.1 ) { // find a close internal node TIsoNode* nClose = 0; list< TIsoNode* > testNodes; @@ -1769,7 +1916,7 @@ bool SMESH_Pattern:: list < TIsoNode* > internNodes; bool needIteration = true; if ( startNodes.empty() ) { - MESSAGE( " Starting UV by compUVByIsoIntersection()"); + //MESSAGE( " Starting UV by compUVByIsoIntersection()"); needIteration = false; map < double, TIsoLine >& isos = isoMap[ 0 ]; map < double, TIsoLine >::iterator isoIt = isos.begin(); @@ -1824,7 +1971,7 @@ bool SMESH_Pattern:: for ( nIt = startNodes.begin(); nIt != startNodes.end(); nIt++ ) { - TIsoNode* prevN[2], *node = *nIt; + TIsoNode *node = *nIt; if ( node->IsUVComputed() || !node->IsMovable() ) continue; gp_XY newUV( 0, 0 ), sumDir( 0, 0 ); @@ -1856,6 +2003,10 @@ bool SMESH_Pattern:: // dir = node->myDir[ 1 - iDir ].XY() * ( isEnd ? -1. : 1. ); //cout << "__________"<myInitUV.X()<<" "<myInitUV.Y()<GetBoundaryNode( iDir, isEnd ); + if ( !bndNode ) { + MESSAGE("Why we are here?"); + continue; + } gp_XY tgt( bndNode->myDir[0].XY() + bndNode->myDir[1].XY() ); dir.SetCoord( 1, tgt.Y() * ( reversed ? 1 : -1 )); dir.SetCoord( 2, tgt.X() * ( reversed ? -1 : 1 )); @@ -1881,10 +2032,10 @@ bool SMESH_Pattern:: newUV += prevNode1->myUV + dir * step[ iDir ]; } sumDir += dir; - prevN[ iDir ] = prevNode1; nbComp++; } } + if ( !nbComp ) continue; newUV /= nbComp; node->myUV = newUV; //cout << "NODE: "<myInitUV.X()<<" "<myInitUV.Y()<myDir[ iDir ] ); } // define ratio - double locR[2] = { 0, 0 }; + bool ok = true; // <- stupid fix TO AVOID PB OF NODES WITH NULL BND NODES +// double locR[2] = { 0, 0 }; for ( iDir = 0; iDir < 2; iDir++ ) { const int iCoord = 2 - iDir; // coord changing along an isoline TIsoNode* bndNode1 = node->GetBoundaryNode( iDir, 0 ); TIsoNode* bndNode2 = node->GetBoundaryNode( iDir, 1 ); + if ( !bndNode1 || !bndNode2 ) { + ok = false; break; + } double par1 = bndNode1->myInitUV.Coord( iCoord ); double par2 = node->myInitUV.Coord( iCoord ); double par3 = bndNode2->myInitUV.Coord( iCoord ); double r = ( par2 - par1 ) / ( par3 - par1 ); r = Abs ( r - 0.5 ) * 2.0; // [0,1] - distance from the middle - locR[ iDir ] = ( 1 - r * r ) * 0.25; +// locR[ iDir ] = ( 1 - r * r ) * 0.25; } //locR[0] = locR[1] = 0.25; // intersect the 2 lines and move a node //IntAna2d_AnaIntersection inter( line[0], line[1] ); - if ( /*inter.IsDone() && inter.NbPoints() ==*/ 1 ) + if ( ok /*inter.IsDone() && inter.NbPoints() ==*/ ) { // double intR = 1 - locR[0] - locR[1]; // gp_XY newUV = inter.Point(1).Value().XY(); @@ -1981,7 +2136,7 @@ bool SMESH_Pattern:: #endif } while ( maxMove > 1e-8 && nbIter++ < maxNbIter ); - MESSAGE( "compUVByElasticIsolines(): Nb iterations " << nbIter << " dist: " << sqrt( maxMove )); + //MESSAGE( "compUVByElasticIsolines(): Nb iterations " << nbIter << " dist: " << sqrt( maxMove )); if ( nbIter >= maxNbIter && sqrt(maxMove) > minUvSize * 0.05 ) { MESSAGE( "compUVByElasticIsolines() failed: "<"< & theWire, int theFirstE int eID = theFirstEdgeID; for ( iE = 0; iE < nbEdges; iE++ ) maxNbPnt = Max ( maxNbPnt, getShapePoints( eID++ ).size() ); - + // compute bnd boxes TopoDS_Face face = TopoDS::Face( myShape ); Bnd_Box2d bndBox, eBndBox; @@ -2060,8 +2214,8 @@ double SMESH_Pattern::setFirstEdge (list< TopoDS_Edge > & theWire, int theFirstE bndBox.Get( minPar[0], minPar[1], maxPar[0], maxPar[1] ); eBndBox.Get( eMinPar[0], eMinPar[1], eMaxPar[0], eMaxPar[1] ); #ifdef DBG_SETFIRSTEDGE - cout << "EDGES: X: " << eMinPar[0] << " - " << eMaxPar[0] << " Y: " - << eMinPar[1] << " - " << eMaxPar[1] << endl; + MESSAGE ( "EDGES: X: " << eMinPar[0] << " - " << eMaxPar[0] << " Y: " + << eMinPar[1] << " - " << eMaxPar[1] ); #endif for ( int iC = 1, i = 0; i < 2; iC++, i++ ) // loop on 2 coordinates { @@ -2087,7 +2241,7 @@ double SMESH_Pattern::setFirstEdge (list< TopoDS_Edge > & theWire, int theFirstE for ( iE = 0 ; iE < nbEdges; iE++ ) { #ifdef DBG_SETFIRSTEDGE - cout << " VARIANT " << iE << endl; + MESSAGE ( " VARIANT " << iE ); #endif // evaluate the distance between UV computed by the 2 methods: // by isos intersection ( myXYZ ) and by edge p-curves ( myUV ) @@ -2101,13 +2255,13 @@ double SMESH_Pattern::setFirstEdge (list< TopoDS_Edge > & theWire, int theFirstE TPoint* p = (*pIt); dist += ( p->myUV - gp_XY( p->myXYZ.X(), p->myXYZ.Y() )).SquareModulus(); #ifdef DBG_SETFIRSTEDGE - cout << " ISO : ( " << p->myXYZ.X() << ", "<< p->myXYZ.Y() << " ) PCURVE : ( " << - p->myUV.X() << ", " << p->myUV.Y() << ") " << endl; + MESSAGE ( " ISO : ( " << p->myXYZ.X() << ", "<< p->myXYZ.Y() << " ) PCURVE : ( " << + p->myUV.X() << ", " << p->myUV.Y() << ") " ); #endif } } #ifdef DBG_SETFIRSTEDGE - cout << "dist -- " << dist << endl; + MESSAGE ( "dist -- " << dist ); #endif if ( dist < minDist ) { minDist = dist; @@ -2163,7 +2317,7 @@ bool SMESH_Pattern::sortSameSizeWires (TListOfEdgesList & theWire list< TPoint* > & ePoints = getShapePoints( eID++ ); TPoint* p = ePoints.front(); if ( !compUVByIsoIntersection( theEdgesPointsList, p->myInitUV, p->myUV, aBool )) { - MESSAGE("cant sortSameSizeWires()"); + MESSAGE("can't sortSameSizeWires()"); return false; } gcVec[iW] += p->myUV; @@ -2214,7 +2368,7 @@ bool SMESH_Pattern::sortSameSizeWires (TListOfEdgesList & theWire // " \t vertex: " << vGcVec[iW].X() << " " << vGcVec[iW].Y() << endl; double minDist = DBL_MAX; gp_XY & wGc = vGcVec[ iW ]; - int bIndex; + int bIndex = 0; for ( int iB = 0; iB < nbWires; iB++ ) { if ( bndFound[ iB ] ) continue; double dist = ( wGc - gcVec[ iB ] ).SquareModulus(); @@ -2227,7 +2381,7 @@ bool SMESH_Pattern::sortSameSizeWires (TListOfEdgesList & theWire bndIndWirePosMap.insert( TIntWirePosMap::value_type( bIndex, wlIt )); } - // Treat each wire + // Treat each wire TIntWirePosMap::iterator bIndWPosIt = bndIndWirePosMap.begin(); eID = theFirstEdgeID; @@ -2238,7 +2392,7 @@ bool SMESH_Pattern::sortSameSizeWires (TListOfEdgesList & theWire // choose the best first edge of a wire setFirstEdge( wire, eID ); - + // compute eventual UV and fill theEdgesPointsList theEdgesPointsList.push_back( list< TPoint* >() ); list< TPoint* > & edgesPoints = theEdgesPointsList.back(); @@ -2267,7 +2421,6 @@ bool SMESH_Pattern::Apply (const TopoDS_Face& theFace, const TopoDS_Vertex& theVertexOnKeyPoint1, const bool theReverse) { - MESSAGE(" ::Apply(face) " ); TopoDS_Face face = theReverse ? TopoDS::Face( theFace.Reversed() ) : theFace; if ( !setShapeToMesh( face )) return false; @@ -2281,7 +2434,7 @@ bool SMESH_Pattern::Apply (const TopoDS_Face& theFace, list< TopoDS_Edge > eList; list< int > nbVertexInWires; - int nbWires = getOrderedEdges( face, theVertexOnKeyPoint1, eList, nbVertexInWires); + int nbWires = SMESH_Block::GetOrderedEdges( face, eList, nbVertexInWires, theVertexOnKeyPoint1); if ( !theVertexOnKeyPoint1.IsSame( TopExp::FirstVertex( eList.front(), true ))) { MESSAGE( " theVertexOnKeyPoint1 not found in the outer wire "); @@ -2297,20 +2450,10 @@ 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 )); - if ( BRep_Tool::IsClosed( *elIt, theFace ) ) - myShapeIDMap.Add( TopExp::LastVertex( *elIt, true )); - } - 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()/* + nbSeamShapes*/ ) { + if ((int) myShapeIDToPointsMap.size() != myShapeIDMap.Extent() ) { MESSAGE( myShapeIDToPointsMap.size() <<" != " << myShapeIDMap.Extent()); return setErrorCode( ERR_APPLF_INTERNAL_EEROR ); } @@ -2319,10 +2462,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++ ) @@ -2337,20 +2481,21 @@ bool SMESH_Pattern::Apply (const TopoDS_Face& theFace, // If there are several wires, define the order of edges of inner wires: // compute UV of inner edge-points using 2 methods: the one for in-face points // and the one for on-edge points and then choose the best edge order - // by the best correspondance of the 2 results + // by the best correspondence of the 2 results. + // The wires are sorted by number of edges to correspond to wires of the pattern if ( nbWires > 1 ) { // compute UV of inner edge-points using the method for in-face points - // and devide eList into a list of separate wires + // and divide eList into a list of separate wires bool aBool; - list< list< TopoDS_Edge > > wireList; + list< TWire > wireList; list::iterator eIt = elIt; list::iterator nbEIt = nbVertexInWires.begin(); for ( nbEIt++; nbEIt != nbVertexInWires.end(); nbEIt++ ) { int nbEdges = *nbEIt; wireList.push_back( list< TopoDS_Edge >() ); - list< TopoDS_Edge > & wire = wireList.back(); + TWire & wire = wireList.back(); for ( iE = 0 ; iE < nbEdges; eIt++, iE++ ) { list< TPoint* > & ePoints = getShapePoints( *eIt ); @@ -2358,7 +2503,7 @@ bool SMESH_Pattern::Apply (const TopoDS_Face& theFace, for ( pIt++; pIt != ePoints.end(); pIt++ ) { TPoint* p = (*pIt); if ( !compUVByIsoIntersection( edgesPointsList, p->myInitUV, p->myUV, aBool )) { - MESSAGE("cant Apply(face)"); + MESSAGE("can't Apply(face)"); return false; } // keep the computed UV to compare against by setFirstEdge() @@ -2381,11 +2526,11 @@ bool SMESH_Pattern::Apply (const TopoDS_Face& theFace, // find points - edge correspondence for wires of unique size, // edge order within a wire should be defined only - list< list< TopoDS_Edge > >::iterator wlIt = wireList.begin(); + list< TWire >::iterator wlIt = wireList.begin(); while ( wlIt != wireList.end() ) { - list< TopoDS_Edge >& wire = (*wlIt); - int nbEdges = wire.size(); + TWire& wire = (*wlIt); + size_t nbEdges = wire.size(); wlIt++; if ( wlIt == wireList.end() || (*wlIt).size() != nbEdges ) // a unique size wire { @@ -2403,17 +2548,23 @@ bool SMESH_Pattern::Apply (const TopoDS_Face& theFace, edgesPoints->insert( edgesPoints->end(), ePoints.begin(), (--ePoints.end())); } } + else + { + // skip same size wires + while ( wlIt != wireList.end() && (*wlIt).size() == nbEdges ) + wlIt++; + } id1 += nbEdges; } // find boundary - wire correspondence for several wires of same size - + id1 = nbVertices + nbEdgesInOuterWire + 1; wlIt = wireList.begin(); while ( wlIt != wireList.end() ) { - int nbSameSize = 0, nbEdges = (*wlIt).size(); - list< list< TopoDS_Edge > >::iterator wlIt2 = wlIt; + size_t nbSameSize = 0, nbEdges = (*wlIt).size(); + list< TWire >::iterator wlIt2 = wlIt; wlIt2++; while ( wlIt2 != wireList.end() && (*wlIt2).size() == nbEdges ) { // a same size wire nbSameSize++; @@ -2427,40 +2578,45 @@ bool SMESH_Pattern::Apply (const TopoDS_Face& theFace, } // add well-ordered edges to eList - + for ( wlIt = wireList.begin(); wlIt != wireList.end(); wlIt++ ) { - list< TopoDS_Edge >& wire = (*wlIt); + TWire& wire = (*wlIt); eList.splice( eList.end(), wire, wire.begin(), wire.end() ); } // 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; for ( iE = nbVertices + 1, elIt = eList.begin(); elIt != eList.end(); elIt++ ) { - double f,l; - Handle(Geom_Curve) C3d = BRep_Tool::Curve( *elIt, loc, f, l ); - const gp_Trsf & aTrsf = loc.Transformation(); + 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 ); - if ( !loc.IsIdentity() ) - aTrsf.Transforms( point->myXYZ.ChangeCoord() ); + point->myXYZ = C3d.Value( point->myU ); } } @@ -2472,7 +2628,7 @@ bool SMESH_Pattern::Apply (const TopoDS_Face& theFace, for ( pIt = fPoints.begin(); !isDeformed && pIt != fPoints.end(); pIt++ ) if ( !compUVByIsoIntersection( edgesPointsList, (*pIt)->myInitUV, (*pIt)->myUV, isDeformed )) { - MESSAGE("cant Apply(face)"); + MESSAGE("can't Apply(face)"); return false; } // try to use a complex algo if it is a difficult case @@ -2481,7 +2637,7 @@ bool SMESH_Pattern::Apply (const TopoDS_Face& theFace, for ( ; pIt != fPoints.end(); pIt++ ) // continue with the simple algo if ( !compUVByIsoIntersection( edgesPointsList, (*pIt)->myInitUV, (*pIt)->myUV, isDeformed )) { - MESSAGE("cant Apply(face)"); + MESSAGE("can't Apply(face)"); return false; } } @@ -2520,8 +2676,9 @@ bool SMESH_Pattern::Apply (const SMDS_MeshFace* theFace, } // check nb of nodes - if (theFace->NbNodes() != myNbKeyPntInBoundary.front() ) { - MESSAGE( myKeyPointIDs.size() << " != " << theFace->NbNodes() ); + const int nbFaceNodes = theFace->NbCornerNodes(); + if ( nbFaceNodes != myNbKeyPntInBoundary.front() ) { + MESSAGE( myKeyPointIDs.size() << " != " << nbFaceNodes ); return setErrorCode( ERR_APPL_BAD_NB_VERTICES ); } @@ -2538,10 +2695,10 @@ bool SMESH_Pattern::Apply (const SMDS_MeshFace* theFace, list< const SMDS_MeshNode* > nodes; list< const SMDS_MeshNode* >::iterator n = nodes.end(); - SMDS_ElemIteratorPtr noIt = theFace->nodesIterator(); + SMDS_NodeIteratorPtr noIt = theFace->nodeIterator(); int iSub = 0; - while ( noIt->more() ) { - const SMDS_MeshNode* node = static_cast( noIt->next() ); + while ( noIt->more() && iSub < nbFaceNodes ) { + const SMDS_MeshNode* node = noIt->next(); nodes.push_back( node ); if ( iSub++ == theNodeIndexOnKeyPoint1 ) n = --nodes.end(); @@ -2556,9 +2713,9 @@ bool SMESH_Pattern::Apply (const SMDS_MeshFace* theFace, nodes.splice( nodes.end(), nodes, nodes.begin(), n ); } list< gp_XYZ > xyzList; - myOrderedNodes.resize( theFace->NbNodes() ); + myOrderedNodes.resize( nbFaceNodes ); for ( iSub = 0, n = nodes.begin(); n != nodes.end(); ++n ) { - xyzList.push_back( gp_XYZ( (*n)->X(), (*n)->Y(), (*n)->Z() )); + xyzList.push_back( SMESH_TNodeXYZ( *n )); myOrderedNodes[ iSub++] = *n; } @@ -2596,7 +2753,7 @@ bool SMESH_Pattern::Apply (const SMDS_MeshFace* theFace, { gp_XYZ& xyz1 = *xyzIt++; gp_XYZ& xyz2 = ( xyzIt != xyzList.end() ) ? *xyzIt : xyzList.front(); - + list< TPoint* > & ePoints = getShapePoints( iSub ); ePoints.back()->myInitU = 1.0; list< TPoint* >::const_iterator pIt = ++ePoints.begin(); @@ -2620,7 +2777,7 @@ bool SMESH_Pattern::Apply (const SMDS_MeshFace* theFace, for ( pIt = fPoints.begin(); !isDeformed && pIt != fPoints.end(); pIt++ ) if ( !compUVByIsoIntersection( edgesPointsList, (*pIt)->myInitUV, (*pIt)->myUV, isDeformed )) { - MESSAGE("cant Apply(face)"); + MESSAGE("can't Apply(face)"); return false; } // try to use a complex algo if it is a difficult case @@ -2629,7 +2786,7 @@ bool SMESH_Pattern::Apply (const SMDS_MeshFace* theFace, for ( ; pIt != fPoints.end(); pIt++ ) // continue with the simple algo if ( !compUVByIsoIntersection( edgesPointsList, (*pIt)->myInitUV, (*pIt)->myUV, isDeformed )) { - MESSAGE("cant Apply(face)"); + MESSAGE("can't Apply(face)"); return false; } } @@ -2644,6 +2801,162 @@ bool SMESH_Pattern::Apply (const SMDS_MeshFace* theFace, return setErrorCode( ERR_OK ); } +//======================================================================= +//function : Apply +//purpose : Compute nodes coordinates applying +// the loaded pattern to . The first key-point +// will be mapped into -th node +//======================================================================= + +bool SMESH_Pattern::Apply (SMESH_Mesh* theMesh, + const SMDS_MeshFace* theFace, + const TopoDS_Shape& theSurface, + const int theNodeIndexOnKeyPoint1, + const bool theReverse) +{ +// MESSAGE(" ::Apply(MeshFace) " ); + if ( theSurface.IsNull() || theSurface.ShapeType() != TopAbs_FACE ) { + return Apply( theFace, theNodeIndexOnKeyPoint1, theReverse); + } + const TopoDS_Face& face = TopoDS::Face( theSurface ); + TopLoc_Location loc; + Handle(Geom_Surface) surface = BRep_Tool::Surface( face, loc ); + const gp_Trsf & aTrsf = loc.Transformation(); + + if ( !IsLoaded() ) { + MESSAGE( "Pattern not loaded" ); + return setErrorCode( ERR_APPL_NOT_LOADED ); + } + + // check nb of nodes + if (theFace->NbNodes() != myNbKeyPntInBoundary.front() ) { + MESSAGE( myKeyPointIDs.size() << " != " << theFace->NbNodes() ); + return setErrorCode( ERR_APPL_BAD_NB_VERTICES ); + } + + // find points on edges, it fills myNbKeyPntInBoundary + if ( !findBoundaryPoints() ) + return false; + + // check that there are no holes in a pattern + if (myNbKeyPntInBoundary.size() > 1 ) { + return setErrorCode( ERR_APPL_BAD_NB_VERTICES ); + } + + // Define the nodes order + + list< const SMDS_MeshNode* > nodes; + list< const SMDS_MeshNode* >::iterator n = nodes.end(); + SMDS_ElemIteratorPtr noIt = theFace->nodesIterator(); + int iSub = 0; + while ( noIt->more() ) { + const SMDS_MeshNode* node = smdsNode( noIt->next() ); + nodes.push_back( node ); + if ( iSub++ == theNodeIndexOnKeyPoint1 ) + n = --nodes.end(); + } + if ( n != nodes.end() ) { + if ( theReverse ) { + if ( n != --nodes.end() ) + nodes.splice( nodes.begin(), nodes, ++n, nodes.end() ); + nodes.reverse(); + } + else if ( n != nodes.begin() ) + nodes.splice( nodes.end(), nodes, nodes.begin(), n ); + } + + // find a node not on a seam edge, if necessary + SMESH_MesherHelper helper( *theMesh ); + helper.SetSubShape( theSurface ); + const SMDS_MeshNode* inFaceNode = 0; + if ( helper.GetNodeUVneedInFaceNode() ) + { + SMESH_MeshEditor editor( theMesh ); + for ( n = nodes.begin(); ( !inFaceNode && n != nodes.end()); ++n ) { + int shapeID = editor.FindShape( *n ); + if ( !shapeID ) + return Apply( theFace, theNodeIndexOnKeyPoint1, theReverse); + if ( !helper.IsSeamShape( shapeID )) + inFaceNode = *n; + } + } + + // Set UV of key-points (i.e. of nodes of theFace ) + vector< gp_XY > keyUV( theFace->NbNodes() ); + myOrderedNodes.resize( theFace->NbNodes() ); + for ( iSub = 1, n = nodes.begin(); n != nodes.end(); ++n, ++iSub ) + { + TPoint* p = getShapePoints( iSub ).front(); + p->myUV = helper.GetNodeUV( face, *n, inFaceNode ); + p->myXYZ = gp_XYZ( (*n)->X(), (*n)->Y(), (*n)->Z() ); + + keyUV[ iSub-1 ] = p->myUV; + myOrderedNodes[ iSub-1 ] = *n; + } + + // points on edges to be used for UV computation of in-face points + list< list< TPoint* > > edgesPointsList; + edgesPointsList.push_back( list< TPoint* >() ); + list< TPoint* > * edgesPoints = & edgesPointsList.back(); + list< TPoint* >::iterator pIt; + + // compute UV and XYZ of points on edges + + for ( size_t i = 0; i < myOrderedNodes.size(); ++i, ++iSub ) + { + gp_XY& uv1 = keyUV[ i ]; + gp_XY& uv2 = ( i+1 < keyUV.size() ) ? keyUV[ i+1 ] : keyUV[ 0 ]; + + list< TPoint* > & ePoints = getShapePoints( iSub ); + ePoints.back()->myInitU = 1.0; + list< TPoint* >::const_iterator pIt = ++ePoints.begin(); + while ( *pIt != ePoints.back() ) + { + TPoint* p = *pIt++; + p->myUV = uv1 * ( 1 - p->myInitU ) + uv2 * p->myInitU; + p->myXYZ = surface->Value( p->myUV.X(), p->myUV.Y() ); + if ( !loc.IsIdentity() ) + aTrsf.Transforms( p->myXYZ.ChangeCoord() ); + } + // collect on-edge points (excluding the last one) + edgesPoints->insert( edgesPoints->end(), ePoints.begin(), --ePoints.end()); + } + + // Compute UV and XYZ of in-face points + + // try to use a simple algo to compute UV + list< TPoint* > & fPoints = getShapePoints( iSub ); + bool isDeformed = false; + for ( pIt = fPoints.begin(); !isDeformed && pIt != fPoints.end(); pIt++ ) + if ( !compUVByIsoIntersection( edgesPointsList, (*pIt)->myInitUV, + (*pIt)->myUV, isDeformed )) { + MESSAGE("can't Apply(face)"); + return false; + } + // try to use a complex algo if it is a difficult case + if ( isDeformed && !compUVByElasticIsolines( edgesPointsList, fPoints )) + { + for ( ; pIt != fPoints.end(); pIt++ ) // continue with the simple algo + if ( !compUVByIsoIntersection( edgesPointsList, (*pIt)->myInitUV, + (*pIt)->myUV, isDeformed )) { + MESSAGE("can't Apply(face)"); + return false; + } + } + + for ( pIt = fPoints.begin(); pIt != fPoints.end(); pIt++ ) + { + TPoint * point = *pIt; + point->myXYZ = surface->Value( point->myUV.X(), point->myUV.Y() ); + if ( !loc.IsIdentity() ) + aTrsf.Transforms( point->myXYZ.ChangeCoord() ); + } + + myIsComputed = true; + + return setErrorCode( ERR_OK ); +} + //======================================================================= //function : undefinedXYZ //purpose : @@ -2672,7 +2985,8 @@ inline static bool isDefined(const gp_XYZ& theXYZ) // will be mapped into -th node //======================================================================= -bool SMESH_Pattern::Apply (std::set& theFaces, +bool SMESH_Pattern::Apply (SMESH_Mesh* theMesh, + std::set& theFaces, const int theNodeIndexOnKeyPoint1, const bool theReverse) { @@ -2703,18 +3017,31 @@ bool SMESH_Pattern::Apply (std::set& theFaces, myXYZ.resize( myPoints.size() * theFaces.size(), undefinedXYZ() ); myElements.reserve( theFaces.size() ); - // to find point index - map< TPoint*, int > pointIndex; - for ( int i = 0; i < myPoints.size(); i++ ) - pointIndex.insert( make_pair( & myPoints[ i ], i )); - int ind1 = 0; // lowest point index for a face + // meshed geometry + TopoDS_Shape shape; +// int shapeID = 0; +// SMESH_MeshEditor editor( theMesh ); + // apply to each face in theFaces set set::iterator face = theFaces.begin(); for ( ; face != theFaces.end(); ++face ) { - if ( !Apply( *face, theNodeIndexOnKeyPoint1, theReverse )) { +// int curShapeId = editor.FindShape( *face ); +// if ( curShapeId != shapeID ) { +// if ( curShapeId ) +// shape = theMesh->GetMeshDS()->IndexToShape( curShapeId ); +// else +// shape.Nullify(); +// shapeID = curShapeId; +// } + bool ok; + if ( shape.IsNull() ) + ok = Apply( *face, theNodeIndexOnKeyPoint1, theReverse ); + else + ok = Apply( theMesh, *face, shape, theNodeIndexOnKeyPoint1, theReverse ); + if ( !ok ) { MESSAGE( "Failed on " << *face ); continue; } @@ -2736,12 +3063,12 @@ bool SMESH_Pattern::Apply (std::set& theFaces, } // put points on links to myIdsOnBoundary, // they will be used to sew new elements on adjacent refined elements - int nbNodes = (*face)->NbNodes(), eID = nbNodes + 1; + int nbNodes = (*face)->NbCornerNodes(), eID = nbNodes + 1; for ( int i = 0; i < nbNodes; i++ ) { list< TPoint* > & linkPoints = getShapePoints( eID++ ); const SMDS_MeshNode* n1 = myOrderedNodes[ i ]; - const SMDS_MeshNode* n2 = myOrderedNodes[ i + 1 == nbNodes ? 0 : i + 1 ]; + const SMDS_MeshNode* n2 = myOrderedNodes[( i+1 ) % nbNodes ]; // make a link and a node set TNodeSet linkSet, node1Set; linkSet.insert( n1 ); @@ -2750,7 +3077,7 @@ bool SMESH_Pattern::Apply (std::set& theFaces, list< TPoint* >::iterator p = linkPoints.begin(); { // map the first link point to n1 - int nId = pointIndex[ *p ] + ind1; + int nId = ( *p - &myPoints[0] ) + ind1; myXYZIdToNodeMap[ nId ] = n1; list< list< int > >& groups = myIdsOnBoundary[ node1Set ]; groups.push_back(list< int > ()); @@ -2762,7 +3089,7 @@ bool SMESH_Pattern::Apply (std::set& theFaces, list< int >& indList = groups.back(); // add points to the map excluding the end points for ( p++; *p != linkPoints.back(); p++ ) - indList.push_back( pointIndex[ *p ] + ind1 ); + indList.push_back( ( *p - &myPoints[0] ) + ind1 ); } ind1 += myPoints.size(); } @@ -2783,8 +3110,6 @@ bool SMESH_Pattern::Apply (std::set & theVolumes, const int theNode000Index, const int theNode001Index) { - MESSAGE(" ::Apply(set) " ); - if ( !IsLoaded() ) { MESSAGE( "Pattern not loaded" ); return setErrorCode( ERR_APPL_NOT_LOADED ); @@ -2812,7 +3137,7 @@ bool SMESH_Pattern::Apply (std::set & theVolumes, // to find point index map< TPoint*, int > pointIndex; - for ( int i = 0; i < myPoints.size(); i++ ) + for ( size_t i = 0; i < myPoints.size(); i++ ) pointIndex.insert( make_pair( & myPoints[ i ], i )); int ind1 = 0; // lowest point index for an element @@ -2889,13 +3214,16 @@ bool SMESH_Pattern::Apply (std::set & theVolumes, //======================================================================= bool SMESH_Pattern::Load (SMESH_Mesh* theMesh, - const TopoDS_Shell& theBlock) + const TopoDS_Shell& theBlock, + bool theKeepNodes) { - MESSAGE(" ::Load(volume) " ); Clear(); myIs2D = false; + myToKeepNodes = theKeepNodes; SMESHDS_SubMesh * aSubMesh; + const bool isQuadMesh = theMesh->NbVolumes( ORDER_QUADRATIC ); + // load shapes in myShapeIDMap SMESH_Block block; TopoDS_Vertex v1, v2; @@ -2903,7 +3231,7 @@ bool SMESH_Pattern::Load (SMESH_Mesh* theMesh, return setErrorCode( ERR_LOADV_BAD_SHAPE ); // count nodes - int nbNodes = 0, shapeID; + smIdType nbNodes = 0; int shapeID; for ( shapeID = 1; shapeID <= myShapeIDMap.Extent(); shapeID++ ) { const TopoDS_Shape& S = myShapeIDMap( shapeID ); @@ -2925,9 +3253,11 @@ bool SMESH_Pattern::Load (SMESH_Mesh* theMesh, SMDS_NodeIteratorPtr nIt = aSubMesh->GetNodes(); if ( !nIt->more() ) continue; - // store a node and a point + // store a node and a point while ( nIt->more() ) { - const SMDS_MeshNode* node = static_cast( nIt->next() ); + const SMDS_MeshNode* node = smdsNode( nIt->next() ); + if ( isQuadMesh && SMESH_MeshEditor::IsMedium( node, SMDSAbs_Volume )) + continue; nodePointIDMap.insert( make_pair( node, iPoint )); if ( block.IsVertexID( shapeID )) myKeyPointIDs.push_back( iPoint ); @@ -2962,10 +3292,10 @@ bool SMESH_Pattern::Load (SMESH_Mesh* theMesh, nIt = aSubMesh->GetNodes(); for ( ; nIt->more(); pIt++ ) { - const SMDS_MeshNode* node = - static_cast( nIt->next() ); - const SMDS_EdgePosition* epos = - static_cast(node->GetPosition().get()); + const SMDS_MeshNode* node = nIt->next(); + if ( isQuadMesh && SMESH_MeshEditor::IsMedium( node, SMDSAbs_Edge )) + continue; + SMDS_EdgePositionPtr epos = node->GetPosition(); double u = ( epos->GetUParameter() - f ) / ( l - f ); (*pIt)->myInitXYZ.SetCoord( iCoord, isForward ? u : 1 - u ); } @@ -2989,16 +3319,25 @@ bool SMESH_Pattern::Load (SMESH_Mesh* theMesh, { SMDS_ElemIteratorPtr elemIt = aSubMesh->GetElements(); while ( elemIt->more() ) { - SMDS_ElemIteratorPtr nIt = elemIt->next()->nodesIterator(); + const SMDS_MeshElement* elem = elemIt->next(); myElemPointIDs.push_back( TElemDef() ); TElemDef& elemPoints = myElemPointIDs.back(); - while ( nIt->more() ) - elemPoints.push_back( nodePointIDMap[ nIt->next() ]); + int nbNodes = elem->NbCornerNodes(); + for ( int i = 0;i < nbNodes; ++i ) + elemPoints.push_back( nodePointIDMap[ elem->GetNode( i )]); } } myIsBoundaryPointsFound = true; + if ( myToKeepNodes ) + { + myInNodes.resize( nodePointIDMap.size() ); + TNodePointIDMap::iterator nIdIt = nodePointIDMap.begin(); + for ( ; nIdIt != nodePointIDMap.end(); nIdIt++ ) + myInNodes[ nIdIt->second ] = smdsNode( nIdIt->first ); + } + return setErrorCode( ERR_OK ); } @@ -3040,8 +3379,6 @@ bool SMESH_Pattern::Apply (const TopoDS_Shell& theBlock, const TopoDS_Vertex& theVertex000, const TopoDS_Vertex& theVertex001) { - MESSAGE(" ::Apply(volume) " ); - if (!findBoundaryPoints() || // bind ID to points !setShapeToMesh( theBlock )) // check theBlock is a suitable shape return false; @@ -3101,8 +3438,6 @@ bool SMESH_Pattern::Apply (const SMDS_MeshVolume* theVolume, const int theNode000Index, const int theNode001Index) { - //MESSAGE(" ::Apply(MeshVolume) " ); - if (!findBoundaryPoints()) // bind ID to points return false; @@ -3159,7 +3494,7 @@ void SMESH_Pattern::mergePoints (const bool uniteGroups) Bnd_Box box; TNodeSet::const_iterator n = nodes.begin(); for ( ; n != nodes.end(); ++n ) - box.Add( gp_Pnt( (*n)->X(), (*n)->Y(), (*n)->Z() )); + box.Add( gp_Pnt( SMESH_TNodeXYZ( *n ))); double x, y, z, X, Y, Z; box.Get( x, y, z, X, Y, Z ); gp_Pnt p( x, y, z ), P( X, Y, Z ); @@ -3170,7 +3505,7 @@ void SMESH_Pattern::mergePoints (const bool uniteGroups) bool unite = ( uniteGroups && nodes.size() == 2 ); map< double, int > distIndMap; const SMDS_MeshNode* node = *nodes.begin(); - gp_Pnt P( node->X(), node->Y(), node->Z() ); + gp_Pnt P = SMESH_TNodeXYZ( node ); // compare points, replace indices @@ -3243,13 +3578,7 @@ void SMESH_Pattern:: myPolyElems.reserve( myIdsOnBoundary.size() ); // make a set of refined elements - map avoidSet, elemSet; - std::vector::iterator itv = myElements.begin(); - for(; itv!=myElements.end(); itv++) { - const SMDS_MeshElement* el = (*itv); - avoidSet.insert( make_pair(el->GetID(),el) ); - } - //avoidSet.insert( myElements.begin(), myElements.end() ); + TIDSortedElemSet elemSet, avoidSet( myElements.begin(), myElements.end() ); map< TNodeSet, list< list< int > > >::iterator indListIt, nn_IdList; @@ -3276,10 +3605,10 @@ void SMESH_Pattern:: while (true) { const SMDS_MeshElement* face = - SMESH_MeshEditor::FindFaceInSet( n1, n2, elemSet, avoidSet ); + SMESH_MeshAlgos::FindFaceInSet( n1, n2, elemSet, avoidSet ); if ( face ) { - avoidSet.insert ( make_pair(face->GetID(),face) ); + avoidSet.insert ( face ); myPolyElems.push_back( face ); // some links of are split; @@ -3291,7 +3620,7 @@ void SMESH_Pattern:: int i = 0, nbNodes = face->NbNodes(); vector nodes( nbNodes + 1 ); while ( nIt->more() ) - nodes[ i++ ] = static_cast( nIt->next() ); + nodes[ i++ ] = smdsNode( nIt->next() ); nodes[ i ] = nodes[ 0 ]; for ( i = 0; i < nbNodes; ++i ) { @@ -3394,13 +3723,13 @@ void SMESH_Pattern:: // loop on nodes of refinedElem SMDS_ElemIteratorPtr nIt = (*refinedElem)->nodesIterator(); while ( nIt->more() ) { - const SMDS_MeshNode* node = static_cast( nIt->next() ); + const SMDS_MeshNode* node = smdsNode( nIt->next() ); // loop on inverse elements of node SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator(); while ( eIt->more() ) { const SMDS_MeshElement* elem = eIt->next(); - if ( !volTool.Set( elem ) || !avoidSet.insert( make_pair(elem->GetID(),elem) ).second ) + if ( !volTool.Set( elem ) || !avoidSet.insert( elem ).second ) continue; // skip faces or refined elements // add polyhedron definition myPolyhedronQuantities.push_back(vector ()); @@ -3441,13 +3770,8 @@ bool SMESH_Pattern:: vector& theQuantity) { bool makePoly = false; -// cout << "FROM FACE NODES: " < bndNodeSet; - for ( int i = 0; i < theNbBndNodes; ++i ) - bndNodeSet.insert( theBndNodes[ i ]); + set< const SMDS_MeshNode* > bndNodeSet( theBndNodes, theBndNodes + theNbBndNodes); map< TNodeSet, list< list< int > > >::iterator nn_IdList; @@ -3456,12 +3780,13 @@ bool SMESH_Pattern:: if ( !myIs2D ) { // for 2D, merge only edges nn_IdList = myIdsOnBoundary.find( bndNodeSet ); if ( nn_IdList != myIdsOnBoundary.end() ) { - makePoly = true; list< int > & faceIds = nn_IdList->second.front(); - ids.insert( faceIds.begin(), faceIds.end() ); + if ( !faceIds.empty() ) { + makePoly = true; + ids.insert( faceIds.begin(), faceIds.end() ); + } } } - //bool hasIdsInFace = !ids.empty(); // add ids on links and bnd nodes int lastFreeId = Max( myXYZIdToNodeMap.rbegin()->first, theNodes.size() ); @@ -3477,22 +3802,26 @@ bool SMESH_Pattern:: bndId = nn_IdList->second.front().front(); ids.insert( bndId ); } - else + else { myXYZIdToNodeMap.insert( make_pair( bndId, theBndNodes[ iN ] )); + } faceDef.push_back( bndId ); // add ids on a link TNodeSet linkNodes; linkNodes.insert( theBndNodes[ iN ]); - linkNodes.insert( theBndNodes[ iN + 1 == theNbBndNodes ? 0 : iN + 1 ]); + linkNodes.insert( theBndNodes[ (iN + 1) % theNbBndNodes] ); nn_IdList = myIdsOnBoundary.find( linkNodes ); if ( nn_IdList != myIdsOnBoundary.end() ) { - makePoly = true; list< int > & linkIds = nn_IdList->second.front(); - ids.insert( linkIds.begin(), linkIds.end() ); - if ( isReversed( theBndNodes[ iN ], linkIds )) - faceDef.insert( faceDef.end(), linkIds.begin(), linkIds.end() ); - else - faceDef.insert( faceDef.end(), linkIds.rbegin(), linkIds.rend() ); + if ( !linkIds.empty() ) + { + makePoly = true; + ids.insert( linkIds.begin(), linkIds.end() ); + if ( isReversed( theBndNodes[ iN ], linkIds )) + faceDef.insert( faceDef.end(), linkIds.begin(), linkIds.end() ); + else + faceDef.insert( faceDef.end(), linkIds.rbegin(), linkIds.rend() ); + } } } @@ -3514,9 +3843,7 @@ bool SMESH_Pattern:: { if ( !checkedVolDefs.insert( *pIdList ).second ) continue; // skip already checked volume definition - vector< int > idVec; - idVec.reserve( (*pIdList)->size() ); - idVec.insert( idVec.begin(), (*pIdList)->begin(), (*pIdList)->end() ); + vector< int > idVec( (*pIdList)->begin(), (*pIdList)->end() ); // loop on face defs of a volume SMDS_VolumeTool::VolumeType volType = vol.GetType( idVec.size() ); if ( volType == SMDS_VolumeTool::UNKNOWN ) @@ -3546,7 +3873,7 @@ bool SMESH_Pattern:: } if ( !defsAdded ) { theQuantity.push_back( faceDef.size() ); - theFaceDefs.splice( theFaceDefs.end(), faceDef, faceDef.begin(), faceDef.end() ); + theFaceDefs.splice( theFaceDefs.end(), faceDef ); } return makePoly; @@ -3563,11 +3890,9 @@ static bool clearSubMesh( SMESH_Mesh* theMesh, bool removed = false; if ( SMESH_subMesh * aSubMesh = theMesh->GetSubMeshContaining( theShape )) { - if ( aSubMesh->GetSubMeshDS() ) { - removed = - aSubMesh->GetSubMeshDS()->NbElements() || aSubMesh->GetSubMeshDS()->NbNodes(); + removed = !aSubMesh->IsEmpty(); + if ( removed ) aSubMesh->ComputeStateEngine( SMESH_subMesh::CLEAN ); - } } else { SMESHDS_Mesh* aMeshDS = theMesh->GetMeshDS(); @@ -3580,7 +3905,7 @@ static bool clearSubMesh( SMESH_Mesh* theMesh, SMDS_NodeIteratorPtr nIt = aSubMeshDS->GetNodes(); removed = removed || nIt->more(); while ( nIt->more() ) - aMeshDS->RemoveNode( static_cast( nIt->next() )); + aMeshDS->RemoveNode( smdsNode( nIt->next() )); } } return removed; @@ -3606,6 +3931,93 @@ 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 @@ -3616,7 +4028,6 @@ bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh, const bool toCreatePolygons, const bool toCreatePolyedrs) { - MESSAGE(" ::MakeMesh() " ); if ( !myIsComputed ) return setErrorCode( ERR_MAKEM_NOT_COMPUTED ); @@ -3639,38 +4050,89 @@ bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh, for ( ; i_node != myXYZIdToNodeMap.end(); i_node++ ) { nodesVector[ i_node->first ] = i_node->second; } - for ( int i = 0; i < myXYZ.size(); ++i ) { + for ( size_t i = 0; i < myXYZ.size(); ++i ) { if ( !nodesVector[ i ] && isDefined( myXYZ[ i ] ) ) nodesVector[ i ] = aMeshDS->AddNode (myXYZ[ i ].X(), myXYZ[ i ].Y(), myXYZ[ i ].Z()); } - } + if ( theMesh->HasShapeToMesh() ) + { + // set nodes on EDGEs (IMP 22368) + SMESH_MesherHelper helper( *theMesh ); + helper.ToFixNodeParameters( true ); + map< TNodeSet, list< list< int > > >::iterator idListIt = myIdsOnBoundary.begin(); + for ( ; idListIt != myIdsOnBoundary.end(); idListIt++ ) + { + list >& groups = idListIt->second; + const TNodeSet& nodes = idListIt->first; + if ( nodes.size() != 2 ) + continue; // not a link + const SMDS_MeshNode* n1 = *nodes.begin(); + const SMDS_MeshNode* n2 = *nodes.rbegin(); + TopoDS_Shape S1 = helper.GetSubShapeByNode( n1, aMeshDS ); + TopoDS_Shape S2 = helper.GetSubShapeByNode( n2, aMeshDS ); + if ( S1.IsNull() || S1.ShapeType() < TopAbs_EDGE || + S2.IsNull() || S2.ShapeType() < TopAbs_EDGE ) + continue; + TopoDS_Shape S; + if ( S1.ShapeType() == TopAbs_EDGE ) + { + if ( S1 == S2 || helper.IsSubShape( S2, S1 )) + S = S1; + } + else if ( S2.ShapeType() == TopAbs_EDGE ) + { + if ( helper.IsSubShape( S1, S2 )) + S = S2; + } + else + { + S = helper.GetCommonAncestor( S1, S2, *theMesh, TopAbs_EDGE ); + } + if ( S.IsNull() ) + continue; + const TopoDS_Edge & E = TopoDS::Edge( S ); + helper.SetSubShape( E ); + list >::iterator g = groups.begin(); + for ( ; g != groups.end(); ++g ) + { + list< int >& ids = *g; + list< int >::iterator id = ids.begin(); + for ( ; id != ids.end(); ++id ) + if ( nodesVector[ *id ] && nodesVector[ *id ]->getshapeId() < 1 ) + { + double u = 1e100; + aMeshDS->SetNodeOnEdge( nodesVector[ *id ], E, u ); + helper.CheckNodeU( E, nodesVector[ *id ], u, 1e-7, true ); + } + } + } + } + } // if ( onMeshElements ) + else { nodesVector.resize( myPoints.size(), 0 ); - // to find point index - map< TPoint*, int > pointIndex; - for ( int i = 0; i < myPoints.size(); i++ ) - pointIndex.insert( make_pair( & myPoints[ i ], i )); - // loop on sub-shapes of myShape: create nodes map< int, list< TPoint* > >::iterator idPointIt = myShapeIDToPointsMap.begin(); for ( ; idPointIt != myShapeIDToPointsMap.end(); idPointIt++ ) { + list< TPoint* > & points = idPointIt->second; TopoDS_Shape S; - SMESHDS_SubMesh * subMeshDS = 0; - if ( !myShapeIDMap.IsEmpty() ) { + if ( !myShapeIDMap.IsEmpty() ) S = myShapeIDMap( idPointIt->first ); - subMeshDS = aMeshDS->MeshElements( S ); - } - 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; SMDS_MeshNode* node = aMeshDS->AddNode (point->myXYZ.X(), @@ -3678,26 +4140,18 @@ bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh, point->myXYZ.Z()); nodesVector [ pIndex ] = node; - if ( subMeshDS ) { + if ( !S.IsNull() ) { + switch ( S.ShapeType() ) { case TopAbs_VERTEX: { - aMeshDS->SetNodeOnVertex( node, TopoDS::Vertex( S )); - break; + aMeshDS->SetNodeOnVertex( node, TopoDS::Vertex( S )); break; } case TopAbs_EDGE: { - aMeshDS->SetNodeOnEdge( node, TopoDS::Edge( S )); - SMDS_EdgePosition* epos = - dynamic_cast(node->GetPosition().get()); - epos->SetUParameter( point->myU ); - break; + aMeshDS->SetNodeOnEdge( node, TopoDS::Edge( S ), point->myU ); break; } case TopAbs_FACE: { - aMeshDS->SetNodeOnFace( node, TopoDS::Face( S )); - SMDS_FacePosition* pos = - dynamic_cast(node->GetPosition().get()); - pos->SetUParameter( point->myUV.X() ); - pos->SetVParameter( point->myUV.Y() ); - break; + aMeshDS->SetNodeOnFace( node, TopoDS::Face( S ), + point->myUV.X(), point->myUV.Y() ); break; } default: aMeshDS->SetNodeInVolume( node, TopoDS::Shell( S )); @@ -3724,6 +4178,12 @@ bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh, createElements( theMesh, nodesVector, myElemPointIDs, myElements ); } + aMeshDS->Modified(); + aMeshDS->CompactMesh(); + + if ( myToKeepNodes ) + myOutNodes.swap( nodesVector ); + // const map& sm = aMeshDS->SubMeshes(); // map::const_iterator i_sm = sm.begin(); // for ( ; i_sm != sm.end(); i_sm++ ) @@ -3750,7 +4210,7 @@ void SMESH_Pattern::createElements(SMESH_Mesh* theMes const vector& theElements) { SMESHDS_Mesh* aMeshDS = theMesh->GetMeshDS(); - SMESH_MeshEditor editor( theMesh ); + SMESH_MeshEditor editor( theMesh ); bool onMeshElements = !theElements.empty(); @@ -3764,7 +4224,7 @@ void SMESH_Pattern::createElements(SMESH_Mesh* theMes groups.resize( theElements.size() ); const set& allGroups = aMeshDS->GetGroups(); set::const_iterator grIt; - for ( int i = 0; i < theElements.size(); i++ ) + for ( size_t i = 0; i < theElements.size(); i++ ) { shapeIDs[ i ] = editor.FindShape( theElements[ i ] ); for ( grIt = allGroups.begin(); grIt != allGroups.end(); grIt++ ) { @@ -3806,7 +4266,7 @@ void SMESH_Pattern::createElements(SMESH_Mesh* theMes TElemDef::const_iterator id = elemNodeInd.begin(); int nbNodes; for ( nbNodes = 0; id != elemNodeInd.end(); id++ ) { - if ( *id < theNodesVector.size() ) + if ( *id < (int) theNodesVector.size() ) nodes[ nbNodes++ ] = theNodesVector[ *id ]; else nodes[ nbNodes++ ] = myXYZIdToNodeMap[ *id ]; @@ -3824,6 +4284,18 @@ void SMESH_Pattern::createElements(SMESH_Mesh* theMes elem = aMeshDS->AddFace( nodes[0], nodes[1], nodes[2] ); break; case 4: elem = aMeshDS->AddFace( nodes[0], nodes[1], nodes[2], nodes[3] ); break; + case 6: + if ( !onMeshElements ) {// create a quadratic face + elem = aMeshDS->AddFace (nodes[0], nodes[1], nodes[2], nodes[3], + nodes[4], nodes[5] ); break; + } // else do not break but create a polygon + // fall through + case 8: + if ( !onMeshElements ) {// create a quadratic face + elem = aMeshDS->AddFace (nodes[0], nodes[1], nodes[2], nodes[3], + nodes[4], nodes[5], nodes[6], nodes[7] ); break; + } // else do not break but create a polygon + // fall through default: elem = aMeshDS->AddPolygonalFace( nodes ); } @@ -3860,12 +4332,14 @@ void SMESH_Pattern::createElements(SMESH_Mesh* theMes } SMDS_ElemIteratorPtr noIt = elem->nodesIterator(); while ( noIt->more() ) { - SMDS_MeshNode* node = const_cast - ( static_cast( noIt->next() )); - if (!node->GetPosition()->GetShapeId() && - shellNodes.find( node ) == shellNodes.end() ) { + SMDS_MeshNode* node = const_cast(smdsNode( noIt->next() )); + if ( node->getshapeId() < 1 && + shellNodes.find( node ) == shellNodes.end() ) + { if ( S.ShapeType() == TopAbs_FACE ) - aMeshDS->SetNodeOnFace( node, shapeID ); + aMeshDS->SetNodeOnFace( node, shapeID, + Precision::Infinite(),// <- it's a sign that UV is not set + Precision::Infinite()); else { aMeshDS->SetNodeInVolume( node, shapeID ); shellNodes.insert( node ); @@ -3887,13 +4361,13 @@ void SMESH_Pattern::createElements(SMESH_Mesh* theMes SMESH_subMesh * subMesh; if ( !myShape.IsNull() ) { - subMesh = theMesh->GetSubMeshContaining( myShape ); + subMesh = theMesh->GetSubMesh( myShape ); if ( subMesh ) subMesh->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); } if ( onMeshElements ) { - list< int > elemIDs; - for ( int i = 0; i < theElements.size(); i++ ) + list< smIdType > elemIDs; + for ( size_t i = 0; i < theElements.size(); i++ ) { subMesh = theMesh->GetSubMeshContaining( shapeIDs[ i ] ); if ( subMesh ) @@ -3922,7 +4396,7 @@ bool SMESH_Pattern::isReversed(const SMDS_MeshNode* theFirstNode, gp_Pnt P[2]; list::const_iterator id = theIdsList.begin(); for ( int i = 0; i < 2; ++i, ++id ) { - if ( *id < myXYZ.size() ) + if ( *id < (int) myXYZ.size() ) P[ i ] = myXYZ[ *id ]; else { map< int, const SMDS_MeshNode*>::const_iterator i_n; @@ -3957,7 +4431,7 @@ void SMESH_Pattern::arrangeBoundaries (list< list< TPoint* > >& boundaryList) if ( nbBoundaries > 2 ) { // move boundaries in tmp list - list< list< TPoint* > > tmpList; + list< list< TPoint* > > tmpList; tmpList.splice( tmpList.begin(), boundaryList, boundaryList.begin(), boundaryList.end()); // make a map nb-key-points to boundary-position-in-tmpList, // boundary-positions get ordered in it @@ -3997,10 +4471,10 @@ void SMESH_Pattern::arrangeBoundaries (list< list< TPoint* > >& boundaryList) } if ( outerBndPos != boundaryList.begin() ) - boundaryList.splice( boundaryList.begin(), boundaryList, outerBndPos, ++outerBndPos ); + boundaryList.splice( boundaryList.begin(), boundaryList, outerBndPos ); } // if nbBoundaries > 1 - + // Check boundaries orientation and re-fill myKeyPointIDs set< TPoint* > keyPointSet; @@ -4092,8 +4566,6 @@ bool SMESH_Pattern::findBoundaryPoints() { if ( myIsBoundaryPointsFound ) return true; - MESSAGE(" findBoundaryPoints() "); - myNbKeyPntInBoundary.clear(); if ( myIs2D ) @@ -4271,7 +4743,7 @@ bool SMESH_Pattern::findBoundaryPoints() getShapePoints( shapeID ).push_back( point ); // detect key-points if ( SMESH_Block::IsVertexID( shapeID )) - myKeyPointIDs.push_back( i ); + myKeyPointIDs.push_back( i ); } } @@ -4295,6 +4767,29 @@ void SMESH_Pattern::Clear() myShapeIDMap.Clear(); myShape.Nullify(); myNbKeyPntInBoundary.clear(); + + myXYZ.clear(); + myElemXYZIDs.clear(); + myXYZIdToNodeMap.clear(); + myElements.clear(); + myOrderedNodes.clear(); + myPolyElems.clear(); + myPolyElemXYZIDs.clear(); + myPolyhedronQuantities.clear(); + myIdsOnBoundary.clear(); + myReverseConnectivity.clear(); +} + +//================================================================================ +/*! + * \brief set ErrorCode and return true if it is Ok + */ +//================================================================================ + +bool SMESH_Pattern::setErrorCode( const ErrorCode theErrorCode ) +{ + myErrorCode = theErrorCode; + return myErrorCode == ERR_OK; } //======================================================================= @@ -4312,25 +4807,31 @@ bool SMESH_Pattern::setShapeToMesh(const TopoDS_Shape& theShape) TopAbs_ShapeEnum aType = theShape.ShapeType(); bool dimOk = ( myIs2D ? aType == TopAbs_FACE : aType == TopAbs_SHELL ); if ( !dimOk ) { - MESSAGE( "Pattern dimention mismatch" ); + MESSAGE( "Pattern dimension mismatch" ); return setErrorCode( ERR_APPL_BAD_DIMENTION ); } // check if a face is closed int nbNodeOnSeamEdge = 0; if ( myIs2D ) { + TopTools_MapOfShape seamVertices; TopoDS_Face face = TopoDS::Face( theShape ); TopExp_Explorer eExp( theShape, TopAbs_EDGE ); - for ( ; eExp.More() && nbNodeOnSeamEdge == 0; eExp.Next() ) - if ( BRep_Tool::IsClosed( TopoDS::Edge( eExp.Current() ), face )) - nbNodeOnSeamEdge = 2; + 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 + if ( !seamVertices.Add( TopExp::FirstVertex( ee ))) nbNodeOnSeamEdge++; + if ( !seamVertices.Add( TopExp::LastVertex( ee ))) nbNodeOnSeamEdge++; + } + } } - + // check nb of vertices TopTools_IndexedMapOfShape vMap; TopExp::MapShapes( theShape, TopAbs_VERTEX, vMap ); - if ( vMap.Extent() + nbNodeOnSeamEdge != myKeyPointIDs.size() ) { - MESSAGE( myKeyPointIDs.size() << " != " << vMap.Extent() ); + if ( vMap.Extent() + nbNodeOnSeamEdge != (int)myKeyPointIDs.size() ) { + MESSAGE( myKeyPointIDs.size() + nbNodeOnSeamEdge << " != " << vMap.Extent() ); return setErrorCode( ERR_APPL_BAD_NB_VERTICES ); } @@ -4427,7 +4928,7 @@ void SMESH_Pattern::DumpPoints() const #ifdef _DEBUG_ vector< TPoint >::const_iterator pVecIt = myPoints.begin(); for ( int i = 0; pVecIt != myPoints.end(); pVecIt++, i++ ) - cout << i << ": " << *pVecIt; + MESSAGE_ADD ( std::endl << i << ": " << *pVecIt ); #endif } @@ -4439,12 +4940,12 @@ void SMESH_Pattern::DumpPoints() const SMESH_Pattern::TPoint::TPoint() { #ifdef _DEBUG_ - myInitXYZ.SetCoord(0,0,0); - myInitUV.SetCoord(0.,0.); - myInitU = 0; - myXYZ.SetCoord(0,0,0); - myUV.SetCoord(0.,0.); - myU = 0; + myInitXYZ.SetCoord(7,7,7); + myInitUV.SetCoord(7.,7.); + myInitU = 7; + myXYZ.SetCoord(7,7,7); + myUV.SetCoord(7.,7.); + myU = 7; #endif } @@ -4467,6 +4968,6 @@ ostream & operator <<(ostream & OS, const SMESH_Pattern::TPoint& p) OS << " uv( " << xy.X() << " " << xy.Y() << " )"; u = p.myU; OS << " u( " << u << " ))" << endl; - + return OS; }