Salome HOME
Try to use length of edges for association in case of a 2-edges wire
[modules/smesh.git] / src / StdMeshers / StdMeshers_Cartesian_3D.cxx
index 9b8e47c9b2a1b246e4e8c48d43dd3c71ee44ced1..6b0c68b93facfbd1f13490635d7730d58eefbac3 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -35,6 +35,7 @@
 
 #include "utilities.h"
 #include "Utils_ExceptHandlers.hxx"
+#include <Basics_OCCTVersion.hxx>
 
 #include <BRepAdaptor_Surface.hxx>
 #include <BRepBndLib.hxx>
@@ -85,6 +86,17 @@ using namespace std;
 
 //#define _MY_DEBUG_
 
+#if OCC_VERSION_LARGE <= 0x06050300
+// workaround it required only for OCCT6.5.3 and older (see OCC22809)
+#define ELLIPSOLID_WORKAROUND
+#endif
+
+#ifdef ELLIPSOLID_WORKAROUND
+#include <BRepIntCurveSurface_Inter.hxx>
+#include <BRepTopAdaptor_TopolTool.hxx>
+#include <BRepAdaptor_HSurface.hxx>
+#endif
+
 //=============================================================================
 /*!
  * Constructor
@@ -246,6 +258,41 @@ namespace
                         const TopoDS_Shape&   shape );
     void ComputeNodes(SMESH_MesherHelper& helper);
   };
+#ifdef ELLIPSOLID_WORKAROUND
+  // --------------------------------------------------------------------------
+  /*!
+   * \brief struct temporary replacing IntCurvesFace_Intersector until
+   *        OCCT bug 0022809 is fixed
+   *        http://tracker.dev.opencascade.org/view.php?id=22809
+   */
+  struct TMP_IntCurvesFace_Intersector
+  {
+    BRepAdaptor_Surface                       _surf;
+    double                                    _tol;
+    BRepIntCurveSurface_Inter                 _intcs;
+    vector<IntCurveSurface_IntersectionPoint> _points;
+    BRepTopAdaptor_TopolTool                  _clsf;
+
+    TMP_IntCurvesFace_Intersector(const TopoDS_Face& face, const double tol)
+      :_surf( face ), _tol( tol ), _clsf( new BRepAdaptor_HSurface(_surf) ) {}
+    Bnd_Box Bounding() const { Bnd_Box b; BRepBndLib::Add (_surf.Face(), b); return b; }
+    void Perform( const gp_Lin& line, const double w0, const double w1 )
+    {
+      _points.clear();
+      for ( _intcs.Init( _surf.Face(), line, _tol ); _intcs.More(); _intcs.Next() )
+        if ( w0 <= _intcs.W() && _intcs.W() <= w1 )
+          _points.push_back( _intcs.Point() );
+    }
+    bool IsDone() const { return true; }
+    int  NbPnt()  const { return _points.size(); }
+    IntCurveSurface_TransitionOnCurve Transition( const int i ) const { return _points[ i-1 ].Transition(); }
+    double       WParameter( const int i ) const { return _points[ i-1 ].W(); }
+    TopAbs_State ClassifyUVPoint(const gp_Pnt2d& p) { return _clsf.Classify( p, _tol ); }
+  };
+#define __IntCurvesFace_Intersector TMP_IntCurvesFace_Intersector
+#else
+#define __IntCurvesFace_Intersector IntCurvesFace_Intersector
+#endif
   // --------------------------------------------------------------------------
   /*!
    * \brief Intersector of TopoDS_Face with all GridLine's
@@ -255,7 +302,7 @@ namespace
     TopoDS_Face _face;
     Grid*       _grid;
     Bnd_Box     _bndBox;
-    IntCurvesFace_Intersector* _surfaceInt;
+    __IntCurvesFace_Intersector* _surfaceInt;
     vector< std::pair< GridLine*, IntersectionPoint > > _intersections;
 
     FaceGridIntersector(): _grid(0), _surfaceInt(0) {}
@@ -272,18 +319,18 @@ namespace
       GetCurveFaceIntersector();
       return _bndBox;
     }
-    IntCurvesFace_Intersector* GetCurveFaceIntersector()
+    __IntCurvesFace_Intersector* GetCurveFaceIntersector()
     {
       if ( !_surfaceInt )
       {
-        _surfaceInt = new IntCurvesFace_Intersector( _face, Precision::PConfusion() );
+        _surfaceInt = new __IntCurvesFace_Intersector( _face, Precision::PConfusion() );
         _bndBox     = _surfaceInt->Bounding();
         if ( _bndBox.IsVoid() )
           BRepBndLib::Add (_face, _bndBox);
       }
       return _surfaceInt;
     }
-    bool IsThreadSafe() const;
+    bool IsThreadSafe(set< const Standard_Transient* >& noSafeTShapes) const;
   };
   // --------------------------------------------------------------------------
   /*!
@@ -301,7 +348,7 @@ namespace
     gp_Cone     _cone;
     gp_Sphere   _sphere;
     gp_Torus    _torus;
-    IntCurvesFace_Intersector* _surfaceInt;
+    __IntCurvesFace_Intersector* _surfaceInt;
 
     vector< IntersectionPoint > _intPoints;
 
@@ -312,6 +359,7 @@ namespace
     void IntersectWithTorus   (const GridLine& gridLine);
     void IntersectWithSurface (const GridLine& gridLine);
 
+    bool UVIsOnFace() const;
     void addIntPoint(const bool toClassify=true);
     bool isParamOnLineOK( const double linLength )
     {
@@ -879,12 +927,20 @@ namespace
   }
   //================================================================================
   /*
-   * Store an intersection if it is In or ON the face
+   * Return true if (_u,_v) is on the face
+   */
+  bool FaceLineIntersector::UVIsOnFace() const
+  {
+    TopAbs_State state = _surfaceInt->ClassifyUVPoint(gp_Pnt2d( _u,_v ));
+    return ( state == TopAbs_IN || state == TopAbs_ON );
+  }
+  //================================================================================
+  /*
+   * Store an intersection if it is IN or ON the face
    */
   void FaceLineIntersector::addIntPoint(const bool toClassify)
   {
-    TopAbs_State state = toClassify ? _surfaceInt->ClassifyUVPoint(gp_Pnt2d( _u, _v )) : TopAbs_IN;
-    if ( state == TopAbs_IN || state == TopAbs_ON )
+    if ( !toClassify || UVIsOnFace() )
     {
       IntersectionPoint p;
       p._paramOnLine = _w;
@@ -952,8 +1008,7 @@ namespace
       _w = linCone.ParamOnConic( i );
       if ( !isParamOnLineOK( gridLine._length )) continue;
       ElSLib::Parameters(_cone, linCone.Point(i) ,_u,_v);
-      TopAbs_State state = _surfaceInt->ClassifyUVPoint(gp_Pnt2d( _u, _v ));
-      if ( state == TopAbs_IN || state == TopAbs_ON )
+      if ( UVIsOnFace() )
       {
         ElSLib::D1( _u, _v, _cone, P, du, dv );
         norm = du ^ dv;
@@ -1023,8 +1078,7 @@ namespace
       _w = linTorus.ParamOnLine( i );
       if ( !isParamOnLineOK( gridLine._length )) continue;
       linTorus.ParamOnTorus( i, _u,_v );
-      TopAbs_State state = _surfaceInt->ClassifyUVPoint(gp_Pnt2d( _u, _v ));
-      if ( state == TopAbs_IN || state == TopAbs_ON )
+      if ( UVIsOnFace() )
       {
         ElSLib::D1( _u, _v, _torus, P, du, dv );
         norm = du ^ dv;
@@ -1060,8 +1114,10 @@ namespace
   /*
    * check if its face can be safely intersected in a thread
    */
-  bool FaceGridIntersector::IsThreadSafe() const
+  bool FaceGridIntersector::IsThreadSafe(set< const Standard_Transient* >& noSafeTShapes) const
   {
+    bool isSafe = true;
+
     // check surface
     TopLoc_Location loc;
     Handle(Geom_Surface) surf = BRep_Tool::Surface( _face, loc );
@@ -1073,12 +1129,14 @@ namespace
     }
     if ( surf->IsKind( STANDARD_TYPE(Geom_BSplineSurface )) ||
          surf->IsKind( STANDARD_TYPE(Geom_BezierSurface )))
-      return false;
+      if ( !noSafeTShapes.insert((const Standard_Transient*) _face.TShape() ).second )
+        isSafe = false;
 
     double f, l;
     TopExp_Explorer exp( _face, TopAbs_EDGE );
     for ( ; exp.More(); exp.Next() )
     {
+      bool edgeIsSafe = true;
       const TopoDS_Edge& e = TopoDS::Edge( exp.Current() );
       // check 3d curve
       {
@@ -1092,10 +1150,11 @@ namespace
           }
           if ( c->IsKind( STANDARD_TYPE(Geom_BSplineCurve )) ||
                c->IsKind( STANDARD_TYPE(Geom_BezierCurve )))
-            return false;
+            edgeIsSafe = false;
         }
       }
       // check 2d curve
+      if ( edgeIsSafe )
       {
         Handle(Geom2d_Curve) c2 = BRep_Tool::CurveOnSurface( e, surf, loc, f, l);
         if ( !c2.IsNull() )
@@ -1107,11 +1166,13 @@ namespace
           }
           if ( c2->IsKind( STANDARD_TYPE(Geom2d_BSplineCurve )) ||
                c2->IsKind( STANDARD_TYPE(Geom2d_BezierCurve )))
-            return false;
+            edgeIsSafe = false;
         }
       }
+      if ( !edgeIsSafe && !noSafeTShapes.insert((const Standard_Transient*) e.TShape() ).second )
+        isSafe = false;
     }
