Back to index

salome-smesh  6.5.0
StdMeshers_Regular_1D.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 //  SMESH SMESH : implementaion of SMESH idl descriptions
00024 //  File   : StdMeshers_Regular_1D.cxx
00025 //           Moved here from SMESH_Regular_1D.cxx
00026 //  Author : Paul RASCLE, EDF
00027 //  Module : SMESH
00028 //
00029 #include "StdMeshers_Regular_1D.hxx"
00030 #include "StdMeshers_Distribution.hxx"
00031 
00032 #include "StdMeshers_Arithmetic1D.hxx"
00033 #include "StdMeshers_AutomaticLength.hxx"
00034 #include "StdMeshers_Deflection1D.hxx"
00035 #include "StdMeshers_LocalLength.hxx"
00036 #include "StdMeshers_MaxLength.hxx"
00037 #include "StdMeshers_NumberOfSegments.hxx"
00038 #include "StdMeshers_Propagation.hxx"
00039 #include "StdMeshers_SegmentLengthAroundVertex.hxx"
00040 #include "StdMeshers_StartEndLength.hxx"
00041 
00042 #include "SMESH_Gen.hxx"
00043 #include "SMESH_Mesh.hxx"
00044 #include "SMESH_HypoFilter.hxx"
00045 #include "SMESH_subMesh.hxx"
00046 #include "SMESH_subMeshEventListener.hxx"
00047 #include "SMESH_Comment.hxx"
00048 
00049 #include "SMDS_MeshElement.hxx"
00050 #include "SMDS_MeshNode.hxx"
00051 
00052 #include "Utils_SALOME_Exception.hxx"
00053 #include "utilities.h"
00054 
00055 #include <BRepAdaptor_Curve.hxx>
00056 #include <BRep_Tool.hxx>
00057 #include <GCPnts_AbscissaPoint.hxx>
00058 #include <GCPnts_UniformAbscissa.hxx>
00059 #include <GCPnts_UniformDeflection.hxx>
00060 #include <Precision.hxx>
00061 #include <TopExp.hxx>
00062 #include <TopExp_Explorer.hxx>
00063 #include <TopoDS.hxx>
00064 #include <TopoDS_Edge.hxx>
00065 
00066 #include <string>
00067 #include <limits>
00068 
00069 using namespace std;
00070 
00071 //=============================================================================
00075 //=============================================================================
00076 
00077 StdMeshers_Regular_1D::StdMeshers_Regular_1D(int hypId, int studyId,
00078         SMESH_Gen * gen):SMESH_1D_Algo(hypId, studyId, gen)
00079 {
00080         MESSAGE("StdMeshers_Regular_1D::StdMeshers_Regular_1D");
00081         _name = "Regular_1D";
00082         _shapeType = (1 << TopAbs_EDGE);
00083         _fpHyp = 0;
00084 
00085         _compatibleHypothesis.push_back("LocalLength");
00086         _compatibleHypothesis.push_back("MaxLength");
00087         _compatibleHypothesis.push_back("NumberOfSegments");
00088         _compatibleHypothesis.push_back("StartEndLength");
00089         _compatibleHypothesis.push_back("Deflection1D");
00090         _compatibleHypothesis.push_back("Arithmetic1D");
00091         _compatibleHypothesis.push_back("FixedPoints1D");
00092         _compatibleHypothesis.push_back("AutomaticLength");
00093 
00094         _compatibleHypothesis.push_back("QuadraticMesh"); // auxiliary !!!
00095         _compatibleHypothesis.push_back("Propagation"); // auxiliary !!!
00096 }
00097 
00098 //=============================================================================
00102 //=============================================================================
00103 
00104 StdMeshers_Regular_1D::~StdMeshers_Regular_1D()
00105 {
00106 }
00107 
00108 //=============================================================================
00112 //=============================================================================
00113 
00114 bool StdMeshers_Regular_1D::CheckHypothesis
00115                          (SMESH_Mesh&                          aMesh,
00116                           const TopoDS_Shape&                  aShape,
00117                           SMESH_Hypothesis::Hypothesis_Status& aStatus)
00118 {
00119   _hypType = NONE;
00120   _quadraticMesh = false;
00121 
00122   const list <const SMESHDS_Hypothesis * > & hyps =
00123     GetUsedHypothesis(aMesh, aShape, /*ignoreAuxiliaryHyps=*/false);
00124 
00125   // find non-auxiliary hypothesis
00126   const SMESHDS_Hypothesis *theHyp = 0;
00127   list <const SMESHDS_Hypothesis * >::const_iterator h = hyps.begin();
00128   for ( ; h != hyps.end(); ++h ) {
00129     if ( static_cast<const SMESH_Hypothesis*>(*h)->IsAuxiliary() ) {
00130       if ( strcmp( "QuadraticMesh", (*h)->GetName() ) == 0 )
00131         _quadraticMesh = true;
00132     }
00133     else {
00134       if ( !theHyp )
00135         theHyp = *h; // use only the first non-auxiliary hypothesis
00136     }
00137   }
00138 
00139   if ( !theHyp )
00140   {
00141     aStatus = SMESH_Hypothesis::HYP_MISSING;
00142     return false;  // can't work without a hypothesis
00143   }
00144 
00145   string hypName = theHyp->GetName();
00146 
00147   if (hypName == "LocalLength")
00148   {
00149     const StdMeshers_LocalLength * hyp =
00150       dynamic_cast <const StdMeshers_LocalLength * >(theHyp);
00151     ASSERT(hyp);
00152     _value[ BEG_LENGTH_IND ] = hyp->GetLength();
00153     _value[ PRECISION_IND ] = hyp->GetPrecision();
00154     ASSERT( _value[ BEG_LENGTH_IND ] > 0 );
00155     _hypType = LOCAL_LENGTH;
00156     aStatus = SMESH_Hypothesis::HYP_OK;
00157   }
00158 
00159   else if (hypName == "MaxLength")
00160   {
00161     const StdMeshers_MaxLength * hyp =
00162       dynamic_cast <const StdMeshers_MaxLength * >(theHyp);
00163     ASSERT(hyp);
00164     _value[ BEG_LENGTH_IND ] = hyp->GetLength();
00165     if ( hyp->GetUsePreestimatedLength() ) {
00166       if ( int nbSeg = aMesh.GetGen()->GetBoundaryBoxSegmentation() )
00167         _value[ BEG_LENGTH_IND ] = aMesh.GetShapeDiagonalSize() / nbSeg;
00168     }
00169     ASSERT( _value[ BEG_LENGTH_IND ] > 0 );
00170     _hypType = MAX_LENGTH;
00171     aStatus = SMESH_Hypothesis::HYP_OK;
00172   }
00173 
00174   else if (hypName == "NumberOfSegments")
00175   {
00176     const StdMeshers_NumberOfSegments * hyp =
00177       dynamic_cast <const StdMeshers_NumberOfSegments * >(theHyp);
00178     ASSERT(hyp);
00179     _ivalue[ NB_SEGMENTS_IND  ] = hyp->GetNumberOfSegments();
00180     ASSERT( _ivalue[ NB_SEGMENTS_IND ] > 0 );
00181     _ivalue[ DISTR_TYPE_IND ] = (int) hyp->GetDistrType();
00182     switch (_ivalue[ DISTR_TYPE_IND ])
00183     {
00184     case StdMeshers_NumberOfSegments::DT_Scale:
00185       _value[ SCALE_FACTOR_IND ] = hyp->GetScaleFactor();
00186       _revEdgesIDs = hyp->GetReversedEdges();
00187       break;
00188     case StdMeshers_NumberOfSegments::DT_TabFunc:
00189       _vvalue[ TAB_FUNC_IND ] = hyp->GetTableFunction();
00190       _revEdgesIDs = hyp->GetReversedEdges();
00191       break;
00192     case StdMeshers_NumberOfSegments::DT_ExprFunc:
00193       _svalue[ EXPR_FUNC_IND ] = hyp->GetExpressionFunction();
00194       _revEdgesIDs = hyp->GetReversedEdges();
00195       break;
00196     case StdMeshers_NumberOfSegments::DT_Regular:
00197       break;
00198     default:
00199       ASSERT(0);
00200       break;
00201     }
00202     if (_ivalue[ DISTR_TYPE_IND ] == StdMeshers_NumberOfSegments::DT_TabFunc ||
00203         _ivalue[ DISTR_TYPE_IND ] == StdMeshers_NumberOfSegments::DT_ExprFunc)
00204         _ivalue[ CONV_MODE_IND ] = hyp->ConversionMode();
00205     _hypType = NB_SEGMENTS;
00206     aStatus = SMESH_Hypothesis::HYP_OK;
00207   }
00208 
00209   else if (hypName == "Arithmetic1D")
00210   {
00211     const StdMeshers_Arithmetic1D * hyp =
00212       dynamic_cast <const StdMeshers_Arithmetic1D * >(theHyp);
00213     ASSERT(hyp);
00214     _value[ BEG_LENGTH_IND ] = hyp->GetLength( true );
00215     _value[ END_LENGTH_IND ] = hyp->GetLength( false );
00216     ASSERT( _value[ BEG_LENGTH_IND ] > 0 && _value[ END_LENGTH_IND ] > 0 );
00217     _hypType = ARITHMETIC_1D;
00218 
00219     _revEdgesIDs = hyp->GetReversedEdges();
00220 
00221     aStatus = SMESH_Hypothesis::HYP_OK;
00222   }
00223 
00224   else if (hypName == "FixedPoints1D") {
00225     _fpHyp = dynamic_cast <const StdMeshers_FixedPoints1D*>(theHyp);
00226     ASSERT(_fpHyp);
00227     _hypType = FIXED_POINTS_1D;
00228 
00229     _revEdgesIDs = _fpHyp->GetReversedEdges();
00230 
00231     aStatus = SMESH_Hypothesis::HYP_OK;
00232   }
00233 
00234   else if (hypName == "StartEndLength")
00235   {
00236     const StdMeshers_StartEndLength * hyp =
00237       dynamic_cast <const StdMeshers_StartEndLength * >(theHyp);
00238     ASSERT(hyp);
00239     _value[ BEG_LENGTH_IND ] = hyp->GetLength( true );
00240     _value[ END_LENGTH_IND ] = hyp->GetLength( false );
00241     ASSERT( _value[ BEG_LENGTH_IND ] > 0 && _value[ END_LENGTH_IND ] > 0 );
00242     _hypType = BEG_END_LENGTH;
00243 
00244     _revEdgesIDs = hyp->GetReversedEdges();
00245 
00246     aStatus = SMESH_Hypothesis::HYP_OK;
00247   }
00248 
00249   else if (hypName == "Deflection1D")
00250   {
00251     const StdMeshers_Deflection1D * hyp =
00252       dynamic_cast <const StdMeshers_Deflection1D * >(theHyp);
00253     ASSERT(hyp);
00254     _value[ DEFLECTION_IND ] = hyp->GetDeflection();
00255     ASSERT( _value[ DEFLECTION_IND ] > 0 );
00256     _hypType = DEFLECTION;
00257     aStatus = SMESH_Hypothesis::HYP_OK;
00258   }
00259 
00260   else if (hypName == "AutomaticLength")
00261   {
00262     StdMeshers_AutomaticLength * hyp = const_cast<StdMeshers_AutomaticLength *>
00263       (dynamic_cast <const StdMeshers_AutomaticLength * >(theHyp));
00264     ASSERT(hyp);
00265     _value[ BEG_LENGTH_IND ] = _value[ END_LENGTH_IND ] = hyp->GetLength( &aMesh, aShape );
00266 //     _value[ BEG_LENGTH_IND ] = hyp->GetLength( &aMesh, aShape );
00267 //     _value[ END_LENGTH_IND ] = Precision::Confusion(); // ?? or set to zero?
00268     ASSERT( _value[ BEG_LENGTH_IND ] > 0 );
00269     _hypType = MAX_LENGTH;
00270     aStatus = SMESH_Hypothesis::HYP_OK;
00271   }
00272   else
00273     aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
00274 
00275   return ( _hypType != NONE );
00276 }
00277 
00278 static bool computeParamByFunc(Adaptor3d_Curve& C3d, double first, double last,
00279                                double length, bool theReverse,
00280                                int nbSeg, Function& func,
00281                                list<double>& theParams)
00282 {
00283   // never do this way
00284   //OSD::SetSignal( true );
00285 
00286   if (nbSeg <= 0)
00287     return false;
00288 
00289   MESSAGE( "computeParamByFunc" );
00290 
00291   int nbPnt = 1 + nbSeg;
00292   vector<double> x(nbPnt, 0.);
00293 
00294   if (!buildDistribution(func, 0.0, 1.0, nbSeg, x, 1E-4))
00295      return false;
00296 
00297   MESSAGE( "Points:\n" );
00298   char buf[1024];
00299   for ( int i=0; i<=nbSeg; i++ )
00300   {
00301     sprintf(  buf, "%f\n", float(x[i] ) );
00302     MESSAGE( buf );
00303   }
00304 
00305 
00306 
00307   // apply parameters in range [0,1] to the space of the curve
00308   double prevU = first;
00309   double sign = 1.;
00310   if (theReverse)
00311   {
00312     prevU = last;
00313     sign = -1.;
00314   }
00315   for( int i = 1; i < nbSeg; i++ )
00316   {
00317     double curvLength = length * (x[i] - x[i-1]) * sign;
00318     GCPnts_AbscissaPoint Discret( C3d, curvLength, prevU );
00319     if ( !Discret.IsDone() )
00320       return false;
00321     double U = Discret.Parameter();
00322     if ( U > first && U < last )
00323       theParams.push_back( U );
00324     else
00325       return false;
00326     prevU = U;
00327   }
00328   if ( theReverse )
00329     theParams.reverse();
00330   return true;
00331 }
00332 
00333 
00334 //================================================================================
00347 //================================================================================
00348 
00349 static void compensateError(double a1, double an,
00350                             double U1, double Un,
00351                             double            length,
00352                             Adaptor3d_Curve&  C3d,
00353                             list<double> &    theParams,
00354                             bool              adjustNeighbors2an = false)
00355 {
00356   int i, nPar = theParams.size();
00357   if ( a1 + an < length && nPar > 1 )
00358   {
00359     bool reverse = ( U1 > Un );
00360     GCPnts_AbscissaPoint Discret(C3d, reverse ? an : -an, Un);
00361     if ( !Discret.IsDone() )
00362       return;
00363     double Utgt = Discret.Parameter(); // target value of the last parameter
00364     list<double>::reverse_iterator itU = theParams.rbegin();
00365     double Ul = *itU++; // real value of the last parameter
00366     double dUn = Utgt - Ul; // parametric error of <an>
00367     if ( Abs(dUn) <= Precision::Confusion() )
00368       return;
00369     double dU = Abs( Ul - *itU ); // parametric length of the last but one segment
00370     if ( adjustNeighbors2an || Abs(dUn) < 0.5 * dU ) { // last segment is a bit shorter than it should
00371       // move the last parameter to the edge beginning
00372     }
00373     else {  // last segment is much shorter than it should -> remove the last param and
00374       theParams.pop_back(); nPar--; // move the rest points toward the edge end
00375       dUn = Utgt - theParams.back();
00376     }
00377 
00378     double q  = dUn / ( nPar - 1 );
00379     if ( !adjustNeighbors2an )
00380     {
00381       q = dUn / ( Utgt - Un ); // (signed) factor of segment length change
00382       for ( itU = theParams.rbegin(), i = 1; i < nPar; i++ ) {
00383         double prevU = *itU;
00384         (*itU) += dUn;
00385         ++itU;
00386         dUn = q * (*itU - prevU) * (prevU-U1)/(Un-U1);
00387       }
00388     }
00389     else {
00390       theParams.back() += dUn;
00391       double sign = reverse ? -1 : 1;
00392       double prevU = theParams.back();
00393       itU = theParams.rbegin();
00394       for ( ++itU, i = 2; i < nPar; ++itU, i++ ) {
00395         double newU = *itU + dUn;
00396         if ( newU*sign < prevU*sign ) {
00397           prevU = *itU = newU;
00398           dUn -= q;
00399         }
00400         else { // set U between prevU and next valid param
00401           list<double>::reverse_iterator itU2 = itU;
00402           ++itU2;
00403           int nb = 2;
00404           while ( (*itU2)*sign > prevU*sign ) {
00405             ++itU2; ++nb;
00406           }
00407           dU = ( *itU2 - prevU ) / nb;
00408           while ( itU != itU2 ) {
00409             *itU += dU; ++itU;
00410           }
00411           break;
00412         }
00413       }
00414     }
00415   }
00416 }
00417 
00418 //================================================================================
00424 //================================================================================
00425 
00426 // struct VertexEventListener : public SMESH_subMeshEventListener
00427 // {
00428 //   VertexEventListener():SMESH_subMeshEventListener(0) // won't be deleted by submesh
00429 //   {}
00430 //   /*!
00431 //    * \brief Clean mesh on edges
00432 //    * \param event - algo_event or compute_event itself (of SMESH_subMesh)
00433 //    * \param eventType - ALGO_EVENT or COMPUTE_EVENT (of SMESH_subMesh)
00434 //    * \param subMesh - the submesh where the event occures
00435 //    */
00436 //   void ProcessEvent(const int event, const int eventType, SMESH_subMesh* subMesh,
00437 //                     EventListenerData*, const SMESH_Hypothesis*)
00438 //   {
00439 //     if ( eventType == SMESH_subMesh::ALGO_EVENT) // all algo events
00440 //     {
00441 //       subMesh->ComputeStateEngine( SMESH_subMesh::MODIF_ALGO_STATE );
00442 //     }
00443 //   }
00444 // }; // struct VertexEventListener
00445 
00446 //=============================================================================
00454 //=============================================================================
00455 
00456 void StdMeshers_Regular_1D::SetEventListener(SMESH_subMesh* subMesh)
00457 {
00458   StdMeshers_Propagation::SetPropagationMgr( subMesh );
00459 }
00460 
00461 //=============================================================================
00468 //=============================================================================
00469 
00470 void StdMeshers_Regular_1D::SubmeshRestored(SMESH_subMesh* subMesh)
00471 {
00472 }
00473 
00474 //=============================================================================
00478 //=============================================================================
00479 
00480 const StdMeshers_SegmentLengthAroundVertex*
00481 StdMeshers_Regular_1D::getVertexHyp(SMESH_Mesh &          theMesh,
00482                                     const TopoDS_Vertex & theV)
00483 {
00484   static SMESH_HypoFilter filter( SMESH_HypoFilter::HasName("SegmentAroundVertex_0D"));
00485   if ( const SMESH_Hypothesis * h = theMesh.GetHypothesis( theV, filter, true ))
00486   {
00487     SMESH_Algo* algo = const_cast< SMESH_Algo* >( static_cast< const SMESH_Algo* > ( h ));
00488     const list <const SMESHDS_Hypothesis *> & hypList = algo->GetUsedHypothesis( theMesh, theV, 0 );
00489     if ( !hypList.empty() && string("SegmentLengthAroundVertex") == hypList.front()->GetName() )
00490       return static_cast<const StdMeshers_SegmentLengthAroundVertex*>( hypList.front() );
00491   }
00492   return 0;
00493 }
00494 
00495 //================================================================================
00504 //================================================================================
00505 
00506 void StdMeshers_Regular_1D::redistributeNearVertices (SMESH_Mesh &          theMesh,
00507                                                       Adaptor3d_Curve &     theC3d,
00508                                                       double                theLength,
00509                                                       std::list< double > & theParameters,
00510                                                       const TopoDS_Vertex & theVf,
00511                                                       const TopoDS_Vertex & theVl)
00512 {
00513   double f = theC3d.FirstParameter(), l = theC3d.LastParameter();
00514   int nPar = theParameters.size();
00515   for ( int isEnd1 = 0; isEnd1 < 2; ++isEnd1 )
00516   {
00517     const TopoDS_Vertex & V = isEnd1 ? theVf : theVl;
00518     const StdMeshers_SegmentLengthAroundVertex* hyp = getVertexHyp (theMesh, V );
00519     if ( hyp ) {
00520       double vertexLength = hyp->GetLength();
00521       if ( vertexLength > theLength / 2.0 )
00522         continue;
00523       if ( isEnd1 ) { // to have a segment of interest at end of theParameters
00524         theParameters.reverse();
00525         std::swap( f, l );
00526       }
00527       if ( _hypType == NB_SEGMENTS )
00528       {
00529         compensateError(0, vertexLength, f, l, theLength, theC3d, theParameters, true );
00530       }
00531       else if ( nPar <= 3 )
00532       {
00533         if ( !isEnd1 )
00534           vertexLength = -vertexLength;
00535         GCPnts_AbscissaPoint Discret(theC3d, vertexLength, l);
00536         if ( Discret.IsDone() ) {
00537           if ( nPar == 0 )
00538             theParameters.push_back( Discret.Parameter());
00539           else {
00540             double L = GCPnts_AbscissaPoint::Length( theC3d, theParameters.back(), l);
00541             if ( vertexLength < L / 2.0 )
00542               theParameters.push_back( Discret.Parameter());
00543             else
00544               compensateError(0, vertexLength, f, l, theLength, theC3d, theParameters, true );
00545           }
00546         }
00547       }
00548       else
00549       {
00550         // recompute params between the last segment and a middle one.
00551         // find size of a middle segment
00552         int nHalf = ( nPar-1 ) / 2;
00553         list< double >::reverse_iterator itU = theParameters.rbegin();
00554         std::advance( itU, nHalf );
00555         double Um = *itU++;
00556         double Lm = GCPnts_AbscissaPoint::Length( theC3d, Um, *itU);
00557         double L = GCPnts_AbscissaPoint::Length( theC3d, *itU, l);
00558         StdMeshers_Regular_1D algo( *this );
00559         algo._hypType = BEG_END_LENGTH;
00560         algo._value[ BEG_LENGTH_IND ] = Lm;
00561         algo._value[ END_LENGTH_IND ] = vertexLength;
00562         double from = *itU, to = l;
00563         if ( isEnd1 ) {
00564           std::swap( from, to );
00565           std::swap( algo._value[ BEG_LENGTH_IND ], algo._value[ END_LENGTH_IND ]);
00566         }
00567         list<double> params;
00568         if ( algo.computeInternalParameters( theMesh, theC3d, L, from, to, params, false ))
00569         {
00570           if ( isEnd1 ) params.reverse();
00571           while ( 1 + nHalf-- )
00572             theParameters.pop_back();
00573           theParameters.splice( theParameters.end(), params );
00574         }
00575         else
00576         {
00577           compensateError(0, vertexLength, f, l, theLength, theC3d, theParameters, true );
00578         }
00579       }
00580       if ( isEnd1 )
00581         theParameters.reverse();
00582     }
00583   }
00584 }
00585 
00586 //=============================================================================
00590 //=============================================================================
00591 bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh &     theMesh,
00592                                                       Adaptor3d_Curve& theC3d,
00593                                                       double           theLength,
00594                                                       double           theFirstU,
00595                                                       double           theLastU,
00596                                                       list<double> &   theParams,
00597                                                       const bool       theReverse,
00598                                                       bool             theConsiderPropagation)
00599 {
00600   theParams.clear();
00601 
00602   double f = theFirstU, l = theLastU;
00603 
00604   switch( _hypType )
00605   {
00606   case LOCAL_LENGTH:
00607   case MAX_LENGTH:
00608   case NB_SEGMENTS: {
00609 
00610     double eltSize = 1;
00611     if ( _hypType == MAX_LENGTH )
00612     {
00613       double nbseg = ceil(theLength / _value[ BEG_LENGTH_IND ]); // integer sup
00614       if (nbseg <= 0)
00615         nbseg = 1;                        // degenerated edge
00616       eltSize = theLength / nbseg;
00617     }
00618     else if ( _hypType == LOCAL_LENGTH )
00619     {
00620       // Local Length hypothesis
00621       double nbseg = ceil(theLength / _value[ BEG_LENGTH_IND ]); // integer sup
00622 
00623       // NPAL17873:
00624       bool isFound = false;
00625       if (theConsiderPropagation && !_mainEdge.IsNull()) // propagated from some other edge
00626       {
00627         // Advanced processing to assure equal number of segments in case of Propagation
00628         SMESH_subMesh* sm = theMesh.GetSubMeshContaining(_mainEdge);
00629         if (sm) {
00630           bool computed = sm->IsMeshComputed();
00631           if (!computed) {
00632             if (sm->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE) {
00633               _gen->Compute( theMesh, _mainEdge, /*anUpward=*/true);
00634               computed = sm->IsMeshComputed();
00635             }
00636           }
00637           if (computed) {
00638             SMESHDS_SubMesh* smds = sm->GetSubMeshDS();
00639             int nb_segments = smds->NbElements();
00640             if (nbseg - 1 <= nb_segments && nb_segments <= nbseg + 1) {
00641               isFound = true;
00642               nbseg = nb_segments;
00643             }
00644           }
00645         }
00646       }
00647       if (!isFound) // not found by meshed edge in the propagation chain, use precision
00648       {
00649         double aPrecision = _value[ PRECISION_IND ];
00650         double nbseg_prec = ceil((theLength / _value[ BEG_LENGTH_IND ]) - aPrecision);
00651         if (nbseg_prec == (nbseg - 1)) nbseg--;
00652       }
00653 
00654       if (nbseg <= 0)
00655         nbseg = 1;                        // degenerated edge
00656       eltSize = theLength / nbseg;
00657     }
00658     else
00659     {
00660       // Number Of Segments hypothesis
00661       int NbSegm = _ivalue[ NB_SEGMENTS_IND ];
00662       if ( NbSegm < 1 )  return false;
00663       if ( NbSegm == 1 ) return true;
00664 
00665       switch (_ivalue[ DISTR_TYPE_IND ])
00666       {
00667       case StdMeshers_NumberOfSegments::DT_Scale:
00668         {
00669           double scale = _value[ SCALE_FACTOR_IND ];
00670 
00671           if (fabs(scale - 1.0) < Precision::Confusion()) {
00672             // special case to avoid division by zero
00673             for (int i = 1; i < NbSegm; i++) {
00674               double param = f + (l - f) * i / NbSegm;
00675               theParams.push_back( param );
00676             }
00677           } else {
00678             // general case of scale distribution
00679             if ( theReverse )
00680               scale = 1.0 / scale;
00681 
00682             double alpha = pow(scale, 1.0 / (NbSegm - 1));
00683             double factor = (l - f) / (1.0 - pow(alpha, NbSegm));
00684 
00685             for (int i = 1; i < NbSegm; i++) {
00686               double param = f + factor * (1.0 - pow(alpha, i));
00687               theParams.push_back( param );
00688             }
00689           }
00690           const double lenFactor = theLength/(l-f);
00691           list<double>::iterator u = theParams.begin(), uEnd = theParams.end();
00692           for ( ; u != uEnd; ++u )
00693           {
00694             GCPnts_AbscissaPoint Discret( theC3d, ((*u)-f) * lenFactor, f );
00695             if ( Discret.IsDone() )
00696               *u = Discret.Parameter();
00697           }
00698           return true;
00699         }
00700         break;
00701       case StdMeshers_NumberOfSegments::DT_TabFunc:
00702         {
00703           FunctionTable func(_vvalue[ TAB_FUNC_IND ], _ivalue[ CONV_MODE_IND ]);
00704           return computeParamByFunc(theC3d, f, l, theLength, theReverse,
00705                                     _ivalue[ NB_SEGMENTS_IND ], func,
00706                                     theParams);
00707         }
00708         break;
00709       case StdMeshers_NumberOfSegments::DT_ExprFunc:
00710         {
00711           FunctionExpr func(_svalue[ EXPR_FUNC_IND ].c_str(), _ivalue[ CONV_MODE_IND ]);
00712           return computeParamByFunc(theC3d, f, l, theLength, theReverse,
00713                                     _ivalue[ NB_SEGMENTS_IND ], func,
00714                                     theParams);
00715         }
00716         break;
00717       case StdMeshers_NumberOfSegments::DT_Regular:
00718         eltSize = theLength / _ivalue[ NB_SEGMENTS_IND ];
00719         break;
00720       default:
00721         return false;
00722       }
00723     }
00724     GCPnts_UniformAbscissa Discret(theC3d, eltSize, f, l);
00725     if ( !Discret.IsDone() )
00726       return error( "GCPnts_UniformAbscissa failed");
00727 
00728     int NbPoints = Discret.NbPoints();
00729     for ( int i = 2; i < NbPoints; i++ )
00730     {
00731       double param = Discret.Parameter(i);
00732       theParams.push_back( param );
00733     }
00734     compensateError( eltSize, eltSize, f, l, theLength, theC3d, theParams ); // for PAL9899
00735     return true;
00736   }
00737 
00738   case BEG_END_LENGTH: {
00739 
00740     // geometric progression: SUM(n) = ( a1 - an * q ) / ( 1 - q ) = theLength
00741 
00742     double a1 = _value[ BEG_LENGTH_IND ];
00743     double an = _value[ END_LENGTH_IND ];
00744     double q  = ( theLength - a1 ) / ( theLength - an );
00745     if ( q < theLength/1e6 || 1.01*theLength < a1 + an)
00746       return error ( SMESH_Comment("Invalid segment lengths (")<<a1<<" and "<<an<<") "<<
00747                      "for an edge of length "<<theLength);
00748 
00749     double U1 = theReverse ? l : f;
00750     double Un = theReverse ? f : l;
00751     double param = U1;
00752     double eltSize = theReverse ? -a1 : a1;
00753     while ( 1 ) {
00754       // computes a point on a curve <theC3d> at the distance <eltSize>
00755       // from the point of parameter <param>.
00756       GCPnts_AbscissaPoint Discret( theC3d, eltSize, param );
00757       if ( !Discret.IsDone() ) break;
00758       param = Discret.Parameter();
00759       if ( f < param && param < l )
00760         theParams.push_back( param );
00761       else
00762         break;
00763       eltSize *= q;
00764     }
00765     compensateError( a1, an, U1, Un, theLength, theC3d, theParams );
00766     if (theReverse) theParams.reverse(); // NPAL18025
00767     return true;
00768   }
00769 
00770   case ARITHMETIC_1D: {
00771 
00772     // arithmetic progression: SUM(n) = ( an - a1 + q ) * ( a1 + an ) / ( 2 * q ) = theLength
00773 
00774     double a1 = _value[ BEG_LENGTH_IND ];
00775     double an = _value[ END_LENGTH_IND ];
00776     if ( 1.01*theLength < a1 + an)
00777       return error ( SMESH_Comment("Invalid segment lengths (")<<a1<<" and "<<an<<") "<<
00778                      "for an edge of length "<<theLength);
00779 
00780     double  q = ( an - a1 ) / ( 2 *theLength/( a1 + an ) - 1 );
00781     int n = int(fabs(q) > numeric_limits<double>::min() ? ( 1+( an-a1 )/q ) : ( 1+theLength/a1 ));
00782 
00783     double U1 = theReverse ? l : f;
00784     double Un = theReverse ? f : l;
00785     double param = U1;
00786     double eltSize = a1;
00787     if ( theReverse ) {
00788       eltSize = -eltSize;
00789       q = -q;
00790     }
00791     while ( n-- > 0 && eltSize * ( Un - U1 ) > 0 ) {
00792       // computes a point on a curve <theC3d> at the distance <eltSize>
00793       // from the point of parameter <param>.
00794       GCPnts_AbscissaPoint Discret( theC3d, eltSize, param );
00795       if ( !Discret.IsDone() ) break;
00796       param = Discret.Parameter();
00797       if ( param > f && param < l )
00798         theParams.push_back( param );
00799       else
00800         break;
00801       eltSize += q;
00802     }
00803     compensateError( a1, an, U1, Un, theLength, theC3d, theParams );
00804     if (theReverse) theParams.reverse(); // NPAL18025
00805 
00806     return true;
00807   }
00808 
00809   case FIXED_POINTS_1D: {
00810     const std::vector<double>& aPnts = _fpHyp->GetPoints();
00811     const std::vector<int>& nbsegs = _fpHyp->GetNbSegments();
00812     int i = 0;
00813     TColStd_SequenceOfReal Params;
00814     for(; i<aPnts.size(); i++) {
00815       if( aPnts[i]<0.0001 || aPnts[i]>0.9999 ) continue;
00816       int j=1;
00817       bool IsExist = false;
00818       for(; j<=Params.Length(); j++) {
00819         if( fabs(aPnts[i]-Params.Value(j)) < 1e-4 ) {
00820           IsExist = true;
00821           break;
00822         }
00823         if( aPnts[i]<Params.Value(j) ) break;
00824       }
00825       if(!IsExist) Params.InsertBefore(j,aPnts[i]);
00826     }
00827     double par2, par1, lp;
00828     par1 = f;
00829     lp = l;
00830     double sign = 1.0;
00831     if(theReverse) {
00832       par1 = l;
00833       lp = f;
00834       sign = -1.0;
00835     }
00836     double eltSize, segmentSize = 0.;
00837     double currAbscissa = 0;
00838     for(i=0; i<Params.Length(); i++) {
00839       int nbseg = ( i > nbsegs.size()-1 ) ? nbsegs[0] : nbsegs[i];
00840       segmentSize = Params.Value(i+1)*theLength - currAbscissa;
00841       currAbscissa += segmentSize;
00842       GCPnts_AbscissaPoint APnt(theC3d, sign*segmentSize, par1);
00843       if( !APnt.IsDone() )
00844         return error( "GCPnts_AbscissaPoint failed");
00845       par2 = APnt.Parameter();
00846       eltSize = segmentSize/nbseg;
00847       GCPnts_UniformAbscissa Discret(theC3d, eltSize, par1, par2);
00848       if(theReverse)
00849         Discret.Initialize(theC3d, eltSize, par2, par1);
00850       else
00851         Discret.Initialize(theC3d, eltSize, par1, par2);
00852       if ( !Discret.IsDone() )
00853         return error( "GCPnts_UniformAbscissa failed");
00854       int NbPoints = Discret.NbPoints();
00855       list<double> tmpParams;
00856       for(int i=2; i<NbPoints; i++) {
00857         double param = Discret.Parameter(i);
00858         tmpParams.push_back( param );
00859       }
00860       if (theReverse) {
00861         compensateError( eltSize, eltSize, par2, par1, segmentSize, theC3d, tmpParams );
00862         tmpParams.reverse();
00863       }
00864       else {
00865         compensateError( eltSize, eltSize, par1, par2, segmentSize, theC3d, tmpParams );
00866       }
00867       list<double>::iterator itP = tmpParams.begin();
00868       for(; itP != tmpParams.end(); itP++) {
00869         theParams.push_back( *(itP) );
00870       }
00871       theParams.push_back( par2 );
00872 
00873       par1 = par2;
00874     }
00875     // add for last
00876     int nbseg = ( nbsegs.size() > Params.Length() ) ? nbsegs[Params.Length()] : nbsegs[0];
00877     segmentSize = theLength - currAbscissa;
00878     eltSize = segmentSize/nbseg;
00879     GCPnts_UniformAbscissa Discret;
00880     if(theReverse)
00881       Discret.Initialize(theC3d, eltSize, par1, lp);
00882     else
00883       Discret.Initialize(theC3d, eltSize, lp, par1);
00884     if ( !Discret.IsDone() )
00885       return error( "GCPnts_UniformAbscissa failed");
00886     int NbPoints = Discret.NbPoints();
00887     list<double> tmpParams;
00888     for(int i=2; i<NbPoints; i++) {
00889       double param = Discret.Parameter(i);
00890       tmpParams.push_back( param );
00891     }
00892     if (theReverse) {
00893       compensateError( eltSize, eltSize, lp, par1, segmentSize, theC3d, tmpParams );
00894       tmpParams.reverse();
00895     }
00896     else {
00897       compensateError( eltSize, eltSize, par1, lp, segmentSize, theC3d, tmpParams );
00898     }
00899     list<double>::iterator itP = tmpParams.begin();
00900     for(; itP != tmpParams.end(); itP++) {
00901       theParams.push_back( *(itP) );
00902     }
00903 
00904     if (theReverse) {
00905       theParams.reverse(); // NPAL18025
00906     }
00907     return true;
00908   }
00909 
00910   case DEFLECTION: {
00911 
00912     GCPnts_UniformDeflection Discret(theC3d, _value[ DEFLECTION_IND ], f, l, true);
00913     if ( !Discret.IsDone() )
00914       return false;
00915 
00916     int NbPoints = Discret.NbPoints();
00917     for ( int i = 2; i < NbPoints; i++ )
00918     {
00919       double param = Discret.Parameter(i);
00920       theParams.push_back( param );
00921     }
00922     return true;
00923   }
00924 
00925   default:;
00926   }
00927 
00928   return false;
00929 }
00930 
00931 //=============================================================================
00935 //=============================================================================
00936 
00937 bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & theShape)
00938 {
00939   if ( _hypType == NONE )
00940     return false;
00941 
00942   SMESHDS_Mesh * meshDS = theMesh.GetMeshDS();
00943 
00944   const TopoDS_Edge & EE = TopoDS::Edge(theShape);
00945   TopoDS_Edge E = TopoDS::Edge(EE.Oriented(TopAbs_FORWARD));
00946   int shapeID = meshDS->ShapeToIndex( E );
00947 
00948   double f, l;
00949   Handle(Geom_Curve) Curve = BRep_Tool::Curve(E, f, l);
00950 
00951   TopoDS_Vertex VFirst, VLast;
00952   TopExp::Vertices(E, VFirst, VLast);   // Vfirst corresponds to f and Vlast to l
00953 
00954   ASSERT(!VFirst.IsNull());
00955   ASSERT(!VLast.IsNull());
00956   const SMDS_MeshNode * idFirst = SMESH_Algo::VertexNode( VFirst, meshDS );
00957   const SMDS_MeshNode * idLast = SMESH_Algo::VertexNode( VLast, meshDS );
00958   if (!idFirst || !idLast)
00959     return error( COMPERR_BAD_INPUT_MESH, "No node on vertex");
00960 
00961   // remove elements created by e.g. patern mapping (PAL21999)
00962   // CLEAN event is incorrectly ptopagated seemingly due to Propagation hyp
00963   // so TEMPORARY solution is to clean the submesh manually
00964   //theMesh.GetSubMesh(theShape)->ComputeStateEngine( SMESH_subMesh::CLEAN );
00965   if (SMESHDS_SubMesh * subMeshDS = meshDS->MeshElements(theShape))
00966   {
00967     SMDS_ElemIteratorPtr ite = subMeshDS->GetElements();
00968     while (ite->more())
00969       meshDS->RemoveFreeElement(ite->next(), subMeshDS);
00970     SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes();
00971     while (itn->more()) {
00972       const SMDS_MeshNode * node = itn->next();
00973       if ( node->NbInverseElements() == 0 )
00974         meshDS->RemoveFreeNode(node, subMeshDS);
00975       else
00976         meshDS->RemoveNode(node);
00977     }
00978   }
00979 
00980   if (!Curve.IsNull())
00981   {
00982     list< double > params;
00983     bool reversed = false;
00984     if ( theMesh.GetShapeToMesh().ShapeType() >= TopAbs_WIRE ) {
00985       // if the shape to mesh is WIRE or EDGE
00986       reversed = ( EE.Orientation() == TopAbs_REVERSED );
00987     }
00988     if ( !_mainEdge.IsNull() ) {
00989       // take into account reversing the edge the hypothesis is propagated from
00990       reversed = ( _mainEdge.Orientation() == TopAbs_REVERSED );
00991       int mainID = meshDS->ShapeToIndex(_mainEdge);
00992       if ( std::find( _revEdgesIDs.begin(), _revEdgesIDs.end(), mainID) != _revEdgesIDs.end())
00993         reversed = !reversed;
00994     }
00995     // take into account this edge reversing
00996     if ( std::find( _revEdgesIDs.begin(), _revEdgesIDs.end(), shapeID) != _revEdgesIDs.end())
00997       reversed = !reversed;
00998 
00999     BRepAdaptor_Curve C3d( E );
01000     double length = EdgeLength( E );
01001     if ( ! computeInternalParameters( theMesh, C3d, length, f, l, params, reversed, true )) {
01002       return false;
01003     }
01004     redistributeNearVertices( theMesh, C3d, length, params, VFirst, VLast );
01005 
01006     // edge extrema (indexes : 1 & NbPoints) already in SMDS (TopoDS_Vertex)
01007     // only internal nodes receive an edge position with param on curve
01008 
01009     const SMDS_MeshNode * idPrev = idFirst;
01010     double parPrev = f;
01011     double parLast = l;
01012 
01013     /* NPAL18025
01014     if (reversed) {
01015       idPrev = idLast;
01016       idLast = idFirst;
01017       idFirst = idPrev;
01018       parPrev = l;
01019       parLast = f;
01020     }
01021     */
01022     for (list<double>::iterator itU = params.begin(); itU != params.end(); itU++) {
01023       double param = *itU;
01024       gp_Pnt P = Curve->Value(param);
01025 
01026       //Add the Node in the DataStructure
01027       SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
01028       meshDS->SetNodeOnEdge(node, shapeID, param);
01029 
01030       if(_quadraticMesh) {
01031         // create medium node
01032         double prm = ( parPrev + param )/2;
01033         gp_Pnt PM = Curve->Value(prm);
01034         SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z());
01035         meshDS->SetNodeOnEdge(NM, shapeID, prm);
01036         SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node, NM);
01037         meshDS->SetMeshElementOnShape(edge, shapeID);
01038       }
01039       else {
01040         SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node);
01041         meshDS->SetMeshElementOnShape(edge, shapeID);
01042       }
01043 
01044       idPrev = node;
01045       parPrev = param;
01046     }
01047     if(_quadraticMesh) {
01048       double prm = ( parPrev + parLast )/2;
01049       gp_Pnt PM = Curve->Value(prm);
01050       SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z());
01051       meshDS->SetNodeOnEdge(NM, shapeID, prm);
01052       SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast, NM);
01053       meshDS->SetMeshElementOnShape(edge, shapeID);
01054     }
01055     else {
01056       SMDS_MeshEdge* edge = meshDS->AddEdge(idPrev, idLast);
01057       meshDS->SetMeshElementOnShape(edge, shapeID);
01058     }
01059   }
01060   else
01061   {
01062     //MESSAGE("************* Degenerated edge! *****************");
01063 
01064     // Edge is a degenerated Edge : We put n = 5 points on the edge.
01065     const int NbPoints = 5;
01066     BRep_Tool::Range( E, f, l ); // PAL15185
01067     double du = (l - f) / (NbPoints - 1);
01068 
01069     gp_Pnt P = BRep_Tool::Pnt(VFirst);
01070 
01071     const SMDS_MeshNode * idPrev = idFirst;
01072     for (int i = 2; i < NbPoints; i++) {
01073       double param = f + (i - 1) * du;
01074       SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
01075       if(_quadraticMesh) {
01076         // create medium node
01077         double prm = param - du/2.;
01078         SMDS_MeshNode * NM = meshDS->AddNode(P.X(), P.Y(), P.Z());
01079         meshDS->SetNodeOnEdge(NM, shapeID, prm);
01080         SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node, NM);
01081         meshDS->SetMeshElementOnShape(edge, shapeID);
01082       }
01083       else {
01084         SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node);
01085         meshDS->SetMeshElementOnShape(edge, shapeID);
01086       }
01087       meshDS->SetNodeOnEdge(node, shapeID, param);
01088       idPrev = node;
01089     }
01090     if(_quadraticMesh) {
01091       // create medium node
01092       double prm = l - du/2.;
01093       SMDS_MeshNode * NM = meshDS->AddNode(P.X(), P.Y(), P.Z());
01094       meshDS->SetNodeOnEdge(NM, shapeID, prm);
01095       SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast, NM);
01096       meshDS->SetMeshElementOnShape(edge, shapeID);
01097     }
01098     else {
01099       SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast);
01100       meshDS->SetMeshElementOnShape(edge, shapeID);
01101     }
01102   }
01103   return true;
01104 }
01105 
01106 
01107 //=============================================================================
01111 //=============================================================================
01112 
01113 bool StdMeshers_Regular_1D::Evaluate(SMESH_Mesh & theMesh,
01114                                      const TopoDS_Shape & theShape,
01115                                      MapShapeNbElems& aResMap)
01116 {
01117   if ( _hypType == NONE )
01118     return false;
01119 
01120   //SMESHDS_Mesh * meshDS = theMesh.GetMeshDS();
01121 
01122   const TopoDS_Edge & EE = TopoDS::Edge(theShape);
01123   TopoDS_Edge E = TopoDS::Edge(EE.Oriented(TopAbs_FORWARD));
01124   //  int shapeID = meshDS->ShapeToIndex( E );
01125 
01126   double f, l;
01127   Handle(Geom_Curve) Curve = BRep_Tool::Curve(E, f, l);
01128 
01129   TopoDS_Vertex VFirst, VLast;
01130   TopExp::Vertices(E, VFirst, VLast);   // Vfirst corresponds to f and Vlast to l
01131 
01132   ASSERT(!VFirst.IsNull());
01133   ASSERT(!VLast.IsNull());
01134 
01135   std::vector<int> aVec(SMDSEntity_Last,0);
01136 
01137   if (!Curve.IsNull()) {
01138     list< double > params;
01139 
01140     BRepAdaptor_Curve C3d( E );
01141     double length = EdgeLength( E );
01142     if ( ! computeInternalParameters( theMesh, C3d, length, f, l, params, false, true )) {
01143       SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
01144       aResMap.insert(std::make_pair(sm,aVec));
01145       SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
01146       smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this));
01147       return false;
01148     }
01149     redistributeNearVertices( theMesh, C3d, length, params, VFirst, VLast );
01150 
01151     if(_quadraticMesh) {
01152       aVec[SMDSEntity_Node] = 2*params.size() + 1;
01153       aVec[SMDSEntity_Quad_Edge] = params.size() + 1;
01154     }
01155     else {
01156       aVec[SMDSEntity_Node] = params.size();
01157       aVec[SMDSEntity_Edge] = params.size() + 1;
01158     }
01159     
01160   }
01161   else {
01162     //MESSAGE("************* Degenerated edge! *****************");
01163     // Edge is a degenerated Edge : We put n = 5 points on the edge.
01164     if(_quadraticMesh) {
01165       aVec[SMDSEntity_Node] = 11;
01166       aVec[SMDSEntity_Quad_Edge] = 6;
01167     }
01168     else {
01169       aVec[SMDSEntity_Node] = 5;
01170       aVec[SMDSEntity_Edge] = 6;
01171     }
01172   }
01173 
01174   SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
01175   aResMap.insert(std::make_pair(sm,aVec));
01176 
01177   return true;
01178 }
01179 
01180 
01181 //=============================================================================
01185 //=============================================================================
01186 
01187 const list <const SMESHDS_Hypothesis *> &
01188 StdMeshers_Regular_1D::GetUsedHypothesis(SMESH_Mesh &         aMesh,
01189                                          const TopoDS_Shape & aShape,
01190                                          const bool           ignoreAuxiliary)
01191 {
01192   _usedHypList.clear();
01193   _mainEdge.Nullify();
01194 
01195   SMESH_HypoFilter auxiliaryFilter, compatibleFilter;
01196   auxiliaryFilter.Init( SMESH_HypoFilter::IsAuxiliary() );
01197   InitCompatibleHypoFilter( compatibleFilter, /*ignoreAux=*/true );
01198 
01199   // get non-auxiliary assigned directly to aShape
01200   int nbHyp = aMesh.GetHypotheses( aShape, compatibleFilter, _usedHypList, false );
01201 
01202   if (nbHyp == 0 && aShape.ShapeType() == TopAbs_EDGE)
01203   {
01204     // Check, if propagated from some other edge
01205     _mainEdge = StdMeshers_Propagation::GetPropagationSource( aMesh, aShape );
01206     if ( !_mainEdge.IsNull() )
01207     {
01208       // Propagation of 1D hypothesis from <aMainEdge> on this edge;
01209       // get non-auxiliary assigned to _mainEdge
01210       nbHyp = aMesh.GetHypotheses( _mainEdge, compatibleFilter, _usedHypList, true );
01211     }
01212   }
01213 
01214   if (nbHyp == 0) // nothing propagated nor assigned to aShape
01215   {
01216     SMESH_Algo::GetUsedHypothesis( aMesh, aShape, ignoreAuxiliary );
01217     nbHyp = _usedHypList.size();
01218   }
01219   else
01220   {
01221     // get auxiliary hyps from aShape
01222     aMesh.GetHypotheses( aShape, auxiliaryFilter, _usedHypList, true );
01223   }
01224   if ( nbHyp > 1 && ignoreAuxiliary )
01225     _usedHypList.clear(); //only one compatible non-auxiliary hypothesis allowed
01226 
01227   return _usedHypList;
01228 }