Salome HOME
Join modifications from branch BR_DEBUG_3_2_0b1
[modules/smesh.git] / src / StdMeshers / StdMeshers_AutomaticLength.cxx
index 36ae6bec58e3668e2b5fd495ecae92302421b149..a91ccebb8f9c7e086795d80b3682384d52c89847 100644 (file)
@@ -17,7 +17,7 @@
 //  License along with this library; if not, write to the Free Software 
 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
 // 
-//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 //
 //
@@ -31,6 +31,7 @@
 #include "SMESH_Mesh.hxx"
 #include "SMESHDS_Mesh.hxx"
 #include "SMESH_Algo.hxx"
+#include "SMESHDS_SubMesh.hxx"
 
 #include "utilities.h"
 
@@ -47,13 +48,14 @@ using namespace std;
  */
 //=============================================================================
 
-StdMeshers_AutomaticLength::StdMeshers_AutomaticLength(int hypId, int studyId,
-       SMESH_Gen * gen):SMESH_Hypothesis(hypId, studyId, gen)
+StdMeshers_AutomaticLength::StdMeshers_AutomaticLength(int hypId, int studyId, SMESH_Gen * gen)
+  :SMESH_Hypothesis(hypId, studyId, gen)
 {
   _name = "AutomaticLength";
   _param_algo_dim = 1; // is used by SMESH_Regular_1D
 
   _mesh = 0;
+  _fineness = 0;
 }
 
 //=============================================================================
@@ -66,6 +68,35 @@ StdMeshers_AutomaticLength::~StdMeshers_AutomaticLength()
 {
 }
 
+//================================================================================
+/*!
+ * \brief Set Fineness
+ * \param theFineness - The Fineness value [0.0-1.0],
+ *                        0 - coarse mesh
+ *                        1 - fine mesh
+ * 
+ * Raise if theFineness is out of range
+ * The "Initial Number of Elements on the Shortest Edge" (S0)
+ * is divided by (0.5 + 4.5 x theFineness)
+ */
+//================================================================================
+
+const double theCoarseConst = 0.5;
+const double theFineConst   = 4.5;
+
+void StdMeshers_AutomaticLength::SetFineness(double theFineness)
+  throw(SALOME_Exception)
+{
+  if ( theFineness < 0.0 || theFineness > 1.0 )
+    throw SALOME_Exception(LOCALIZED("theFineness is out of range [0.0-1.0]"));
+
+  if ( _fineness != theFineness )
+  {
+    NotifySubMeshesHypothesisModification();
+    _fineness = theFineness;
+  }
+}
+
 //================================================================================
 /*!
  * \brief Return pointer to TopoDS_TShape
@@ -86,12 +117,11 @@ inline const TopoDS_TShape* getTShape(const TopoDS_Shape& theShape)
  */
 //================================================================================
 
