Salome HOME
23627: [IMACS] ASERIS: project point to the mesh and create a slot
[modules/smesh.git] / src / SMESH_I / SMESH_Measurements_i.cxx
index 2fcac5a7f9122551b4efb276f0f3c77fd0daf3a0..4d573980aae364244c42ad3147a8e4e9722dc5ae 100644 (file)
@@ -38,6 +38,7 @@
 #include "SMESH_MeshAlgos.hxx"
 #include "SMESH_PythonDump.hxx"
 
+#include <cmath>
 
 using namespace SMESH;
 
@@ -119,6 +120,33 @@ static bool getNodeNodeDistance (SMESH::Measure& theMeasure,
   return true;
 }
 
+static bool getNodeElemDistance (SMESH::Measure&        theMeasure,
+                                 const SMDS_MeshNode*   theNode,
+                                 SMESH_ElementSearcher* theElemSearcher)
+{
+  if ( !theNode || !theElemSearcher )
+    return false;
+
+  const SMDS_MeshElement* closestElement = 0;
+  gp_Pnt        point = SMESH_NodeXYZ( theNode );
+  gp_Pnt closestPoint = theElemSearcher->Project( point, SMDSAbs_All, &closestElement );
+
+  if ( closestElement )
+  {
+    theMeasure.value = point.Distance( closestPoint );
+    theMeasure.node1 = theNode->GetID();
+    theMeasure.elem2 = closestElement->GetID();
+    theMeasure.maxX  = closestPoint.X();
+    theMeasure.maxY  = closestPoint.Y();
+    theMeasure.maxZ  = closestPoint.Z();
+    theMeasure.minX  = closestPoint.X() - point.X();
+    theMeasure.minY  = closestPoint.Y() - point.Y();
+    theMeasure.minZ  = closestPoint.Z() - point.Z();
+  }
+
+  return closestElement;
+}
+
 static SMESHDS_Mesh* getMesh(SMESH::SMESH_IDSource_ptr theSource)
 {
   if (!CORBA::is_nil( theSource ))
@@ -182,7 +210,6 @@ SMESH::Measure Measurements_i::MinDistance
 
   SMESH::long_array_var aElementsId1 = theSource1->GetIDs();
   SMESH::long_array_var aElementsId2;
-  if ( !isOrigin ) aElementsId2 = theSource2->GetIDs();
 
   // compute distance between two entities
   /* NOTE: currently only node-to-node case is implemented
@@ -195,10 +222,25 @@ SMESH::Measure Measurements_i::MinDistance
     // node - node
     const SMESHDS_Mesh* aMesh1 = getMesh( theSource1 );
     const SMESHDS_Mesh* aMesh2 = isOrigin ? 0 : getMesh( theSource2 );
+    if ( !isOrigin ) aElementsId2 = theSource2->GetIDs();
     const SMDS_MeshNode* theNode1 = aMesh1 ? aMesh1->FindNode( aElementsId1[0] ) : 0;
     const SMDS_MeshNode* theNode2 = aMesh2 ? aMesh2->FindNode( aElementsId2[0] ) : 0;
     getNodeNodeDistance( aMeasure, theNode1, theNode2 );
   }
+  if (isNode1 && !isNode2 && aElementsId1->length() == 1 )
+  {
+    // node - elements
+    SMESHDS_Mesh* aMesh1 = getMesh( theSource1 );
+    SMESHDS_Mesh* aMesh2 = getMesh( theSource2 );
+    if ( aMesh1 && aMesh2 )
+    {
+      const SMDS_MeshNode* aNode    = aMesh1->FindNode( aElementsId1[0] );
+      SMDS_ElemIteratorPtr anElemIt = SMESH_Mesh_i::GetElements( theSource2, SMESH::ALL );
+      std::unique_ptr< SMESH_ElementSearcher > aSearcher
+        ( SMESH_MeshAlgos::GetElementSearcher( *aMesh2, anElemIt ));
+      getNodeElemDistance( aMeasure, aNode, aSearcher.get() );
+    }
+  }
   else
   {
     // NOT_IMPLEMENTED
@@ -346,3 +388,30 @@ SMESH::PointStruct Measurements_i::GravityCenter(SMESH::SMESH_IDSource_ptr theSo
 
   return grCenter;
 }
+
+//=======================================================================
+//function : Angle
+//purpose  : Return angle in radians defined by 3 points <(p1,p2,p3)
+//=======================================================================
+
+CORBA::Double Measurements_i::Angle(const SMESH::PointStruct& p1,
+                                    const SMESH::PointStruct& p2,
+                                    const SMESH::PointStruct& p3 )
+{
+  gp_Vec v1( p1.x - p2.x, p1.y - p2.y, p1.z - p2.z );
+  gp_Vec v2( p3.x - p2.x, p3.y - p2.y, p3.z - p2.z );
+
+  double angle = -1;
+
+  try
+  {
+    angle = v1.Angle( v2 );
+  }
+  catch(...)
+  {
+  }
+  if ( std::isnan( angle ))
+    angle = -1;
+
+  return angle;
+}