-// 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()
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;
}