Salome HOME
PAL0023627: [IMACS] ASERIS: project point to the mesh
[modules/smesh.git] / src / SMESHUtils / SMESH_MeshAlgos.cxx
index 646fb7bffcab3f0c6c2a995a2350e08deff7b4d0..f42e24c11603b48beb73ef36b8881f127679de89 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "SMESH_MeshAlgos.hxx"
 
+#include "ObjectPool.hxx"
 #include "SMDS_FaceOfNodes.hxx"
 #include "SMDS_LinearEdge.hxx"
 #include "SMDS_Mesh.hxx"
@@ -69,7 +70,7 @@ struct SMESH_NodeSearcherImpl: public SMESH_NodeSearcher
 
     TIDSortedNodeSet nodes;
     if ( theMesh ) {
-      SMDS_NodeIteratorPtr nIt = theMesh->nodesIterator(/*idInceasingOrder=*/true);
+      SMDS_NodeIteratorPtr nIt = theMesh->nodesIterator();
       while ( nIt->more() )
         nodes.insert( nodes.end(), nIt->next() );
     }
@@ -1242,11 +1243,11 @@ gp_XYZ SMESH_ElementSearcherImpl::Project(const gp_Pnt&            point,
 
   ElementBndBoxTree*& ebbTree = _ebbTree[ _elementType ];
   if ( !ebbTree )
-    ebbTree = new ElementBndBoxTree( *_mesh, _elementType );
+    ebbTree = new ElementBndBoxTree( *_mesh, _elementType, _meshPartIt );
 
   gp_XYZ p = point.XYZ();
   ElementBndBoxTree* ebbLeaf = ebbTree->getLeafAtPoint( p );
-  const Bnd_B3d* box = ebbLeaf->getBox();
+  const Bnd_B3d* box = ebbLeaf ? ebbLeaf->getBox() : ebbTree->getBox();
   double radius = ( box->CornerMax() - box->CornerMin() ).Modulus();
 
   ElementBndBoxTree::TElemSeq elems;
@@ -1292,7 +1293,7 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
 
   std::vector< SMESH_TNodeXYZ > xyz; xyz.reserve( element->NbNodes()+1 );
 
-  SMDS_ElemIteratorPtr nodeIt = element->interlacedNodesElemIterator();
+  SMDS_NodeIteratorPtr nodeIt = element->interlacedNodesIterator();
   for ( int i = 0; nodeIt->more(); ++i )
     xyz.push_back( SMESH_TNodeXYZ( nodeIt->next() ));
 
@@ -1475,9 +1476,9 @@ namespace
 
   //================================================================================
   /*!
-   * \brief Return of a point relative to a segment
+   * \brief Return position of a point relative to a segment
    *  \param point2D      - the point to analyze position of
-   *  \param xyVec        - end points of segments
+   *  \param segEnds      - end points of segments
    *  \param index0       - 0-based index of the first point of segment
    *  \param posToFindOut - flags of positions to detect
    *  \retval PointPos - point position
@@ -1528,11 +1529,11 @@ double SMESH_MeshAlgos::GetDistance( const SMDS_MeshElement* elem,
   switch ( elem->GetType() )
   {
   case SMDSAbs_Volume:
-    return GetDistance( dynamic_cast<const SMDS_MeshVolume*>( elem ), point, closestPnt );
+    return GetDistance( static_cast<const SMDS_MeshVolume*>( elem ), point, closestPnt );
   case SMDSAbs_Face:
-    return GetDistance( dynamic_cast<const SMDS_MeshFace*>( elem ), point, closestPnt );
+    return GetDistance( static_cast<const SMDS_MeshFace*>( elem ), point, closestPnt );
   case SMDSAbs_Edge:
-    return GetDistance( dynamic_cast<const SMDS_MeshEdge*>( elem ), point, closestPnt );
+    return GetDistance( static_cast<const SMDS_MeshEdge*>( elem ), point, closestPnt );
   case SMDSAbs_Node:
     if ( closestPnt ) *closestPnt = SMESH_TNodeXYZ( elem );
     return point.Distance( SMESH_TNodeXYZ( elem ));
@@ -1606,46 +1607,63 @@ double SMESH_MeshAlgos::GetDistance( const SMDS_MeshFace* face,
   }
 
   // compute distance
-  PointPos pos = *pntPosSet.begin();
-  switch ( pos._name )
-  {
-  case POS_LEFT:
-  {
-    // point is most close to an edge
-    gp_Vec edge( xyz[ pos._index ], xyz[ pos._index+1 ]);
-    gp_Vec n1p ( xyz[ pos._index ], point  );
-    double u = ( edge * n1p ) / edge.SquareMagnitude(); // param [0,1] on the edge
-    // projection of the point on the edge
-    gp_XYZ proj = xyz[ pos._index ] + u * edge.XYZ();
-    if ( closestPnt ) *closestPnt = proj;
-    return point.Distance( proj );
-  }
-  case POS_RIGHT:
+
+  double minDist2 = Precision::Infinite();
+  for ( std::set< PointPos >::iterator posIt = pntPosSet.begin(); posIt != pntPosSet.end(); ++posIt)
   {
-    // point is inside the face
-    double distToFacePlane = Abs( tmpPnt.Y() );
-    if ( closestPnt )
+    PointPos pos = *posIt;
+    if ( pos._name != pntPosSet.begin()->_name )
+      break;
+    switch ( pos._name )
     {
-      if ( distToFacePlane < std::numeric_limits<double>::min() ) {
-        *closestPnt = point.XYZ();
+    case POS_LEFT: // point is most close to an edge
+    {
+      gp_Vec edge( xyz[ pos._index ], xyz[ pos._index+1 ]);
+      gp_Vec n1p ( xyz[ pos._index ], point  );
+      double u = ( edge * n1p ) / edge.SquareMagnitude(); // param [0,1] on the edge
+      // projection of the point on the edge
+      gp_XYZ proj = xyz[ pos._index ] + u * edge.XYZ();
+      double dist2 = point.SquareDistance( proj );
+      if ( dist2 < minDist2 )
+      {
+        if ( closestPnt ) *closestPnt = proj;
+        minDist2 = dist2;
       }
-      else {
-        tmpPnt.SetY( 0 );
-        trsf.Inverted().Transforms( tmpPnt );
-        *closestPnt = tmpPnt;
+      break;
+    }
+
+    case POS_RIGHT: // point is inside the face
+    {
+      double distToFacePlane = Abs( tmpPnt.Y() );
+      if ( closestPnt )
+      {
+        if ( distToFacePlane < std::numeric_limits<double>::min() ) {
+          *closestPnt = point.XYZ();
+        }
+        else {
+          tmpPnt.SetY( 0 );
+          trsf.Inverted().Transforms( tmpPnt );
+          *closestPnt = tmpPnt;
+        }
       }
+      return distToFacePlane;
+    }
+
+    case POS_VERTEX: // point is most close to a node
+    {
+      double dist2 = point.SquareDistance( xyz[ pos._index ]);
+      if ( dist2 < minDist2 )
+      {
+        if ( closestPnt ) *closestPnt = xyz[ pos._index ];
+        minDist2 = dist2;
+      }
+      break;
+    }
+    default:;
+      return badDistance;
     }
-    return distToFacePlane;
-  }
-  case POS_VERTEX:
-  {
-    // point is most close to a node
-    gp_Vec distVec( point, xyz[ pos._index ]);
-    return distVec.Magnitude();
-  }
-  default:;
   }
-  return badDistance;
+  return Sqrt( minDist2 );
 }
 
 //=======================================================================
@@ -1664,9 +1682,8 @@ double SMESH_MeshAlgos::GetDistance( const SMDS_MeshEdge* seg,
   int i = 0, nbNodes = seg->NbNodes();
 
   std::vector< SMESH_TNodeXYZ > xyz( nbNodes );
-  SMDS_ElemIteratorPtr nodeIt = seg->interlacedNodesElemIterator();
-  while ( nodeIt->more() )
-    xyz[ i++ ].Set( nodeIt->next() );
+  for ( SMDS_NodeIteratorPtr nodeIt = seg->interlacedNodesIterator(); nodeIt->more(); i++ )
+    xyz[ i ].Set( nodeIt->next() );
 
   for ( i = 1; i < nbNodes; ++i )
   {
@@ -1790,7 +1807,7 @@ void SMESH_MeshAlgos::GetBarycentricCoords( const gp_XY& p,
   const double t11 = T22, t12 = -T12, t21 = -T21, t22 = T11;
   // vector
   const double r11 = p.X()-t2.X(), r12 = p.Y()-t2.Y();
-  // barycentric coordinates: mutiply matrix by vector
+  // barycentric coordinates: multiply matrix by vector
   bc0 = (t11 * r11 + t12 * r12)/Tdet;
   bc1 = (t21 * r11 + t22 * r12)/Tdet;
 }
@@ -1836,7 +1853,7 @@ SMESH_MeshAlgos::FindFaceInSet(const SMDS_MeshNode*    n1,
     if ( !face && elem->IsQuadratic())
     {
       // analysis for quadratic elements using all nodes
-      SMDS_ElemIteratorPtr anIter = elem->interlacedNodesElemIterator();
+      SMDS_NodeIteratorPtr anIter = elem->interlacedNodesIterator();
       const SMDS_MeshNode* prevN = static_cast<const SMDS_MeshNode*>( anIter->next() );
       for ( i1 = -1, i2 = 0; anIter->more() && !face; i1++, i2++ )
       {