+//=======================================================================
+/*!
+ * \brief Return minimal distance from a point to an edge
+ */
+//=======================================================================
+
+double SMESH_MeshAlgos::GetDistance( const SMDS_MeshEdge* seg, const gp_Pnt& point )
+{
+ double dist = Precision::Infinite();
+ if ( !seg ) return dist;
+
+ int i = 0, nbNodes = seg->NbNodes();
+
+ vector< SMESH_TNodeXYZ > xyz( nbNodes );
+ SMDS_ElemIteratorPtr nodeIt = seg->interlacedNodesElemIterator();
+ while ( nodeIt->more() )
+ xyz[ i++ ].Set( nodeIt->next() );
+
+ for ( i = 1; i < nbNodes; ++i )
+ {
+ gp_Vec edge( xyz[i-1], xyz[i] );
+ gp_Vec n1p ( xyz[i-1], point );
+ double u = ( edge * n1p ) / edge.SquareMagnitude(); // param [0,1] on the edge
+ if ( u <= 0. ) {
+ dist = Min( dist, n1p.SquareMagnitude() );
+ }
+ else if ( u >= 1. ) {
+ dist = Min( dist, point.SquareDistance( xyz[i] ));
+ }
+ else {
+ gp_XYZ proj = ( 1. - u ) * xyz[i-1] + u * xyz[i]; // projection of the point on the edge
+ dist = Min( dist, point.SquareDistance( proj ));
+ }
+ }
+ return Sqrt( dist );
+}
+
+//=======================================================================
+/*!
+ * \brief Return minimal distance from a point to a volume
+ *
+ * Currently we ignore non-planarity and 2nd order
+ */
+//=======================================================================
+
+double SMESH_MeshAlgos::GetDistance( const SMDS_MeshVolume* volume, const gp_Pnt& point )
+{
+ SMDS_VolumeTool vTool( volume );
+ vTool.SetExternalNormal();
+ const int iQ = volume->IsQuadratic() ? 2 : 1;
+
+ double n[3], bc[3];
+ double minDist = 1e100, dist;
+ for ( int iF = 0; iF < vTool.NbFaces(); ++iF )
+ {
+ // skip a facet with normal not "looking at" the point
+ if ( !vTool.GetFaceNormal( iF, n[0], n[1], n[2] ) ||
+ !vTool.GetFaceBaryCenter( iF, bc[0], bc[1], bc[2] ))
+ continue;
+ gp_XYZ bcp = point.XYZ() - gp_XYZ( bc[0], bc[1], bc[2] );
+ if ( gp_XYZ( n[0], n[1], n[2] ) * bcp < 1e-6 )
+ continue;
+
+ // find distance to a facet
+ const SMDS_MeshNode** nodes = vTool.GetFaceNodes( iF );
+ switch ( vTool.NbFaceNodes( iF ) / iQ ) {
+ case 3:
+ {
+ SMDS_FaceOfNodes tmpFace( nodes[0], nodes[ 1*iQ ], nodes[ 2*iQ ] );
+ dist = GetDistance( &tmpFace, point );
+ break;
+ }
+ case 4:
+ {
+ SMDS_FaceOfNodes tmpFace( nodes[0], nodes[ 1*iQ ], nodes[ 2*iQ ], nodes[ 3*iQ ]);
+ dist = GetDistance( &tmpFace, point );
+ break;
+ }
+ default:
+ vector<const SMDS_MeshNode *> nvec( nodes, nodes + vTool.NbFaceNodes( iF ));
+ SMDS_PolygonalFaceOfNodes tmpFace( nvec );
+ dist = GetDistance( &tmpFace, point );
+ }
+ minDist = Min( minDist, dist );
+ }
+ return minDist;
+}
+