Salome HOME
[bos #32517][EDF] Dynamic log messages switched on and off by SALOME_VERBOSE environm...
[modules/geom.git] / src / GEOMUtils / GEOMUtils.cxx
index ab91abb4c3d6dd60ef87ca84eb97064aa1114f1a..24d7318c0ef8ce06a30f3df0287aa693ca0570b3 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2022  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
@@ -24,9 +24,6 @@
 
 #include <GEOMUtils.hxx>
 
-#include <Basics_OCCTVersion.hxx>
-
-#include <OpUtil.hxx>
 #include <Utils_ExceptHandlers.hxx>
 
 // OCCT Includes
@@ -40,6 +37,7 @@
 #include <BRepGProp.hxx>
 #include <BRepTools.hxx>
 
+#include <BRepClass_FaceClassifier.hxx>
 #include <BRepClass3d_SolidClassifier.hxx>
 
 #include <BRepBuilderAPI_MakeFace.hxx>
@@ -67,6 +65,8 @@
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 #include <TopTools_Array1OfShape.hxx>
 
+#include <GeomAPI_ProjectPointOnSurf.hxx>
+
 #include <Geom_Circle.hxx>
 #include <Geom_Surface.hxx>
 #include <Geom_Plane.hxx>
@@ -96,6 +96,8 @@
 #include <sstream>
 #include <algorithm>
 
+#include <V3d_Coordinate.hxx>
+
 #include <Standard_Failure.hxx>
 #include <Standard_NullObject.hxx>
 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
@@ -262,7 +264,7 @@ namespace
         levelsListStr.push_back( substr );
     }
     GEOMUtils::LevelsList levelsListData;
