Salome HOME
0022523: [CEA 1096] Add a colomn "biquadratic" in "Mesh Information"
[modules/smesh.git] / src / StdMeshers / StdMeshers_FaceSide.cxx
index 4d72e2f68bcab49d12faab351cc4564b4539ae49..b543928dcabd653c2e7adfda7f4f26fca61b11c5 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2014  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
@@ -6,7 +6,7 @@
 // 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.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -51,6 +51,7 @@
 #include <TopoDS_Wire.hxx>
 
 #include <map>
+#include <limits>
 
 #include "utilities.h"
 
@@ -202,36 +203,123 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&   theFace,
 //================================================================================
 /*!
  * \brief Constructor of a side for vertex using data from other FaceSide
 * \param theVertex - the vertex
 * \param theSide - the side
 \param theVertex - the vertex
 \param theSide - the side
  */
 //================================================================================
 
-StdMeshers_FaceSide::StdMeshers_FaceSide(const SMDS_MeshNode*       theNode,
-                                         const gp_Pnt2d             thePnt2d,
-                                         const StdMeshers_FaceSide* theSide)
+StdMeshers_FaceSide::StdMeshers_FaceSide(const StdMeshers_FaceSide*  theSide,
+                                         const SMDS_MeshNode*        theNode,
+                                         const gp_Pnt2d*             thePnt2d1,
+                                         const gp_Pnt2d*             thePnt2d2,
+                                         const Handle(Geom2d_Curve)& theC2d,
+                                         const double                theUFirst,
+                                         const double                theULast)
 {
-  myC2d.resize(1);
+  myC2d.push_back      ( theC2d );
+  myFirst.push_back    ( theUFirst );
+  myLast.push_back     ( theULast );
+  myNormPar.push_back  ( 1. );
+  myIsUniform.push_back( true );
+  myEdgeID.push_back   ( 0 );
   myLength       = 0;
   myProxyMesh    = theSide->myProxyMesh;
-  myDefaultPnt2d = thePnt2d;
-
-  myPoints = theSide->GetUVPtStruct();
-  myNbPonits = myPoints.size();
-  myNbSegments = theSide->myNbSegments;
-  std::vector<uvPtStruct>::iterator it = myPoints.begin();
-  for(; it!=myPoints.end(); it++) {
-    (*it).u = thePnt2d.X();
-    (*it).v = thePnt2d.Y();
-    (*it).y = 0.0;
-    (*it).node = theNode;
+  myDefaultPnt2d = *thePnt2d1;
+  myPoints       = theSide->GetUVPtStruct();
+  myNbPonits     = myPoints.size();
+  myNbSegments   = theSide->myNbSegments;
+  if ( thePnt2d2 )
+    for ( size_t i = 0; i < myPoints.size(); ++i )
+    {
+      double r = i / ( myPoints.size() - 1. );
+      myPoints[i].u = (1-r) * thePnt2d1->X() + r * thePnt2d2->X();
+      myPoints[i].v = (1-r) * thePnt2d1->Y() + r * thePnt2d2->Y();
+      myPoints[i].node = theNode;
+    }
+  else
+    for ( size_t i = 0; i < myPoints.size(); ++i )
+    {
+      myPoints[i].u = thePnt2d1->X();
+      myPoints[i].v = thePnt2d1->Y();
+      myPoints[i].node = theNode;
+    }
+}
+
+//================================================================================
+/*
+ * Create a side from an UVPtStructVec
+ */
+//================================================================================
+
+StdMeshers_FaceSide::StdMeshers_FaceSide(UVPtStructVec&     theSideNodes,
+                                         const TopoDS_Face& theFace)
+{
+  myEdge.resize( 1 );
+  myEdgeID.resize( 1, -1 );
+  myC2d.resize( 1 );
+  myC3dAdaptor.resize( 1 );
+  myFirst.resize( 1, 0. );
+  myLast.resize( 1, 1. );
+  myNormPar.resize( 1, 1. );
+  myIsUniform.resize( 1, 1 );
+  myMissingVertexNodes = myIgnoreMediumNodes = false;
+  myDefaultPnt2d.SetCoord( 1e100, 1e100 );
+
+  myPoints     = theSideNodes;
+  myNbPonits   = myPoints.size();
+  myNbSegments = myNbPonits + 1;
+
+  myLength = 0;
+  if ( !myPoints.empty() )
+  {
+    myPoints[0].normParam = 0;
+    if ( myPoints[0].node &&
+         myPoints.back().node &&
+         myPoints[ myNbPonits/2 ].node )
+    {
+      gp_Pnt pPrev = SMESH_TNodeXYZ( myPoints[0].node );
+      for ( size_t i = 1; i < myPoints.size(); ++i )
+      {
+        gp_Pnt p = SMESH_TNodeXYZ( myPoints[i].node );
+        myLength += p.Distance( pPrev );
+        myPoints[i].normParam = myLength;
+        pPrev = p;
+      }
+    }
+    else if ( !theFace.IsNull() )
+    {
+      TopLoc_Location loc;
+      Handle(Geom_Surface) surf = BRep_Tool::Surface( theFace, loc );
+      gp_Pnt pPrev = surf->Value( myPoints[0].u, myPoints[0].v );
+      for ( size_t i = 1; i < myPoints.size(); ++i )
+      {
+        gp_Pnt p = surf->Value( myPoints[i].u, myPoints[i].v );
+        myLength += p.Distance( pPrev );
+        myPoints[i].normParam = myLength;
+        pPrev = p;
+      }
+    }
+    else
+    {
+      gp_Pnt2d pPrev = myPoints[0].UV();
+      for ( size_t i = 1; i < myPoints.size(); ++i )
+      {
+        gp_Pnt2d p = myPoints[i].UV();
+        myLength += p.Distance( pPrev );
+        myPoints[i].normParam = myLength;
+        pPrev = p;
+      }
+    }
+    if ( myLength > std::numeric_limits<double>::min() )
+      for ( size_t i = 1; i < myPoints.size(); ++i )
+        myPoints[i].normParam /= myLength;
   }
+  myEdgeLength.resize( 1, myLength );
 }
 
 //================================================================================
-/*!
- * \brief Return info on nodes on the side
-  * \retval UVPtStruct* - array of data structures
+/*
+ * Return info on nodes on the side
  */
 //================================================================================
 
@@ -358,13 +446,22 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
       {
         const UVPtStructVec& edgeUVPtStruct = proxySubMesh[iE]->GetUVPtStructVec();
         std::copy( edgeUVPtStruct.begin(), edgeUVPtStruct.end(), & points[iPt] );
+        // check orientation
+        double du1 = edgeUVPtStruct.back().param - edgeUVPtStruct[0].param;
+        double du2 = myLast[iE] - myFirst[iE];
+        if ( du1 * du2 < 0 )
+        {
+          std::reverse( & points[iPt], & points[iPt + edgeUVPtStruct.size()]);
+          for ( size_t i = 0; i < edgeUVPtStruct.size(); ++i )
+            points[iPt+i].normParam = 1. - points[iPt+i].normParam;
+        }
         // update normalized params
         if ( myEdge.size() > 1 ) {
           for ( size_t i = 0; i < edgeUVPtStruct.size(); ++i, ++iPt )
           {
             UVPtStruct & uvPt = points[iPt];
-            uvPt.normParam = prevNormPar + uvPt.normParam * paramSize;
-            uvPt.x = uvPt.y = uvPt.normParam;
+            uvPt.normParam    = prevNormPar + uvPt.normParam * paramSize;
+            uvPt.x = uvPt.y   = uvPt.normParam;
           }
           --iPt; // to point to the 1st VERTEX of the next EDGE
         }
@@ -579,7 +676,8 @@ void StdMeshers_FaceSide::Reverse()
   int nbEdges = myEdge.size();
   for ( int i = nbEdges-1; i >= 0; --i ) {
     std::swap( myFirst[i], myLast[i] );
-    myEdge[i].Reverse();
+    if ( !myEdge[i].IsNull() )
+      myEdge[i].Reverse();
     if ( i > 0 ) // at the first loop 1. is overwritten
       myNormPar[i] = 1 - myNormPar[i-1];
   }
@@ -597,13 +695,37 @@ void StdMeshers_FaceSide::Reverse()
   if ( nbEdges > 0 )
   {
     myNormPar[nbEdges-1]=1.;
-    myPoints.clear();
-    myFalsePoints.clear();
-    for ( size_t i = 0; i < myEdge.size(); ++i )
-      reverseProxySubmesh( myEdge[i] );
+    if ( !myEdge[0].IsNull() )
+    {
+      for ( size_t i = 0; i < myEdge.size(); ++i )
+        reverseProxySubmesh( myEdge[i] );
+      myPoints.clear();
+      myFalsePoints.clear();
+    }
+    else
+    {
+      for ( size_t i = 0; i < myPoints.size(); ++i )
+      {
+        UVPtStruct & uvPt = myPoints[i];
+        uvPt.normParam = 1 - uvPt.normParam;
+        uvPt.x         = 1 - uvPt.x;
+        uvPt.y         = 1 - uvPt.y;
+      }
+      reverse( myPoints );
+
+      for ( size_t i = 0; i < myFalsePoints.size(); ++i )
+      {
+        UVPtStruct & uvPt = myFalsePoints[i];
+        uvPt.normParam = 1 - uvPt.normParam;
+        uvPt.x         = 1 - uvPt.x;
+        uvPt.y         = 1 - uvPt.y;
+      }
+      reverse( myFalsePoints );
+    }
   }
   for ( size_t i = 0; i < myEdge.size(); ++i )
   {
+    if ( myEdge[i].IsNull() ) continue; // for a side on points only
     double fp,lp;
     Handle(Geom_Curve) C3d = BRep_Tool::Curve(myEdge[i],fp,lp);
     if ( !C3d.IsNull() )
@@ -836,6 +958,18 @@ gp_Pnt2d StdMeshers_FaceSide::Value2d(double U) const
     return myC2d[ i ]->Value(par);
 
   }
+  else if ( !myPoints.empty() )
+  {
+    int i = U * double( myPoints.size()-1 );
+    while ( i > 0 && myPoints[ i ].normParam > U )
+      --i;
+    while ( i+1 < myPoints.size() && myPoints[ i+1 ].normParam < U )
+      ++i;
+    double r = (( U - myPoints[ i ].normParam ) /
+                ( myPoints[ i+1 ].normParam - myPoints[ i ].normParam ));
+    return ( myPoints[ i   ].UV() * ( 1 - r ) +
+             myPoints[ i+1 ].UV() * r );
+  }
   return myDefaultPnt2d;
 }