-    return true;
+    return isSafe;
   }
   //================================================================================
   /*!
@@ -1510,7 +1571,7 @@ namespace
     nbIntHex = 0;
     for ( size_t i = 0; i < intersectedHex.size(); ++i )
     {
-      Hexahedron * hex = intersectedHex[ i ];
+      Hexahedron * hex = intersectedHex[ i ];
       if ( hex )
       {
         intHexInd[ nbIntHex++ ] = i;
@@ -1538,6 +1599,14 @@ namespace
           --nbIntHex;
         }
       }
+      else if ( _nbCornerNodes > 3  && !hex )
+      {
+        // all intersection of hex with geometry are at grid nodes
+        hex = new Hexahedron( *this );
+        hex->init( i );
+        intHexInd.push_back(0);
+        intHexInd[ nbIntHex++ ] = i;
+      }
     }
 
     // add elements resulted from hexadron intersection
@@ -1545,7 +1614,7 @@ namespace
     intHexInd.resize( nbIntHex );
     tbb::parallel_for ( tbb::blocked_range<size_t>( 0, nbIntHex ),
                         ParallelHexahedron( intersectedHex, intHexInd ),
-                        tbb::simple_partitioner());
+                        tbb::simple_partitioner()); // ComputeElements() is called here
     for ( size_t i = 0; i < intHexInd.size(); ++i )
       if ( Hexahedron * hex = intersectedHex[ intHexInd[ i ]] )
         nbAdded += hex->addElements( helper );
@@ -1571,6 +1640,7 @@ namespace
    */
   int Hexahedron::addElements(SMESH_MesherHelper& helper)
   {
+    int nbAdded = 0;
     // add elements resulted from hexahedron intersection
     //for ( size_t i = 0; i < _volumeDefs.size(); ++i )
     {
@@ -1596,9 +1666,10 @@ namespace
           break;
         }
       }
