Back to index

salome-smesh  6.5.0
StdMeshers_AutomaticLength.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_AutomaticLength.cxx
00025 //  Author : Edward AGAPOV, OCC
00026 //  Module : SMESH
00027 
00028 #include "StdMeshers_AutomaticLength.hxx"
00029 
00030 #include "SMESH_Mesh.hxx"
00031 #include "SMESHDS_Mesh.hxx"
00032 #include "SMESH_Algo.hxx"
00033 #include "SMESHDS_SubMesh.hxx"
00034 
00035 #include "utilities.h"
00036 
00037 #include <TopTools_IndexedMapOfShape.hxx>
00038 #include <TopExp.hxx>
00039 #include <TopoDS.hxx>
00040 #include <TopoDS_Edge.hxx>
00041 
00042 using namespace std;
00043 
00044 //=============================================================================
00048 //=============================================================================
00049 
00050 StdMeshers_AutomaticLength::StdMeshers_AutomaticLength(int hypId, int studyId, SMESH_Gen * gen)
00051   :SMESH_Hypothesis(hypId, studyId, gen)
00052 {
00053   _name = "AutomaticLength";
00054   _param_algo_dim = 1; // is used by SMESH_Regular_1D
00055 
00056   _mesh = 0;
00057   _fineness = 0;
00058 }
00059 
00060 //=============================================================================
00064 //=============================================================================
00065 
00066 StdMeshers_AutomaticLength::~StdMeshers_AutomaticLength()
00067 {
00068 }
00069 
00070 //================================================================================
00081 //================================================================================
00082 
00083 const double theCoarseConst = 0.5;
00084 const double theFineConst   = 4.5;
00085 
00086 void StdMeshers_AutomaticLength::SetFineness(double theFineness)
00087   throw(SALOME_Exception)
00088 {
00089   if ( theFineness < 0.0 || theFineness > 1.0 )
00090     throw SALOME_Exception(LOCALIZED("theFineness is out of range [0.0-1.0]"));
00091 
00092   if ( _fineness != theFineness )
00093   {
00094     NotifySubMeshesHypothesisModification();
00095     _fineness = theFineness;
00096   }
00097 }
00098 
00099 namespace {
00100 
00101   //================================================================================
00107   //================================================================================
00108 
00109   inline const TopoDS_TShape* getTShape(const TopoDS_Shape& theShape)
00110   {
00111     return theShape.TShape().operator->();
00112   }
00113 
00114   //================================================================================
00118   //================================================================================
00119 
00120   const double a14divPI = 14. / M_PI;
00121 
00122   inline double segLength(double S0, double edgeLen, double minLen )
00123   {
00124     // PAL10237
00125     // S = S0 * f(L/Lmin) where f(x) = 1 + (2/Pi * 7 * atan(x/5) )
00126     // =>
00127     // S = S0 * ( 1 + 14/PI * atan( L / ( 5 * Lmin )))
00128     return S0 * ( 1. + a14divPI * atan( edgeLen / ( 5 * minLen )));
00129   }
00130 
00131   //================================================================================
00137   //================================================================================
00138 
00139   void computeLengths( SMESHDS_Mesh*                       aMesh,
00140                        map<const TopoDS_TShape*, double> & theTShapeToLengthMap,
00141                        double &                            theS0,
00142                        double &                            theMinLen)
00143   {
00144     theTShapeToLengthMap.clear();
00145 
00146     TopoDS_Shape aMainShape = aMesh->ShapeToMesh();
00147 
00148     // Find length of longest and shortest edge
00149     double Lmin = DBL_MAX, Lmax = -DBL_MAX;
00150     TopTools_IndexedMapOfShape edgeMap;
00151     TopExp::MapShapes( aMainShape, TopAbs_EDGE, edgeMap);
00152     for ( int i = 1; i <= edgeMap.Extent(); ++i )
00153     {
00154       TopoDS_Edge edge = TopoDS::Edge( edgeMap(i) );
00155       //if ( BRep_Tool::Degenerated( edge )) continue;
00156 
00157       Standard_Real L = SMESH_Algo::EdgeLength( edge );
00158       if ( L < DBL_MIN ) continue;
00159 
00160       if ( L > Lmax ) Lmax = L;
00161       if ( L < Lmin ) Lmin = L;
00162 
00163       // remember i-th edge length
00164       theTShapeToLengthMap.insert( make_pair( getTShape( edge ), L ));
00165     }
00166 
00167     // Compute S0
00168 
00169     // image attached to PAL10237
00170 
00171     //   NbSeg
00172     //     ^
00173     //     |
00174     //   10|\
00175     //     | \
00176     //     |  \
00177     //     |   \
00178     //    5|    --------
00179     //     |
00180     //     +------------>
00181     //     1    10       Lmax/Lmin
00182 
00183     const int NbSegMin = 5, NbSegMax = 10; //  on axis NbSeg
00184     const double Lrat1 = 1., Lrat2 = 10.;  //  on axis Lmax/Lmin
00185 
00186     double Lratio = Lmax/Lmin;
00187     double NbSeg = NbSegMin;
00188     if ( Lratio < Lrat2 )
00189       NbSeg += ( Lrat2 - Lratio ) / ( Lrat2 - Lrat1 )  * ( NbSegMax - NbSegMin );
00190 
00191     double S0 = Lmin / (int) NbSeg;
00192     MESSAGE( "S0 = " << S0 << ", Lmin = " << Lmin << ", Nbseg = " << (int) NbSeg);
00193 
00194     // Compute segments length for all edges
00195     map<const TopoDS_TShape*, double>::iterator tshape_length = theTShapeToLengthMap.begin();
00196     for ( ; tshape_length != theTShapeToLengthMap.end(); ++tshape_length )
00197     {
00198       double & L = tshape_length->second;
00199       L = segLength( S0, L, Lmin );
00200     }
00201     theS0 = S0;
00202     theMinLen = Lmin;
00203   }
00204 }
00205 
00206 //=============================================================================
00210 //=============================================================================
00211 
00212 double StdMeshers_AutomaticLength::GetLength(const SMESH_Mesh* theMesh,
00213                                              const double      theEdgeLength)
00214   throw(SALOME_Exception)
00215 {
00216   if ( !theMesh ) throw SALOME_Exception(LOCALIZED("NULL Mesh"));
00217 
00218   SMESHDS_Mesh* aMeshDS = const_cast< SMESH_Mesh* > ( theMesh )->GetMeshDS();
00219   if ( theMesh != _mesh )
00220   {
00221     computeLengths( aMeshDS, _TShapeToLength, _S0, _minLen );
00222     _mesh = theMesh;
00223   }
00224   double L = segLength( _S0, theEdgeLength, _minLen );
00225   return L / (theCoarseConst + theFineConst * _fineness);
00226 }
00227 
00228 //=============================================================================
00232 //=============================================================================
00233 
00234 double StdMeshers_AutomaticLength::GetLength(const SMESH_Mesh*   theMesh,
00235                                              const TopoDS_Shape& anEdge)
00236   throw(SALOME_Exception)
00237 {
00238   if ( !theMesh ) throw SALOME_Exception(LOCALIZED("NULL Mesh"));
00239 
00240   if ( anEdge.IsNull() || anEdge.ShapeType() != TopAbs_EDGE )
00241     throw SALOME_Exception(LOCALIZED("Bad edge shape"));
00242 
00243   if ( theMesh != _mesh )
00244   {
00245     SMESHDS_Mesh* aMeshDS = const_cast< SMESH_Mesh* > ( theMesh )->GetMeshDS();
00246     computeLengths( aMeshDS, _TShapeToLength, _S0, _minLen );
00247     _mesh = theMesh;
00248   }
00249 
00250   map<const TopoDS_TShape*, double>::iterator tshape_length =
00251     _TShapeToLength.find( getTShape( anEdge ));
00252 
00253   if ( tshape_length == _TShapeToLength.end() )
00254     return 1; // it is a dgenerated edge
00255 
00256   return tshape_length->second / (theCoarseConst + theFineConst * _fineness);
00257 }
00258 
00259 //=============================================================================
00263 //=============================================================================
00264 
00265 ostream & StdMeshers_AutomaticLength::SaveTo(ostream & save)
00266 {
00267   save << _fineness;
00268   return save;
00269 }
00270 
00271 //=============================================================================
00275 //=============================================================================
00276 
00277 istream & StdMeshers_AutomaticLength::LoadFrom(istream & load)
00278 {
00279   if ( ! ( load >> _fineness ))
00280     load.clear(ios::badbit | load.rdstate());
00281   return load;
00282 }
00283 
00284 //=============================================================================
00288 //=============================================================================
00289 
00290 ostream & operator <<(ostream & save, StdMeshers_AutomaticLength & hyp)
00291 {
00292   return hyp.SaveTo( save );
00293 }
00294 
00295 //=============================================================================
00299 //=============================================================================
00300 
00301 istream & operator >>(istream & load, StdMeshers_AutomaticLength & hyp)
00302 {
00303   return hyp.LoadFrom( load );
00304 }
00305 
00306 //================================================================================
00313 //================================================================================
00314 
00315 bool StdMeshers_AutomaticLength::SetParametersByMesh(const SMESH_Mesh*   theMesh,
00316                                                      const TopoDS_Shape& theShape)
00317 {
00318   if ( !theMesh || theShape.IsNull() )
00319     return false;
00320 
00321   _fineness = 0;
00322 
00323   SMESHDS_Mesh* aMeshDS = const_cast< SMESH_Mesh* >( theMesh )->GetMeshDS();
00324 
00325   int nbEdges = 0;
00326   TopTools_IndexedMapOfShape edgeMap;
00327   TopExp::MapShapes( theShape, TopAbs_EDGE, edgeMap );
00328   for ( int i = 1; i <= edgeMap.Extent(); ++i )
00329   {
00330     const TopoDS_Edge& edge = TopoDS::Edge( edgeMap( i ));
00331 
00332     // assure the base automatic length is stored in _TShapeToLength
00333     if ( i == 1 ) 
00334       GetLength( theMesh, edge );
00335 
00336     // get current segment length
00337     double L = SMESH_Algo::EdgeLength( edge );
00338     if ( L <= DBL_MIN )
00339       continue;
00340     SMESHDS_SubMesh * eSubMesh = aMeshDS->MeshElements( edge );
00341     if ( !eSubMesh )
00342       return false;
00343     int nbSeg = eSubMesh->NbElements();
00344     if ( nbSeg < 1 )
00345       continue;
00346     double segLen = L / nbSeg;
00347 
00348     // get segment length from _TShapeToLength
00349     map<const TopoDS_TShape*, double>::iterator tshape_length =
00350       _TShapeToLength.find( getTShape( edge ));
00351     if ( tshape_length == _TShapeToLength.end() )
00352       continue;
00353     double autoLen = tshape_length->second;
00354 
00355     // segLen = autoLen / (theCoarseConst + theFineConst * _fineness) -->
00356     _fineness += ( autoLen / segLen - theCoarseConst ) / theFineConst;
00357 
00358     ++nbEdges;
00359   }
00360   if ( nbEdges )
00361     _fineness /= nbEdges;
00362 
00363   if (_fineness > 1.0)
00364     _fineness = 1.0;
00365   else if (_fineness < 0.0)
00366     _fineness = 0.0;
00367 
00368   return nbEdges;
00369 }
00370 
00371 //================================================================================
00376 //================================================================================
00377 
00378 bool StdMeshers_AutomaticLength::SetParametersByDefaults(const TDefaults&  /*theDflts*/,
00379                                                          const SMESH_Mesh* /*theMesh*/)
00380 {
00381   return false;
00382 
00383   // assure the base automatic length is stored in _TShapeToLength
00384 //   GetLength( theMesh, elemLenght );
00385 
00386 //   // find maximal edge length
00387 //   double maxLen = 0;
00388 //   map<const TopoDS_TShape*, double>::iterator
00389 //     tshape_length = _TShapeToLength.begin(), slEnd = _TShapeToLength.end();
00390 //   for ( ; tshape_length != slEnd; ++tshape_length )
00391 //     if ( tshape_length->second > maxLen )
00392 //       maxLen = tshape_length->second;
00393 
00394 //   // automatic length for longest element
00395 //   double autoLen = GetLength( theMesh, maxLen );
00396 
00397 //   // elemLenght = autoLen / (theCoarseConst + theFineConst * _fineness) -->
00398 //   _fineness = ( autoLen / elemLenght - theCoarseConst ) / theFineConst;
00399 
00400 //   return true;
00401 }