00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "StdMeshers_MEFISTO_2D.hxx"
00030
00031 #include "SMESH_Gen.hxx"
00032 #include "SMESH_Mesh.hxx"
00033 #include "SMESH_subMesh.hxx"
00034 #include "SMESH_Block.hxx"
00035 #include "SMESH_MesherHelper.hxx"
00036 #include "SMESH_Comment.hxx"
00037
00038 #include "StdMeshers_FaceSide.hxx"
00039 #include "StdMeshers_MaxElementArea.hxx"
00040 #include "StdMeshers_LengthFromEdges.hxx"
00041
00042 #include "Rn.h"
00043 #include "aptrte.h"
00044
00045 #include "SMDS_MeshElement.hxx"
00046 #include "SMDS_MeshNode.hxx"
00047 #include "SMDS_EdgePosition.hxx"
00048 #include "SMDS_FacePosition.hxx"
00049
00050 #include "utilities.h"
00051
00052 #include <BRepTools.hxx>
00053 #include <BRep_Tool.hxx>
00054 #include <Geom_Curve.hxx>
00055 #include <Geom2d_Curve.hxx>
00056 #include <Geom_Surface.hxx>
00057 #include <Precision.hxx>
00058 #include <TopExp.hxx>
00059 #include <TopExp_Explorer.hxx>
00060 #include <TopTools_ListIteratorOfListOfShape.hxx>
00061 #include <TopTools_ListOfShape.hxx>
00062 #include <TopTools_MapOfShape.hxx>
00063 #include <TopoDS.hxx>
00064 #include <TopoDS_Edge.hxx>
00065 #include <TopoDS_Face.hxx>
00066 #include <TopoDS_Iterator.hxx>
00067 #include <gp_Pnt2d.hxx>
00068
00069 #include <BRep_Tool.hxx>
00070 #include <GProp_GProps.hxx>
00071 #include <BRepGProp.hxx>
00072
00073 using namespace std;
00074
00075
00079
00080
00081 StdMeshers_MEFISTO_2D::StdMeshers_MEFISTO_2D(int hypId, int studyId, SMESH_Gen * gen):
00082 SMESH_2D_Algo(hypId, studyId, gen)
00083 {
00084 MESSAGE("StdMeshers_MEFISTO_2D::StdMeshers_MEFISTO_2D");
00085 _name = "MEFISTO_2D";
00086 _shapeType = (1 << TopAbs_FACE);
00087 _compatibleHypothesis.push_back("MaxElementArea");
00088 _compatibleHypothesis.push_back("LengthFromEdges");
00089
00090 _edgeLength = 0;
00091 _maxElementArea = 0;
00092 _hypMaxElementArea = NULL;
00093 _hypLengthFromEdges = NULL;
00094 myTool = 0;
00095 }
00096
00097
00101
00102
00103 StdMeshers_MEFISTO_2D::~StdMeshers_MEFISTO_2D()
00104 {
00105 MESSAGE("StdMeshers_MEFISTO_2D::~StdMeshers_MEFISTO_2D");
00106 }
00107
00108
00112
00113
00114 bool StdMeshers_MEFISTO_2D::CheckHypothesis
00115 (SMESH_Mesh& aMesh,
00116 const TopoDS_Shape& aShape,
00117 SMESH_Hypothesis::Hypothesis_Status& aStatus)
00118 {
00119 _hypMaxElementArea = NULL;
00120 _hypLengthFromEdges = NULL;
00121 _edgeLength = 0;
00122 _maxElementArea = 0;
00123
00124 list <const SMESHDS_Hypothesis * >::const_iterator itl;
00125 const SMESHDS_Hypothesis *theHyp;
00126
00127 const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
00128 int nbHyp = hyps.size();
00129 if (!nbHyp)
00130 {
00131 aStatus = SMESH_Hypothesis::HYP_OK;
00132 return true;
00133 }
00134
00135 itl = hyps.begin();
00136 theHyp = (*itl);
00137
00138 string hypName = theHyp->GetName();
00139
00140 bool isOk = false;
00141
00142 if (hypName == "MaxElementArea")
00143 {
00144 _hypMaxElementArea = static_cast<const StdMeshers_MaxElementArea *>(theHyp);
00145 ASSERT(_hypMaxElementArea);
00146 _maxElementArea = _hypMaxElementArea->GetMaxArea();
00147 isOk = true;
00148 aStatus = SMESH_Hypothesis::HYP_OK;
00149 }
00150
00151 else if (hypName == "LengthFromEdges")
00152 {
00153 _hypLengthFromEdges = static_cast<const StdMeshers_LengthFromEdges *>(theHyp);
00154 ASSERT(_hypLengthFromEdges);
00155 isOk = true;
00156 aStatus = SMESH_Hypothesis::HYP_OK;
00157 }
00158 else
00159 aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
00160
00161 if (isOk)
00162 {
00163 isOk = false;
00164 if (_maxElementArea > 0)
00165 {
00166
00167 _edgeLength = sqrt(2. * _maxElementArea/sqrt(3.0));
00168 isOk = true;
00169 }
00170 else
00171 isOk = (_hypLengthFromEdges != NULL);
00172 if (!isOk)
00173 aStatus = SMESH_Hypothesis::HYP_BAD_PARAMETER;
00174 }
00175
00176 return isOk;
00177 }
00178
00179
00183
00184
00185 bool StdMeshers_MEFISTO_2D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape)
00186 {
00187 MESSAGE("StdMeshers_MEFISTO_2D::Compute");
00188
00189 TopoDS_Face F = TopoDS::Face(aShape.Oriented(TopAbs_FORWARD));
00190
00191
00192 SMESH_MesherHelper helper(aMesh);
00193 myTool = &helper;
00194 _quadraticMesh = myTool->IsQuadraticSubMesh(aShape);
00195 const bool ignoreMediumNodes = _quadraticMesh;
00196
00197
00198 TError problem;
00199 TWireVector wires = StdMeshers_FaceSide::GetFaceWires( F, aMesh, ignoreMediumNodes, problem );
00200 int nbWires = wires.size();
00201 if ( problem && !problem->IsOK() ) return error( problem );
00202 if ( nbWires == 0 ) return error( "Problem in StdMeshers_FaceSide::GetFaceWires()");
00203 if ( wires[0]->NbSegments() < 3 )
00204 return error(COMPERR_BAD_INPUT_MESH,
00205 SMESH_Comment("Too few segments: ")<<wires[0]->NbSegments());
00206
00207
00208 if (!_hypMaxElementArea)
00209 {
00210 _edgeLength = 0;
00211 int nbSegments = 0;
00212 for ( int iW = 0; iW < nbWires; ++iW )
00213 {
00214 StdMeshers_FaceSidePtr wire = wires[ iW ];
00215 _edgeLength += wire->Length();
00216 nbSegments += wire->NbSegments();
00217 }
00218 if ( nbSegments )
00219 _edgeLength /= nbSegments;
00220 }
00221
00222 if ( _edgeLength < DBL_MIN )
00223 _edgeLength = 100;
00224
00225 Z nblf;
00226 Z *nudslf = NULL;
00227 R2 *uvslf = NULL;
00228 Z nbpti = 0;
00229 R2 *uvpti = NULL;
00230
00231 Z nbst;
00232 R2 *uvst = NULL;
00233 Z nbt;
00234 Z *nust = NULL;
00235 Z ierr = 0;
00236
00237 Z nutysu = 1;
00238
00239 R aretmx = _edgeLength;
00240 if ( _hypMaxElementArea )
00241 aretmx *= 1.5;
00242
00243 nblf = nbWires;
00244
00245 nudslf = new Z[1 + nblf];
00246 nudslf[0] = 0;
00247 int iw = 1;
00248 int nbpnt = 0;
00249
00250
00251 for ( int iW = 0; iW < nbWires; ++iW )
00252 {
00253 nbpnt += wires[iW]->NbPoints() - 1;
00254 nudslf[iw++] = nbpnt;
00255 }
00256
00257 uvslf = new R2[nudslf[nblf]];
00258
00259 double scalex, scaley;
00260 ComputeScaleOnFace(aMesh, F, scalex, scaley);
00261
00262
00263 vector< const SMDS_MeshNode*> mefistoToDS(nbpnt, (const SMDS_MeshNode*)0);
00264
00265 bool isOk = false;
00266
00267
00268 if ( LoadPoints(wires, uvslf, mefistoToDS, scalex, scaley) )
00269 {
00270
00271 aptrte(nutysu, aretmx,
00272 nblf, nudslf, uvslf, nbpti, uvpti, nbst, uvst, nbt, nust, ierr);
00273
00274 if (ierr == 0)
00275 {
00276 MESSAGE("... End Triangulation Generated Triangle Number " << nbt);
00277 MESSAGE(" Node Number " << nbst);
00278 StoreResult(nbst, uvst, nbt, nust, mefistoToDS, scalex, scaley);
00279 isOk = true;
00280 }
00281 else
00282 {
00283 error(ierr,"Error in Triangulation (aptrte())");
00284 }
00285 }
00286 if (nudslf != NULL) delete[]nudslf;
00287 if (uvslf != NULL) delete[]uvslf;
00288 if (uvst != NULL) delete[]uvst;
00289 if (nust != NULL) delete[]nust;
00290
00291 return isOk;
00292 }
00293
00294
00295
00299
00300
00301 bool StdMeshers_MEFISTO_2D::Evaluate(SMESH_Mesh & aMesh,
00302 const TopoDS_Shape & aShape,
00303 MapShapeNbElems& aResMap)
00304 {
00305 MESSAGE("StdMeshers_MEFISTO_2D::Evaluate");
00306
00307 TopoDS_Face F = TopoDS::Face(aShape.Oriented(TopAbs_FORWARD));
00308
00309 double aLen = 0.0;
00310 int NbSeg = 0;
00311 bool IsQuadratic = false;
00312 bool IsFirst = true;
00313 TopExp_Explorer exp(F,TopAbs_EDGE);
00314 for(; exp.More(); exp.Next()) {
00315 TopoDS_Edge E = TopoDS::Edge(exp.Current());
00316 MapShapeNbElemsItr anIt = aResMap.find( aMesh.GetSubMesh(E) );
00317 if( anIt == aResMap.end() ) continue;
00318 std::vector<int> aVec = (*anIt).second;
00319 int nbe = Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]);
00320 NbSeg += nbe;
00321 if(IsFirst) {
00322 IsQuadratic = ( aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge] );
00323 IsFirst = false;
00324 }
00325 double a,b;
00326 TopLoc_Location L;
00327 Handle(Geom_Curve) C = BRep_Tool::Curve(E,L,a,b);
00328 gp_Pnt P1;
00329 C->D0(a,P1);
00330 double dp = (b-a)/nbe;
00331 for(int i=1; i<=nbe; i++) {
00332 gp_Pnt P2;
00333 C->D0(a+i*dp,P2);
00334 aLen += P1.Distance(P2);
00335 P1 = P2;
00336 }
00337 }
00338 if(NbSeg<1) {
00339 std::vector<int> aResVec(SMDSEntity_Last);
00340 for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
00341 SMESH_subMesh * sm = aMesh.GetSubMesh(aShape);
00342 aResMap.insert(std::make_pair(sm,aResVec));
00343 SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
00344 smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,
00345 "Submesh can not be evaluated",this));
00346 return false;
00347 }
00348 aLen = aLen/NbSeg;
00349
00350 _edgeLength = Precision::Infinite();
00351 double tmpLength = Min( _edgeLength, aLen );
00352
00353 GProp_GProps G;
00354 BRepGProp::SurfaceProperties(aShape,G);
00355 double anArea = G.Mass();
00356
00357 int nbFaces = Precision::IsInfinite( tmpLength ) ? 0 :
00358 (int)( anArea/(tmpLength*tmpLength*sqrt(3.)/4) );
00359 int nbNodes = (int) ( nbFaces*3 - (NbSeg-1)*2 ) / 6;
00360
00361 std::vector<int> aVec(SMDSEntity_Last);
00362 for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i] = 0;
00363 if(IsQuadratic) {
00364 aVec[SMDSEntity_Quad_Triangle] = nbFaces;
00365 aVec[SMDSEntity_Node] = (int)( nbNodes + nbFaces*3 - (NbSeg-1) );
00366 }
00367 else {
00368 aVec[SMDSEntity_Node] = nbNodes;
00369 aVec[SMDSEntity_Triangle] = nbFaces;
00370 }
00371 SMESH_subMesh * sm = aMesh.GetSubMesh(aShape);
00372 aResMap.insert(std::make_pair(sm,aVec));
00373
00374 return true;
00375 }
00376
00377
00378
00379
00380
00381
00382
00383 static bool fixOverlappedLinkUV( R2& uv0, const R2& uv1, const R2& uv2 )
00384 {
00385 gp_XY v1( uv0.x - uv1.x, uv0.y - uv1.y );
00386 gp_XY v2( uv2.x - uv1.x, uv2.y - uv1.y );
00387
00388 double tol2 = DBL_MIN * DBL_MIN;
00389 double sqMod1 = v1.SquareModulus();
00390 if ( sqMod1 <= tol2 ) return false;
00391 double sqMod2 = v2.SquareModulus();
00392 if ( sqMod2 <= tol2 ) return false;
00393
00394 double dot = v1*v2;
00395
00396
00397 const double minSin = 1.e-3;
00398 if ( dot > 0 && 1 - dot * dot / ( sqMod1 * sqMod2 ) < minSin * minSin ) {
00399 MESSAGE(" ___ FIX UV ____" << uv0.x << " " << uv0.y);
00400 v1.SetCoord( -v1.Y(), v1.X() );
00401 double delta = sqrt( sqMod1 ) * minSin;
00402 if ( v1.X() < 0 )
00403 uv0.x -= delta;
00404 else
00405 uv0.x += delta;
00406 if ( v1.Y() < 0 )
00407 uv0.y -= delta;
00408 else
00409 uv0.y += delta;
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 return true;
00425 }
00426 return false;
00427 }
00428
00429
00430
00431
00432
00433
00434 static bool fixCommonVertexUV (R2 & theUV,
00435 const TopoDS_Vertex& theV,
00436 const TopoDS_Face& theF,
00437 const TopTools_IndexedDataMapOfShapeListOfShape & theVWMap,
00438 SMESH_Mesh & theMesh,
00439 const double theScaleX,
00440 const double theScaleY,
00441 const bool theCreateQuadratic)
00442 {
00443 if( !theVWMap.Contains( theV )) return false;
00444
00445
00446 const TopTools_ListOfShape& WList = theVWMap.FindFromKey( theV );
00447 TopTools_ListIteratorOfListOfShape aWIt;
00448 TopTools_MapOfShape aWires;
00449 for ( aWIt.Initialize( WList ); aWIt.More(); aWIt.Next() )
00450 aWires.Add( aWIt.Value() );
00451 if ( aWires.Extent() < 2 ) return false;
00452
00453 TopoDS_Shape anOuterWire = BRepTools::OuterWire(theF);
00454 TopoDS_Shape anInnerWire;
00455 for ( aWIt.Initialize( WList ); aWIt.More() && anInnerWire.IsNull(); aWIt.Next() )
00456 if ( !anOuterWire.IsSame( aWIt.Value() ))
00457 anInnerWire = aWIt.Value();
00458
00459 TopTools_ListOfShape EList;
00460 list< double > UList;
00461
00462
00463
00464 gp_Vec2d N(0.,0.);
00465 TopoDS_Iterator itE( anInnerWire );
00466 for ( ; itE.More(); itE.Next() )
00467 {
00468 const TopoDS_Edge& E = TopoDS::Edge( itE.Value() );
00469 TopoDS_Iterator itV( E );
00470 for ( ; itV.More(); itV.Next() )
00471 {
00472 const TopoDS_Vertex & V = TopoDS::Vertex( itV.Value() );
00473 if ( !V.IsSame( theV ))
00474 continue;
00475 EList.Append( E );
00476 Standard_Real u = BRep_Tool::Parameter( V, E );
00477 UList.push_back( u );
00478 double f, l;
00479 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, theF, f, l);
00480 gp_Vec2d d1;
00481 gp_Pnt2d p;
00482 C2d->D1( u, p, d1 );
00483 gp_Vec2d n( d1.Y() * theScaleX, -d1.X() * theScaleY);
00484 if ( E.Orientation() == TopAbs_REVERSED )
00485 n.Reverse();
00486 N += n.Normalized();
00487 }
00488 }
00489
00490
00491
00492 gp_Pnt2d nextUV;
00493 gp_Pnt2d thisUV( theUV.x, theUV.y );
00494 double maxDist = -DBL_MAX;
00495 TopTools_ListIteratorOfListOfShape aEIt (EList);
00496 list< double >::iterator aUIt = UList.begin();
00497 for ( ; aEIt.More(); aEIt.Next(), aUIt++ )
00498 {
00499 const TopoDS_Edge& E = TopoDS::Edge( aEIt.Value() );
00500 double f, l;
00501 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, theF, f, l);
00502
00503 double umin = DBL_MAX, umax = -DBL_MAX;
00504 SMDS_NodeIteratorPtr nIt = theMesh.GetSubMesh(E)->GetSubMeshDS()->GetNodes();
00505 if ( !nIt->more() )
00506 {
00507 umin = l;
00508 umax = f;
00509 }
00510 else {
00511 while ( nIt->more() ) {
00512 const SMDS_MeshNode* node = nIt->next();
00513
00514 if ( theCreateQuadratic && SMESH_MesherHelper::IsMedium( node, SMDSAbs_Edge ))
00515 continue;
00516 const SMDS_EdgePosition* epos =
00517 static_cast<const SMDS_EdgePosition*>(node->GetPosition());
00518 double u = epos->GetUParameter();
00519 if ( u < umin )
00520 umin = u;
00521 if ( u > umax )
00522 umax = u;
00523 }
00524 }
00525 bool isFirstCommon = ( *aUIt == f );
00526 gp_Pnt2d uv = C2d->Value( isFirstCommon ? umin : umax );
00527 double dist = thisUV.SquareDistance( uv );
00528 if ( dist > maxDist ) {
00529 maxDist = dist;
00530 nextUV = uv;
00531 }
00532 }
00533 R2 uv0, uv1, uv2;
00534 uv0.x = thisUV.X(); uv0.y = thisUV.Y();
00535 uv1.x = nextUV.X(); uv1.y = nextUV.Y();
00536 uv2.x = thisUV.X(); uv2.y = thisUV.Y();
00537
00538 uv1.x *= theScaleX; uv1.y *= theScaleY;
00539
00540 if ( fixOverlappedLinkUV( uv0, uv1, uv2 ))
00541 {
00542 double step = thisUV.Distance( gp_Pnt2d( uv0.x, uv0.y ));
00543
00544
00545
00546 N *= step;
00547
00548 MESSAGE("--fixCommonVertexUV move(" << theUV.x << " " << theUV.x
00549 << ") by (" << N.X() << " " << N.Y() << ")"
00550 << endl << "--- MAX DIST " << maxDist);
00551
00552 theUV.x += N.X();
00553 theUV.y += N.Y();
00554
00555 return true;
00556 }
00557 return false;
00558 }
00559
00560
00564
00565
00566 bool StdMeshers_MEFISTO_2D::LoadPoints(TWireVector & wires,
00567 R2 * uvslf,
00568 vector<const SMDS_MeshNode*>& mefistoToDS,
00569 double scalex,
00570 double scaley)
00571 {
00572
00573 TopoDS_Face F;
00574 TopTools_IndexedDataMapOfShapeListOfShape VWMap;
00575 if ( wires.size() > 1 )
00576 {
00577 F = TopoDS::Face( myTool->GetSubShape() );
00578 TopExp::MapShapesAndAncestors( F, TopAbs_VERTEX, TopAbs_WIRE, VWMap );
00579 int nbVertices = 0;
00580 for ( int iW = 0; iW < wires.size(); ++iW )
00581 nbVertices += wires[ iW ]->NbEdges();
00582 if ( nbVertices == VWMap.Extent() )
00583 VWMap.Clear();
00584 }
00585
00586 int m = 0;
00587
00588 for ( int iW = 0; iW < wires.size(); ++iW )
00589 {
00590 const vector<UVPtStruct>& uvPtVec = wires[ iW ]->GetUVPtStruct();
00591 if ( uvPtVec.size() != wires[ iW ]->NbPoints() ) {
00592 return error(COMPERR_BAD_INPUT_MESH,SMESH_Comment("Unexpected nb of points on wire ")
00593 << iW << ": " << uvPtVec.size()<<" != "<<wires[ iW ]->NbPoints()
00594 << ", probably because of invalid node parameters on geom edges");
00595 }
00596 if ( m + uvPtVec.size()-1 > mefistoToDS.size() ) {
00597 MESSAGE("Wrong mefistoToDS.size: "<<mefistoToDS.size()<<" < "<<m + uvPtVec.size()-1);
00598 return error("Internal error");
00599 }
00600
00601 list< int > mOnVertex;
00602 vector<UVPtStruct>::const_iterator uvPt = uvPtVec.begin();
00603 for ( ++uvPt; uvPt != uvPtVec.end(); ++uvPt )
00604 {
00605
00606 mefistoToDS[m] = uvPt->node;
00607
00608 uvslf[m].x = uvPt->u * scalex;
00609 uvslf[m].y = uvPt->v * scaley;
00610 switch ( uvPt->node->GetPosition()->GetTypeOfPosition())
00611 {
00612 case SMDS_TOP_VERTEX:
00613 mOnVertex.push_back( m );
00614 break;
00615 case SMDS_TOP_EDGE:
00616
00617
00618 if ( myTool->IsDegenShape( uvPt->node->getshapeId() ))
00619 {
00620 int edgeID = uvPt->node->getshapeId();
00621 SMESH_subMesh* edgeSM = myTool->GetMesh()->GetSubMeshContaining( edgeID );
00622 SMESH_subMeshIteratorPtr smIt = edgeSM->getDependsOnIterator( 0,
00623 0);
00624 if ( smIt->more() )
00625 {
00626 SMESH_subMesh* vertexSM = smIt->next();
00627 SMDS_NodeIteratorPtr nIt = vertexSM->GetSubMeshDS()->GetNodes();
00628 if ( nIt->more() )
00629 mefistoToDS[m] = nIt->next();
00630 }
00631 }
00632 break;
00633 default:;
00634 }
00635 m++;
00636 }
00637
00638 int mFirst = mOnVertex.front(), mLast = m - 1;
00639 list< int >::iterator mIt = mOnVertex.begin();
00640 for ( ; mIt != mOnVertex.end(); ++mIt)
00641 {
00642 int m = *mIt;
00643 if ( iW && !VWMap.IsEmpty()) {
00644
00645 int vID = mefistoToDS[m]->getshapeId();
00646 TopoDS_Vertex V = TopoDS::Vertex( myTool->GetMeshDS()->IndexToShape( vID ));
00647 if ( fixCommonVertexUV( uvslf[m], V, F, VWMap, *myTool->GetMesh(),
00648 scalex, scaley, _quadraticMesh )) {
00649 myNodesOnCommonV.push_back( mefistoToDS[m] );
00650 continue;
00651 }
00652 }
00653
00654
00655 int mB = m - 1, mA = m + 1;
00656 if ( mB < mFirst ) mB = mLast;
00657 if ( mA > mLast ) mA = mFirst;
00658 fixOverlappedLinkUV (uvslf[ mB ], uvslf[ m ], uvslf[ mA ]);
00659 }
00660 }
00661
00662
00663
00664
00665 return true;
00666 }
00667
00668
00672
00673
00674 void StdMeshers_MEFISTO_2D::ComputeScaleOnFace(SMESH_Mesh & aMesh,
00675 const TopoDS_Face & aFace,
00676 double & scalex,
00677 double & scaley)
00678 {
00679 TopoDS_Wire W = BRepTools::OuterWire(aFace);
00680
00681 double xmin = 1.e300;
00682 double xmax = -1.e300;
00683 double ymin = 1.e300;
00684 double ymax = -1.e300;
00685 int nbp = 23;
00686 scalex = 1;
00687 scaley = 1;
00688
00689 TopExp_Explorer wexp(W, TopAbs_EDGE);
00690 for ( ; wexp.More(); wexp.Next())
00691 {
00692 const TopoDS_Edge & E = TopoDS::Edge( wexp.Current() );
00693 double f, l;
00694 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, aFace, f, l);
00695 if ( C2d.IsNull() ) continue;
00696 double du = (l - f) / double (nbp);
00697 for (int i = 0; i <= nbp; i++)
00698 {
00699 double param = f + double (i) * du;
00700 gp_Pnt2d p = C2d->Value(param);
00701 if (p.X() < xmin)
00702 xmin = p.X();
00703 if (p.X() > xmax)
00704 xmax = p.X();
00705 if (p.Y() < ymin)
00706 ymin = p.Y();
00707 if (p.Y() > ymax)
00708 ymax = p.Y();
00709
00710 }
00711 }
00712
00713
00714
00715
00716 double xmoy = (xmax + xmin) / 2.;
00717 double ymoy = (ymax + ymin) / 2.;
00718 double xsize = xmax - xmin;
00719 double ysize = ymax - ymin;
00720
00721 TopLoc_Location L;
00722 Handle(Geom_Surface) S = BRep_Tool::Surface(aFace,L);
00723
00724 double length_x = 0;
00725 double length_y = 0;
00726 gp_Pnt PX0 = S->Value(xmin, ymoy);
00727 gp_Pnt PY0 = S->Value(xmoy, ymin);
00728 double dx = xsize / double (nbp);
00729 double dy = ysize / double (nbp);
00730 for (int i = 1; i <= nbp; i++)
00731 {
00732 double x = xmin + double (i) * dx;
00733 gp_Pnt PX = S->Value(x, ymoy);
00734 double y = ymin + double (i) * dy;
00735 gp_Pnt PY = S->Value(xmoy, y);
00736 length_x += PX.Distance(PX0);
00737 length_y += PY.Distance(PY0);
00738 PX0 = PX;
00739 PY0 = PY;
00740 }
00741 scalex = length_x / xsize;
00742 scaley = length_y / ysize;
00743
00744
00745 double xyratio = xsize*scalex/(ysize*scaley);
00746 const double maxratio = 1.e2;
00747
00748 if (xyratio > maxratio) {
00749 SCRUTE( scaley );
00750 scaley *= xyratio / maxratio;
00751 SCRUTE( scaley );
00752 }
00753 else if (xyratio < 1./maxratio) {
00754 SCRUTE( scalex );
00755 scalex *= 1 / xyratio / maxratio;
00756 SCRUTE( scalex );
00757 }
00758 ASSERT(scalex);
00759 ASSERT(scaley);
00760 }
00761
00762
00766
00767
00768 void StdMeshers_MEFISTO_2D::StoreResult(Z nbst, R2 * uvst, Z nbt, Z * nust,
00769 vector< const SMDS_MeshNode*>&mefistoToDS,
00770 double scalex, double scaley)
00771 {
00772 SMESHDS_Mesh * meshDS = myTool->GetMeshDS();
00773 int faceID = myTool->GetSubShapeID();
00774
00775 TopoDS_Face F = TopoDS::Face( myTool->GetSubShape() );
00776 Handle(Geom_Surface) S = BRep_Tool::Surface( F );
00777
00778 Z n = mefistoToDS.size();
00779 mefistoToDS.resize( nbst );
00780 for ( ; n < nbst; n++)
00781 {
00782 if (!mefistoToDS[n])
00783 {
00784 double u = uvst[n][0] / scalex;
00785 double v = uvst[n][1] / scaley;
00786 gp_Pnt P = S->Value(u, v);
00787
00788 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
00789 meshDS->SetNodeOnFace(node, faceID, u, v);
00790
00791
00792 mefistoToDS[n] = node;
00793
00794 }
00795 }
00796
00797 Z m = 0;
00798
00799
00800
00801
00802 bool triangleIsWellOriented = ( F.Orientation() == TopAbs_FORWARD );
00803
00804 for (n = 1; n <= nbt; n++)
00805 {
00806 const SMDS_MeshNode * n1 = mefistoToDS[ nust[m++] - 1 ];
00807 const SMDS_MeshNode * n2 = mefistoToDS[ nust[m++] - 1 ];
00808 const SMDS_MeshNode * n3 = mefistoToDS[ nust[m++] - 1 ];
00809
00810
00811 bool isDegen = ( myTool->HasDegeneratedEdges() && ( n1 == n2 || n1 == n3 || n2 == n3 ));
00812 if ( !isDegen )
00813 {
00814 SMDS_MeshElement * elt;
00815 if (triangleIsWellOriented)
00816 elt = myTool->AddFace(n1, n2, n3);
00817 else
00818 elt = myTool->AddFace(n1, n3, n2);
00819 meshDS->SetMeshElementOnShape(elt, faceID);
00820 }
00821 m++;
00822 }
00823
00824
00825
00826 list<const SMDS_MeshNode*>::iterator itN = myNodesOnCommonV.begin();
00827 for ( ; itN != myNodesOnCommonV.end(); itN++ )
00828 {
00829 const SMDS_MeshNode* node = *itN;
00830 SMDS_ElemIteratorPtr invElemIt = node->GetInverseElementIterator();
00831 while ( invElemIt->more() )
00832 {
00833 const SMDS_MeshElement* elem = invElemIt->next();
00834 SMDS_ElemIteratorPtr itN = elem->nodesIterator();
00835 int nbSame = 0;
00836 while ( itN->more() )
00837 if ( itN->next() == node)
00838 nbSame++;
00839 if (nbSame > 1) {
00840 MESSAGE( "RM bad element " << elem->GetID());
00841 meshDS->RemoveElement( elem );
00842 }
00843 }
00844 }
00845 }