X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FStdMeshers%2FStdMeshers_MEFISTO_2D.cxx;h=49ac4365d5089d7ba3a16bbd1b076dd664d9b233;hp=6229e4c6d0148b058fdf875ee9576667c820a014;hb=9d11375af40826e967ab2c3bcb77d1f9d439c90c;hpb=c3bf92bd87b770fd81631a3853f7f5bb1ac6a4e8 diff --git a/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx b/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx index 6229e4c6d..49ac4365d 100644 --- a/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx +++ b/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx @@ -17,7 +17,7 @@ // 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 +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // // @@ -27,10 +27,10 @@ // Module : SMESH // $Header$ -using namespace std; #include "StdMeshers_MEFISTO_2D.hxx" #include "SMESH_Gen.hxx" #include "SMESH_Mesh.hxx" +#include "SMESH_subMesh.hxx" #include "StdMeshers_MaxElementArea.hxx" #include "StdMeshers_LengthFromEdges.hxx" @@ -58,9 +58,8 @@ using namespace std; #include #include #include - -#include -#include +#include +#include //============================================================================= /*! @@ -69,19 +68,19 @@ using namespace std; //============================================================================= StdMeshers_MEFISTO_2D::StdMeshers_MEFISTO_2D(int hypId, int studyId, - SMESH_Gen * gen):SMESH_2D_Algo(hypId, studyId, gen) + SMESH_Gen * gen):SMESH_2D_Algo(hypId, studyId, gen) { - MESSAGE("StdMeshers_MEFISTO_2D::StdMeshers_MEFISTO_2D"); - _name = "MEFISTO_2D"; -// _shapeType = TopAbs_FACE; - _shapeType = (1 << TopAbs_FACE); - _compatibleHypothesis.push_back("MaxElementArea"); - _compatibleHypothesis.push_back("LengthFromEdges"); - - _edgeLength = 0; - _maxElementArea = 0; - _hypMaxElementArea = NULL; - _hypLengthFromEdges = NULL; + MESSAGE("StdMeshers_MEFISTO_2D::StdMeshers_MEFISTO_2D"); + _name = "MEFISTO_2D"; + _shapeType = (1 << TopAbs_FACE); + _compatibleHypothesis.push_back("MaxElementArea"); + _compatibleHypothesis.push_back("LengthFromEdges"); + + _edgeLength = 0; + _maxElementArea = 0; + _hypMaxElementArea = NULL; + _hypLengthFromEdges = NULL; + myTool = 0; } //============================================================================= @@ -92,7 +91,7 @@ StdMeshers_MEFISTO_2D::StdMeshers_MEFISTO_2D(int hypId, int studyId, StdMeshers_MEFISTO_2D::~StdMeshers_MEFISTO_2D() { - MESSAGE("StdMeshers_MEFISTO_2D::~StdMeshers_MEFISTO_2D"); + MESSAGE("StdMeshers_MEFISTO_2D::~StdMeshers_MEFISTO_2D"); } //============================================================================= @@ -126,7 +125,7 @@ bool StdMeshers_MEFISTO_2D::CheckHypothesis theHyp = (*itl); // use only the first hypothesis string hypName = theHyp->GetName(); - int hypId = theHyp->GetID(); + //int hypId = theHyp->GetID(); //SCRUTE(hypName); bool isOk = false; @@ -158,7 +157,8 @@ bool StdMeshers_MEFISTO_2D::CheckHypothesis isOk = false; if (_maxElementArea > 0) { - _edgeLength = 2 * sqrt(_maxElementArea); // triangles : minorant +// _edgeLength = 2 * sqrt(_maxElementArea); // triangles : minorant + _edgeLength = 2 * sqrt(_maxElementArea/sqrt(3.0)); isOk = true; } else @@ -180,121 +180,296 @@ bool StdMeshers_MEFISTO_2D::CheckHypothesis bool StdMeshers_MEFISTO_2D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape) { - MESSAGE("StdMeshers_MEFISTO_2D::Compute"); - - if (_hypLengthFromEdges) - _edgeLength = ComputeEdgeElementLength(aMesh, aShape); - - bool isOk = false; - const SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); - SMESH_subMesh *theSubMesh = aMesh.GetSubMesh(aShape); - - const TopoDS_Face & FF = TopoDS::Face(aShape); - bool faceIsForward = (FF.Orientation() == TopAbs_FORWARD); - TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD)); - - Z nblf; //nombre de lignes fermees (enveloppe en tete) - Z *nudslf = NULL; //numero du dernier sommet de chaque ligne fermee - R2 *uvslf = NULL; - Z nbpti = 0; //nombre points internes futurs sommets de la triangulation - R2 *uvpti = NULL; - - Z nbst; - R2 *uvst = NULL; - Z nbt; - Z *nust = NULL; - Z ierr = 0; - - Z nutysu = 1; // 1: il existe un fonction areteideale_() - // Z nutysu=0; // 0: on utilise aretmx - R aretmx = _edgeLength; // longueur max aretes future triangulation - //SCRUTE(aretmx); - - nblf = NumberOfWires(F); - //SCRUTE(nblf); - - nudslf = new Z[1 + nblf]; - nudslf[0] = 0; - int iw = 1; - int nbpnt = 0; - - const TopoDS_Wire OW1 = BRepTools::OuterWire(F); - nbpnt += NumberOfPoints(aMesh, OW1); - nudslf[iw++] = nbpnt; - //SCRUTE(nbpnt); - - for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next()) - { - const TopoDS_Wire & W = TopoDS::Wire(exp.Current()); - if (!OW1.IsSame(W)) - { - nbpnt += NumberOfPoints(aMesh, W); - nudslf[iw++] = nbpnt; - //SCRUTE(nbpnt); - } - } + MESSAGE("StdMeshers_MEFISTO_2D::Compute"); + + if (_hypLengthFromEdges) + _edgeLength = ComputeEdgeElementLength(aMesh, aShape); + + bool isOk = false; + //const SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); + //SMESH_subMesh *theSubMesh = aMesh.GetSubMesh(aShape); + + const TopoDS_Face & FF = TopoDS::Face(aShape); + bool faceIsForward = (FF.Orientation() == TopAbs_FORWARD); + TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD)); + + Z nblf; //nombre de lignes fermees (enveloppe en tete) + Z *nudslf = NULL; //numero du dernier sommet de chaque ligne fermee + R2 *uvslf = NULL; + Z nbpti = 0; //nombre points internes futurs sommets de la triangulation + R2 *uvpti = NULL; + + Z nbst; + R2 *uvst = NULL; + Z nbt; + Z *nust = NULL; + Z ierr = 0; + + Z nutysu = 1; // 1: il existe un fonction areteideale_() + // Z nutysu=0; // 0: on utilise aretmx + R aretmx = _edgeLength; // longueur max aretes future triangulation + + nblf = NumberOfWires(F); + + nudslf = new Z[1 + nblf]; + nudslf[0] = 0; + int iw = 1; + int nbpnt = 0; + + myTool = new SMESH_MesherHelper(aMesh); + _quadraticMesh = myTool->IsQuadraticSubMesh(aShape); + + if ( _quadraticMesh && _hypLengthFromEdges ) + aretmx *= 2.; + + myOuterWire = BRepTools::OuterWire(F); + nbpnt += NumberOfPoints(aMesh, myOuterWire); + if ( nbpnt < 3 ) { // ex: a circle with 2 segments + delete myTool; myTool = 0; + return false; + } + nudslf[iw++] = nbpnt; + + for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next()) { + const TopoDS_Wire & W = TopoDS::Wire(exp.Current()); + if (!myOuterWire.IsSame(W)) { + nbpnt += NumberOfPoints(aMesh, W); + nudslf[iw++] = nbpnt; + } + } + + // avoid passing same uv points for a vertex common to 2 wires + TopTools_IndexedDataMapOfShapeListOfShape VWMap; + if ( iw - 1 > 1 ) // nbofWires > 1 + TopExp::MapShapesAndAncestors( F , TopAbs_VERTEX, TopAbs_WIRE, VWMap ); + + uvslf = new R2[nudslf[nblf]]; + int m = 0; + + double scalex, scaley; + ComputeScaleOnFace(aMesh, F, scalex, scaley); + + map mefistoToDS; // correspondence mefisto index--> points IDNodes + if ( !LoadPoints(aMesh, F, myOuterWire, uvslf, m, + mefistoToDS, scalex, scaley, VWMap) ) { + delete myTool; myTool = 0; + return false; + } + + for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next()) + { + const TopoDS_Wire & W = TopoDS::Wire(exp.Current()); + if (!myOuterWire.IsSame(W)) + { + if (! LoadPoints(aMesh, F, W, uvslf, m, + mefistoToDS, scalex, scaley, VWMap )) { + delete myTool; myTool = 0; + return false; + } + } + } + + uvst = NULL; + nust = NULL; + aptrte(nutysu, aretmx, + nblf, nudslf, uvslf, nbpti, uvpti, nbst, uvst, nbt, nust, ierr); + + if (ierr == 0) + { + MESSAGE("... End Triangulation Generated Triangle Number " << nbt); + MESSAGE(" Node Number " << nbst); + StoreResult(aMesh, nbst, uvst, nbt, nust, F, + faceIsForward, mefistoToDS, scalex, scaley); + isOk = true; + } + else + { + MESSAGE("Error in Triangulation"); + isOk = false; + } + if (nudslf != NULL) + delete[]nudslf; + if (uvslf != NULL) + delete[]uvslf; + if (uvst != NULL) + delete[]uvst; + if (nust != NULL) + delete[]nust; + delete myTool; myTool = 0; + + return isOk; +} - uvslf = new R2[nudslf[nblf]]; - //SCRUTE(nudslf[nblf]); - int m = 0; +//======================================================================= +//function : fixOverlappedLinkUV +//purpose : prevent failure due to overlapped adjacent links +//======================================================================= - map mefistoToDS; // correspondence mefisto index--> points IDNodes - TopoDS_Wire OW = BRepTools::OuterWire(F); - LoadPoints(aMesh, F, OW, uvslf, m, mefistoToDS); - //SCRUTE(m); +static bool fixOverlappedLinkUV( R2& uv0, const R2& uv1, const R2& uv2 ) +{ + gp_XY v1( uv0.x - uv1.x, uv0.y - uv1.y ); + gp_XY v2( uv2.x - uv1.x, uv2.y - uv1.y ); + + double tol2 = DBL_MIN * DBL_MIN; + double sqMod1 = v1.SquareModulus(); + if ( sqMod1 <= tol2 ) return false; + double sqMod2 = v2.SquareModulus(); + if ( sqMod2 <= tol2 ) return false; + + double dot = v1*v2; + + // check sinus >= 1.e-3 + const double minSin = 1.e-3; + if ( dot > 0 && 1 - dot * dot / ( sqMod1 * sqMod2 ) < minSin * minSin ) { + MESSAGE(" ___ FIX UV ____" << uv0.x << " " << uv0.y); + v1.SetCoord( -v1.Y(), v1.X() ); + double delta = sqrt( sqMod1 ) * minSin; + if ( v1.X() < 0 ) + uv0.x -= delta; + else + uv0.x += delta; + if ( v1.Y() < 0 ) + uv0.y -= delta; + else + uv0.y += delta; +// #ifdef _DEBUG_ +// MESSAGE(" -> " << uv0.x << " " << uv0.y << " "); +// MESSAGE("v1( " << v1.X() << " " << v1.Y() << " ) " << +// "v2( " << v2.X() << " " << v2.Y() << " ) "); +// MESSAGE("SIN: " << sqrt(1 - dot * dot / (sqMod1 * sqMod2))); +// v1.SetCoord( uv0.x - uv1.x, uv0.y - uv1.y ); +// v2.SetCoord( uv2.x - uv1.x, uv2.y - uv1.y ); +// gp_XY v3( uv2.x - uv0.x, uv2.y - uv0.y ); +// sqMod1 = v1.SquareModulus(); +// sqMod2 = v2.SquareModulus(); +// dot = v1*v2; +// double sin = sqrt(1 - dot * dot / (sqMod1 * sqMod2)); +// MESSAGE("NEW SIN: " << sin); +// #endif + return true; + } + return false; +} - for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next()) - { - const TopoDS_Wire & W = TopoDS::Wire(exp.Current()); - if (!OW.IsSame(W)) - { - LoadPoints(aMesh, F, W, uvslf, m, mefistoToDS); - //SCRUTE(m); - } - } -// SCRUTE(nudslf[nblf]); -// for (int i=0; i<=nblf; i++) -// { -// MESSAGE(" -+- " < UList; + + // find edges of theW sharing theV + // and find 2d normal to them at theV + gp_Vec2d N(0.,0.); + TopoDS_Iterator itE( theW ); + for ( ; itE.More(); itE.Next() ) + { + const TopoDS_Edge& E = TopoDS::Edge( itE.Value() ); + TopoDS_Iterator itV( E ); + for ( ; itV.More(); itV.Next() ) + { + const TopoDS_Vertex & V = TopoDS::Vertex( itV.Value() ); + if ( !V.IsSame( theV )) + continue; + EList.Append( E ); + Standard_Real u = BRep_Tool::Parameter( V, E ); + UList.push_back( u ); + double f, l; + Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, theF, f, l); + gp_Vec2d d1; + gp_Pnt2d p; + C2d->D1( u, p, d1 ); + gp_Vec2d n( d1.Y(), -d1.X() ); + if ( E.Orientation() == TopAbs_REVERSED ) + n.Reverse(); + N += n.Normalized(); + } + } + + // define step size by which to move theUV + + gp_Pnt2d nextUV; // uv of next node on edge, most distant of the four + double maxDist = -DBL_MAX; + TopTools_ListIteratorOfListOfShape aEIt (EList); + list< double >::iterator aUIt = UList.begin(); + for ( ; aEIt.More(); aEIt.Next(), aUIt++ ) + { + const TopoDS_Edge& E = TopoDS::Edge( aEIt.Value() ); + double f, l; + Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, theF, f, l); + + double umin = DBL_MAX, umax = -DBL_MAX; + SMDS_NodeIteratorPtr nIt = theMesh.GetSubMesh(E)->GetSubMeshDS()->GetNodes(); + if ( !nIt->more() ) // no nodes on edge, only on vertices + { + umin = l; + umax = f; + } + else { + while ( nIt->more() ) { + const SMDS_MeshNode* node = nIt->next(); + // check if node is medium + if ( CreateQuadratic && SMESH_MesherHelper::IsMedium( node, SMDSAbs_Edge )) + continue; + const SMDS_EdgePosition* epos = + static_cast(node->GetPosition().get()); + double u = epos->GetUParameter(); + if ( u < umin ) + umin = u; + if ( u > umax ) + umax = u; + } + } + bool isFirstCommon = ( *aUIt == f ); + gp_Pnt2d uv = C2d->Value( isFirstCommon ? umin : umax ); + double dist = theUV.SquareDistance( uv ); + if ( dist > maxDist ) { + maxDist = dist; + nextUV = uv; + } + } + R2 uv0, uv1, uv2; + uv0.x = theUV.X(); uv0.y = theUV.Y(); + uv1.x = nextUV.X(); uv1.y = nextUV.Y(); + uv2.x = uv0.x; uv2.y = uv0.y; + if ( fixOverlappedLinkUV( uv0, uv1, uv2 )) + { + double step = theUV.Distance( gp_Pnt2d( uv0.x, uv0.y )); + + // move theUV along the normal by the step + + N *= step; + + MESSAGE("--fixCommonVertexUV move(" << theUV.X() << " " << theUV.Y() + << ") by (" << N.X() << " " << N.Y() << ")" + << endl << "--- MAX DIST " << maxDist); + + theUV.SetXY( theUV.XY() + N.XY() ); + + return true; + } + return false; } //============================================================================= @@ -303,111 +478,114 @@ bool StdMeshers_MEFISTO_2D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh */ //============================================================================= -void StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh & aMesh, - const TopoDS_Face & FF, - const TopoDS_Wire & WW, R2 * uvslf, int &m, - map&mefistoToDS) +bool StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh & aMesh, + const TopoDS_Face & FF, + const TopoDS_Wire & WW, + R2 * uvslf, + int & m, + map&mefistoToDS, + double scalex, + double scaley, + const TopTools_IndexedDataMapOfShapeListOfShape& VWMap) { - MESSAGE("StdMeshers_MEFISTO_2D::LoadPoints"); - - SMDS_Mesh * meshDS = aMesh.GetMeshDS(); - - double scalex; - double scaley; - TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD)); - ComputeScaleOnFace(aMesh, F, scalex, scaley); - - TopoDS_Wire W = TopoDS::Wire(WW.Oriented(TopAbs_FORWARD)); - BRepTools_WireExplorer wexp(W, F); - for (wexp.Init(W, F); wexp.More(); wexp.Next()) - { - const TopoDS_Edge & E = wexp.Current(); - - // --- IDNodes of first and last Vertex - - TopoDS_Vertex VFirst, VLast; - TopExp::Vertices(E, VFirst, VLast); // corresponds to f and l - - ASSERT(!VFirst.IsNull()); - SMDS_NodeIteratorPtr lid= - aMesh.GetSubMesh(VFirst)->GetSubMeshDS()->GetNodes(); - const SMDS_MeshNode* idFirst = lid->next(); - - ASSERT(!VLast.IsNull()); - lid=aMesh.GetSubMesh(VLast)->GetSubMeshDS()->GetNodes(); - const SMDS_MeshNode* idLast = lid->next(); - - // --- edge internal IDNodes (relies on good order storage, not checked) - - int nbPoints = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes(); - //SCRUTE(nbPoints); - - double f, l; - Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l); - - SMDS_NodeIteratorPtr ite= aMesh.GetSubMesh(E)->GetSubMeshDS()->GetNodes(); - - bool isForward = (E.Orientation() == TopAbs_FORWARD); - map params; - - while(ite->more()) - { - const SMDS_MeshNode * node = ite->next(); - const SMDS_EdgePosition* epos = - static_cast(node->GetPosition().get()); - double param = epos->GetUParameter(); - params[param] = node; - } - // --- load 2D values into MEFISTO structure, - // add IDNodes in mefistoToDS map - - if (E.Orientation() == TopAbs_FORWARD) - { - gp_Pnt2d p = C2d->Value(f); // first point = Vertex Forward - uvslf[m].x = scalex * p.X(); - uvslf[m].y = scaley * p.Y(); - mefistoToDS[m + 1] = idFirst; - //MESSAGE(" "<::iterator itp = params.begin(); - for (int i = 1; i <= nbPoints; i++) // nbPoints internal - { - double param = (*itp).first; - gp_Pnt2d p = C2d->Value(param); - uvslf[m].x = scalex * p.X(); - uvslf[m].y = scaley * p.Y(); - mefistoToDS[m + 1] = (*itp).second; -// MESSAGE(" "<Value(l); // last point = Vertex Reversed - uvslf[m].x = scalex * p.X(); - uvslf[m].y = scaley * p.Y(); - mefistoToDS[m + 1] = idLast; -// MESSAGE(" "<::reverse_iterator itp = params.rbegin(); - for (int i = nbPoints; i >= 1; i--) - { - double param = (*itp).first; - gp_Pnt2d p = C2d->Value(param); - uvslf[m].x = scalex * p.X(); - uvslf[m].y = scaley * p.Y(); - mefistoToDS[m + 1] = (*itp).second; -// MESSAGE(" "< mOnVertex; + + gp_XY scale( scalex, scaley ); + + TopoDS_Wire W = TopoDS::Wire(WW.Oriented(TopAbs_FORWARD)); + BRepTools_WireExplorer wexp(W, F); + for ( wexp.Init(W, F); wexp.More(); wexp.Next() ) + { + const TopoDS_Edge & E = wexp.Current(); + bool isForward = (E.Orientation() == TopAbs_FORWARD); + + // --- IDNodes of first and last Vertex + + TopoDS_Vertex VFirst, VLast, V; + TopExp::Vertices(E, VFirst, VLast); // corresponds to f and l + V = isForward ? VFirst : VLast; + + ASSERT(!V.IsNull()); + SMDS_NodeIteratorPtr lid= aMesh.GetSubMesh(V)->GetSubMeshDS()->GetNodes(); + if ( !lid->more() ) { + MESSAGE (" NO NODE BUILT ON VERTEX "); + return false; + } + const SMDS_MeshNode* idFirst = lid->next(); + + // --- edge internal IDNodes (relies on good order storage, not checked) + + map params; + const SMDS_MeshNode * node; + + SMDS_NodeIteratorPtr nodeIt= aMesh.GetSubMesh(E)->GetSubMeshDS()->GetNodes(); + while ( nodeIt->more() ) + { + node = nodeIt->next(); + if ( _quadraticMesh && SMESH_MesherHelper::IsMedium( node, SMDSAbs_Edge )) + continue; + const SMDS_EdgePosition* epos = + static_cast(node->GetPosition().get()); + double param = epos->GetUParameter(); + if ( !isForward ) param = -param; + if ( !params.insert( make_pair( param, node )).second ) + { + MESSAGE( "BAD NODE ON EDGE POSITIONS" ); + return false; + } + } + + // --- load 2D values into MEFISTO structure, + // add IDNodes in mefistoToDS map + + double f, l, uFirst, u; + Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l); + uFirst = isForward ? f : l; + + // vertex node + gp_Pnt2d p = C2d->Value( uFirst ).XY().Multiplied( scale ); + if ( fixCommonVertexUV( p, V, W, myOuterWire, F, VWMap, aMesh, _quadraticMesh )) + myNodesOnCommonV.push_back( idFirst ); + mOnVertex.push_back( m ); + uvslf[m].x = p.X(); + uvslf[m].y = p.Y(); + mefistoToDS[m + 1] = idFirst; + //MESSAGE(" "<::iterator u_n = params.begin(); + for ( int i = 0; u_n != params.end(); ++u_n, ++i ) + { + u = isForward ? u_n->first : - u_n->first; + gp_Pnt2d p = C2d->Value( u ).XY().Multiplied( scale ); + uvslf[m].x = p.X(); + uvslf[m].y = p.Y(); + mefistoToDS[m + 1] = u_n->second; + //MESSAGE(" "<::iterator mIt = mOnVertex.begin(); + for ( ; mIt != mOnVertex.end(); ++mIt ) { + int i = *mIt; + int iB = i - 1, iA = i + 1; // indices Before and After + if ( iB < mFirst ) iB = mLast; + if ( iA > mLast ) iA = mFirst; + fixOverlappedLinkUV (uvslf[ iB ], uvslf[ i ], uvslf[ iA ]); + } + + return true; } //============================================================================= @@ -416,76 +594,91 @@ void StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh & aMesh, */ //============================================================================= -// **** a mettre dans SMESH_Algo ou SMESH_2D_Algo - void StdMeshers_MEFISTO_2D::ComputeScaleOnFace(SMESH_Mesh & aMesh, const TopoDS_Face & aFace, double &scalex, double &scaley) { - //MESSAGE("StdMeshers_MEFISTO_2D::ComputeScaleOnFace"); - TopoDS_Face F = TopoDS::Face(aFace.Oriented(TopAbs_FORWARD)); - TopoDS_Wire W = BRepTools::OuterWire(F); - - BRepTools_WireExplorer wexp(W, F); - - double xmin = 1.e300; // min & max of face 2D parametric coord. - double xmax = -1.e300; - double ymin = 1.e300; - double ymax = -1.e300; - int nbp = 50; - scalex = 1; - scaley = 1; - for (wexp.Init(W, F); wexp.More(); wexp.Next()) - { - const TopoDS_Edge & E = wexp.Current(); - double f, l; - Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l); - for (int i = 0; i <= nbp; i++) - { - double param = f + (double (i) / double (nbp))*(l - f); - gp_Pnt2d p = C2d->Value(param); - if (p.X() < xmin) - xmin = p.X(); - if (p.X() > xmax) - xmax = p.X(); - if (p.Y() < ymin) - ymin = p.Y(); - if (p.Y() > ymax) - ymax = p.Y(); -// MESSAGE(" "<< f<<" "<Value(xmin, ymoy); - gp_Pnt PY0 = S->Value(xmoy, ymin); - for (int i = 1; i <= nbp; i++) - { - double x = xmin + (double (i) / double (nbp))*(xmax - xmin); - gp_Pnt PX = S->Value(x, ymoy); - double y = ymin + (double (i) / double (nbp))*(ymax - ymin); - gp_Pnt PY = S->Value(xmoy, y); - length_x += PX.Distance(PX0); - length_y += PY.Distance(PY0); - PX0.SetCoord(PX.X(), PX.Y(), PX.Z()); - PY0.SetCoord(PY.X(), PY.Y(), PY.Z()); - } -// SCRUTE(length_x); -// SCRUTE(length_y); - scalex = length_x / (xmax - xmin); - scaley = length_y / (ymax - ymin); -// SCRUTE(scalex); -// SCRUTE(scaley); - ASSERT(scalex); - ASSERT(scaley); + //MESSAGE("StdMeshers_MEFISTO_2D::ComputeScaleOnFace"); + TopoDS_Face F = TopoDS::Face(aFace.Oriented(TopAbs_FORWARD)); + TopoDS_Wire W = BRepTools::OuterWire(F); + + double xmin = 1.e300; // min & max of face 2D parametric coord. + double xmax = -1.e300; + double ymin = 1.e300; + double ymax = -1.e300; + int nbp = 23; + scalex = 1; + scaley = 1; + + TopExp_Explorer wexp(W, TopAbs_EDGE); + for ( ; wexp.More(); wexp.Next()) + { + const TopoDS_Edge & E = TopoDS::Edge( wexp.Current() ); + double f, l; + Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l); + if ( C2d.IsNull() ) continue; + double du = (l - f) / double (nbp); + for (int i = 0; i <= nbp; i++) + { + double param = f + double (i) * du; + gp_Pnt2d p = C2d->Value(param); + if (p.X() < xmin) + xmin = p.X(); + if (p.X() > xmax) + xmax = p.X(); + if (p.Y() < ymin) + ymin = p.Y(); + if (p.Y() > ymax) + ymax = p.Y(); + // MESSAGE(" "<< f<<" "<Value(xmin, ymoy); + gp_Pnt PY0 = S->Value(xmoy, ymin); + double dx = xsize / double (nbp); + double dy = ysize / double (nbp); + for (int i = 1; i <= nbp; i++) + { + double x = xmin + double (i) * dx; + gp_Pnt PX = S->Value(x, ymoy); + double y = ymin + double (i) * dy; + gp_Pnt PY = S->Value(xmoy, y); + length_x += PX.Distance(PX0); + length_y += PY.Distance(PY0); + PX0 = PX; + PY0 = PY; + } + scalex = length_x / xsize; + scaley = length_y / ysize; +// SCRUTE(xsize); +// SCRUTE(ysize); + double xyratio = xsize*scalex/(ysize*scaley); + const double maxratio = 1.e2; + //SCRUTE(xyratio); + if (xyratio > maxratio) { + SCRUTE( scaley ); + scaley *= xyratio / maxratio; + SCRUTE( scaley ); + } + else if (xyratio < 1./maxratio) { + SCRUTE( scalex ); + scalex *= 1 / xyratio / maxratio; + SCRUTE( scalex ); + } + ASSERT(scalex); + ASSERT(scaley); } //============================================================================= @@ -495,70 +688,81 @@ void StdMeshers_MEFISTO_2D::ComputeScaleOnFace(SMESH_Mesh & aMesh, //============================================================================= void StdMeshers_MEFISTO_2D::StoreResult(SMESH_Mesh & aMesh, - Z nbst, R2 * uvst, Z nbt, Z * nust, - const TopoDS_Face & F, bool faceIsForward, - map&mefistoToDS) + Z nbst, R2 * uvst, Z nbt, Z * nust, + const TopoDS_Face & F, bool faceIsForward, + map&mefistoToDS, + double scalex, double scaley) { - double scalex; - double scaley; - ComputeScaleOnFace(aMesh, F, scalex, scaley); - - SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); + SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); + int faceID = meshDS->ShapeToIndex( F ); + + Z n, m; + Handle(Geom_Surface) S = BRep_Tool::Surface(F); + + for (n = 0; n < nbst; n++) + { + if (mefistoToDS.find(n + 1) == mefistoToDS.end()) + { + double u = uvst[n][0] / scalex; + double v = uvst[n][1] / scaley; + gp_Pnt P = S->Value(u, v); + + SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(node, faceID, u, v); + + //MESSAGE(P.X()<<" "<AddFace(n1, n2, n3); + elt = myTool->AddFace(n1, n2, n3); + else + //elt = meshDS->AddFace(n1, n3, n2); + elt = myTool->AddFace(n1, n3, n2); + + meshDS->SetMeshElementOnShape(elt, faceID); + m++; + } + + // remove bad elements built on vertices shared by wires + + list::iterator itN = myNodesOnCommonV.begin(); + for ( ; itN != myNodesOnCommonV.end(); itN++ ) + { + const SMDS_MeshNode* node = *itN; + SMDS_ElemIteratorPtr invElemIt = node->GetInverseElementIterator(); + while ( invElemIt->more() ) + { + const SMDS_MeshElement* elem = invElemIt->next(); + SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + int nbSame = 0; + while ( itN->more() ) + if ( itN->next() == node) + nbSame++; + if (nbSame > 1) { + MESSAGE( "RM bad element " << elem->GetID()); + meshDS->RemoveElement( elem ); + } + } + } - Z n, m; - Handle(Geom_Surface) S = BRep_Tool::Surface(F); - - for (n = 0; n < nbst; n++) - { - double u = uvst[n][0] / scalex; - double v = uvst[n][1] / scaley; - gp_Pnt P = S->Value(u, v); - - if (mefistoToDS.find(n + 1) == mefistoToDS.end()) - { - SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z()); - meshDS->SetNodeOnFace(node, F); - - //MESSAGE(nodeId<<" "<(node->GetPosition().get()); - fpos->SetUParameter(u); - fpos->SetVParameter(v); - } - } - - m = 0; - int mt = 0; - - //SCRUTE(faceIsForward); - for (n = 1; n <= nbt; n++) - { - int inode1 = nust[m++]; - int inode2 = nust[m++]; - int inode3 = nust[m++]; - - const SMDS_MeshNode *n1, *n2, *n3; - n1 = mefistoToDS[inode1]; - n2 = mefistoToDS[inode2]; - n3 = mefistoToDS[inode3]; - //MESSAGE("-- "<AddFace(n1, n2, n3); - else - elt = meshDS->AddFace(n1, n3, n2); - - meshDS->SetMeshElementOnShape(elt, F); - m++; - } } //============================================================================= @@ -570,20 +774,17 @@ void StdMeshers_MEFISTO_2D::StoreResult(SMESH_Mesh & aMesh, double StdMeshers_MEFISTO_2D::ComputeEdgeElementLength(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape) { - MESSAGE("StdMeshers_MEFISTO_2D::ComputeEdgeElementLength"); + //MESSAGE("StdMeshers_MEFISTO_2D::ComputeEdgeElementLength"); // **** a mettre dans SMESH_2D_Algo ? - const TopoDS_Face & FF = TopoDS::Face(aShape); - bool faceIsForward = (FF.Orientation() == TopAbs_FORWARD); - TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD)); + //const TopoDS_Face & FF = TopoDS::Face(aShape); + //bool faceIsForward = (FF.Orientation() == TopAbs_FORWARD); + //TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD)); double meanElementLength = 100; double wireLength = 0; int wireElementsNumber = 0; - for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next()) - { - const TopoDS_Wire & W = TopoDS::Wire(exp.Current()); - for (TopExp_Explorer expe(W, TopAbs_EDGE); expe.More(); expe.Next()) + for (TopExp_Explorer expe(aShape, TopAbs_EDGE); expe.More(); expe.Next()) { const TopoDS_Edge & E = TopoDS::Edge(expe.Current()); int nb = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes(); @@ -591,7 +792,6 @@ double StdMeshers_MEFISTO_2D::ComputeEdgeElementLength(SMESH_Mesh & aMesh, wireLength += length; wireElementsNumber += nb; } - } if (wireElementsNumber) meanElementLength = wireLength / wireElementsNumber; //SCRUTE(meanElementLength);