Version: 6.3.1

src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.cxx

Go to the documentation of this file.
00001 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 
00020 //  SMESH SMESH : implementaion of SMESH idl descriptions
00021 // File      : StdMeshers_RadialQuadrangle_1D2D.cxx
00022 // Module    : SMESH
00023 // Created   : Fri Oct 20 11:37:07 2006
00024 // Author    : Edward AGAPOV (eap)
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 //function : StdMeshers_RadialQuadrangle_1D2D
00067 //purpose  : 
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);        // 1 bit per shape type
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 //function : CheckHypothesis
00099 //purpose  : 
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   // check aShape 
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;  // can work with no hypothesis
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(/*isDeletable=*/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*  /*hyp*/)
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 //   bool isEdgeCompatiballyMeshed(const TopoDS_Edge& edge, SMESH_subMesh* faceSubMesh)
00194 //   {
00195 //     if ( SMESH_subMesh* edgeSM = faceSubMesh->GetFather()->GetSubMeshContaining( edge ))
00196 //     {
00197 //       if ( SMESH_subMeshEventListenerData* otherFaceData =
00198 //            edgeSM->GetEventListenerData( TEdgeMarker::getListener() ))
00199 //       {
00200 //         // compare hypothesis aplied to two disk faces sharing radial edges
00201 //         SMESH_Mesh& mesh = *faceSubMesh->GetFather();
00202 //         SMESH_Algo* radialQuadAlgo = mesh.GetGen()->GetAlgo(mesh, faceSubMesh->GetSubShape() );
00203 //         SMESH_subMesh* otherFaceSubMesh = otherFaceData->mySubMeshes.front();
00204 //         list <const SMESHDS_Hypothesis *> hyps1 =
00205 //           radialQuadAlgo->GetUsedHypothesis( mesh, faceSubMesh->GetSubShape());
00206 //         list <const SMESHDS_Hypothesis *> hyps2 =
00207 //           radialQuadAlgo->GetUsedHypothesis( mesh, otherFaceSubMesh->GetSubShape());
00208 //         if( hyps1.empty() && hyps2.empty() )
00209 //           return true; // defaul hyps
00210 //         if ( hyps1.size() != hyps2.size() )
00211 //           return false;
00212 //         return *hyps1.front() == *hyps2.front();
00213 //       }
00214 //     }
00215 //     return false;
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       // find any 1d hyp assigned (there can be a hyp w/o algo)
00350       myUsedHyps = SMESH_Algo::GetUsedHypothesis(aMesh, anEdge, /*ignoreAux=*/true);
00351       Hypothesis_Status aStatus;
00352       if ( !StdMeshers_Regular_1D::CheckHypothesis( aMesh, anEdge, aStatus ))
00353       {
00354         // no valid 1d hyp assigned, use default nb of segments
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     // find any 1d hyp assigned
00374     myUsedHyps = SMESH_Algo::GetUsedHypothesis(aMesh, anEdge, /*ignoreAux=*/true);
00375     Hypothesis_Status aStatus;
00376     if ( !StdMeshers_Regular_1D::CheckHypothesis( aMesh, anEdge, aStatus ))
00377     {
00378       // no valid 1d hyp assigned, use default nb of segments
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 //function : Compute
00424 //purpose  : 
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   // to delete helper at exit from Compute()
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   // points for rotation
00448   TColgp_SequenceOfPnt Points;
00449   // angles for rotation
00450   TColStd_SequenceOfReal Angles;
00451   // Nodes1 and Nodes2 - nodes along radiuses
00452   // CNodes - nodes on circle edge
00453   vector< const SMDS_MeshNode* > Nodes1, Nodes2, CNodes;
00454   SMDS_MeshNode * NC;
00455   // parameters edge nodes on face
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     // one curve must be a half of circle and other curve must be
00528     // a segment of line
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       // not half of circle
00533       return error(COMPERR_BAD_SHAPE);
00534     }
00535     Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast( getCurve( LinEdge1 ));
00536     if( aLine.IsNull() ) {
00537       // other curve not line
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       // check orientation
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       // get UV points for edge
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       // add nodes on edge
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         // parameters on face
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       // create 1D elements on edge
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 // nbe==3 or ( nbe==2 && linEdge is INTERNAL )
00664   {
00665     if (nbe==2 && LinEdge1.Orientation() == TopAbs_INTERNAL )
00666       LinEdge2 = LinEdge1;
00667 
00668     // one curve must be a part of circle and other curves must be
00669     // segments of line
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     // check that both linear edges have same hypotheses
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     // LinEdge1
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       // check orientation
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       // get UV points for edge
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         // parameters on face
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       // create 1D elements on edge
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     // LinEdge2
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       // check orientation
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       // get UV points for edge
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         // parameters on face
00866         gp_Pnt2d P2d( PC.X() + V2d.X()*myLayerPositions[i],
00867                       PC.Y() + V2d.Y()*myLayerPositions[i] );
00868       }
00869       Nodes2[ myLayerPositions.size() ] = NL;
00870       // create 1D elements on edge
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   // orientation
00883   bool IsForward = ( CircEdge.Orientation()==TopAbs_FORWARD );
00884 
00885   // create nodes and mesh elements on face
00886   // find axis of rotation
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   // create elements
00892   int i = 1;
00893   //cout<<"Angles.Length() = "<<Angles.Length()<<"   Points.Length() = "<<Points.Length()<<endl;
00894   //cout<<"Nodes1.size() = "<<Nodes1.size()<<"   Pnts2d1.Length() = "<<Pnts2d1.Length()<<endl;
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     // create nodes
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       // find parameters on face
00911       Pnts2d1.Value(j).Coord( cx, cy );
00912       aTrsf2d.Transforms( cx, cy );
00913       // set node on face
00914       meshDS->SetNodeOnFace( node, faceID, cx, cy );
00915       tmpNodes[j-1] = node;
00916     }
00917     // create faces
00918     tmpNodes[Points.Length()] = CNodes[i];
00919     // quad
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     // tria
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   // create last faces
00942   // quad
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   // tria
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   // First, try to compute positions of layers
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     // No own algo hypotheses assigned, so first try to find any 1D hypothesis.
00988     // We need some edge
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       // find a hyp usable by TNodeDistributor
00996       SMESH_HypoFilter hypKind;
00997       TNodeDistributor::GetDistributor(*mesh)->InitCompatibleHypoFilter(hypKind,/*ignoreAux=*/1);
00998       hyp1D = mesh->GetHypothesis( edge, hypKind, /*fromAncestors=*/true);
00999     }
01000   }
01001   if ( hyp1D ) // try to compute with hyp1D
01002   {
01003     if ( !TNodeDistributor::GetDistributor(*mesh)->Compute( myLayerPositions,p1,p2,*mesh,hyp1D )) {
01004       if ( myDistributionHypo ) { // bad hyp assigned 
01005         return error( TNodeDistributor::GetDistributor(*mesh)->GetComputeError() );
01006       }
01007       else {
01008         // bad hyp found, its Ok, lets try with default nb of segnents
01009       }
01010     }
01011   }
01012   
01013   if ( myLayerPositions.empty() ) // try to use nb of layers
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   // Second, check presence of a mesh built by other algo on linEdge
01027   // and mesh conformity to my hypothesis
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     // nb of present nodes must be different in cases of 1 and 2 straight edges
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; // 2 straight edges
01050     if ( !pointsAreOnVertices )
01051       nbNodes = ( nodeParams.size() - 3 ) / 2; // 1 straight edge
01052 
01053     if ( myLayerPositions.empty() )
01054     {
01055       myLayerPositions.resize( nbNodes );
01056     }
01057     else if ( myDistributionHypo || myNbLayerHypo )
01058     {
01059       // linEdge is computed by other algo. Check if there is a meshed face
01060       // using nodes on linEdge
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         // rebuild them
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 //function : Evaluate
01085 //purpose  : 
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     // C1 must be a circle
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         // main nodes
01132         nb0d = (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
01133         // radial medium nodes
01134         nb0d += (aVec[SMDSEntity_Node]+1) * (myLayerPositions.size()+1);
01135         // other medium nodes
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     // one curve must be a half of circle and other curve must be
01148     // a segment of line
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       // not half of circle
01153       return error(COMPERR_BAD_SHAPE);
01154     }
01155     Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast( getCurve( LinEdge1 ));
01156     if( aLine.IsNull() ) {
01157       // other curve not line
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         // main nodes
01173         nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size();
01174         // radial medium nodes
01175         nb0d += aVec[SMDSEntity_Node] * (myLayerPositions.size()+1);
01176         // other medium nodes
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       // add evaluation for edges
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  // nbe==3 or ( nbe==2 && linEdge is INTERNAL )
01198   {
01199     if (nbe==2 && LinEdge1.Orientation() == TopAbs_INTERNAL )
01200       LinEdge2 = LinEdge1;
01201 
01202     // one curve must be a part of circle and other curves must be
01203     // segments of line
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       // other curve not line
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; // override other 1d hyps
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; // override other 1d hyps
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         // main nodes
01240         nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size();
01241         // radial medium nodes
01242         nb0d += aVec[SMDSEntity_Node] * (myLayerPositions.size()+1);
01243         // other medium nodes
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       // add evaluation for edges
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   // invalid case
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 
Copyright © 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
Copyright © 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS