]> SALOME platform Git repositories - modules/smesh.git/commitdiff
Salome HOME
020676: EDF 1212 GEOM: Partition operation creates vertices which causes mesh computa...
authoreap <eap@opencascade.com>
Tue, 23 Mar 2010 08:04:58 +0000 (08:04 +0000)
committereap <eap@opencascade.com>
Tue, 23 Mar 2010 08:04:58 +0000 (08:04 +0000)
 * Cash GeomAPI_ProjectPointOnSurf's
 * Make applyFunc() public under name applyIn2D()

+   * \brief Define a pointer to wrapper over a function of gp_XY class,
+   *       suitable to pass as xyFunPtr to applyIn2D().
+   *       For exaple gp_XY_FunPtr(Added) defines pointer gp_XY_Added to function
+   *       calling gp_XY::Added(gp_XY), which is to be used like following
+   *       applyIn2D(surf, uv1, uv2, gp_XY_Added)
+   */
+#define gp_XY_FunPtr(meth) \
+  static gp_XY __gpXY_##meth (const gp_XY& uv1, const gp_XY& uv2) { return uv1.meth( uv2 ); } \
+  static xyFunPtr gp_XY_##meth = & __gpXY_##meth

+  /*!
+   * \brief Perform given operation on two 2d points in parameric space of given surface.
+   *        It takes into account period of the surface. Use gp_XY_FunPtr macro
+   *        to easily define pointer to function of gp_XY class.
+   */
+  static gp_XY applyIn2D(const Handle(Geom_Surface)& surface,
+                         const gp_XY&                uv1,
+                         const gp_XY&                uv2,
+                         xyFunPtr                    fun,
+                         const bool                  resultInPeriod=true);
+

src/SMESH/SMESH_MesherHelper.cxx
src/SMESH/SMESH_MesherHelper.hxx

index 3c92c01f1296f72d7f3562f42274271ae9c59cca..1647d0a4657dfb2e71a2f6ed78d6b662422affc4 100644 (file)
@@ -79,6 +79,18 @@ SMESH_MesherHelper::SMESH_MesherHelper(SMESH_Mesh& theMesh)
   mySetElemOnShape = ( ! myMesh->HasShapeToMesh() );
 }
 
+//=======================================================================
+//function : ~SMESH_MesherHelper
+//purpose  : 
+//=======================================================================
+
+SMESH_MesherHelper::~SMESH_MesherHelper()
+{
+  TID2Projector::iterator i_proj = myFace2Projector.begin();
+  for ( ; i_proj != myFace2Projector.end(); ++i_proj )
+    delete i_proj->second;
+}
+
 //=======================================================================
 //function : IsQuadraticSubMesh
 //purpose  : Check submesh for given shape: if all elements on this shape 