-    for( int level = 0; level < levelsListStr.size(); level++ ) {
+    for( size_t level = 0; level < levelsListStr.size(); level++ ) {
       std::vector<std::string> namesListStr;
       std::stringstream ss1( levelsListStr[level] );
       while ( std::getline( ss1, substr, ',' ) ) {
@@ -270,7 +272,7 @@ namespace
           namesListStr.push_back( substr );
       }
       GEOMUtils::LevelInfo levelInfoData;
-      for( int node = 0; node < namesListStr.size(); node++ ) {
+      for( size_t node = 0; node < namesListStr.size(); node++ ) {
         std::vector<std::string> linksListStr;
         std::stringstream ss2( namesListStr[node] );
         while ( std::getline( ss2, substr, '_' ) ) {
@@ -280,7 +282,7 @@ namespace
         std::string nodeItem = linksListStr[0];
         if( !nodeItem.empty() ) {
           GEOMUtils::NodeLinks linksListData;
-          for( int link = 1; link < linksListStr.size(); link++ ) {
+          for( size_t link = 1; link < linksListStr.size(); link++ ) {
             std::string linkItem = linksListStr[link];
             linksListData.push_back( linkItem );
           }// Links
@@ -994,12 +996,13 @@ Standard_Real GEOMUtils::GetMinDistance
 
   // skl 30.06.2008
   // additional workaround for bugs 19899, 19908 and 19910 from Mantis
-  double dist = GEOMUtils::GetMinDistanceSingular
-      (theShape1, theShape2, thePnt1, thePnt2);
+  aResult = GEOMUtils::GetMinDistanceSingular(theShape1, theShape2, thePnt1, thePnt2);
 
+  /*
   if (dist > -1.0) {
     return dist;
   }
+  */
 
   BRepExtrema_DistShapeShape dst (theShape1, theShape2);
   if (dst.IsDone()) {
@@ -1010,7 +1013,7 @@ Standard_Real GEOMUtils::GetMinDistance
       P2 = dst.PointOnShape2(i);
 
       Standard_Real Dist = P1.Distance(P2);
-      if (aResult > Dist) {
+      if (aResult < 0 || aResult > Dist) {
         aResult = Dist;
         thePnt1 = P1;
         thePnt2 = P2;
@@ -1021,23 +1024,82 @@ Standard_Real GEOMUtils::GetMinDistance
   return aResult;
 }
 
+//=======================================================================
+// function : ProjectPointOnFace()
+// purpose  : Returns the projection (3d point) if found, throws an exception otherwise
+//=======================================================================
+gp_Pnt GEOMUtils::ProjectPointOnFace(const gp_Pnt& thePoint,
+                                     const TopoDS_Shape& theFace,
+                                     double& theU, double& theV)
+{
+  if (theFace.IsNull() || theFace.ShapeType() != TopAbs_FACE)
+    Standard_TypeMismatch::Raise
+      ("Projection aborted : the target shape is not a face");
+
+  TopoDS_Face aFace = TopoDS::Face(theFace);
+  Handle(Geom_Surface) surface = BRep_Tool::Surface(aFace);
+  double U1, U2, V1, V2;
+  BRepTools::UVBounds(aFace, U1, U2, V1, V2);
+
+  // projector
+  Standard_Real tol = 1.e-4;        
+  GeomAPI_ProjectPointOnSurf proj;
+  proj.Init(surface, U1, U2, V1, V2, tol);
+  proj.Perform(thePoint);
+  if (!proj.IsDone())
+    StdFail_NotDone::Raise("Projection aborted : the algorithm failed");
+  int nbPoints = proj.NbPoints();
+  if (nbPoints < 1)
+    Standard_ConstructionError::Raise("Projection aborted : No solution found");
+  proj.LowerDistanceParameters(theU, theV);
+  gp_Pnt2d aProjPnt (theU, theV);
+
+  // classifier
+  BRepClass_FaceClassifier aClsf (aFace, aProjPnt, tol);
+  if (aClsf.State() != TopAbs_IN && aClsf.State() != TopAbs_ON) {
+    bool isSol = false;
+    double minDist = RealLast();
+    for (int i = 1; i <= nbPoints; i++) {
+      Standard_Real Ui, Vi;
+      proj.Parameters(i, Ui, Vi);
+      aProjPnt = gp_Pnt2d(Ui, Vi);
+      aClsf.Perform(aFace, aProjPnt, tol);
+      if (aClsf.State() == TopAbs_IN || aClsf.State() == TopAbs_ON) {
+        isSol = true;
+        double dist = proj.Distance(i);
+        if (dist < minDist) {
+          minDist = dist;
+          theU = Ui;
+          theV = Vi;
+        }
+      }
+    }
+    if (!isSol) {
+      Standard_ConstructionError::Raise("Projection aborted : No solution found");
+    }
+  }
+
+  gp_Pnt surfPnt = surface->Value(theU, theV);
+  return surfPnt;
+}
+
 //=======================================================================
 // function : ConvertClickToPoint()
 // purpose  : Returns the point clicked in 3D view
 //=======================================================================
 gp_Pnt GEOMUtils::ConvertClickToPoint( int x, int y, Handle(V3d_View) aView )
 {
-  V3d_Coordinate XEye, YEye, ZEye, XAt, YAt, ZAt;
-  aView->Eye( XEye, YEye, ZEye );
-
-  aView->At( XAt, YAt, ZAt );
-  gp_Pnt EyePoint( XEye, YEye, ZEye );
-  gp_Pnt AtPoint( XAt, YAt, ZAt );
+  // We can't rely on Eye and At points to get EyeDir, because they collapse
+  // for views with flat bounding boxes. For example if you create a circle and
+  // switch to the top view, then both camera's Eye and At points will fall to zero
+  // inside V3d_View::FitMinMax() method. It's by occt design.
+  // So, we should use camera direction instead.
 
-  gp_Vec EyeVector( EyePoint, AtPoint );
-  gp_Dir EyeDir( EyeVector );
+  V3d_Coordinate XAt, YAt, ZAt;
+  aView->At(XAt, YAt, ZAt);
+  gp_Pnt AtPoint(XAt, YAt, ZAt);
 
-  gp_Pln PlaneOfTheView = gp_Pln( AtPoint, EyeDir );
+  gp_Pln PlaneOfTheView = gp_Pln( AtPoint, aView->Camera()->Direction() );
   Standard_Real X, Y, Z;
   aView->Convert( x, y, X, Y, Z );
   gp_Pnt ConvertedPoint( X, Y, Z );
@@ -1082,8 +1144,8 @@ void GEOMUtils::ConvertStringToTree( const std::string& dependencyStr,
     std::string objectEntry = dependencyStr.substr( cursor, objectIndex - cursor );
     cursor = objectIndex;
 
-    std::size_t upwardIndexBegin = dependencyStr.find("{",cursor) + 1;
-    std::size_t upwardIndexFinish = dependencyStr.find("}",upwardIndexBegin);
+    //std::size_t upwardIndexBegin = dependencyStr.find("{",cursor) + 1;
+    //std::size_t upwardIndexFinish = dependencyStr.find("}",upwardIndexBegin);
     LevelsList upwardList = parseWard( dependencyStr, cursor );
 
     LevelsList downwardList = parseWard( dependencyStr, cursor );
@@ -1280,7 +1342,7 @@ bool GEOMUtils::IsOpenPath(const TopoDS_Shape &theShape)
       const TopAbs_ShapeEnum aType = theShape.ShapeType();
 
       if (aType == TopAbs_EDGE || aType == TopAbs_WIRE) {
-        // Check if path ends are coinsident.
+        // Check if path ends are coincident.
         TopoDS_Vertex aV[2];
 
         if (aType == TopAbs_EDGE) {