Salome HOME
Make SHAPER STUDY fields exported in SMESH into MED file
[modules/shaper.git] / src / GeomAPI / GeomAPI_Angle.cpp
index 60c3761a03068dbd5105f1de7bedca3791384901..02e16ef892f84ca629299ab46c8edf1945477d5f 100644 (file)
-// Copyright (C) 2016-20xx CEA/DEN, EDF R&D
-
-// File:        GeomAPI_Angle.cpp
-// Created:     19 April 2016
-// Author:      Artem ZHIDKOV
+// Copyright (C) 2018-2019  CEA/DEN, EDF R&D
+//
+// 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, 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
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
 
 #include <GeomAPI_Angle.h>
-#include <GeomAPI_Dir.h>
-#include <GeomAPI_Lin.h>
-#include <GeomAPI_Pnt.h>
-#include <GeomAPI_XYZ.h>
 
-#include <gp_Dir.hxx>
-#include <gp_Pnt.hxx>
-#include <gp_XYZ.hxx>
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Pnt.h>
 
-struct ThreePoints {
-  gp_Pnt myCenter;
-  gp_Pnt myFirst;
-  gp_Pnt mySecond;
-  bool myReversed[2];
+#include <BRep_Tool.hxx>
+#include <ElCLib.hxx>
+#include <Geom_Curve.hxx>
+#include <GeomAPI_ProjectPointOnCurve.hxx>
+#include <Precision.hxx>
+#include <TopoDS_Edge.hxx>
+
+/// \struct AngleDirections
+/// \brief Used to store info about angle.
+struct AngleDirections {
+  gp_Vec myDir1;
+  gp_Vec myDir2;
 };
 
-#define MY_ANGLE implPtr<ThreePoints>()
+#define MY_ANGLE implPtr<AngleDirections>()
 #define PI 3.1415926535897932
 
-static ThreePoints* newAngle(const std::shared_ptr<GeomAPI_Pnt>& theCenter,
-                             const std::shared_ptr<GeomAPI_Pnt>& theFirst,
-                             const std::shared_ptr<GeomAPI_Pnt>& theSecond)
-{
-  ThreePoints* aResult = new ThreePoints;
-  aResult->myCenter = gp_Pnt(theCenter->x(), theCenter->y(), theCenter->z());
-  aResult->myFirst  = gp_Pnt(theFirst->x(), theFirst->y(), theFirst->z());
-  aResult->mySecond = gp_Pnt(theSecond->x(), theSecond->y(), theSecond->z());
-  aResult->myReversed[0] = aResult->myReversed[1] = false;
-  return aResult;
-}
 
-static ThreePoints* newAngle(const std::shared_ptr<GeomAPI_Pnt>& theStart1,
-                             const std::shared_ptr<GeomAPI_Pnt>& theEnd1,
-                             const std::shared_ptr<GeomAPI_Pnt>& theStart2,
-                             const std::shared_ptr<GeomAPI_Pnt>& theEnd2)
+GeomAPI_Angle::GeomAPI_Angle(const std::shared_ptr<GeomAPI_Edge>& theEdge1,
+                             const std::shared_ptr<GeomAPI_Edge>& theEdge2,
+                             const std::shared_ptr<GeomAPI_Pnt>&  thePoint)
 {
-  std::shared_ptr<GeomAPI_Lin> aLine1(new GeomAPI_Lin(theStart1, theEnd1));
-  std::shared_ptr<GeomAPI_Lin> aLine2(new GeomAPI_Lin(theStart2, theEnd2));
-  std::shared_ptr<GeomAPI_Pnt> aCenter = aLine1->intersect(aLine2);
-  bool isParallel = !aCenter;
-  if (isParallel)
-    aCenter = theStart1;
-  std::shared_ptr<GeomAPI_Pnt> aPoint1, aPoint2;
-  if (isParallel)
-    aPoint1 = aPoint2 = theEnd1;
-  else {
-    aPoint1 = theStart1->distance(aCenter) < theEnd1->distance(aCenter) ? theEnd1 : theStart1;
-    aPoint2 = theStart2->distance(aCenter) < theEnd2->distance(aCenter) ? theEnd2 : theStart2;
+  gp_Pnt aPoint = thePoint->impl<gp_Pnt>();
+  const TopoDS_Edge& anEdge1 = theEdge1->impl<TopoDS_Edge>();
+  const TopoDS_Edge& anEdge2 = theEdge2->impl<TopoDS_Edge>();
+
+  double aF1, aL1;
+  Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(anEdge1, aF1, aL1);
+  double aF2, aL2;
+  Handle(Geom_Curve) aCurve2 = BRep_Tool::Curve(anEdge2, aF2, aL2);
+
+  AngleDirections* anAngle = new AngleDirections;
+  gp_Pnt aP;
+
+  GeomAPI_ProjectPointOnCurve aProj1(aPoint, aCurve1);
+  if (aProj1.NbPoints() > 0) {
+    aCurve1->D1(aProj1.LowerDistanceParameter(), aP, anAngle->myDir1);
+    if (aCurve1->Value(aF1).SquareDistance(aPoint) < aCurve1->Value(aL1).SquareDistance(aPoint))
+      anAngle->myDir1.Reverse();
   }
-  ThreePoints* anAngle = newAngle(aCenter, aPoint1, aPoint2);
-  anAngle->myReversed[0] = aPoint1 == theStart1;
-  anAngle->myReversed[1] = !isParallel && aPoint2 == theStart2;
-  return anAngle;
-}
-
-static ThreePoints* newAngle(const std::shared_ptr<GeomAPI_Lin>& theLine1, bool theReversed1,
-                             const std::shared_ptr<GeomAPI_Lin>& theLine2, bool theReversed2)
-{
-  std::shared_ptr<GeomAPI_Pnt> aCenter = theLine1->intersect(theLine2);
-  if (!aCenter)
-    aCenter = theLine1->location();
-  double aCoeff = theReversed1 ? -1.0 : 1.0;
-  std::shared_ptr<GeomAPI_Pnt> aPoint1(new GeomAPI_Pnt(
-      aCenter->xyz()->added(theLine1->direction()->xyz()->multiplied(aCoeff))));
-  aCoeff = theReversed2 ? -1.0 : 1.0;
-  std::shared_ptr<GeomAPI_Pnt> aPoint2(new GeomAPI_Pnt(
-      aCenter->xyz()->added(theLine2->direction()->xyz()->multiplied(aCoeff))));
-  ThreePoints* anAngle = newAngle(aCenter, aPoint1, aPoint2);
-  anAngle->myReversed[0] = theReversed1;
-  anAngle->myReversed[1] = theReversed2;
-  return anAngle;
-}
-
-
-
-GeomAPI_Angle::GeomAPI_Angle(const std::shared_ptr<GeomAPI_Pnt>& theStartLine1,
-                             const std::shared_ptr<GeomAPI_Pnt>& theEndLine1,
-                             const std::shared_ptr<GeomAPI_Pnt>& theStartLine2,
-                             const std::shared_ptr<GeomAPI_Pnt>& theEndLine2)
-    : GeomAPI_Interface(newAngle(theStartLine1, theEndLine1, theStartLine2, theEndLine2))
-{
-}
 
-GeomAPI_Angle::GeomAPI_Angle(const std::shared_ptr<GeomAPI_Lin>& theLine1, bool theReversed1,
-                             const std::shared_ptr<GeomAPI_Lin>& theLine2, bool theReversed2)
-    : GeomAPI_Interface(newAngle(theLine1, theReversed1, theLine2, theReversed2))
-{
-}
-
-GeomAPI_Angle::GeomAPI_Angle(const std::shared_ptr<GeomAPI_Pnt>& theCenter,
-                             const std::shared_ptr<GeomAPI_Pnt>& thePoint1,
-                             const std::shared_ptr<GeomAPI_Pnt>& thePoint2)
-    : GeomAPI_Interface(newAngle(theCenter, thePoint1, thePoint2))
-{
-}
-
-std::shared_ptr<GeomAPI_Pnt> GeomAPI_Angle::center()
-{
-  gp_Pnt aPnt = MY_ANGLE->myCenter;
-  return std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aPnt.X(), aPnt.Y(), aPnt.Z()));
-}
+  GeomAPI_ProjectPointOnCurve aProj2(aPoint, aCurve2);
+  if (aProj2.NbPoints() > 0) {
+    aCurve2->D1(aProj2.LowerDistanceParameter(), aP, anAngle->myDir2);
+    if (aCurve2->Value(aF2).SquareDistance(aPoint) < aCurve2->Value(aL2).SquareDistance(aPoint))
+      anAngle->myDir2.Reverse();
+  }
 
