Salome HOME
Integrate patch from G.David (add missing include)
[modules/smesh.git] / src / StdMeshers / StdMeshers_Regular_1D.cxx
index b2a5074332644b76cb0acec0002e959fb3ed4e80..331d29aea2990d95f9aa63e63e2cdf872a8dcdb9 100644 (file)
@@ -1,43 +1,42 @@
-//  SMESH SMESH : implementaion of SMESH idl descriptions
+//  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
 //
-//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
-// 
-//  This library is free software; you can redistribute it and/or 
-//  modify it under the terms of the GNU Lesser General Public 
-//  License as published by the Free Software Foundation; either 
-//  version 2.1 of the License. 
-// 
-//  This library is distributed in the hope that it will be useful, 
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
-//  Lesser General Public License for more details. 
-// 
-//  You should have received a copy of the GNU Lesser General Public 
-//  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.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
 //
+//  You should have received a copy of the GNU Lesser General Public
+//  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.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
+//  SMESH SMESH : implementaion of SMESH idl descriptions
 //  File   : StdMeshers_Regular_1D.cxx
 //           Moved here from SMESH_Regular_1D.cxx
 //  Author : Paul RASCLE, EDF
 //  Module : SMESH
-//  $Header$
 
 #include "StdMeshers_Regular_1D.hxx"
 #include "StdMeshers_Distribution.hxx"
 
-#include "StdMeshers_LocalLength.hxx"
-#include "StdMeshers_NumberOfSegments.hxx"
 #include "StdMeshers_Arithmetic1D.hxx"
-#include "StdMeshers_StartEndLength.hxx"
-#include "StdMeshers_Deflection1D.hxx"
 #include "StdMeshers_AutomaticLength.hxx"
-#include "StdMeshers_SegmentLengthAroundVertex.hxx"
+#include "StdMeshers_Deflection1D.hxx"
+#include "StdMeshers_LocalLength.hxx"
+#include "StdMeshers_MaxLength.hxx"
+#include "StdMeshers_NumberOfSegments.hxx"
 #include "StdMeshers_Propagation.hxx"
+#include "StdMeshers_SegmentLengthAroundVertex.hxx"
+#include "StdMeshers_StartEndLength.hxx"
 
 #include "SMESH_Gen.hxx"
 #include "SMESH_Mesh.hxx"
@@ -64,6 +63,7 @@
 #include <TopoDS_Edge.hxx>
 
 #include <string>
+#include <limits>
 
 using namespace std;
 
@@ -74,21 +74,24 @@ using namespace std;
 //=============================================================================
 
 StdMeshers_Regular_1D::StdMeshers_Regular_1D(int hypId, int studyId,
-       SMESH_Gen * gen):SMESH_1D_Algo(hypId, studyId, gen)
+        SMESH_Gen * gen):SMESH_1D_Algo(hypId, studyId, gen)
 {
-       MESSAGE("StdMeshers_Regular_1D::StdMeshers_Regular_1D");
-       _name = "Regular_1D";
-       _shapeType = (1 << TopAbs_EDGE);
-
-       _compatibleHypothesis.push_back("LocalLength");
-       _compatibleHypothesis.push_back("NumberOfSegments");
-       _compatibleHypothesis.push_back("StartEndLength");
-       _compatibleHypothesis.push_back("Deflection1D");
-       _compatibleHypothesis.push_back("Arithmetic1D");
-       _compatibleHypothesis.push_back("AutomaticLength");
-
-       _compatibleHypothesis.push_back("QuadraticMesh"); // auxiliary !!!
-       _compatibleHypothesis.push_back("Propagation"); // auxiliary !!!
+        MESSAGE("StdMeshers_Regular_1D::StdMeshers_Regular_1D");
+        _name = "Regular_1D";
+        _shapeType = (1 << TopAbs_EDGE);
+        _fpHyp = 0;
+
+        _compatibleHypothesis.push_back("LocalLength");
+        _compatibleHypothesis.push_back("MaxLength");
+        _compatibleHypothesis.push_back("NumberOfSegments");
+        _compatibleHypothesis.push_back("StartEndLength");
+        _compatibleHypothesis.push_back("Deflection1D");
+        _compatibleHypothesis.push_back("Arithmetic1D");
+        _compatibleHypothesis.push_back("FixedPoints1D");
+        _compatibleHypothesis.push_back("AutomaticLength");
+
+        _compatibleHypothesis.push_back("QuadraticMesh"); // auxiliary !!!
+        _compatibleHypothesis.push_back("Propagation"); // auxiliary !!!
 }
 
 //=============================================================================
