Salome HOME
NPAL18095: Pb. with dump python and mesh group by filter.
[modules/smesh.git] / src / StdMeshers / StdMeshers_Regular_1D.cxx
index 7bb54f6b00ba4f5ad02534aad0f74a8da89ed179..9d051ae1ac9557ff87dce8843b146ad02d170329 100644 (file)
 #include "StdMeshers_Deflection1D.hxx"
 #include "StdMeshers_AutomaticLength.hxx"
 #include "StdMeshers_SegmentLengthAroundVertex.hxx"
+#include "StdMeshers_Propagation.hxx"
 
 #include "SMESH_Gen.hxx"
 #include "SMESH_Mesh.hxx"
 #include "SMESH_HypoFilter.hxx"
 #include "SMESH_subMesh.hxx"
 #include "SMESH_subMeshEventListener.hxx"
+#include "SMESH_Comment.hxx"
 
 #include "SMDS_MeshElement.hxx"
 #include "SMDS_MeshNode.hxx"
 
 #include <BRepAdaptor_Curve.hxx>
 #include <BRep_Tool.hxx>
-#include <TopoDS_Edge.hxx>
-#include <TopExp_Explorer.hxx>
 #include <GCPnts_AbscissaPoint.hxx>
 #include <GCPnts_UniformAbscissa.hxx>
 #include <GCPnts_UniformDeflection.hxx>
 #include <Precision.hxx>
-
-#include <Standard_ErrorHandler.hxx>
-#include <Standard_Failure.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Edge.hxx>
 
 #include <string>
-//#include <math.h>
 
 using namespace std;
 
@@ -88,6 +88,7 @@ StdMeshers_Regular_1D::StdMeshers_Regular_1D(int hypId, int studyId,
        _compatibleHypothesis.push_back("AutomaticLength");
 
        _compatibleHypothesis.push_back("QuadraticMesh"); // auxiliary !!!
+       _compatibleHypothesis.push_back("Propagation"); // auxiliary !!!
 }
 
 //=============================================================================