@@ -467,7 +479,8 @@ bool SMESH_MesherHelper::CheckNodeUV(const TopoDS_Face&   F,
          nodePnt.Distance( surface->Value( uv.X(), uv.Y() )) > tol )
     {
       // uv incorrect, project the node to surface
-      GeomAPI_ProjectPointOnSurf projector( nodePnt, surface, tol );
+      GeomAPI_ProjectPointOnSurf& projector = GetProjector( F, loc, tol );
+      projector.Perform( nodePnt );
       if ( !projector.IsDone() || projector.NbPoints() < 1 )
       {
         MESSAGE( "SMESH_MesherHelper::CheckNodeUV() failed to project" );
@@ -490,61 +503,77 @@ bool SMESH_MesherHelper::CheckNodeUV(const TopoDS_Face&   F,
   return true;
 }
 
-namespace
+//=======================================================================
+//function : GetProjector
+//purpose  : Return projector intitialized by given face without location, which is returned
+//=======================================================================
+
+GeomAPI_ProjectPointOnSurf& SMESH_MesherHelper::GetProjector(const TopoDS_Face& F,
+                                                             TopLoc_Location&   loc,
+                                                             double             tol ) const
 {
-  struct TMiddle
+  Handle(Geom_Surface) surface = BRep_Tool::Surface( F,loc );
+  int faceID = GetMeshDS()->ShapeToIndex( F );
+  TID2Projector& i2proj = const_cast< TID2Projector&>( myFace2Projector );
+  TID2Projector::iterator i_proj = i2proj.find( faceID );
+  if ( i_proj == i2proj.end() )
   {
-    gp_XY operator()(const gp_XY& uv1, const gp_XY& uv2) const { return ( uv1 + uv2 ) / 2.; }
-  };
-  struct TAdd
-  {
-    gp_XY operator()(const gp_XY& uv1, const gp_XY& uv2) const { return ( uv1 + uv2 ); }
-  };
-  struct TSubtract
-  {
-    gp_XY operator()(const gp_XY& uv1, const gp_XY& uv2) const { return ( uv1 - uv2 ); }
-  };
+    if ( tol == 0 ) tol = BRep_Tool::Tolerance( F );
+    double U1, U2, V1, V2;
+    surface->Bounds(U1, U2, V1, V2);
+    GeomAPI_ProjectPointOnSurf* proj = new GeomAPI_ProjectPointOnSurf();
+    proj->Init( surface, U1, U2, V1, V2, tol );
+    i_proj = i2proj.insert( make_pair( faceID, proj )).first;
+  }
+  return *( i_proj->second );
+}
 
-  //================================================================================
-  /*!
-   * \brief Perform given operation on two points in parametric space of given surface
-   * Example: gp_XY uvSum = applyXYFUN( surf, uv1, uv2, gp_XYFun(Added))
-   */
-  //================================================================================
+namespace
+{
+  gp_XY AverageUV(const gp_XY& uv1, const gp_XY& uv2) { return ( uv1 + uv2 ) / 2.; }
+  gp_XY_FunPtr(Added); // define gp_XY_Added pointer to function calling gp_XY::Added(gp_XY)
+  gp_XY_FunPtr(Subtracted); 
+}
 
-  template<typename FUNC>
-  gp_XY applyFunc(const Handle(Geom_Surface)& surface,
-                  const gp_XY&                uv1,
-                  gp_XY                       uv2,
-                  const bool                  resultInPeriod=true)
-  {
-    Standard_Boolean isUPeriodic = surface.IsNull() ? false : surface->IsUPeriodic();
-    Standard_Boolean isVPeriodic = surface.IsNull() ? false : surface->IsVPeriodic();
-    if ( !isUPeriodic && !isVPeriodic )
-      return FUNC()(uv1,uv2);
+//=======================================================================
+//function : applyIn2D
+//purpose  : Perform given operation on two 2d points in parameric space of given surface.
+//           It takes into account period of the surface. Use gp_XY_FunPtr macro
+//           to easily define pointer to function of gp_XY class.
+//=======================================================================
 
-    // move uv2 not far than half-period from uv1
+gp_XY SMESH_MesherHelper::applyIn2D(const Handle(Geom_Surface)& surface,
+                                    const gp_XY&                uv1,
+                                    const gp_XY&                uv2,
+                                    xyFunPtr                    fun,
+                                    const bool                  resultInPeriod)
+{
+  Standard_Boolean isUPeriodic = surface.IsNull() ? false : surface->IsUPeriodic();
+  Standard_Boolean isVPeriodic = surface.IsNull() ? false : surface->IsVPeriodic();
+  if ( !isUPeriodic && !isVPeriodic )
+    return fun(uv1,uv2);
+
+  // move uv2 not far than half-period from uv1
+  double u2 = 
+    uv2.X()+(isUPeriodic ? ShapeAnalysis::AdjustByPeriod(uv2.X(),uv1.X(),surface->UPeriod()) :0);
+  double v2 = 
+    uv2.Y()+(isVPeriodic ? ShapeAnalysis::AdjustByPeriod(uv2.Y(),uv1.Y(),surface->VPeriod()) :0);
+
+  // execute operation
+  gp_XY res = fun( uv1, gp_XY(u2,v2) );
+
+  // move result within period
+  if ( resultInPeriod )
+  {
+    Standard_Real UF,UL,VF,VL;
+    surface->Bounds(UF,UL,VF,VL);
     if ( isUPeriodic )
-      uv2.SetX( uv2.X()+ShapeAnalysis::AdjustByPeriod(uv2.X(),uv1.X(),surface->UPeriod()) );
+      res.SetX( res.X() + ShapeAnalysis::AdjustToPeriod(res.X(),UF,UL));
     if ( isVPeriodic )
-      uv2.SetY( uv2.Y()+ShapeAnalysis::AdjustByPeriod(uv2.Y(),uv1.Y(),surface->VPeriod()) );
-
-    // execute operation
-    gp_XY res = FUNC()(uv1,uv2);
-
-    // move result within period
-    if ( resultInPeriod )
-    {
-      Standard_Real UF,UL,VF,VL;
-      surface->Bounds(UF,UL,VF,VL);
-      if ( isUPeriodic )
-        res.SetX( res.X() + ShapeAnalysis::AdjustToPeriod(res.X(),UF,UL));
-      if ( isVPeriodic )
-        res.SetY( res.Y() + ShapeAnalysis::AdjustToPeriod(res.Y(),VF,VL));
-    }
-
-    return res;
+      res.SetY( res.Y() + ShapeAnalysis::AdjustToPeriod(res.Y(),VF,VL));
   }
+
+  return res;
 }
 //=======================================================================
 //function : GetMiddleUV
@@ -555,7 +584,7 @@ gp_XY SMESH_MesherHelper::GetMiddleUV(const Handle(Geom_Surface)& surface,
                                       const gp_XY&                p1,
                                       const gp_XY&                p2)
 {
-  return applyFunc<TMiddle>( surface, p1, p2 );
+  return applyIn2D( surface, p1, p2, & AverageUV );
 }
 
 //=======================================================================
@@ -2585,7 +2614,7 @@ void SMESH_MesherHelper::FixQuadraticElements(bool volumeOnly)
                 gp_XY uv2 = GetNodeUV( face, link->node2(), nodeOnFace, &checkUV);
                 gp_XY uv12 = GetMiddleUV( surf, uv1, uv2);
                 // uvMove = uvm - uv12
-                gp_XY uvMove = applyFunc<TSubtract>(surf, uvm, uv12,/*inPeriod=*/false);
+                gp_XY uvMove = applyIn2D(surf, uvm, uv12, gp_XY_Subtracted, /*inPeriod=*/false);
                 ( is1 ? move1 : move0 ).SetCoord( uvMove.X(), uvMove.Y(), 0 );
               }
               if ( move0.SquareMagnitude() < straightTol2 &&
@@ -2633,7 +2662,7 @@ void SMESH_MesherHelper::FixQuadraticElements(bool volumeOnly)
               // compute 3D displacement by 2D one
               Handle(Geom_Surface) s = BRep_Tool::Surface(face,loc);
               gp_XY oldUV   = GetNodeUV( face, (*link1)->_mediumNode, 0, &checkUV);
-              gp_XY newUV   = applyFunc<TAdd>( s, oldUV, gp_XY( move.X(),move.Y() ));
+              gp_XY newUV   = applyIn2D( s, oldUV, gp_XY( move.X(),move.Y()), gp_XY_Added);
               gp_Pnt newPnt = s->Value( newUV.X(), newUV.Y());
               move = gp_Vec( XYZ((*link1)->_mediumNode), newPnt.Transformed(loc) );
 #ifdef _DEBUG_
index c9305b9094007eacfcd5ac95b71628acd8a48541..c4623a57a39ff9359b35a0fb2ba705fc2ee5eabe 100644 (file)
@@ -39,6 +39,8 @@
 
 #include <map>
 
+class GeomAPI_ProjectPointOnSurf;
+
 typedef std::map<SMESH_TLink, const SMDS_MeshNode*>           TLinkNodeMap;
 typedef std::map<SMESH_TLink, const SMDS_MeshNode*>::iterator ItTLinkNode;
 
@@ -48,6 +50,8 @@ typedef boost::shared_ptr< PShapeIterator > PShapeIteratorPtr;
 typedef std::vector<const SMDS_MeshNode* > TNodeColumn;
 typedef std::map< double, TNodeColumn >    TParam2ColumnMap;
 
+typedef gp_XY (*xyFunPtr)(const gp_XY& uv1, const gp_XY& uv2);
+
 //=======================================================================
 /*!
  * \brief It helps meshers to add elements
@@ -294,6 +298,28 @@ public:
   static gp_XY GetMiddleUV(const Handle(Geom_Surface)& surface,
                            const gp_XY&                uv1,
                            const gp_XY&                uv2);
+  /*!
+   * \brief Define a pointer to wrapper over a function of gp_XY class,
+   *       suitable to pass as xyFunPtr to applyIn2D().
+   *       For exaple gp_XY_FunPtr(Added) defines pointer gp_XY_Added to function
+   *       calling gp_XY::Added(gp_XY), which is to be used like following
+   *       applyIn2D(surf, uv1, uv2, gp_XY_Added)
+   */
+#define gp_XY_FunPtr(meth) \
+  static gp_XY __gpXY_##meth (const gp_XY& uv1, const gp_XY& uv2) { return uv1.meth( uv2 ); } \
+  static xyFunPtr gp_XY_##meth = & __gpXY_##meth
+
+  /*!
+   * \brief Perform given operation on two 2d points in parameric space of given surface.
+   *        It takes into account period of the surface. Use gp_XY_FunPtr macro
+   *        to easily define pointer to function of gp_XY class.
+   */
+  static gp_XY applyIn2D(const Handle(Geom_Surface)& surface,
+                         const gp_XY&                uv1,
+                         const gp_XY&                uv2,
+                         xyFunPtr                    fun,
+                         const bool                  resultInPeriod=true);
+                          
   /*!
    * \brief Check if inFaceNode argument is necessary for call GetNodeUV(F,..)
     * \retval bool - return true if the face is periodic
@@ -303,6 +329,13 @@ public:
    */
   bool GetNodeUVneedInFaceNode(const TopoDS_Face& F = TopoDS_Face()) const;
 
+  /*!
+   * \brief Return projector intitialized by given face without location, which is returned
+   */
+  GeomAPI_ProjectPointOnSurf& GetProjector(const TopoDS_Face& F,
+                                           TopLoc_Location&   loc,
+                                           double             tol=0 ) const; 
+
   /*!
    * \brief Check if shape is a degenerated edge or it's vertex
     * \param subShape - edge or vertex index in SMESHDS
@@ -401,6 +434,8 @@ public:
   enum MType{ LINEAR, QUADRATIC, COMP };
   MType IsQuadraticMesh();
   
+  virtual ~SMESH_MesherHelper();
+
 protected:
 
   /*!
@@ -424,6 +459,9 @@ protected:
   double          myPar1[2], myPar2[2]; // U and V bounds of a closed periodic surface
   int             myParIndex;     // bounds' index (1-U, 2-V, 3-both)
 
+  typedef std::map< int, GeomAPI_ProjectPointOnSurf* > TID2Projector;
+  TID2Projector   myFace2Projector;
+
   TopoDS_Shape    myShape;
   SMESH_Mesh*     myMesh;
   int             myShapeID;