-std::shared_ptr<GeomAPI_Pnt> GeomAPI_Angle::firstPoint()
-{
-  gp_Pnt aPnt = MY_ANGLE->myFirst;
-  return std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aPnt.X(), aPnt.Y(), aPnt.Z()));
+  setImpl(anAngle);
 }
 
-std::shared_ptr<GeomAPI_Pnt> GeomAPI_Angle::secondPoint()
+GeomAPI_Angle::GeomAPI_Angle(const std::shared_ptr<GeomAPI_Pnt>& thePoint1,
+                             const std::shared_ptr<GeomAPI_Pnt>& thePoint2,
+                             const std::shared_ptr<GeomAPI_Pnt>& thePoint3)
 {
-  gp_Pnt aPnt = MY_ANGLE->mySecond;
-  return std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aPnt.X(), aPnt.Y(), aPnt.Z()));
+  gp_Pnt aPoint1 = thePoint1->impl<gp_Pnt>();
+  gp_Pnt aPoint2 = thePoint2->impl<gp_Pnt>();
+  gp_Pnt aPoint3 = thePoint3->impl<gp_Pnt>();
+
+  AngleDirections* anAngle = new AngleDirections;
+  anAngle->myDir1.SetXYZ(aPoint1.XYZ() - aPoint2.XYZ());
+  anAngle->myDir2.SetXYZ(aPoint3.XYZ() - aPoint2.XYZ());
+  setImpl(anAngle);
 }
 
 double GeomAPI_Angle::angleDegree()
@@ -126,13 +94,16 @@ double GeomAPI_Angle::angleDegree()
 
 double GeomAPI_Angle::angleRadian()
 {
-  ThreePoints* anAngle = MY_ANGLE;
-  gp_Dir aDir1(anAngle->myFirst.XYZ() - anAngle->myCenter.XYZ());
-  gp_Dir aDir2(anAngle->mySecond.XYZ() - anAngle->myCenter.XYZ());
-  return aDir1.Angle(aDir2);
-}
-
-bool GeomAPI_Angle::isReversed(int theIndex)
-{
-  return MY_ANGLE->myReversed[theIndex & 0x1];
+  AngleDirections* anAngle = MY_ANGLE;
+  if (anAngle->myDir1.SquareMagnitude() < Precision::SquareConfusion() ||
+      anAngle->myDir2.SquareMagnitude() < Precision::SquareConfusion())
+    return 0.0;
+
+  gp_Dir aDir1(anAngle->myDir1);
+  gp_Dir aDir2(anAngle->myDir2);
+  double aRes = aDir1.Angle(aDir2);
+  aRes = ElCLib::InPeriod(aRes, 0.0, 2.0 * PI);
+  if (Abs(aRes) < 1.e-12)
+    aRes = 0.0;
+  return aRes;
 }