@@ -146,14 +149,28 @@ bool StdMeshers_Regular_1D::CheckHypothesis
     const StdMeshers_LocalLength * hyp =
       dynamic_cast <const StdMeshers_LocalLength * >(theHyp);
     ASSERT(hyp);
-    //_value[ BEG_LENGTH_IND ] = _value[ END_LENGTH_IND ] = hyp->GetLength();
     _value[ BEG_LENGTH_IND ] = hyp->GetLength();
-    _value[ END_LENGTH_IND ] = hyp->GetPrecision();
+    _value[ PRECISION_IND ] = hyp->GetPrecision();
     ASSERT( _value[ BEG_LENGTH_IND ] > 0 );
     _hypType = LOCAL_LENGTH;
     aStatus = SMESH_Hypothesis::HYP_OK;
   }
 
+  else if (hypName == "MaxLength")
+  {
+    const StdMeshers_MaxLength * hyp =
+      dynamic_cast <const StdMeshers_MaxLength * >(theHyp);
+    ASSERT(hyp);
+    _value[ BEG_LENGTH_IND ] = hyp->GetLength();
+    if ( hyp->GetUsePreestimatedLength() ) {
+      if ( int nbSeg = aMesh.GetGen()->GetBoundaryBoxSegmentation() )
+        _value[ BEG_LENGTH_IND ] = aMesh.GetShapeDiagonalSize() / nbSeg;
+    }
+    ASSERT( _value[ BEG_LENGTH_IND ] > 0 );
+    _hypType = MAX_LENGTH;
+    aStatus = SMESH_Hypothesis::HYP_OK;
+  }
+
   else if (hypName == "NumberOfSegments")
   {
     const StdMeshers_NumberOfSegments * hyp =
@@ -166,12 +183,15 @@ bool StdMeshers_Regular_1D::CheckHypothesis
     {
     case StdMeshers_NumberOfSegments::DT_Scale:
       _value[ SCALE_FACTOR_IND ] = hyp->GetScaleFactor();
+      _revEdgesIDs = hyp->GetReversedEdges();
       break;
     case StdMeshers_NumberOfSegments::DT_TabFunc:
       _vvalue[ TAB_FUNC_IND ] = hyp->GetTableFunction();
+      _revEdgesIDs = hyp->GetReversedEdges();
       break;
     case StdMeshers_NumberOfSegments::DT_ExprFunc:
       _svalue[ EXPR_FUNC_IND ] = hyp->GetExpressionFunction();
+      _revEdgesIDs = hyp->GetReversedEdges();
       break;
     case StdMeshers_NumberOfSegments::DT_Regular:
       break;
@@ -195,6 +215,19 @@ bool StdMeshers_Regular_1D::CheckHypothesis
     _value[ END_LENGTH_IND ] = hyp->GetLength( false );
     ASSERT( _value[ BEG_LENGTH_IND ] > 0 && _value[ END_LENGTH_IND ] > 0 );
     _hypType = ARITHMETIC_1D;
+
+    _revEdgesIDs = hyp->GetReversedEdges();
+
+    aStatus = SMESH_Hypothesis::HYP_OK;
+  }
+
+  else if (hypName == "FixedPoints1D") {
+    _fpHyp = dynamic_cast <const StdMeshers_FixedPoints1D*>(theHyp);
+    ASSERT(_fpHyp);
+    _hypType = FIXED_POINTS_1D;
+
+    _revEdgesIDs = _fpHyp->GetReversedEdges();
+
     aStatus = SMESH_Hypothesis::HYP_OK;
   }
 
@@ -207,6 +240,9 @@ bool StdMeshers_Regular_1D::CheckHypothesis
     _value[ END_LENGTH_IND ] = hyp->GetLength( false );
     ASSERT( _value[ BEG_LENGTH_IND ] > 0 && _value[ END_LENGTH_IND ] > 0 );
     _hypType = BEG_END_LENGTH;
+
+    _revEdgesIDs = hyp->GetReversedEdges();
+
     aStatus = SMESH_Hypothesis::HYP_OK;
   }
 
@@ -226,11 +262,11 @@ bool StdMeshers_Regular_1D::CheckHypothesis
     StdMeshers_AutomaticLength * hyp = const_cast<StdMeshers_AutomaticLength *>
       (dynamic_cast <const StdMeshers_AutomaticLength * >(theHyp));
     ASSERT(hyp);
