Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #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;
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. / PI;
00121
00122 inline double segLength(double S0, double edgeLen, double minLen )
00123 {
00124
00125
00126
00127
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
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
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
00164 theTShapeToLengthMap.insert( make_pair( getTShape( edge ), L ));
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 const int NbSegMin = 5, NbSegMax = 10;
00184 const double Lrat1 = 1., Lrat2 = 10.;
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
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;
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
00333 if ( i == 1 )
00334 GetLength( theMesh, edge );
00335
00336
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
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
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& ,
00379 const SMESH_Mesh* )
00380 {
00381 return false;
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 }
00402
00403