@@ -235,7 +236,7 @@ bool StdMeshers_Regular_1D::CheckHypothesis
 }
 
 static bool computeParamByFunc(Adaptor3d_Curve& C3d, double first, double last,
-                               double length, bool theReverse, 
+                               double length, bool theReverse,
                                int nbSeg, Function& func,
                                list<double>& theParams)
 {
@@ -260,7 +261,7 @@ static bool computeParamByFunc(Adaptor3d_Curve& C3d, double first, double last,
     sprintf(  buf, "%f\n", float(x[i] ) );
     MESSAGE( buf );
   }
-    
+
 
 
   // apply parameters in range [0,1] to the space of the curve
@@ -313,28 +314,24 @@ static void compensateError(double a1, double an,
   int i, nPar = theParams.size();
   if ( a1 + an < length && nPar > 1 )
   {
+    bool reverse = ( U1 > Un );
+    GCPnts_AbscissaPoint Discret(C3d, reverse ? an : -an, Un);
+    if ( !Discret.IsDone() )
+      return;
+    double Utgt = Discret.Parameter(); // target value of the last parameter
     list<double>::reverse_iterator itU = theParams.rbegin();
-    double Ul = *itU++;
-    // dist from the last point to the edge end <Un>, it should be equal to <an>
-    double Ln = GCPnts_AbscissaPoint::Length( C3d, Ul, Un );
-    double dLn = an - Ln; // signed error of <an>
-    if ( Abs( dLn ) <= Precision::Confusion() )
+    double Ul = *itU++; // real value of the last parameter
+    double dUn = Utgt - Ul; // parametric error of <an>
+    if ( Abs(dUn) <= Precision::Confusion() )
       return;
     double dU = Abs( Ul - *itU ); // parametric length of the last but one segment
-    double dUn = dLn * Abs( Un - U1 ) / length; // parametric error of <an>
-    if ( adjustNeighbors2an || dUn < 0.5 * dU ) { // last segment is a bit shorter than it should
-      dUn = -dUn; // move the last parameter to the edge beginning
+    if ( adjustNeighbors2an || Abs(dUn) < 0.5 * dU ) { // last segment is a bit shorter than it should
+      // move the last parameter to the edge beginning
     }
     else {  // last segment is much shorter than it should -> remove the last param and
       theParams.pop_back(); nPar--; // move the rest points toward the edge end
-      Ln = GCPnts_AbscissaPoint::Length( C3d, theParams.back(), Un );
-      dUn = ( an - Ln ) * Abs( Un - U1 ) / length;
-      if ( dUn < 0.5 * dU )
-        dUn = -dUn;
+      dUn = Utgt - theParams.back();
     }
-    bool reverse = ( U1 > Un );
-    if ( reverse )
-      dUn = -dUn;
 
     double q  = dUn / ( nPar - 1 );
     if ( !adjustNeighbors2an ) {
@@ -348,7 +345,7 @@ static void compensateError(double a1, double an,
       double sign = reverse ? -1 : 1;
       double prevU = theParams.back();
       itU = theParams.rbegin();
-      for ( ++itU, i = 1; i < nPar; ++itU, i++ ) {
+      for ( ++itU, i = 2; i < nPar; ++itU, i++ ) {
         double newU = *itU + dUn;
         if ( newU*sign < prevU*sign ) {
           prevU = *itU = newU;
@@ -380,25 +377,25 @@ static void compensateError(double a1, double an,
  */
 //================================================================================
 
-struct VertexEventListener : public SMESH_subMeshEventListener
-{
-  VertexEventListener():SMESH_subMeshEventListener(0) // won't be deleted by submesh
-  {}
-  /*!
-   * \brief Clean mesh on edges
-   * \param event - algo_event or compute_event itself (of SMESH_subMesh)
-   * \param eventType - ALGO_EVENT or COMPUTE_EVENT (of SMESH_subMesh)
-   * \param subMesh - the submesh where the event occures
-   */
-  void ProcessEvent(const int event, const int eventType, SMESH_subMesh* subMesh,
-                    EventListenerData*, SMESH_Hypothesis*)
-  {
-    if ( eventType == SMESH_subMesh::ALGO_EVENT) // all algo events
-    {
-      subMesh->ComputeStateEngine( SMESH_subMesh::MODIF_ALGO_STATE );
-    }
-  }
-}; // struct VertexEventListener
+// struct VertexEventListener : public SMESH_subMeshEventListener
+// {
+//   VertexEventListener():SMESH_subMeshEventListener(0) // won't be deleted by submesh
+//   {}
+//   /*!
+//    * \brief Clean mesh on edges
+//    * \param event - algo_event or compute_event itself (of SMESH_subMesh)
+//    * \param eventType - ALGO_EVENT or COMPUTE_EVENT (of SMESH_subMesh)
+//    * \param subMesh - the submesh where the event occures
+//    */
+//   void ProcessEvent(const int event, const int eventType, SMESH_subMesh* subMesh,
+//                     EventListenerData*, const SMESH_Hypothesis*)
+//   {
+//     if ( eventType == SMESH_subMesh::ALGO_EVENT) // all algo events
+//     {
+//       subMesh->ComputeStateEngine( SMESH_subMesh::MODIF_ALGO_STATE );
+//     }
+//   }
+// }; // struct VertexEventListener
 
 //=============================================================================
 /*!
@@ -412,13 +409,12 @@ struct VertexEventListener : public SMESH_subMeshEventListener
 
 void StdMeshers_Regular_1D::SetEventListener(SMESH_subMesh* subMesh)
 {
-  static VertexEventListener listener;
-  const map < int, SMESH_subMesh * >& vSMs = subMesh->DependsOn();
-  map < int, SMESH_subMesh * >::const_iterator itsub;
-  for (itsub = vSMs.begin(); itsub != vSMs.end(); itsub++)
-  {
-    subMesh->SetEventListener( &listener, 0, itsub->second );
-  }
+//   static VertexEventListener listener;
+//   SMESH_subMeshIteratorPtr smIt = subMesh->getDependsOnIterator(false,false);
+//   while (smIt->more()) {
+//     subMesh->SetEventListener( &listener, 0, smIt->next() );
+//   }
+  StdMeshers_Propagation::SetPropagationMgr( subMesh );
 }
 
 //=============================================================================
@@ -444,9 +440,15 @@ const StdMeshers_SegmentLengthAroundVertex*
 StdMeshers_Regular_1D::getVertexHyp(SMESH_Mesh &          theMesh,
                                     const TopoDS_Vertex & theV)
 {
-  static SMESH_HypoFilter filter( SMESH_HypoFilter::HasName("SegmentLengthAroundVertex"));
-  const SMESH_Hypothesis * hyp = theMesh.GetHypothesis( theV, filter, true );
-  return static_cast<const StdMeshers_SegmentLengthAroundVertex*>( hyp );
+  static SMESH_HypoFilter filter( SMESH_HypoFilter::HasName("SegmentAroundVertex_0D"));
+  if ( const SMESH_Hypothesis * h = theMesh.GetHypothesis( theV, filter, true ))
+  {
+    SMESH_Algo* algo = const_cast< SMESH_Algo* >( static_cast< const SMESH_Algo* > ( h ));
+    const list <const SMESHDS_Hypothesis *> & hypList = algo->GetUsedHypothesis( theMesh, theV, 0 );
+    if ( !hypList.empty() && string("SegmentLengthAroundVertex") == hypList.front()->GetName() )
+      return static_cast<const StdMeshers_SegmentLengthAroundVertex*>( hypList.front() );
+  }
+  return 0;
 }
 
 //================================================================================
@@ -465,7 +467,7 @@ void StdMeshers_Regular_1D::redistributeNearVertices (SMESH_Mesh &          theM
                                                       double                theLength,
                                                       std::list< double > & theParameters,
                                                       const TopoDS_Vertex & theVf,
-                                                      const TopoDS_Vertex & theVl) const
+                                                      const TopoDS_Vertex & theVl)
 {
   double f = theC3d.FirstParameter(), l = theC3d.LastParameter();
   int nPar = theParameters.size();
@@ -477,14 +479,31 @@ void StdMeshers_Regular_1D::redistributeNearVertices (SMESH_Mesh &          theM
       double vertexLength = hyp->GetLength();
       if ( vertexLength > theLength / 2.0 )
         continue;
-      if ( isEnd1 ) {
+      if ( isEnd1 ) { // to have a segment of interest at end of theParameters
         theParameters.reverse();
         std::swap( f, l );
       }
-      if ( _hypType == NB_SEGMENTS || nPar < 5 )
+      if ( _hypType == NB_SEGMENTS )
       {
         compensateError(0, vertexLength, f, l, theLength, theC3d, theParameters, true );
       }
+      else if ( nPar <= 3 )
+      {
+        if ( !isEnd1 )
+          vertexLength = -vertexLength;
+        GCPnts_AbscissaPoint Discret(theC3d, vertexLength, l);
+        if ( Discret.IsDone() ) {
+          if ( nPar == 0 )
+            theParameters.push_back( Discret.Parameter());
+          else {
+            double L = GCPnts_AbscissaPoint::Length( theC3d, theParameters.back(), l);
+            if ( vertexLength < L / 2.0 )
+              theParameters.push_back( Discret.Parameter());
+            else
+              compensateError(0, vertexLength, f, l, theLength, theC3d, theParameters, true );
+          }
+        }
+      }
       else
       {
         // recompute params between the last segment and a middle one.
@@ -533,7 +552,7 @@ bool StdMeshers_Regular_1D::computeInternalParameters(Adaptor3d_Curve& theC3d,
                                                       double           theFirstU,
                                                       double           theLastU,
                                                       list<double> &   theParams,
-                                                      const bool       theReverse) const
+                                                      const bool       theReverse)
 {
   theParams.clear();
 
@@ -613,7 +632,7 @@ bool StdMeshers_Regular_1D::computeInternalParameters(Adaptor3d_Curve& theC3d,
     }
     GCPnts_UniformAbscissa Discret(theC3d, eltSize, f, l);
     if ( !Discret.IsDone() )
-      return false;
+      return error( "GCPnts_UniformAbscissa failed");
 
     int NbPoints = Discret.NbPoints();
     for ( int i = 2; i < NbPoints; i++ )
@@ -643,13 +662,14 @@ bool StdMeshers_Regular_1D::computeInternalParameters(Adaptor3d_Curve& theC3d,
       GCPnts_AbscissaPoint Discret( theC3d, eltSize, param );
       if ( !Discret.IsDone() ) break;
       param = Discret.Parameter();
-      if ( param > f && param < l )
+      if ( f < param && param < l )
         theParams.push_back( param );
       else
         break;
       eltSize *= q;
     }
     compensateError( a1, an, U1, Un, theLength, theC3d, theParams );
+    if (theReverse) theParams.reverse(); // NPAL18025
     return true;
   }
 
@@ -684,6 +704,7 @@ bool StdMeshers_Regular_1D::computeInternalParameters(Adaptor3d_Curve& theC3d,
       eltSize += q;
     }
     compensateError( a1, an, U1, Un, theLength, theC3d, theParams );
+    if (theReverse) theParams.reverse(); // NPAL18025
 
     return true;
   }
@@ -701,7 +722,6 @@ bool StdMeshers_Regular_1D::computeInternalParameters(Adaptor3d_Curve& theC3d,
       theParams.push_back( param );
     }
     return true;
-    
   }
 
   default:;
@@ -718,8 +738,6 @@ bool StdMeshers_Regular_1D::computeInternalParameters(Adaptor3d_Curve& theC3d,
 
 bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape)
 {
-  //MESSAGE("StdMeshers_Regular_1D::Compute");
-
   if ( _hypType == NONE )
     return false;
 
@@ -736,38 +754,25 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh
   TopExp::Vertices(E, VFirst, VLast);   // Vfirst corresponds to f and Vlast to l
 
   ASSERT(!VFirst.IsNull());
-  const SMDS_MeshNode * idFirst = SMESH_Algo::VertexNode( VFirst, meshDS );
-  if (!idFirst) {
-    MESSAGE (" NO NODE BUILT ON VERTEX ");
-    return false;
-  }
-
   ASSERT(!VLast.IsNull());
+  const SMDS_MeshNode * idFirst = SMESH_Algo::VertexNode( VFirst, meshDS );
   const SMDS_MeshNode * idLast = SMESH_Algo::VertexNode( VLast, meshDS );
-  if (!idLast) {
-    MESSAGE (" NO NODE BUILT ON VERTEX ");
-    return false;
-  }
+  if (!idFirst || !idLast)
+    return error( COMPERR_BAD_INPUT_MESH, "No node on vertex");
 
-  if (!Curve.IsNull()) {
+  if (!Curve.IsNull())
+  {
     list< double > params;
     bool reversed = false;
     if ( !_mainEdge.IsNull() )
-      reversed = aMesh.IsReversedInChain( EE, _mainEdge );
+      reversed = ( _mainEdge.Orientation() == TopAbs_REVERSED );
+
     BRepAdaptor_Curve C3d( E );
     double length = EdgeLength( E );
-    try {
-#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
-      OCC_CATCH_SIGNALS;
-#endif
-      if ( ! computeInternalParameters( C3d, length, f, l, params, reversed )) {
-        return false;
-      }
-      redistributeNearVertices( aMesh, C3d, length, params, VFirst, VLast );
-    }
-    catch ( Standard_Failure ) {
+    if ( ! computeInternalParameters( C3d, length, f, l, params, reversed )) {
       return false;
     }
+    redistributeNearVertices( aMesh, C3d, length, params, VFirst, VLast );
 
     // edge extrema (indexes : 1 & NbPoints) already in SMDS (TopoDS_Vertex)
     // only internal nodes receive an edge position with param on curve
@@ -775,7 +780,17 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh
     const SMDS_MeshNode * idPrev = idFirst;
     double parPrev = f;
     double parLast = l;
-    
+
+    /* NPAL18025
+    if (reversed) {
+      idPrev = idLast;
+      idLast = idFirst;
+      idFirst = idPrev;
+      parPrev = l;
+      parLast = f;
+    }
+    */
+
     for (list<double>::iterator itU = params.begin(); itU != params.end(); itU++) {
       double param = *itU;
       gp_Pnt P = Curve->Value(param);
@@ -814,11 +829,14 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh
       meshDS->SetMeshElementOnShape(edge, shapeID);
     }
   }
-  else {
+  else
+  {
+    //MESSAGE("************* Degenerated edge! *****************");
+
     // Edge is a degenerated Edge : We put n = 5 points on the edge.
     const int NbPoints = 5;
+    BRep_Tool::Range( E, f, l ); // PAL15185
     double du = (l - f) / (NbPoints - 1);
-    //MESSAGE("************* Degenerated edge! *****************");
 
     gp_Pnt P = BRep_Tool::Pnt(VFirst);
 
@@ -879,11 +897,11 @@ StdMeshers_Regular_1D::GetUsedHypothesis(SMESH_Mesh &         aMesh,
   // get non-auxiliary assigned to aShape
   int nbHyp = aMesh.GetHypotheses( aShape, compatibleFilter, _usedHypList, false );
 
-  if (nbHyp == 0)
+  if (nbHyp == 0 && aShape.ShapeType() == TopAbs_EDGE)
   {
     // Check, if propagated from some other edge
-    if (aShape.ShapeType() == TopAbs_EDGE &&
-        aMesh.IsPropagatedHypothesis(aShape, _mainEdge))
+    _mainEdge = StdMeshers_Propagation::GetPropagationSource( aMesh, aShape );
+    if ( !_mainEdge.IsNull() )
     {
       // Propagation of 1D hypothesis from <aMainEdge> on this edge;
       // get non-auxiliary assigned to _mainEdge