+      nbAdded += int ( _volumeDefs._nodes.size() > 0 );
     }
 
-    return 1;//(int) _volumeDefs.size();
+    return nbAdded;
   }
   //================================================================================
   /*!
@@ -1620,7 +1691,7 @@ namespace
                               li.LineIndex10(),
                               li.LineIndex01(),
                               li.LineIndex11() };
-      bool allLinksOut = true;
+      bool allLinksOut = true, hasLinks = false;
       for ( int iL = 0; iL < 4 && allLinksOut; ++iL ) // loop on 4 links parallel to iDir
       {
         const _Link& link = _hexLinks[ iL + 4*iDir ];
@@ -1640,10 +1711,13 @@ namespace
           firstIntPnt = link._intNodes[0]._intPoint;
         }
 
-        if ( firstIntPnt && firstIntPnt->_transition == Trans_IN )
-          allLinksOut = false;
+        if ( firstIntPnt )
+        {
+          hasLinks = true;
+          allLinksOut = ( firstIntPnt->_transition == Trans_OUT );
+        }
       }
-      if ( allLinksOut )
+      if ( hasLinks && allLinksOut )
         return true;
     }
     return false;
@@ -1847,6 +1921,9 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh &         theMesh,
   // - skip a cell, if it is too small according to the size threshold
   // - add a hexahedron in the mesh, if all nodes are inside
   // - add a polyhedron in the mesh, if some nodes are inside and some outside
+
+  _computeCanceled = false;
+
   try
   {
     Grid grid;
@@ -1884,9 +1961,15 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh &         theMesh,
       if ( gridBox.IsOut( gp_Pnt( x0,y0,z0 )) ||
            gridBox.IsOut( gp_Pnt( x1,y1,z1 )))
         for ( size_t i = 0; i < facesItersectors.size(); ++i )
+        {
           if ( !facesItersectors[i].IsInGrid( gridBox ))
             return error("The grid doesn't enclose the geometry");
+#ifdef ELLIPSOLID_WORKAROUND
+          delete facesItersectors[i]._surfaceInt, facesItersectors[i]._surfaceInt = 0;
+#endif
+        }
     }
+    if ( _computeCanceled ) return false;
 
 #ifdef WITH_TBB
     { // copy partner faces and curves of not thread-safe types
@@ -1894,8 +1977,7 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh &         theMesh,
       BRepBuilderAPI_Copy copier;
       for ( size_t i = 0; i < facesItersectors.size(); ++i )
       {
-        if ( !facesItersectors[i].IsThreadSafe() &&
-             !tshapes.insert((const Standard_Transient*) facesItersectors[i]._face.TShape() ).second )
+        if ( !facesItersectors[i].IsThreadSafe(tshapes) )
         {
           copier.Perform( facesItersectors[i]._face );
           facesItersectors[i]._face = TopoDS::Face( copier );
@@ -1922,9 +2004,13 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh &         theMesh,
     helper.SetSubShape( solidExp.Current() );
     helper.SetElementsOnShape( true );
 
+    if ( _computeCanceled ) return false;
+
     // create nodes on the geometry
     grid.ComputeNodes(helper);
 
+    if ( _computeCanceled ) return false;
+
     // create volume elements
     Hexahedron hex( _hyp->GetSizeThreshold(), &grid );
     int nbAdded = hex.MakeElements( helper );