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 #include "StdMeshers_RadialQuadrangle_1D2D.hxx"
00027
00028 #include "StdMeshers_NumberOfLayers.hxx"
00029 #include "StdMeshers_LayerDistribution.hxx"
00030 #include "StdMeshers_Regular_1D.hxx"
00031 #include "StdMeshers_NumberOfSegments.hxx"
00032
00033 #include "SMDS_MeshNode.hxx"
00034 #include "SMESHDS_SubMesh.hxx"
00035 #include "SMESH_Gen.hxx"
00036 #include "SMESH_HypoFilter.hxx"
00037 #include "SMESH_Mesh.hxx"
00038 #include "SMESH_MesherHelper.hxx"
00039 #include "SMESH_subMesh.hxx"
00040 #include "SMESH_subMeshEventListener.hxx"
00041
00042 #include "utilities.h"
00043
00044 #include <BRepAdaptor_Curve.hxx>
00045 #include <BRepBuilderAPI_MakeEdge.hxx>
00046 #include <BRep_Tool.hxx>
00047 #include <GeomAPI_ProjectPointOnSurf.hxx>
00048 #include <Geom_Circle.hxx>
00049 #include <Geom_Line.hxx>
00050 #include <Geom_TrimmedCurve.hxx>
00051 #include <TColgp_SequenceOfPnt.hxx>
00052 #include <TColgp_SequenceOfPnt2d.hxx>
00053 #include <TopExp.hxx>
00054 #include <TopExp_Explorer.hxx>
00055 #include <TopTools_ListIteratorOfListOfShape.hxx>
00056 #include <TopoDS.hxx>
00057
00058
00059 using namespace std;
00060
00061 #define RETURN_BAD_RESULT(msg) { MESSAGE(")-: Error: " << msg); return false; }
00062 #define gpXYZ(n) gp_XYZ(n->X(),n->Y(),n->Z())
00063
00064
00065
00066
00067
00068
00069
00070 StdMeshers_RadialQuadrangle_1D2D::StdMeshers_RadialQuadrangle_1D2D(int hypId,
00071 int studyId,
00072 SMESH_Gen* gen)
00073 :SMESH_2D_Algo(hypId, studyId, gen)
00074 {
00075 _name = "RadialQuadrangle_1D2D";
00076 _shapeType = (1 << TopAbs_FACE);
00077
00078 _compatibleHypothesis.push_back("LayerDistribution2D");
00079 _compatibleHypothesis.push_back("NumberOfLayers2D");
00080 myNbLayerHypo = 0;
00081 myDistributionHypo = 0;
00082 _requireDescretBoundary = false;
00083 _supportSubmeshes = true;
00084 }
00085
00086
00087
00091
00092
00093 StdMeshers_RadialQuadrangle_1D2D::~StdMeshers_RadialQuadrangle_1D2D()
00094 {}
00095
00096
00097
00098
00099
00100
00101
00102 bool StdMeshers_RadialQuadrangle_1D2D::CheckHypothesis
00103 (SMESH_Mesh& aMesh,
00104 const TopoDS_Shape& aShape,
00105 SMESH_Hypothesis::Hypothesis_Status& aStatus)
00106 {
00107
00108 myNbLayerHypo = 0;
00109 myDistributionHypo = 0;
00110
00111 list <const SMESHDS_Hypothesis * >::const_iterator itl;
00112
00113 const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
00114 if ( hyps.size() == 0 ) {
00115 aStatus = SMESH_Hypothesis::HYP_OK;
00116 return true;
00117 }
00118
00119 if ( hyps.size() > 1 ) {
00120 aStatus = SMESH_Hypothesis::HYP_ALREADY_EXIST;
00121 return false;
00122 }
00123
00124 const SMESHDS_Hypothesis *theHyp = hyps.front();
00125
00126 string hypName = theHyp->GetName();
00127
00128 if (hypName == "NumberOfLayers2D") {
00129 myNbLayerHypo = static_cast<const StdMeshers_NumberOfLayers *>(theHyp);
00130 aStatus = SMESH_Hypothesis::HYP_OK;
00131 return true;
00132 }
00133 if (hypName == "LayerDistribution2D") {
00134 myDistributionHypo = static_cast<const StdMeshers_LayerDistribution *>(theHyp);
00135 aStatus = SMESH_Hypothesis::HYP_OK;
00136 return true;
00137 }
00138 aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
00139 return true;
00140 }
00141
00142 namespace
00143 {
00144
00148 class TEdgeMarker : public SMESH_subMeshEventListener
00149 {
00150 TEdgeMarker(): SMESH_subMeshEventListener(false) {}
00151 public:
00153 static SMESH_subMeshEventListener* getListener()
00154 {
00155 static TEdgeMarker theEdgeMarker;
00156 return &theEdgeMarker;
00157 }
00159 void ProcessEvent(const int event,
00160 const int eventType,
00161 SMESH_subMesh* edgeSubMesh,
00162 EventListenerData* data,
00163 const SMESH_Hypothesis* )
00164 {
00165 if ( data && !data->mySubMeshes.empty() && eventType == SMESH_subMesh::ALGO_EVENT)
00166 {
00167 ASSERT( data->mySubMeshes.front() != edgeSubMesh );
00168 SMESH_subMesh* faceSubMesh = data->mySubMeshes.front();
00169 faceSubMesh->ComputeStateEngine( SMESH_subMesh::CLEAN );
00170 }
00171 }
00172 };
00173
00174
00178 void markEdgeAsComputedByMe(const TopoDS_Edge& edge, SMESH_subMesh* faceSubMesh)
00179 {
00180 if ( SMESH_subMesh* edgeSM = faceSubMesh->GetFather()->GetSubMeshContaining( edge ))
00181 {
00182 if ( !edgeSM->GetEventListenerData( TEdgeMarker::getListener() ))
00183 faceSubMesh->SetEventListener( TEdgeMarker::getListener(),
00184 SMESH_subMeshEventListenerData::MakeData(faceSubMesh),
00185 edgeSM);
00186 }
00187 }
00188
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00222
00223
00224 Handle(Geom_Curve) getCurve(const TopoDS_Edge& edge, double* f=0, double* l=0)
00225 {
00226 Handle(Geom_Curve) C;
00227 if ( !edge.IsNull() )
00228 {
00229 double first = 0., last = 0.;
00230 C = BRep_Tool::Curve(edge, first, last);
00231 if ( !C.IsNull() )
00232 {
00233 Handle(Geom_TrimmedCurve) tc = Handle(Geom_TrimmedCurve)::DownCast(C);
00234 while( !tc.IsNull() ) {
00235 C = tc->BasisCurve();
00236 tc = Handle(Geom_TrimmedCurve)::DownCast(C);
00237 }
00238 if ( f ) *f = first;
00239 if ( l ) *l = last;
00240 }
00241 }
00242 return C;
00243 }
00244
00245
00250
00251
00252 int analyseFace(const TopoDS_Shape& face,
00253 TopoDS_Edge& CircEdge,
00254 TopoDS_Edge& LinEdge1,
00255 TopoDS_Edge& LinEdge2)
00256 {
00257 CircEdge.Nullify(); LinEdge1.Nullify(); LinEdge2.Nullify();
00258 int nbe = 0;
00259
00260 for ( TopExp_Explorer exp( face, TopAbs_EDGE ); exp.More(); exp.Next(), ++nbe )
00261 {
00262 const TopoDS_Edge& E = TopoDS::Edge( exp.Current() );
00263 double f,l;
00264 Handle(Geom_Curve) C = getCurve(E,&f,&l);
00265 if ( !C.IsNull() )
00266 {
00267 if ( C->IsKind( STANDARD_TYPE(Geom_Circle)))
00268 {
00269 if ( CircEdge.IsNull() )
00270 CircEdge = E;
00271 else
00272 return 0;
00273 }
00274 else if ( LinEdge1.IsNull() )
00275 LinEdge1 = E;
00276 else
00277 LinEdge2 = E;
00278 }
00279 }
00280 return nbe;
00281 }
00282
00283
00284
00289
00290
00291
00292 class TNodeDistributor: public StdMeshers_Regular_1D
00293 {
00294 list <const SMESHDS_Hypothesis *> myUsedHyps;
00295 public:
00296
00297 static TNodeDistributor* GetDistributor(SMESH_Mesh& aMesh)
00298 {
00299 const int myID = -1000;
00300 map < int, SMESH_1D_Algo * > & algoMap = aMesh.GetGen()->_map1D_Algo;
00301 map < int, SMESH_1D_Algo * >::iterator id_algo = algoMap.find( myID );
00302 if ( id_algo == algoMap.end() )
00303 return new TNodeDistributor( myID, 0, aMesh.GetGen() );
00304 return static_cast< TNodeDistributor* >( id_algo->second );
00305 }
00306
00308 bool Compute( vector< double > & positions,
00309 gp_Pnt pIn,
00310 gp_Pnt pOut,
00311 SMESH_Mesh& aMesh,
00312 const SMESH_Hypothesis* hyp1d)
00313 {
00314 if ( !hyp1d ) return error( "Invalid LayerDistribution hypothesis");
00315
00316 double len = pIn.Distance( pOut );
00317 if ( len <= DBL_MIN ) return error("Too close points of inner and outer shells");
00318
00319 myUsedHyps.clear();
00320 myUsedHyps.push_back( hyp1d );
00321
00322 TopoDS_Edge edge = BRepBuilderAPI_MakeEdge( pIn, pOut );
00323 SMESH_Hypothesis::Hypothesis_Status aStatus;
00324 if ( !StdMeshers_Regular_1D::CheckHypothesis( aMesh, edge, aStatus ))
00325 return error( "StdMeshers_Regular_1D::CheckHypothesis() failed "
00326 "with LayerDistribution hypothesis");
00327
00328 BRepAdaptor_Curve C3D(edge);
00329 double f = C3D.FirstParameter(), l = C3D.LastParameter();
00330 list< double > params;
00331 if ( !StdMeshers_Regular_1D::computeInternalParameters( aMesh, C3D, len, f, l, params, false ))
00332 return error("StdMeshers_Regular_1D failed to compute layers distribution");
00333
00334 positions.clear();
00335 positions.reserve( params.size() );
00336 for (list<double>::iterator itU = params.begin(); itU != params.end(); itU++)
00337 positions.push_back( *itU / len );
00338 return true;
00339 }
00340
00342 bool ComputeCircularEdge(SMESH_Mesh& aMesh,
00343 const TopoDS_Edge& anEdge)
00344 {
00345 _gen->Compute( aMesh, anEdge);
00346 SMESH_subMesh *sm = aMesh.GetSubMesh(anEdge);
00347 if ( sm->GetComputeState() != SMESH_subMesh::COMPUTE_OK)
00348 {
00349
00350 myUsedHyps = SMESH_Algo::GetUsedHypothesis(aMesh, anEdge, true);
00351 Hypothesis_Status aStatus;
00352 if ( !StdMeshers_Regular_1D::CheckHypothesis( aMesh, anEdge, aStatus ))
00353 {
00354
00355 _hypType = NB_SEGMENTS;
00356 _ivalue[ DISTR_TYPE_IND ] = StdMeshers_NumberOfSegments::DT_Regular;
00357 _ivalue[ NB_SEGMENTS_IND ] = _gen->GetDefaultNbSegments();
00358 }
00359 return StdMeshers_Regular_1D::Compute( aMesh, anEdge );
00360 }
00361 return true;
00362 }
00363
00365 bool EvaluateCircularEdge(SMESH_Mesh& aMesh,
00366 const TopoDS_Edge& anEdge,
00367 MapShapeNbElems& aResMap)
00368 {
00369 _gen->Evaluate( aMesh, anEdge, aResMap );
00370 if ( aResMap.count( aMesh.GetSubMesh( anEdge )))
00371 return true;
00372
00373
00374 myUsedHyps = SMESH_Algo::GetUsedHypothesis(aMesh, anEdge, true);
00375 Hypothesis_Status aStatus;
00376 if ( !StdMeshers_Regular_1D::CheckHypothesis( aMesh, anEdge, aStatus ))
00377 {
00378
00379 _hypType = NB_SEGMENTS;
00380 _ivalue[ DISTR_TYPE_IND ] = StdMeshers_NumberOfSegments::DT_Regular;
00381 _ivalue[ NB_SEGMENTS_IND ] = _gen->GetDefaultNbSegments();
00382 }
00383 return StdMeshers_Regular_1D::Evaluate( aMesh, anEdge, aResMap );
00384 }
00385 protected:
00386
00387 TNodeDistributor( int hypId, int studyId, SMESH_Gen* gen)
00388 : StdMeshers_Regular_1D( hypId, studyId, gen)
00389 {
00390 }
00391
00392 virtual const list <const SMESHDS_Hypothesis *> &
00393 GetUsedHypothesis(SMESH_Mesh &, const TopoDS_Shape &, const bool)
00394 {
00395 return myUsedHyps;
00396 }
00397
00398 };
00399 }
00400
00401
00408
00409
00410 void StdMeshers_RadialQuadrangle_1D2D::SubmeshRestored(SMESH_subMesh* faceSubMesh)
00411 {
00412 if ( !faceSubMesh->IsEmpty() )
00413 {
00414 TopoDS_Edge CircEdge, LinEdge1, LinEdge2;
00415 analyseFace( faceSubMesh->GetSubShape(), CircEdge, LinEdge1, LinEdge2 );
00416 if ( !CircEdge.IsNull() ) markEdgeAsComputedByMe( CircEdge, faceSubMesh );
00417 if ( !LinEdge1.IsNull() ) markEdgeAsComputedByMe( LinEdge1, faceSubMesh );
00418 if ( !LinEdge2.IsNull() ) markEdgeAsComputedByMe( LinEdge2, faceSubMesh );
00419 }
00420 }
00421
00422
00423
00424
00425
00426
00427 bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh& aMesh,
00428 const TopoDS_Shape& aShape)
00429 {
00430 TopExp_Explorer exp;
00431 SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
00432
00433 myHelper = new SMESH_MesherHelper( aMesh );
00434 myHelper->IsQuadraticSubMesh( aShape );
00435
00436 auto_ptr<SMESH_MesherHelper> helperDeleter( myHelper );
00437
00438 TNodeDistributor* algo1d = TNodeDistributor::GetDistributor(aMesh);
00439
00440 TopoDS_Edge CircEdge, LinEdge1, LinEdge2;
00441 int nbe = analyseFace( aShape, CircEdge, LinEdge1, LinEdge2 );
00442 Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
00443 if( nbe>3 || nbe < 1 || aCirc.IsNull() )
00444 return error("The face must be a full circle or a part of circle (i.e. the number of edges is less or equal to 3 and one of them is a circle curve)");
00445
00446 gp_Pnt P0, P1;
00447
00448 TColgp_SequenceOfPnt Points;
00449
00450 TColStd_SequenceOfReal Angles;
00451
00452
00453 vector< const SMDS_MeshNode* > Nodes1, Nodes2, CNodes;
00454 SMDS_MeshNode * NC;
00455
00456 TColgp_SequenceOfPnt2d Pnts2d1;
00457 gp_Pnt2d PC;
00458
00459 int faceID = meshDS->ShapeToIndex(aShape);
00460 TopoDS_Face F = TopoDS::Face(aShape);
00461 Handle(Geom_Surface) S = BRep_Tool::Surface(F);
00462
00463
00464 if(nbe==1)
00465 {
00466 if (!algo1d->ComputeCircularEdge( aMesh, CircEdge ))
00467 return error( algo1d->GetComputeError() );
00468 map< double, const SMDS_MeshNode* > theNodes;
00469 if ( !GetSortedNodesOnEdge(aMesh.GetMeshDS(),CircEdge,true,theNodes))
00470 return error("Circular edge is incorrectly meshed");
00471
00472 CNodes.clear();
00473 map< double, const SMDS_MeshNode* >::iterator itn = theNodes.begin();
00474 const SMDS_MeshNode* NF = (*itn).second;
00475 CNodes.push_back( (*itn).second );
00476 double fang = (*itn).first;
00477 if ( itn != theNodes.end() ) {
00478 itn++;
00479 for(; itn != theNodes.end(); itn++ ) {
00480 CNodes.push_back( (*itn).second );
00481 double ang = (*itn).first - fang;
00482 if( ang>PI ) ang = ang - 2*PI;
00483 if( ang<-PI ) ang = ang + 2*PI;
00484 Angles.Append( ang );
00485 }
00486 }
00487 P1 = gp_Pnt( NF->X(), NF->Y(), NF->Z() );
00488 P0 = aCirc->Location();
00489
00490 if ( !computeLayerPositions(P0,P1))
00491 return false;
00492
00493 exp.Init( CircEdge, TopAbs_VERTEX );
00494 TopoDS_Vertex V1 = TopoDS::Vertex( exp.Current() );
00495 gp_Pnt2d p2dV = BRep_Tool::Parameters( V1, TopoDS::Face(aShape) );
00496
00497 NC = meshDS->AddNode(P0.X(), P0.Y(), P0.Z());
00498 GeomAPI_ProjectPointOnSurf PPS(P0,S);
00499 double U0,V0;
00500 PPS.Parameters(1,U0,V0);
00501 meshDS->SetNodeOnFace(NC, faceID, U0, V0);
00502 PC = gp_Pnt2d(U0,V0);
00503
00504 gp_Vec aVec(P0,P1);
00505 gp_Vec2d aVec2d(PC,p2dV);
00506 Nodes1.resize( myLayerPositions.size()+1 );
00507 Nodes2.resize( myLayerPositions.size()+1 );
00508 int i = 0;
00509 for(; i<myLayerPositions.size(); i++) {
00510 gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
00511 P0.Y() + aVec.Y()*myLayerPositions[i],
00512 P0.Z() + aVec.Z()*myLayerPositions[i] );
00513 Points.Append(P);
00514 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
00515 Nodes1[i] = node;
00516 Nodes2[i] = node;
00517 double U = PC.X() + aVec2d.X()*myLayerPositions[i];
00518 double V = PC.Y() + aVec2d.Y()*myLayerPositions[i];
00519 meshDS->SetNodeOnFace( node, faceID, U, V );
00520 Pnts2d1.Append(gp_Pnt2d(U,V));
00521 }
00522 Nodes1[Nodes1.size()-1] = NF;
00523 Nodes2[Nodes1.size()-1] = NF;
00524 }
00525 else if(nbe==2 && LinEdge1.Orientation() != TopAbs_INTERNAL )
00526 {
00527
00528
00529 double fp, lp;
00530 Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge, &fp, &lp ));
00531 if( fabs(fabs(lp-fp)-PI) > Precision::Confusion() ) {
00532
00533 return error(COMPERR_BAD_SHAPE);
00534 }
00535 Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast( getCurve( LinEdge1 ));
00536 if( aLine.IsNull() ) {
00537
00538 return error(COMPERR_BAD_SHAPE);
00539 }
00540
00541 if ( !algo1d->ComputeCircularEdge( aMesh, CircEdge ))
00542 return error( algo1d->GetComputeError() );
00543 map< double, const SMDS_MeshNode* > theNodes;
00544 if ( !GetSortedNodesOnEdge(aMesh.GetMeshDS(),CircEdge,true,theNodes) )
00545 return error("Circular edge is incorrectly meshed");
00546
00547 map< double, const SMDS_MeshNode* >::iterator itn = theNodes.begin();
00548 CNodes.clear();
00549 CNodes.push_back( itn->second );
00550 double fang = (*itn).first;
00551 itn++;
00552 for(; itn != theNodes.end(); itn++ ) {
00553 CNodes.push_back( (*itn).second );
00554 double ang = (*itn).first - fang;
00555 if( ang>PI ) ang = ang - 2*PI;
00556 if( ang<-PI ) ang = ang + 2*PI;
00557 Angles.Append( ang );
00558 }
00559 const SMDS_MeshNode* NF = theNodes.begin()->second;
00560 const SMDS_MeshNode* NL = theNodes.rbegin()->second;
00561 P1 = gp_Pnt( NF->X(), NF->Y(), NF->Z() );
00562 gp_Pnt P2( NL->X(), NL->Y(), NL->Z() );
00563 P0 = aCirc->Location();
00564
00565 bool linEdgeComputed;
00566 if ( !computeLayerPositions(P0,P1,LinEdge1,&linEdgeComputed))
00567 return false;
00568
00569 if ( linEdgeComputed )
00570 {
00571 if (!GetSortedNodesOnEdge(aMesh.GetMeshDS(),LinEdge1,true,theNodes))
00572 return error("Invalid mesh on a straight edge");
00573
00574 Nodes1.resize( myLayerPositions.size()+1 );
00575 Nodes2.resize( myLayerPositions.size()+1 );
00576 vector< const SMDS_MeshNode* > *pNodes1 = &Nodes1, *pNodes2 = &Nodes2;
00577 bool nodesFromP0ToP1 = ( theNodes.rbegin()->second == NF );
00578 if ( !nodesFromP0ToP1 ) std::swap( pNodes1, pNodes2 );
00579
00580 map< double, const SMDS_MeshNode* >::reverse_iterator ritn = theNodes.rbegin();
00581 itn = theNodes.begin();
00582 for ( int i = Nodes1.size()-1; i > -1; ++itn, ++ritn, --i )
00583 {
00584 (*pNodes1)[i] = ritn->second;
00585 (*pNodes2)[i] = itn->second;
00586 Points.Prepend( gpXYZ( Nodes1[i]));
00587 Pnts2d1.Prepend( myHelper->GetNodeUV( F, Nodes1[i]));
00588 }
00589 NC = const_cast<SMDS_MeshNode*>( itn->second );
00590 Points.Remove( Nodes1.size() );
00591 }
00592 else
00593 {
00594 gp_Vec aVec(P0,P1);
00595 int edgeID = meshDS->ShapeToIndex(LinEdge1);
00596
00597 Handle(Geom_Curve) Crv = BRep_Tool::Curve(LinEdge1,fp,lp);
00598 gp_Pnt Ptmp;
00599 Crv->D0(fp,Ptmp);
00600 bool ori = true;
00601 if( P1.Distance(Ptmp) > Precision::Confusion() )
00602 ori = false;
00603
00604 gp_Pnt2d PF,PL;
00605 BRep_Tool::UVPoints( LinEdge1, TopoDS::Face(aShape), PF, PL );
00606 PC = gp_Pnt2d( (PF.X()+PL.X())/2, (PF.Y()+PL.Y())/2 );
00607 gp_Vec2d V2d;
00608 if(ori) V2d = gp_Vec2d(PC,PF);
00609 else V2d = gp_Vec2d(PC,PL);
00610
00611 double cp = (fp+lp)/2;
00612 double dp2 = (lp-fp)/2;
00613 NC = meshDS->AddNode(P0.X(), P0.Y(), P0.Z());
00614 meshDS->SetNodeOnEdge(NC, edgeID, cp);
00615 Nodes1.resize( myLayerPositions.size()+1 );
00616 Nodes2.resize( myLayerPositions.size()+1 );
00617 int i = 0;
00618 for(; i<myLayerPositions.size(); i++) {
00619 gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
00620 P0.Y() + aVec.Y()*myLayerPositions[i],
00621 P0.Z() + aVec.Z()*myLayerPositions[i] );
00622 Points.Append(P);
00623 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
00624 Nodes1[i] = node;
00625 double param;
00626 if(ori)
00627 param = fp + dp2*(1-myLayerPositions[i]);
00628 else
00629 param = cp + dp2*myLayerPositions[i];
00630 meshDS->SetNodeOnEdge(node, edgeID, param);
00631 P = gp_Pnt( P0.X() - aVec.X()*myLayerPositions[i],
00632 P0.Y() - aVec.Y()*myLayerPositions[i],
00633 P0.Z() - aVec.Z()*myLayerPositions[i] );
00634 node = meshDS->AddNode(P.X(), P.Y(), P.Z());
00635 Nodes2[i] = node;
00636 if(!ori)
00637 param = fp + dp2*(1-myLayerPositions[i]);
00638 else
00639 param = cp + dp2*myLayerPositions[i];
00640 meshDS->SetNodeOnEdge(node, edgeID, param);
00641
00642 gp_Pnt2d P2d( PC.X() + V2d.X()*myLayerPositions[i],
00643 PC.Y() + V2d.Y()*myLayerPositions[i] );
00644 Pnts2d1.Append(P2d);
00645 }
00646 Nodes1[ myLayerPositions.size() ] = NF;
00647 Nodes2[ myLayerPositions.size() ] = NL;
00648
00649 vector< const SMDS_MeshNode* > tmpNodes;
00650 tmpNodes.resize(2*Nodes1.size()+1);
00651 for(i=0; i<Nodes2.size(); i++)
00652 tmpNodes[Nodes2.size()-i-1] = Nodes2[i];
00653 tmpNodes[Nodes2.size()] = NC;
00654 for(i=0; i<Nodes1.size(); i++)
00655 tmpNodes[Nodes2.size()+1+i] = Nodes1[i];
00656 for(i=1; i<tmpNodes.size(); i++) {
00657 SMDS_MeshEdge* ME = myHelper->AddEdge( tmpNodes[i-1], tmpNodes[i] );
00658 if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
00659 }
00660 markEdgeAsComputedByMe( LinEdge1, aMesh.GetSubMesh( F ));
00661 }
00662 }
00663 else
00664 {
00665 if (nbe==2 && LinEdge1.Orientation() == TopAbs_INTERNAL )
00666 LinEdge2 = LinEdge1;
00667
00668
00669
00670 double fp, lp;
00671 Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
00672 Handle(Geom_Line) aLine1 = Handle(Geom_Line)::DownCast( getCurve( LinEdge1 ));
00673 Handle(Geom_Line) aLine2 = Handle(Geom_Line)::DownCast( getCurve( LinEdge2 ));
00674 if( aCirc.IsNull() || aLine1.IsNull() || aLine2.IsNull() )
00675 return error(COMPERR_BAD_SHAPE);
00676
00677 if ( !algo1d->ComputeCircularEdge( aMesh, CircEdge ))
00678 return error( algo1d->GetComputeError() );
00679 map< double, const SMDS_MeshNode* > theNodes;
00680 if ( !GetSortedNodesOnEdge(aMesh.GetMeshDS(),CircEdge,true,theNodes))
00681 return error("Circular edge is incorrectly meshed");
00682
00683 const SMDS_MeshNode* NF = theNodes.begin()->second;
00684 const SMDS_MeshNode* NL = theNodes.rbegin()->second;
00685 CNodes.clear();
00686 CNodes.push_back( NF );
00687 map< double, const SMDS_MeshNode* >::iterator itn = theNodes.begin();
00688 double fang = (*itn).first;
00689 itn++;
00690 for(; itn != theNodes.end(); itn++ ) {
00691 CNodes.push_back( (*itn).second );
00692 double ang = (*itn).first - fang;
00693 if( ang>PI ) ang = ang - 2*PI;
00694 if( ang<-PI ) ang = ang + 2*PI;
00695 Angles.Append( ang );
00696 }
00697 P1 = gp_Pnt( NF->X(), NF->Y(), NF->Z() );
00698 gp_Pnt P2( NL->X(), NL->Y(), NL->Z() );
00699 P0 = aCirc->Location();
00700
00701 bool linEdge1Computed, linEdge2Computed;
00702 if ( !computeLayerPositions(P0,P1,LinEdge1,&linEdge1Computed))
00703 return false;
00704
00705 Nodes1.resize( myLayerPositions.size()+1 );
00706 Nodes2.resize( myLayerPositions.size()+1 );
00707
00708
00709 if ( !computeLayerPositions(P0,P1,LinEdge2, &linEdge2Computed))
00710 return false;
00711 if ( Nodes1.size() != myLayerPositions.size()+1 )
00712 return error("Different hypotheses apply to radial edges");
00713
00714 exp.Init( LinEdge1, TopAbs_VERTEX );
00715 TopoDS_Vertex V1 = TopoDS::Vertex( exp.Current() );
00716 exp.Next();
00717 TopoDS_Vertex V2 = TopoDS::Vertex( exp.Current() );
00718 gp_Pnt PE1 = BRep_Tool::Pnt(V1);
00719 gp_Pnt PE2 = BRep_Tool::Pnt(V2);
00720 if( ( P1.Distance(PE1) > Precision::Confusion() ) &&
00721 ( P1.Distance(PE2) > Precision::Confusion() ) )
00722 {
00723 std::swap( LinEdge1, LinEdge2 );
00724 std::swap( linEdge1Computed, linEdge2Computed );
00725 }
00726 TopoDS_Vertex VC = V2;
00727 if( ( P1.Distance(PE1) > Precision::Confusion() ) &&
00728 ( P2.Distance(PE1) > Precision::Confusion() ) )
00729 VC = V1;
00730 int vertID = meshDS->ShapeToIndex(VC);
00731
00732
00733 if ( linEdge1Computed )
00734 {
00735 if (!GetSortedNodesOnEdge(aMesh.GetMeshDS(),LinEdge1,true,theNodes))
00736 return error("Invalid mesh on a straight edge");
00737
00738 bool nodesFromP0ToP1 = ( theNodes.rbegin()->second == NF );
00739 NC = const_cast<SMDS_MeshNode*>
00740 ( nodesFromP0ToP1 ? theNodes.begin()->second : theNodes.rbegin()->second );
00741 int i = 0, ir = Nodes1.size()-1;
00742 int * pi = nodesFromP0ToP1 ? &i : &ir;
00743 itn = theNodes.begin();
00744 if ( nodesFromP0ToP1 ) ++itn;
00745 for ( ; i < Nodes1.size(); ++i, --ir, ++itn )
00746 {
00747 Nodes1[*pi] = itn->second;
00748 }
00749 for ( i = 0; i < Nodes1.size()-1; ++i )
00750 {
00751 Points.Append( gpXYZ( Nodes1[i]));
00752 Pnts2d1.Append( myHelper->GetNodeUV( F, Nodes1[i]));
00753 }
00754 }
00755 else
00756 {
00757 int edgeID = meshDS->ShapeToIndex(LinEdge1);
00758 gp_Vec aVec(P0,P1);
00759
00760 Handle(Geom_Curve) Crv = BRep_Tool::Curve(LinEdge1,fp,lp);
00761 gp_Pnt Ptmp = Crv->Value(fp);
00762 bool ori = false;
00763 if( P1.Distance(Ptmp) > Precision::Confusion() )
00764 ori = true;
00765
00766 gp_Pnt2d PF,PL;
00767 BRep_Tool::UVPoints( LinEdge1, TopoDS::Face(aShape), PF, PL );
00768 gp_Vec2d V2d;
00769 if(ori) {
00770 V2d = gp_Vec2d(PF,PL);
00771 PC = PF;
00772 }
00773 else {
00774 V2d = gp_Vec2d(PL,PF);
00775 PC = PL;
00776 }
00777 NC = const_cast<SMDS_MeshNode*>( VertexNode( VC, meshDS ));
00778 if ( !NC )
00779 {
00780 NC = meshDS->AddNode(P0.X(), P0.Y(), P0.Z());
00781 meshDS->SetNodeOnVertex(NC, vertID);
00782 }
00783 double dp = lp-fp;
00784 int i = 0;
00785 for(; i<myLayerPositions.size(); i++) {
00786 gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
00787 P0.Y() + aVec.Y()*myLayerPositions[i],
00788 P0.Z() + aVec.Z()*myLayerPositions[i] );
00789 Points.Append(P);
00790 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
00791 Nodes1[i] = node;
00792 double param;
00793 if(!ori)
00794 param = fp + dp*(1-myLayerPositions[i]);
00795 else
00796 param = fp + dp*myLayerPositions[i];
00797 meshDS->SetNodeOnEdge(node, edgeID, param);
00798
00799 gp_Pnt2d P2d( PC.X() + V2d.X()*myLayerPositions[i],
00800 PC.Y() + V2d.Y()*myLayerPositions[i] );
00801 Pnts2d1.Append(P2d);
00802 }
00803 Nodes1[ myLayerPositions.size() ] = NF;
00804
00805 SMDS_MeshEdge* ME = myHelper->AddEdge( NC, Nodes1[0] );
00806 if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
00807 for(i=1; i<Nodes1.size(); i++) {
00808 ME = myHelper->AddEdge( Nodes1[i-1], Nodes1[i] );
00809 if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
00810 }
00811 if (nbe==2 && LinEdge1.Orientation() == TopAbs_INTERNAL )
00812 Nodes2 = Nodes1;
00813 }
00814 markEdgeAsComputedByMe( LinEdge1, aMesh.GetSubMesh( F ));
00815
00816
00817 if ( linEdge2Computed )
00818 {
00819 if (!GetSortedNodesOnEdge(aMesh.GetMeshDS(),LinEdge2,true,theNodes))
00820 return error("Invalid mesh on a straight edge");
00821
00822 bool nodesFromP0ToP2 = ( theNodes.rbegin()->second == NL );
00823 int i = 0, ir = Nodes1.size()-1;
00824 int * pi = nodesFromP0ToP2 ? &i : &ir;
00825 itn = theNodes.begin();
00826 if ( nodesFromP0ToP2 ) ++itn;
00827 for ( ; i < Nodes2.size(); ++i, --ir, ++itn )
00828 Nodes2[*pi] = itn->second;
00829 }
00830 else
00831 {
00832 int edgeID = meshDS->ShapeToIndex(LinEdge2);
00833 gp_Vec aVec = gp_Vec(P0,P2);
00834
00835 Handle(Geom_Curve) Crv = BRep_Tool::Curve(LinEdge2,fp,lp);
00836 gp_Pnt Ptmp = Crv->Value(fp);
00837 bool ori = false;
00838 if( P2.Distance(Ptmp) > Precision::Confusion() )
00839 ori = true;
00840
00841 gp_Pnt2d PF,PL;
00842 BRep_Tool::UVPoints( LinEdge2, TopoDS::Face(aShape), PF, PL );
00843 gp_Vec2d V2d;
00844 if(ori) {
00845 V2d = gp_Vec2d(PF,PL);
00846 PC = PF;
00847 }
00848 else {
00849 V2d = gp_Vec2d(PL,PF);
00850 PC = PL;
00851 }
00852 double dp = lp-fp;
00853 for(int i=0; i<myLayerPositions.size(); i++) {
00854 gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
00855 P0.Y() + aVec.Y()*myLayerPositions[i],
00856 P0.Z() + aVec.Z()*myLayerPositions[i] );
00857 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
00858 Nodes2[i] = node;
00859 double param;
00860 if(!ori)
00861 param = fp + dp*(1-myLayerPositions[i]);
00862 else
00863 param = fp + dp*myLayerPositions[i];
00864 meshDS->SetNodeOnEdge(node, edgeID, param);
00865
00866 gp_Pnt2d P2d( PC.X() + V2d.X()*myLayerPositions[i],
00867 PC.Y() + V2d.Y()*myLayerPositions[i] );
00868 }
00869 Nodes2[ myLayerPositions.size() ] = NL;
00870
00871 SMDS_MeshEdge* ME = myHelper->AddEdge( NC, Nodes2[0] );
00872 if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
00873 for(int i=1; i<Nodes2.size(); i++) {
00874 ME = myHelper->AddEdge( Nodes2[i-1], Nodes2[i] );
00875 if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
00876 }
00877 }
00878 markEdgeAsComputedByMe( LinEdge2, aMesh.GetSubMesh( F ));
00879 }
00880 markEdgeAsComputedByMe( CircEdge, aMesh.GetSubMesh( F ));
00881
00882
00883 bool IsForward = ( CircEdge.Orientation()==TopAbs_FORWARD );
00884
00885
00886
00887 gp_Pnt P2 = gp_Pnt( CNodes[1]->X(), CNodes[1]->Y(), CNodes[1]->Z() );
00888 gp_Vec Vec1(P0,P1);
00889 gp_Vec Vec2(P0,P2);
00890 gp_Vec Axis = Vec1.Crossed(Vec2);
00891
00892 int i = 1;
00893
00894
00895 for(; i<Angles.Length(); i++) {
00896 vector< const SMDS_MeshNode* > tmpNodes;
00897 tmpNodes.reserve(Nodes1.size());
00898 gp_Trsf aTrsf;
00899 gp_Ax1 theAxis(P0,gp_Dir(Axis));
00900 aTrsf.SetRotation( theAxis, Angles.Value(i) );
00901 gp_Trsf2d aTrsf2d;
00902 aTrsf2d.SetRotation( PC, Angles.Value(i) );
00903
00904 int j = 1;
00905 for(; j<=Points.Length(); j++) {
00906 double cx,cy,cz;
00907 Points.Value(j).Coord( cx, cy, cz );
00908 aTrsf.Transforms( cx, cy, cz );
00909 SMDS_MeshNode* node = myHelper->AddNode( cx, cy, cz );
00910
00911 Pnts2d1.Value(j).Coord( cx, cy );
00912 aTrsf2d.Transforms( cx, cy );
00913
00914 meshDS->SetNodeOnFace( node, faceID, cx, cy );
00915 tmpNodes[j-1] = node;
00916 }
00917
00918 tmpNodes[Points.Length()] = CNodes[i];
00919
00920 for(j=0; j<Nodes1.size()-1; j++) {
00921 SMDS_MeshFace* MF;
00922 if(IsForward)
00923 MF = myHelper->AddFace( tmpNodes[j], Nodes1[j],
00924 Nodes1[j+1], tmpNodes[j+1] );
00925 else
00926 MF = myHelper->AddFace( tmpNodes[j], tmpNodes[j+1],
00927 Nodes1[j+1], Nodes1[j] );
00928 if(MF) meshDS->SetMeshElementOnShape(MF, faceID);
00929 }
00930
00931 SMDS_MeshFace* MF;
00932 if(IsForward)
00933 MF = myHelper->AddFace( NC, Nodes1[0], tmpNodes[0] );
00934 else
00935 MF = myHelper->AddFace( NC, tmpNodes[0], Nodes1[0] );
00936 if(MF) meshDS->SetMeshElementOnShape(MF, faceID);
00937 for(j=0; j<Nodes1.size(); j++) {
00938 Nodes1[j] = tmpNodes[j];
00939 }
00940 }
00941
00942
00943 for(i=0; i<Nodes1.size()-1; i++) {
00944 SMDS_MeshFace* MF;
00945 if(IsForward)
00946 MF = myHelper->AddFace( Nodes2[i], Nodes1[i],
00947 Nodes1[i+1], Nodes2[i+1] );
00948 else
00949 MF = myHelper->AddFace( Nodes2[i], Nodes2[i+1],
00950 Nodes1[i+1], Nodes1[i] );
00951 if(MF) meshDS->SetMeshElementOnShape(MF, faceID);
00952 }
00953
00954 SMDS_MeshFace* MF;
00955 if(IsForward)
00956 MF = myHelper->AddFace( NC, Nodes1[0], Nodes2[0] );
00957 else
00958 MF = myHelper->AddFace( NC, Nodes2[0], Nodes1[0] );
00959 if(MF) meshDS->SetMeshElementOnShape(MF, faceID);
00960
00961 return true;
00962 }
00963
00964
00969
00970
00971 bool StdMeshers_RadialQuadrangle_1D2D::computeLayerPositions(const gp_Pnt& p1,
00972 const gp_Pnt& p2,
00973 const TopoDS_Edge& linEdge,
00974 bool* linEdgeComputed)
00975 {
00976
00977
00978 myLayerPositions.clear();
00979
00980 SMESH_Mesh * mesh = myHelper->GetMesh();
00981
00982 const SMESH_Hypothesis* hyp1D = myDistributionHypo ? myDistributionHypo->GetLayerDistribution() : 0;
00983 int nbLayers = myNbLayerHypo ? myNbLayerHypo->GetNumberOfLayers() : 0;
00984
00985 if ( !hyp1D && !nbLayers )
00986 {
00987
00988
00989 TopoDS_Shape edge = linEdge;
00990 if ( edge.IsNull() && !myHelper->GetSubShape().IsNull())
00991 for ( TopExp_Explorer e(myHelper->GetSubShape(), TopAbs_EDGE); e.More(); e.Next())
00992 edge = e.Current();
00993 if ( !edge.IsNull() )
00994 {
00995
00996 SMESH_HypoFilter hypKind;
00997 TNodeDistributor::GetDistributor(*mesh)->InitCompatibleHypoFilter(hypKind,1);
00998 hyp1D = mesh->GetHypothesis( edge, hypKind, true);
00999 }
01000 }
01001 if ( hyp1D )
01002 {
01003 if ( !TNodeDistributor::GetDistributor(*mesh)->Compute( myLayerPositions,p1,p2,*mesh,hyp1D )) {
01004 if ( myDistributionHypo ) {
01005 return error( TNodeDistributor::GetDistributor(*mesh)->GetComputeError() );
01006 }
01007 else {
01008
01009 }
01010 }
01011 }
01012
01013 if ( myLayerPositions.empty() )
01014 {
01015 if ( !nbLayers )
01016 nbLayers = _gen->GetDefaultNbSegments();
01017
01018 if ( nbLayers )
01019 {
01020 myLayerPositions.resize( nbLayers - 1 );
01021 for ( int z = 1; z < nbLayers; ++z )
01022 myLayerPositions[ z - 1 ] = double( z )/ double( nbLayers );
01023 }
01024 }
01025
01026
01027
01028
01029 bool meshComputed = (!linEdge.IsNull() && !mesh->GetSubMesh(linEdge)->IsEmpty() );
01030 if ( linEdgeComputed ) *linEdgeComputed = meshComputed;
01031
01032 if ( meshComputed )
01033 {
01034 vector< double > nodeParams;
01035 GetNodeParamOnEdge( mesh->GetMeshDS(), linEdge, nodeParams );
01036
01037
01038
01039 TopoDS_Vertex VV[2];
01040 TopExp::Vertices( linEdge, VV[0], VV[1]);
01041 const gp_Pnt* points[] = { &p1, &p2 };
01042 gp_Pnt vPoints[] = { BRep_Tool::Pnt(VV[0]), BRep_Tool::Pnt(VV[1]) };
01043 const double tol[] = { BRep_Tool::Tolerance(VV[0]), BRep_Tool::Tolerance(VV[1]) };
01044 bool pointsAreOnVertices = true;
01045 for ( int iP = 0; iP < 2 && pointsAreOnVertices; ++iP )
01046 pointsAreOnVertices = ( points[iP]->Distance( vPoints[0] ) < tol[0] ||
01047 points[iP]->Distance( vPoints[1] ) < tol[1] );
01048
01049 int nbNodes = nodeParams.size() - 2;
01050 if ( !pointsAreOnVertices )
01051 nbNodes = ( nodeParams.size() - 3 ) / 2;
01052
01053 if ( myLayerPositions.empty() )
01054 {
01055 myLayerPositions.resize( nbNodes );
01056 }
01057 else if ( myDistributionHypo || myNbLayerHypo )
01058 {
01059
01060
01061 bool nodesAreUsed = false;
01062 TopTools_ListIteratorOfListOfShape ancestIt = mesh->GetAncestors( linEdge );
01063 for ( ; ancestIt.More() && !nodesAreUsed; ancestIt.Next() )
01064 if ( ancestIt.Value().ShapeType() == TopAbs_FACE )
01065 nodesAreUsed = (!mesh->GetSubMesh( ancestIt.Value() )->IsEmpty());
01066 if ( !nodesAreUsed ) {
01067
01068 mesh->GetSubMesh( linEdge )->ComputeStateEngine( SMESH_subMesh::CLEAN );
01069 if ( linEdgeComputed ) *linEdgeComputed = false;
01070 }
01071 else {
01072
01073 if ( myLayerPositions.size() != nbNodes )
01074 return error("Radial edge is meshed by other algorithm");
01075 }
01076 }
01077 }
01078
01079 return !myLayerPositions.empty();
01080 }
01081
01082
01083
01084
01085
01086
01087
01088 bool StdMeshers_RadialQuadrangle_1D2D::Evaluate(SMESH_Mesh& aMesh,
01089 const TopoDS_Shape& aShape,
01090 MapShapeNbElems& aResMap)
01091 {
01092 if( aShape.ShapeType() != TopAbs_FACE ) {
01093 return false;
01094 }
01095 SMESH_subMesh * sm = aMesh.GetSubMesh(aShape);
01096 if( aResMap.count(sm) )
01097 return false;
01098
01099 vector<int>& aResVec =
01100 aResMap.insert( make_pair(sm, vector<int>(SMDSEntity_Last,0))).first->second;
01101
01102 myHelper = new SMESH_MesherHelper( aMesh );
01103 myHelper->SetSubShape( aShape );
01104 auto_ptr<SMESH_MesherHelper> helperDeleter( myHelper );
01105
01106 TNodeDistributor* algo1d = TNodeDistributor::GetDistributor(aMesh);
01107
01108 TopoDS_Edge CircEdge, LinEdge1, LinEdge2;
01109 int nbe = analyseFace( aShape, CircEdge, LinEdge1, LinEdge2 );
01110 if( nbe>3 || nbe < 1 || CircEdge.IsNull() )
01111 return false;
01112
01113 Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
01114 if( aCirc.IsNull() )
01115 return error(COMPERR_BAD_SHAPE);
01116
01117 gp_Pnt P0 = aCirc->Location();
01118 gp_Pnt P1 = aCirc->Value(0.);
01119 computeLayerPositions( P0, P1, LinEdge1 );
01120
01121 int nb0d=0, nb2d_tria=0, nb2d_quad=0;
01122 bool isQuadratic = false, ok = true;
01123 if(nbe==1)
01124 {
01125
01126 ok = algo1d->EvaluateCircularEdge( aMesh, CircEdge, aResMap );
01127 if(ok) {
01128 const vector<int>& aVec = aResMap[aMesh.GetSubMesh(CircEdge)];
01129 isQuadratic = aVec[SMDSEntity_Quad_Edge]>aVec[SMDSEntity_Edge];
01130 if(isQuadratic) {
01131
01132 nb0d = (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
01133
01134 nb0d += (aVec[SMDSEntity_Node]+1) * (myLayerPositions.size()+1);
01135
01136 nb0d += (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
01137 }
01138 else {
01139 nb0d = (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
01140 }
01141 nb2d_tria = aVec[SMDSEntity_Node] + 1;
01142 nb2d_quad = nb0d;
01143 }
01144 }
01145 else if(nbe==2 && LinEdge1.Orientation() != TopAbs_INTERNAL)
01146 {
01147
01148
01149 double fp, lp;
01150 Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge, &fp, &lp ));
01151 if( fabs(fabs(lp-fp)-PI) > Precision::Confusion() ) {
01152
01153 return error(COMPERR_BAD_SHAPE);
01154 }
01155 Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast( getCurve( LinEdge1 ));
01156 if( aLine.IsNull() ) {
01157
01158 return error(COMPERR_BAD_SHAPE);
01159 }
01160 ok = !aResMap.count( aMesh.GetSubMesh(LinEdge1) );
01161 if ( !ok ) {
01162 const vector<int>& aVec = aResMap[ aMesh.GetSubMesh(LinEdge1) ];
01163 ok = ( aVec[SMDSEntity_Node] == myLayerPositions.size() );
01164 }
01165 if(ok) {
01166 ok = algo1d->EvaluateCircularEdge( aMesh, CircEdge, aResMap );
01167 }
01168 if(ok) {
01169 const vector<int>& aVec = aResMap[ aMesh.GetSubMesh(CircEdge) ];
01170 isQuadratic = aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge];
01171 if(isQuadratic) {
01172
01173 nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size();
01174
01175 nb0d += aVec[SMDSEntity_Node] * (myLayerPositions.size()+1);
01176
01177 nb0d += (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
01178 }
01179 else {
01180 nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size();
01181 }
01182 nb2d_tria = aVec[SMDSEntity_Node] + 1;
01183 nb2d_quad = nb2d_tria * myLayerPositions.size();
01184
01185 vector<int> aResVec(SMDSEntity_Last,0);
01186 if(isQuadratic) {
01187 aResVec[SMDSEntity_Node] = 4*myLayerPositions.size() + 3;
01188 aResVec[SMDSEntity_Quad_Edge] = 2*myLayerPositions.size() + 2;
01189 }
01190 else {
01191 aResVec[SMDSEntity_Node] = 2*myLayerPositions.size() + 1;
01192 aResVec[SMDSEntity_Edge] = 2*myLayerPositions.size() + 2;
01193 }
01194 aResMap[ aMesh.GetSubMesh(LinEdge1) ] = aResVec;
01195 }
01196 }
01197 else
01198 {
01199 if (nbe==2 && LinEdge1.Orientation() == TopAbs_INTERNAL )
01200 LinEdge2 = LinEdge1;
01201
01202
01203
01204 Handle(Geom_Line) aLine1 = Handle(Geom_Line)::DownCast( getCurve( LinEdge1 ));
01205 Handle(Geom_Line) aLine2 = Handle(Geom_Line)::DownCast( getCurve( LinEdge2 ));
01206 if( aLine1.IsNull() || aLine2.IsNull() ) {
01207
01208 return error(COMPERR_BAD_SHAPE);
01209 }
01210 int nbLayers = myLayerPositions.size();
01211 computeLayerPositions( P0, P1, LinEdge2 );
01212 if ( nbLayers != myLayerPositions.size() )
01213 return error("Different hypotheses apply to radial edges");
01214
01215 bool ok = !aResMap.count( aMesh.GetSubMesh(LinEdge1));
01216 if ( !ok ) {
01217 if ( myDistributionHypo || myNbLayerHypo )
01218 ok = true;
01219 else {
01220 const vector<int>& aVec = aResMap[ aMesh.GetSubMesh(LinEdge1) ];
01221 ok = ( aVec[SMDSEntity_Node] == myLayerPositions.size() );
01222 }
01223 }
01224 if( ok && aResMap.count( aMesh.GetSubMesh(LinEdge2) )) {
01225 if ( myDistributionHypo || myNbLayerHypo )
01226 ok = true;
01227 else {
01228 const vector<int>& aVec = aResMap[ aMesh.GetSubMesh(LinEdge2) ];
01229 ok = ( aVec[SMDSEntity_Node] == myLayerPositions.size() );
01230 }
01231 }
01232 if(ok) {
01233 ok = algo1d->EvaluateCircularEdge( aMesh, CircEdge, aResMap );
01234 }
01235 if(ok) {
01236 const vector<int>& aVec = aResMap[ aMesh.GetSubMesh(CircEdge) ];
01237 isQuadratic = aVec[SMDSEntity_Quad_Edge]>aVec[SMDSEntity_Edge];
01238 if(isQuadratic) {
01239
01240 nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size();
01241
01242 nb0d += aVec[SMDSEntity_Node] * (myLayerPositions.size()+1);
01243
01244 nb0d += (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
01245 }
01246 else {
01247 nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size();
01248 }
01249 nb2d_tria = aVec[SMDSEntity_Node] + 1;
01250 nb2d_quad = nb2d_tria * myLayerPositions.size();
01251
01252 vector<int> aResVec(SMDSEntity_Last, 0);
01253 if(isQuadratic) {
01254 aResVec[SMDSEntity_Node] = 2*myLayerPositions.size() + 1;
01255 aResVec[SMDSEntity_Quad_Edge] = myLayerPositions.size() + 1;
01256 }
01257 else {
01258 aResVec[SMDSEntity_Node] = myLayerPositions.size();
01259 aResVec[SMDSEntity_Edge] = myLayerPositions.size() + 1;
01260 }
01261 sm = aMesh.GetSubMesh(LinEdge1);
01262 aResMap[sm] = aResVec;
01263 sm = aMesh.GetSubMesh(LinEdge2);
01264 aResMap[sm] = aResVec;
01265 }
01266 }
01267
01268 if(nb0d>0) {
01269 aResVec[0] = nb0d;
01270 if(isQuadratic) {
01271 aResVec[SMDSEntity_Quad_Triangle] = nb2d_tria;
01272 aResVec[SMDSEntity_Quad_Quadrangle] = nb2d_quad;
01273 }
01274 else {
01275 aResVec[SMDSEntity_Triangle] = nb2d_tria;
01276 aResVec[SMDSEntity_Quadrangle] = nb2d_quad;
01277 }
01278 return true;
01279 }
01280
01281
01282 sm = aMesh.GetSubMesh(aShape);
01283 SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
01284 smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,
01285 "Submesh can not be evaluated",this));
01286 return false;
01287
01288 }
01289