1 // SMESH SMESH : implementaion of SMESH idl descriptions
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : StdMeshers_MEFISTO_2D.cxx
25 // Moved here from SMESH_MEFISTO_2D.cxx
26 // Author : Paul RASCLE, EDF
31 #include "StdMeshers_MEFISTO_2D.hxx"
32 #include "SMESH_Gen.hxx"
33 #include "SMESH_Mesh.hxx"
34 #include "SMESH_subMesh.hxx"
36 #include "StdMeshers_MaxElementArea.hxx"
37 #include "StdMeshers_LengthFromEdges.hxx"
42 #include "SMDS_MeshElement.hxx"
43 #include "SMDS_MeshNode.hxx"
44 #include "SMDS_EdgePosition.hxx"
45 #include "SMDS_FacePosition.hxx"
47 #include "utilities.h"
49 #include <TopoDS_Face.hxx>
50 #include <TopoDS_Edge.hxx>
51 #include <TopoDS_Shape.hxx>
52 #include <Geom_Surface.hxx>
53 #include <GeomAdaptor_Curve.hxx>
54 #include <Geom2d_Curve.hxx>
55 #include <gp_Pnt2d.hxx>
56 #include <BRep_Tool.hxx>
57 #include <BRepTools.hxx>
58 #include <BRepTools_WireExplorer.hxx>
59 #include <GCPnts_AbscissaPoint.hxx>
60 #include <GCPnts_UniformAbscissa.hxx>
61 #include <TColStd_ListIteratorOfListOfInteger.hxx>
62 #include <TopTools_ListIteratorOfListOfShape.hxx>
63 #include <TopTools_ListOfShape.hxx>
66 //#include <algorithm>
68 //=============================================================================
72 //=============================================================================
74 StdMeshers_MEFISTO_2D::StdMeshers_MEFISTO_2D(int hypId, int studyId,
75 SMESH_Gen * gen):SMESH_2D_Algo(hypId, studyId, gen)
77 MESSAGE("StdMeshers_MEFISTO_2D::StdMeshers_MEFISTO_2D");
79 // _shapeType = TopAbs_FACE;
80 _shapeType = (1 << TopAbs_FACE);
81 _compatibleHypothesis.push_back("MaxElementArea");
82 _compatibleHypothesis.push_back("LengthFromEdges");
86 _hypMaxElementArea = NULL;
87 _hypLengthFromEdges = NULL;
90 //=============================================================================
94 //=============================================================================
96 StdMeshers_MEFISTO_2D::~StdMeshers_MEFISTO_2D()
98 MESSAGE("StdMeshers_MEFISTO_2D::~StdMeshers_MEFISTO_2D");
101 //=============================================================================
105 //=============================================================================
107 bool StdMeshers_MEFISTO_2D::CheckHypothesis
109 const TopoDS_Shape& aShape,
110 SMESH_Hypothesis::Hypothesis_Status& aStatus)
112 //MESSAGE("StdMeshers_MEFISTO_2D::CheckHypothesis");
114 _hypMaxElementArea = NULL;
115 _hypLengthFromEdges = NULL;
117 list <const SMESHDS_Hypothesis * >::const_iterator itl;
118 const SMESHDS_Hypothesis *theHyp;
120 const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
121 int nbHyp = hyps.size();
124 aStatus = SMESH_Hypothesis::HYP_MISSING;
125 return false; // can't work with no hypothesis
129 theHyp = (*itl); // use only the first hypothesis
131 string hypName = theHyp->GetName();
132 int hypId = theHyp->GetID();
137 if (hypName == "MaxElementArea")
139 _hypMaxElementArea = static_cast<const StdMeshers_MaxElementArea *>(theHyp);
140 ASSERT(_hypMaxElementArea);
141 _maxElementArea = _hypMaxElementArea->GetMaxArea();
144 aStatus = SMESH_Hypothesis::HYP_OK;
147 else if (hypName == "LengthFromEdges")
149 _hypLengthFromEdges = static_cast<const StdMeshers_LengthFromEdges *>(theHyp);
150 ASSERT(_hypLengthFromEdges);
154 aStatus = SMESH_Hypothesis::HYP_OK;
157 aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
162 if (_maxElementArea > 0)
164 // _edgeLength = 2 * sqrt(_maxElementArea); // triangles : minorant
165 _edgeLength = 2 * sqrt(_maxElementArea/sqrt(3.0));
169 isOk = (_hypLengthFromEdges != NULL); // **** check mode
171 aStatus = SMESH_Hypothesis::HYP_BAD_PARAMETER;
174 //SCRUTE(_edgeLength);
175 //SCRUTE(_maxElementArea);
179 //=============================================================================
183 //=============================================================================
185 bool StdMeshers_MEFISTO_2D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape)
187 MESSAGE("StdMeshers_MEFISTO_2D::Compute");
189 if (_hypLengthFromEdges)
190 _edgeLength = ComputeEdgeElementLength(aMesh, aShape);
193 const SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
194 SMESH_subMesh *theSubMesh = aMesh.GetSubMesh(aShape);
196 const TopoDS_Face & FF = TopoDS::Face(aShape);
197 bool faceIsForward = (FF.Orientation() == TopAbs_FORWARD);
198 TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD));
200 Z nblf; //nombre de lignes fermees (enveloppe en tete)
201 Z *nudslf = NULL; //numero du dernier sommet de chaque ligne fermee
203 Z nbpti = 0; //nombre points internes futurs sommets de la triangulation
212 Z nutysu = 1; // 1: il existe un fonction areteideale_()
213 // Z nutysu=0; // 0: on utilise aretmx
214 R aretmx = _edgeLength; // longueur max aretes future triangulation
216 nblf = NumberOfWires(F);
218 nudslf = new Z[1 + nblf];
223 myOuterWire = BRepTools::OuterWire(F);
224 nbpnt += NumberOfPoints(aMesh, myOuterWire);
225 if ( nbpnt < 3 ) // ex: a circle with 2 segments
227 nudslf[iw++] = nbpnt;
229 for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next())
231 const TopoDS_Wire & W = TopoDS::Wire(exp.Current());
232 if (!myOuterWire.IsSame(W))
234 nbpnt += NumberOfPoints(aMesh, W);
235 nudslf[iw++] = nbpnt;
239 // avoid passing same uv points for a vertex common to 2 wires
240 TopTools_IndexedDataMapOfShapeListOfShape VWMap;
241 if ( iw - 1 > 1 ) // nbofWires > 1
242 TopExp::MapShapesAndAncestors( F , TopAbs_VERTEX, TopAbs_WIRE, VWMap );
244 uvslf = new R2[nudslf[nblf]];
247 double scalex, scaley;
248 ComputeScaleOnFace(aMesh, F, scalex, scaley);
250 map<int, const SMDS_MeshNode*> mefistoToDS; // correspondence mefisto index--> points IDNodes
251 if ( !LoadPoints(aMesh, F, myOuterWire, uvslf, m,
252 mefistoToDS, scalex, scaley, VWMap))
255 for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next())
257 const TopoDS_Wire & W = TopoDS::Wire(exp.Current());
258 if (!myOuterWire.IsSame(W))
260 if (! LoadPoints(aMesh, F, W, uvslf, m,
261 mefistoToDS, scalex, scaley, VWMap ))
268 aptrte(nutysu, aretmx,
269 nblf, nudslf, uvslf, nbpti, uvpti, nbst, uvst, nbt, nust, ierr);
273 MESSAGE("... End Triangulation Generated Triangle Number " << nbt);
274 MESSAGE(" Node Number " << nbst);
275 StoreResult(aMesh, nbst, uvst, nbt, nust, F,
276 faceIsForward, mefistoToDS, scalex, scaley);
281 MESSAGE("Error in Triangulation");
295 //=======================================================================
296 //function : fixOverlappedLinkUV
297 //purpose : prevent failure due to overlapped adjacent links
298 //=======================================================================
300 static bool fixOverlappedLinkUV( R2& uv0, const R2& uv1, const R2& uv2 )
302 gp_XY v1( uv0.x - uv1.x, uv0.y - uv1.y );
303 gp_XY v2( uv2.x - uv1.x, uv2.y - uv1.y );
305 double tol2 = DBL_MIN * DBL_MIN;
306 double sqMod1 = v1.SquareModulus();
307 if ( sqMod1 <= tol2 ) return false;
308 double sqMod2 = v2.SquareModulus();
309 if ( sqMod2 <= tol2 ) return false;
313 // check sinus >= 1.e-3
314 const double minSin = 1.e-3;
315 if ( dot > 0 && 1 - dot * dot / ( sqMod1 * sqMod2 ) < minSin * minSin ) {
316 MESSAGE(" ___ FIX UV ____" << uv0.x << " " << uv0.y);
317 v1.SetCoord( -v1.Y(), v1.X() );
318 double delta = sqrt( sqMod1 ) * minSin;
327 // MESSAGE(" -> " << uv0.x << " " << uv0.y << " ");
328 // MESSAGE("v1( " << v1.X() << " " << v1.Y() << " ) " <<
329 // "v2( " << v2.X() << " " << v2.Y() << " ) ");
330 // MESSAGE("SIN: " << sqrt(1 - dot * dot / (sqMod1 * sqMod2)));
331 // v1.SetCoord( uv0.x - uv1.x, uv0.y - uv1.y );
332 // v2.SetCoord( uv2.x - uv1.x, uv2.y - uv1.y );
333 // gp_XY v3( uv2.x - uv0.x, uv2.y - uv0.y );
334 // sqMod1 = v1.SquareModulus();
335 // sqMod2 = v2.SquareModulus();
337 // double sin = sqrt(1 - dot * dot / (sqMod1 * sqMod2));
338 // MESSAGE("NEW SIN: " << sin);
344 //=======================================================================
345 //function : fixCommonVertexUV
347 //=======================================================================
349 static bool fixCommonVertexUV (gp_Pnt2d & theUV,
350 const TopoDS_Vertex& theV,
351 const TopoDS_Wire& theW,
352 const TopoDS_Wire& theOW,
353 const TopoDS_Face& theF,
354 const TopTools_IndexedDataMapOfShapeListOfShape & theVWMap,
355 SMESH_Mesh & theMesh)
357 if( theW.IsSame( theOW ) ||
358 !theVWMap.Contains( theV )) return false;
360 // check if there is another wire sharing theV
361 const TopTools_ListOfShape& WList = theVWMap.FindFromKey( theV );
362 TopTools_ListIteratorOfListOfShape aWIt;
363 for ( aWIt.Initialize( WList ); aWIt.More(); aWIt.Next() )
364 if ( !theW.IsSame( aWIt.Value() ))
366 if ( !aWIt.More() ) return false;
368 TopTools_ListOfShape EList;
369 list< double > UList;
371 // find edges of theW sharing theV
372 // and find 2d normal to them at theV
374 TopoDS_Iterator itE( theW );
375 for ( ; itE.More(); itE.Next() )
377 const TopoDS_Edge& E = TopoDS::Edge( itE.Value() );
378 TopoDS_Iterator itV( E );
379 for ( ; itV.More(); itV.Next() )
381 const TopoDS_Vertex & V = TopoDS::Vertex( itV.Value() );
382 if ( !V.IsSame( theV ))
385 Standard_Real u = BRep_Tool::Parameter( V, E );
386 UList.push_back( u );
388 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, theF, f, l);
392 gp_Vec2d n( d1.Y(), -d1.X() );
393 if ( E.Orientation() == TopAbs_REVERSED )
399 // define step size by which to move theUV
401 gp_Pnt2d nextUV; // uv of next node on edge, most distant of the four
402 double maxDist = -DBL_MAX;
403 TopTools_ListIteratorOfListOfShape aEIt (EList);
404 list< double >::iterator aUIt = UList.begin();
405 for ( ; aEIt.More(); aEIt.Next(), aUIt++ )
407 const TopoDS_Edge& E = TopoDS::Edge( aEIt.Value() );
409 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, theF, f, l);
411 double umin = DBL_MAX, umax = -DBL_MAX;
412 SMDS_NodeIteratorPtr nIt = theMesh.GetSubMesh(E)->GetSubMeshDS()->GetNodes();
413 if ( !nIt->more() ) // no nodes on edge, only on vertices
420 while ( nIt->more() ) {
421 const SMDS_MeshNode* node = nIt->next();
422 const SMDS_EdgePosition* epos =
423 static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
424 double u = epos->GetUParameter();
431 bool isFirstCommon = ( *aUIt == f );
432 gp_Pnt2d uv = C2d->Value( isFirstCommon ? umin : umax );
433 double dist = theUV.SquareDistance( uv );
434 if ( dist > maxDist ) {
440 uv0.x = theUV.X(); uv0.y = theUV.Y();
441 uv1.x = nextUV.X(); uv1.y = nextUV.Y();
442 uv2.x = uv0.x; uv2.y = uv0.y;
443 if ( fixOverlappedLinkUV( uv0, uv1, uv2 ))
445 double step = theUV.Distance( gp_Pnt2d( uv0.x, uv0.y ));
447 // move theUV along the normal by the step
451 MESSAGE("--fixCommonVertexUV move(" << theUV.X() << " " << theUV.Y()
452 << ") by (" << N.X() << " " << N.Y() << ")"
453 << endl << "--- MAX DIST " << maxDist);
455 theUV.SetXY( theUV.XY() + N.XY() );
462 //=============================================================================
466 //=============================================================================
468 bool StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh & aMesh,
469 const TopoDS_Face & FF,
470 const TopoDS_Wire & WW,
473 map<int, const SMDS_MeshNode*>&mefistoToDS,
476 const TopTools_IndexedDataMapOfShapeListOfShape& VWMap)
478 // MESSAGE("StdMeshers_MEFISTO_2D::LoadPoints");
480 SMDS_Mesh * meshDS = aMesh.GetMeshDS();
482 TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD));
484 int mInit = m, mFirst, iEdge;
485 gp_XY scale( scalex, scaley );
487 TopoDS_Wire W = TopoDS::Wire(WW.Oriented(TopAbs_FORWARD));
488 BRepTools_WireExplorer wexp(W, F);
489 for (wexp.Init(W, F), iEdge = 0; wexp.More(); wexp.Next(), iEdge++)
491 const TopoDS_Edge & E = wexp.Current();
493 // --- IDNodes of first and last Vertex
495 TopoDS_Vertex VFirst, VLast;
496 TopExp::Vertices(E, VFirst, VLast); // corresponds to f and l
498 ASSERT(!VFirst.IsNull());
499 SMDS_NodeIteratorPtr lid=
500 aMesh.GetSubMesh(VFirst)->GetSubMeshDS()->GetNodes();
501 if ( !lid->more() ) {
502 MESSAGE (" NO NODE BUILT ON VERTEX ");
505 const SMDS_MeshNode* idFirst = lid->next();
507 ASSERT(!VLast.IsNull());
508 lid=aMesh.GetSubMesh(VLast)->GetSubMeshDS()->GetNodes();
509 if ( !lid->more() ) {
510 MESSAGE (" NO NODE BUILT ON VERTEX ");
513 const SMDS_MeshNode* idLast = lid->next();
515 // --- edge internal IDNodes (relies on good order storage, not checked)
517 int nbPoints = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes();
520 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
522 SMDS_NodeIteratorPtr ite= aMesh.GetSubMesh(E)->GetSubMeshDS()->GetNodes();
524 bool isForward = (E.Orientation() == TopAbs_FORWARD);
525 map<double, const SMDS_MeshNode*> params;
529 const SMDS_MeshNode * node = ite->next();
530 const SMDS_EdgePosition* epos =
531 static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
532 double param = epos->GetUParameter();
533 params[param] = node;
535 if ( nbPoints != params.size())
537 MESSAGE( "BAD NODE ON EDGE POSITIONS" );
543 // --- load 2D values into MEFISTO structure,
544 // add IDNodes in mefistoToDS map
545 if (E.Orientation() == TopAbs_FORWARD)
547 gp_Pnt2d p = C2d->Value(f).XY().Multiplied( scale ); // first point = Vertex Forward
548 if ( fixCommonVertexUV( p, VFirst, W, myOuterWire, F, VWMap, aMesh ))
549 myNodesOnCommonV.push_back( idFirst );
552 mefistoToDS[m + 1] = idFirst;
553 //MESSAGE(" "<<m<<" "<<mefistoToDS[m+1]);
554 //MESSAGE("__ f "<<f<<" "<<uvslf[m].x <<" "<<uvslf[m].y);
556 map<double, const SMDS_MeshNode*>::iterator itp = params.begin();
557 for (int i = 1; i <= nbPoints; i++) // nbPoints internal
559 double param = (*itp).first;
560 gp_Pnt2d p = C2d->Value(param).XY().Multiplied( scale );
563 mefistoToDS[m + 1] = (*itp).second;
564 //MESSAGE(" "<<m<<" "<<mefistoToDS[m+1]);
565 //MESSAGE("__ "<<i<<" "<<param<<" "<<uvslf[m].x <<" "<<uvslf[m].y);
572 gp_Pnt2d p = C2d->Value(l).XY().Multiplied( scale ); // last point = Vertex Reversed
573 if ( fixCommonVertexUV( p, VLast, W, myOuterWire, F, VWMap, aMesh ))
574 myNodesOnCommonV.push_back( idLast );
577 mefistoToDS[m + 1] = idLast;
578 //MESSAGE(" "<<m<<" "<<mefistoToDS[m+1]);
579 //MESSAGE("__ l "<<l<<" "<<uvslf[m].x <<" "<<uvslf[m].y);
581 map<double, const SMDS_MeshNode*>::reverse_iterator itp = params.rbegin();
582 for (int i = nbPoints; i >= 1; i--)
584 double param = (*itp).first;
585 gp_Pnt2d p = C2d->Value(param).XY().Multiplied( scale );
588 mefistoToDS[m + 1] = (*itp).second;
589 //MESSAGE(" "<<m<<" "<<mefistoToDS[m+1]);
590 //MESSAGE("__ "<<i<<" "<<param<<" "<<uvslf[m].x <<" "<<uvslf[m].y);
595 // prevent failure on overlapped adjacent links
597 fixOverlappedLinkUV (uvslf[ mFirst - 1],
599 uvslf[ mFirst + 1 ]);
603 fixOverlappedLinkUV (uvslf[ m - 1],
610 //=============================================================================
614 //=============================================================================
616 void StdMeshers_MEFISTO_2D::ComputeScaleOnFace(SMESH_Mesh & aMesh,
617 const TopoDS_Face & aFace, double &scalex, double &scaley)
619 //MESSAGE("StdMeshers_MEFISTO_2D::ComputeScaleOnFace");
620 TopoDS_Face F = TopoDS::Face(aFace.Oriented(TopAbs_FORWARD));
621 TopoDS_Wire W = BRepTools::OuterWire(F);
623 double xmin = 1.e300; // min & max of face 2D parametric coord.
624 double xmax = -1.e300;
625 double ymin = 1.e300;
626 double ymax = -1.e300;
631 TopExp_Explorer wexp(W, TopAbs_EDGE);
632 for ( ; wexp.More(); wexp.Next())
634 const TopoDS_Edge & E = TopoDS::Edge( wexp.Current() );
636 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
637 if ( C2d.IsNull() ) continue;
638 double du = (l - f) / double (nbp);
639 for (int i = 0; i <= nbp; i++)
641 double param = f + double (i) * du;
642 gp_Pnt2d p = C2d->Value(param);
651 // MESSAGE(" "<< f<<" "<<l<<" "<<param<<" "<<xmin<<" "<<xmax<<" "<<ymin<<" "<<ymax);
658 double xmoy = (xmax + xmin) / 2.;
659 double ymoy = (ymax + ymin) / 2.;
660 double xsize = xmax - xmin;
661 double ysize = ymax - ymin;
663 Handle(Geom_Surface) S = BRep_Tool::Surface(F); // 3D surface
667 gp_Pnt PX0 = S->Value(xmin, ymoy);
668 gp_Pnt PY0 = S->Value(xmoy, ymin);
669 double dx = xsize / double (nbp);
670 double dy = ysize / double (nbp);
671 for (int i = 1; i <= nbp; i++)
673 double x = xmin + double (i) * dx;
674 gp_Pnt PX = S->Value(x, ymoy);
675 double y = ymin + double (i) * dy;
676 gp_Pnt PY = S->Value(xmoy, y);
677 length_x += PX.Distance(PX0);
678 length_y += PY.Distance(PY0);
682 scalex = length_x / xsize;
683 scaley = length_y / ysize;
686 double xyratio = xsize*scalex/(ysize*scaley);
687 const double maxratio = 1.e2;
689 if (xyratio > maxratio) {
691 scaley *= xyratio / maxratio;
694 else if (xyratio < 1./maxratio) {
696 scalex *= 1 / xyratio / maxratio;
703 //=============================================================================
707 //=============================================================================
709 void StdMeshers_MEFISTO_2D::StoreResult(SMESH_Mesh & aMesh,
710 Z nbst, R2 * uvst, Z nbt, Z * nust,
711 const TopoDS_Face & F, bool faceIsForward,
712 map<int, const SMDS_MeshNode*>&mefistoToDS,
713 double scalex, double scaley)
715 SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
718 Handle(Geom_Surface) S = BRep_Tool::Surface(F);
720 for (n = 0; n < nbst; n++)
722 if (mefistoToDS.find(n + 1) == mefistoToDS.end())
724 double u = uvst[n][0] / scalex;
725 double v = uvst[n][1] / scaley;
726 gp_Pnt P = S->Value(u, v);
728 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
729 meshDS->SetNodeOnFace(node, F);
731 //MESSAGE(P.X()<<" "<<P.Y()<<" "<<P.Z());
732 mefistoToDS[n + 1] = node;
733 //MESSAGE("NEW: "<<n<<" "<<mefistoToDS[n+1]);
734 SMDS_FacePosition* fpos =
735 static_cast<SMDS_FacePosition*>(node->GetPosition().get());
736 fpos->SetUParameter(u);
737 fpos->SetVParameter(v);
744 //SCRUTE(faceIsForward);
745 for (n = 1; n <= nbt; n++)
747 int inode1 = nust[m++];
748 int inode2 = nust[m++];
749 int inode3 = nust[m++];
751 const SMDS_MeshNode *n1, *n2, *n3;
752 n1 = mefistoToDS[inode1];
753 n2 = mefistoToDS[inode2];
754 n3 = mefistoToDS[inode3];
755 //MESSAGE("-- "<<inode1<<" "<<inode2<<" "<<inode3);
757 // triangle points must be in trigonometric order if face is Forward
758 // else they must be put clockwise
760 bool triangleIsWellOriented = faceIsForward;
762 SMDS_MeshElement * elt;
763 if (triangleIsWellOriented)
764 elt = meshDS->AddFace(n1, n2, n3);
766 elt = meshDS->AddFace(n1, n3, n2);
768 meshDS->SetMeshElementOnShape(elt, F);
772 // remove bad elements build on vertices shared by wires
774 list<const SMDS_MeshNode*>::iterator itN = myNodesOnCommonV.begin();
775 for ( ; itN != myNodesOnCommonV.end(); itN++ )
777 const SMDS_MeshNode* node = *itN;
778 SMDS_ElemIteratorPtr invElemIt = node->GetInverseElementIterator();
779 while ( invElemIt->more() )
781 const SMDS_MeshElement* elem = invElemIt->next();
782 SMDS_ElemIteratorPtr itN = elem->nodesIterator();
784 while ( itN->more() )
785 if ( itN->next() == node)
788 MESSAGE( "RM bad element " << elem->GetID());
789 meshDS->RemoveElement( elem );
796 //=============================================================================
800 //=============================================================================
802 double StdMeshers_MEFISTO_2D::ComputeEdgeElementLength(SMESH_Mesh & aMesh,
803 const TopoDS_Shape & aShape)
805 //MESSAGE("StdMeshers_MEFISTO_2D::ComputeEdgeElementLength");
806 // **** a mettre dans SMESH_2D_Algo ?
808 const TopoDS_Face & FF = TopoDS::Face(aShape);
809 bool faceIsForward = (FF.Orientation() == TopAbs_FORWARD);
810 TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD));
812 double meanElementLength = 100;
813 double wireLength = 0;
814 int wireElementsNumber = 0;
815 for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next())
817 const TopoDS_Wire & W = TopoDS::Wire(exp.Current());
818 for (TopExp_Explorer expe(W, TopAbs_EDGE); expe.More(); expe.Next())
820 const TopoDS_Edge & E = TopoDS::Edge(expe.Current());
821 int nb = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes();
822 double length = EdgeLength(E);
823 wireLength += length;
824 wireElementsNumber += nb;
827 if (wireElementsNumber)
828 meanElementLength = wireLength / wireElementsNumber;
829 //SCRUTE(meanElementLength);
830 return meanElementLength;
833 //=============================================================================
837 //=============================================================================
839 ostream & StdMeshers_MEFISTO_2D::SaveTo(ostream & save)
844 //=============================================================================
848 //=============================================================================
850 istream & StdMeshers_MEFISTO_2D::LoadFrom(istream & load)
855 //=============================================================================
859 //=============================================================================
861 ostream & operator <<(ostream & save, StdMeshers_MEFISTO_2D & hyp)
863 return hyp.SaveTo( save );
866 //=============================================================================
870 //=============================================================================
872 istream & operator >>(istream & load, StdMeshers_MEFISTO_2D & hyp)
874 return hyp.LoadFrom( load );