-static void computeLengths( const SMESH_Mesh*                   theMesh,
+static void computeLengths( SMESHDS_Mesh*                       aMesh,
                             map<const TopoDS_TShape*, double> & theTShapeToLengthMap)
 {
   theTShapeToLengthMap.clear();
 
-  SMESHDS_Mesh* aMesh = const_cast< SMESH_Mesh* > ( theMesh )->GetMeshDS();
   TopoDS_Shape aMainShape = aMesh->ShapeToMesh();
 
   // Find length of longest and shortest edge
@@ -101,14 +131,16 @@ static void computeLengths( const SMESH_Mesh*                   theMesh,
   for ( int i = 1; i <= edgeMap.Extent(); ++i )
   {
     TopoDS_Edge edge = TopoDS::Edge( edgeMap(i) );
+    //if ( BRep_Tool::Degenerated( edge )) continue;
+
     Standard_Real L = SMESH_Algo::EdgeLength( edge );
-    if ( L > Lmax )
-      Lmax = L;
-    if ( L < Lmin )
-      Lmin = L;
+    if ( L < DBL_MIN ) continue;
+
+    if ( L > Lmax ) Lmax = L;
+    if ( L < Lmin ) Lmin = L;
+
     // remember i-th edge length
-    theTShapeToLengthMap.insert( theTShapeToLengthMap.end(),
-                                 make_pair( getTShape( edge ), L ));
+    theTShapeToLengthMap.insert( make_pair( getTShape( edge ), L ));
   }
 
   // Compute S0
@@ -168,15 +200,20 @@ double StdMeshers_AutomaticLength::GetLength(const SMESH_Mesh*   theMesh,
   if ( anEdge.IsNull() || anEdge.ShapeType() != TopAbs_EDGE )
     throw SALOME_Exception(LOCALIZED("Bad edge shape"));
 
-  if ( theMesh != _mesh ) {
-    computeLengths( theMesh, _TShapeToLength );
+  if ( theMesh != _mesh )
+  {
+    SMESHDS_Mesh* aMeshDS = const_cast< SMESH_Mesh* > ( theMesh )->GetMeshDS();
+    computeLengths( aMeshDS, _TShapeToLength );
     _mesh = theMesh;
   }
 
   map<const TopoDS_TShape*, double>::iterator tshape_length =
     _TShapeToLength.find( getTShape( anEdge ));
-  ASSERT( tshape_length != _TShapeToLength.end() );
-  return tshape_length->second;
+
+  if ( tshape_length == _TShapeToLength.end() )
+    return 1; // it is a dgenerated edge
+
+  return tshape_length->second / (theCoarseConst + theFineConst * _fineness);
 }
 
 //=============================================================================
@@ -187,6 +224,7 @@ double StdMeshers_AutomaticLength::GetLength(const SMESH_Mesh*   theMesh,
 
 ostream & StdMeshers_AutomaticLength::SaveTo(ostream & save)
 {
+  save << _fineness;
   return save;
 }
 
@@ -198,6 +236,8 @@ ostream & StdMeshers_AutomaticLength::SaveTo(ostream & save)
 
 istream & StdMeshers_AutomaticLength::LoadFrom(istream & load)
 {
+  if ( ! ( load >> _fineness ))
+    load.clear(ios::badbit | load.rdstate());
   return load;
 }
 
@@ -222,3 +262,68 @@ istream & operator >>(istream & load, StdMeshers_AutomaticLength & hyp)
 {
   return hyp.LoadFrom( load );
 }
+
+//================================================================================
+/*!
+ * \brief Initialize Fineness by the mesh built on the geometry
+ * \param theMesh - the built mesh
+ * \param theShape - the geometry of interest
+ * \retval bool - true if parameter values have been successfully defined
+ */
+//================================================================================
+
+bool StdMeshers_AutomaticLength::SetParametersByMesh(const SMESH_Mesh*   theMesh,
+                                                     const TopoDS_Shape& theShape)
+{
+  if ( !theMesh || theShape.IsNull() )
+    return false;
+
+  _fineness = 0;
+
+  SMESHDS_Mesh* aMeshDS = const_cast< SMESH_Mesh* >( theMesh )->GetMeshDS();
+
+  int nbEdges = 0;
+  TopTools_IndexedMapOfShape edgeMap;
+  TopExp::MapShapes( theShape, TopAbs_EDGE, edgeMap );
+  for ( int i = 1; i <= edgeMap.Extent(); ++i )
+  {
+    const TopoDS_Edge& edge = TopoDS::Edge( edgeMap( i ));
+
+    // assure the base automatic length is stored in _TShapeToLength
+    if ( i == 1 ) 
+      GetLength( theMesh, edge );
+
+    // get current segment length
+    double L = SMESH_Algo::EdgeLength( edge );
+    if ( L <= DBL_MIN )
+      continue;
+    SMESHDS_SubMesh * eSubMesh = aMeshDS->MeshElements( edge );
+    if ( !eSubMesh )
+      return false;
+    int nbSeg = eSubMesh->NbElements();
+    if ( nbSeg < 1 )
+      continue;
+    double segLen = L / nbSeg;
+
+    // get segment length from _TShapeToLength
+    map<const TopoDS_TShape*, double>::iterator tshape_length =
+      _TShapeToLength.find( getTShape( edge ));
+    if ( tshape_length == _TShapeToLength.end() )
+      continue;
+    double autoLen = tshape_length->second;
+
+    // segLen = autoLen / (theCoarseConst + theFineConst * _fineness) -->
+    _fineness += ( autoLen / segLen - theCoarseConst ) / theFineConst;
+
+    ++nbEdges;
+  }
+  if ( nbEdges )
+    _fineness /= nbEdges;
+
+  if (_fineness > 1.0)
+    _fineness = 1.0;
+  else if (_fineness < 0.0)
+    _fineness = 0.0;
+
+  return nbEdges;
+}