-    //_value[ BEG_LENGTH_IND ] = _value[ END_LENGTH_IND ] = hyp->GetLength( &aMesh, aShape );
-    _value[ BEG_LENGTH_IND ] = hyp->GetLength( &aMesh, aShape );
-    _value[ END_LENGTH_IND ] = Precision::Confusion(); // ?? or set to zero?
+    _value[ BEG_LENGTH_IND ] = _value[ END_LENGTH_IND ] = hyp->GetLength( &aMesh, aShape );
+//     _value[ BEG_LENGTH_IND ] = hyp->GetLength( &aMesh, aShape );
+//     _value[ END_LENGTH_IND ] = Precision::Confusion(); // ?? or set to zero?
     ASSERT( _value[ BEG_LENGTH_IND ] > 0 );
-    _hypType = LOCAL_LENGTH;
+    _hypType = MAX_LENGTH;
     aStatus = SMESH_Hypothesis::HYP_OK;
   }
   else
@@ -413,11 +449,6 @@ static void compensateError(double a1, double an,
 
 void StdMeshers_Regular_1D::SetEventListener(SMESH_subMesh* subMesh)
 {
-//   static VertexEventListener listener;
-//   SMESH_subMeshIteratorPtr smIt = subMesh->getDependsOnIterator(false,false);
-//   while (smIt->more()) {
-//     subMesh->SetEventListener( &listener, 0, smIt->next() );
-//   }
   StdMeshers_Propagation::SetPropagationMgr( subMesh );
 }
 
@@ -567,10 +598,18 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh &     theMesh,
   switch( _hypType )
   {
   case LOCAL_LENGTH:
+  case MAX_LENGTH:
   case NB_SEGMENTS: {
 
     double eltSize = 1;
-    if ( _hypType == LOCAL_LENGTH )
+    if ( _hypType == MAX_LENGTH )
+    {
+      double nbseg = ceil(theLength / _value[ BEG_LENGTH_IND ]); // integer sup
+      if (nbseg <= 0)
+        nbseg = 1;                        // degenerated edge
+      eltSize = theLength / nbseg;
+    }
+    else if ( _hypType == LOCAL_LENGTH )
     {
       // Local Length hypothesis
       double nbseg = ceil(theLength / _value[ BEG_LENGTH_IND ]); // integer sup
@@ -601,7 +640,7 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh &     theMesh,
       }
       if (!isFound) // not found by meshed edge in the propagation chain, use precision
       {
-        double aPrecision = _value[ END_LENGTH_IND ];
+        double aPrecision = _value[ PRECISION_IND ];
         double nbseg_prec = ceil((theLength / _value[ BEG_LENGTH_IND ]) - aPrecision);
         if (nbseg_prec == (nbseg - 1)) nbseg--;
       }
@@ -624,7 +663,7 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh &     theMesh,
           double scale = _value[ SCALE_FACTOR_IND ];
 
           if (fabs(scale - 1.0) < Precision::Confusion()) {
-            // special case to avoid division on zero
+            // special case to avoid division by zero
             for (int i = 1; i < NbSegm; i++) {
               double param = f + (l - f) * i / NbSegm;
               theParams.push_back( param );
@@ -719,7 +758,7 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh &     theMesh,
     double an = _value[ END_LENGTH_IND ];
 
     double  q = ( an - a1 ) / ( 2 *theLength/( a1 + an ) - 1 );
-    int     n = int( 1 + ( an - a1 ) / q );
+    int n = fabs(q) > numeric_limits<double>::min() ? int( 1 + ( an - a1 ) / q ) : 1+theLength/a1;
 
     double U1 = theReverse ? l : f;
     double Un = theReverse ? f : l;
@@ -747,6 +786,62 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh &     theMesh,
     return true;
   }
 
+  case FIXED_POINTS_1D: {
+    const std::vector<double>& aPnts = _fpHyp->GetPoints();
+    const std::vector<int>& nbsegs = _fpHyp->GetNbSegments();
+    int i = 0;
+    TColStd_SequenceOfReal Params;
+    for(; i<aPnts.size(); i++) {
+      if( aPnts[i]<0.0001 || aPnts[i]>0.9999 ) continue;
+      int j=1;
+      bool IsExist = false;
+      for(; j<=Params.Length(); j++) {
+        if( fabs(aPnts[i]-Params.Value(j)) < 1e-4 ) {
+          IsExist = true;
+          break;
+        }
+        if( aPnts[i]<Params.Value(j) ) break;
+      }
+      if(!IsExist) Params.InsertBefore(j,aPnts[i]);
+    }
+    double pf, pl, par2, par1, psize;
+    if (theReverse) {
+      pf = l;
+      pl = f;
+    }
+    else {
+      pf = f;
+      pl = l;
+    }
+    psize = pl - pf;
+    par1 = pf;
+    //cout<<"aPnts.size() = "<<aPnts.size()<<"  Params.Length() = "
+    //    <<Params.Length()<<"   nbsegs.size() = "<<nbsegs.size()<<endl;
+    for(i=0; i<Params.Length(); i++) {
+      par2 = pf + Params.Value(i+1)*psize;
+      int nbseg = ( i > nbsegs.size()-1 ) ? nbsegs[0] : nbsegs[i];
+      double dp = (par2-par1)/nbseg;
+      int j = 1;
+      for(; j<=nbseg; j++) {
+        double param = par1 + dp*j;
+        theParams.push_back( param );
+      }
+      par1 = par2;
+    }
+    // add for last
+    int nbseg = ( nbsegs.size() > Params.Length() ) ? nbsegs[Params.Length()] : nbsegs[0];
+    double dp = (pl-par1)/nbseg;
+    int j = 1;
+    for(; j<nbseg; j++) {
+      double param = par1 + dp*j;
+      theParams.push_back( param );
+    }
+    if (theReverse) {
+      theParams.reverse(); // NPAL18025
+    }
+    return true;
+  }
+
   case DEFLECTION: {
 
     GCPnts_UniformDeflection Discret(theC3d, _value[ DEFLECTION_IND ], f, l, true);
@@ -802,8 +897,19 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & t
   {
     list< double > params;
     bool reversed = false;
-    if ( !_mainEdge.IsNull() )
+    if ( theMesh.GetShapeToMesh().ShapeType() >= TopAbs_WIRE ) {
+      reversed = ( EE.Orientation() == TopAbs_REVERSED );
+    }
+    if ( !_mainEdge.IsNull() ) {
       reversed = ( _mainEdge.Orientation() == TopAbs_REVERSED );
+    }
+    else if ( _revEdgesIDs.size() > 0 ) {
+      for ( int i = 0; i < _revEdgesIDs.size(); i++) {
+        if ( _revEdgesIDs[i] == shapeID ) {
+          reversed = !reversed;
+        }
+      }
+    }
 
     BRepAdaptor_Curve C3d( E );
     double length = EdgeLength( E );
@@ -913,6 +1019,82 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & t
   return true;
 }
 
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+bool StdMeshers_Regular_1D::Evaluate(SMESH_Mesh & theMesh,
+                                     const TopoDS_Shape & theShape,
+                                     MapShapeNbElems& aResMap)
+{
+  if ( _hypType == NONE )
+    return false;
+
+  SMESHDS_Mesh * meshDS = theMesh.GetMeshDS();
+
+  const TopoDS_Edge & EE = TopoDS::Edge(theShape);
+  TopoDS_Edge E = TopoDS::Edge(EE.Oriented(TopAbs_FORWARD));
+  //  int shapeID = meshDS->ShapeToIndex( E );
+
+  double f, l;
+  Handle(Geom_Curve) Curve = BRep_Tool::Curve(E, f, l);
+
+  TopoDS_Vertex VFirst, VLast;
+  TopExp::Vertices(E, VFirst, VLast);   // Vfirst corresponds to f and Vlast to l
+
+  ASSERT(!VFirst.IsNull());
+  ASSERT(!VLast.IsNull());
+
+  std::vector<int> aVec(SMDSEntity_Last);
+  for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i] = 0;
+
+  if (!Curve.IsNull()) {
+    list< double > params;
+
+    BRepAdaptor_Curve C3d( E );
+    double length = EdgeLength( E );
+    if ( ! computeInternalParameters( theMesh, C3d, length, f, l, params, false, true )) {
+      SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
+      aResMap.insert(std::make_pair(sm,aVec));
+      SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
+      smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this));
+      return false;
+    }
+    redistributeNearVertices( theMesh, C3d, length, params, VFirst, VLast );
+
+    if(_quadraticMesh) {
+      aVec[SMDSEntity_Node] = 2*params.size() + 1;
+      aVec[SMDSEntity_Quad_Edge] = params.size() + 1;
+    }
+    else {
+      aVec[SMDSEntity_Node] = params.size();
+      aVec[SMDSEntity_Edge] = params.size() + 1;
+    }
+    
+  }
+  else {
+    //MESSAGE("************* Degenerated edge! *****************");
+    // Edge is a degenerated Edge : We put n = 5 points on the edge.
+    if(_quadraticMesh) {
+      aVec[SMDSEntity_Node] = 11;
+      aVec[SMDSEntity_Quad_Edge] = 6;
+    }
+    else {
+      aVec[SMDSEntity_Node] = 5;
+      aVec[SMDSEntity_Edge] = 6;
+    }
+  }
+
+  SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
+  aResMap.insert(std::make_pair(sm,aVec));
+
+  return true;
+}
+
+
 //=============================================================================
 /*!
  *  See comments in SMESH_Algo.cxx