Salome HOME
Task 2.12. New entities: ellipses and arcs of ellipses (issue #3003)
[modules/shaper.git] / src / GeomAPI / GeomAPI_Ellipse2d.cpp
1 // Copyright (C) 2017-2019  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 // File:        GeomAPI_Ellipse2d.cpp
21 // Created:     26 April 2017
22 // Author:      Artem ZHIDKOV
23
24 #include <GeomAPI_Ellipse2d.h>
25 #include <GeomAPI_Circ2d.h>
26 #include <GeomAPI_Dir2d.h>
27 #include <GeomAPI_Lin2d.h>
28 #include <GeomAPI_Pnt2d.h>
29
30 #include <Extrema_ExtCC2d.hxx>
31 #include <Extrema_ExtElC2d.hxx>
32 #include <Geom2d_Ellipse.hxx>
33 #include <Geom2dAdaptor_Curve.hxx>
34 #include <gp_Ax22d.hxx>
35 #include <gp_Elips2d.hxx>
36 #include <Precision.hxx>
37
38 #define MY_ELLIPSE implPtr<gp_Elips2d>()
39
40 static gp_Elips2d* newEllipse(const gp_Pnt2d& theCenter,
41                               const gp_Dir2d& theXAxis,
42                               const double theMajorRadius,
43                               const double theMinorRadius)
44 {
45   if (theMajorRadius < theMinorRadius - Precision::Confusion()) {
46     return newEllipse(theCenter, gp_Dir2d(-theXAxis.Y(), theXAxis.X()),
47                       theMinorRadius, theMajorRadius);
48   }
49
50   gp_Ax22d anAxis(theCenter, theXAxis);
51   return new gp_Elips2d(anAxis, theMajorRadius, theMinorRadius);
52 }
53
54 static gp_Elips2d* newEllipse(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
55                               const std::shared_ptr<GeomAPI_Pnt2d>& theAxisPoint,
56                               const std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint)
57 {
58   const gp_Pnt2d& aCenter = theCenter->impl<gp_Pnt2d>();
59   const gp_Pnt2d& anAxisPnt = theAxisPoint->impl<gp_Pnt2d>();
60   const gp_Pnt2d& aPassedPnt = thePassingPoint->impl<gp_Pnt2d>();
61
62   gp_Dir2d aXAxis(anAxisPnt.XY() - aCenter.XY());
63   double aMajorRadius = anAxisPnt.Distance(aCenter);
64
65   gp_XY aPassedDir = aPassedPnt.XY() - aCenter.XY();
66
67   double X = aPassedDir.Dot(aXAxis.XY()) / aMajorRadius;
68   if (Abs(X) > 1.0 - Precision::Confusion())
69     return 0; // ellipse cannot be created for such parameters
70
71   double Y = aPassedDir.CrossMagnitude(aXAxis.XY());
72   double aMinorRadius = Y / Sqrt(1. - X * X);
73
74   return newEllipse(aCenter, aXAxis, aMajorRadius, aMinorRadius);
75 }
76
77
78 GeomAPI_Ellipse2d::GeomAPI_Ellipse2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
79                                      const std::shared_ptr<GeomAPI_Dir2d>& theXAxis,
80                                      const double theMajorRadius,
81                                      const double theMinorRadius)
82   : GeomAPI_Interface(newEllipse(theCenter->impl<gp_Pnt2d>(), theXAxis->impl<gp_Dir2d>(),
83                                  theMajorRadius, theMinorRadius))
84 {
85 }
86
87 GeomAPI_Ellipse2d::GeomAPI_Ellipse2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
88                                      const std::shared_ptr<GeomAPI_Pnt2d>& theAxisPoint,
89                                      const std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint)
90   : GeomAPI_Interface(newEllipse(theCenter, theAxisPoint, thePassingPoint))
91 {
92 }
93
94 std::shared_ptr<GeomAPI_Pnt2d> GeomAPI_Ellipse2d::center() const
95 {
96   const gp_Pnt2d& aCenter = MY_ELLIPSE->Location();
97   return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aCenter.X(), aCenter.Y()));
98 }
99
100 std::shared_ptr<GeomAPI_Pnt2d> GeomAPI_Ellipse2d::firstFocus() const
101 {
102   const gp_Pnt2d& aFirst = MY_ELLIPSE->Focus1();
103   return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aFirst.X(), aFirst.Y()));
104 }
105
106 std::shared_ptr<GeomAPI_Pnt2d> GeomAPI_Ellipse2d::secondFocus() const
107 {
108   const gp_Pnt2d& aSecond = MY_ELLIPSE->Focus2();
109   return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aSecond.X(), aSecond.Y()));
110 }
111
112 double GeomAPI_Ellipse2d::minorRadius() const
113 {
114   return MY_ELLIPSE->MinorRadius();
115 }
116
117 double GeomAPI_Ellipse2d::majorRadius() const
118 {
119   return MY_ELLIPSE->MajorRadius();
120 }
121
122 template <typename EXTREMAPTR>
123 static double extrema(EXTREMAPTR theAlgo,
124                       GeomPnt2dPtr& thePoint1,
125                       GeomPnt2dPtr& thePoint2)
126 {
127   double aDistance = Precision::Infinite();
128   if (theAlgo->IsDone() && theAlgo->NbExt() > 0) {
129     Extrema_POnCurv2d aP1, aP2;
130     for (int i = 1; i <= theAlgo->NbExt(); ++i)
131       if (theAlgo->SquareDistance(i) < aDistance) {
132         aDistance = Sqrt(theAlgo->SquareDistance(i));
133         theAlgo->Points(i, aP1, aP2);
134       }
135
136     aDistance = Sqrt(aDistance);
137     thePoint1 = GeomPnt2dPtr(new GeomAPI_Pnt2d(aP1.Value().X(), aP1.Value().Y()));
138     thePoint2 = GeomPnt2dPtr(new GeomAPI_Pnt2d(aP2.Value().X(), aP2.Value().Y()));
139   }
140   return aDistance;
141 }
142
143 double GeomAPI_Ellipse2d::distance(const std::shared_ptr<GeomAPI_Lin2d>& theLine,
144                                    std::shared_ptr<GeomAPI_Pnt2d>& thePointOnMe,
145                                    std::shared_ptr<GeomAPI_Pnt2d>& thePointOnLine)
146 {
147   Extrema_ExtElC2d anExtema(theLine->impl<gp_Lin2d>(), *MY_ELLIPSE);
148   return extrema(&anExtema, thePointOnLine, thePointOnMe);
149 }
150
151 double GeomAPI_Ellipse2d::distance(const std::shared_ptr<GeomAPI_Circ2d>& theCircle,
152                                    std::shared_ptr<GeomAPI_Pnt2d>& thePointOnMe,
153                                    std::shared_ptr<GeomAPI_Pnt2d>& thePointOnCircle)
154 {
155   Extrema_ExtElC2d anExtema(theCircle->impl<gp_Circ2d>(), *MY_ELLIPSE);
156   return extrema(&anExtema, thePointOnCircle, thePointOnMe);
157 }
158
159 double GeomAPI_Ellipse2d::distance(const std::shared_ptr<GeomAPI_Ellipse2d>& theEllipse,
160                                    std::shared_ptr<GeomAPI_Pnt2d>& thePointOnMe,
161                                    std::shared_ptr<GeomAPI_Pnt2d>& thePointOnEllipse)
162 {
163   Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(theEllipse->impl<gp_Elips2d>());
164   Handle(Geom2d_Ellipse) anEllipse2 = new Geom2d_Ellipse(*MY_ELLIPSE);
165
166   Extrema_ExtCC2d* anExtema =
167       new Extrema_ExtCC2d(Geom2dAdaptor_Curve(anEllipse1), Geom2dAdaptor_Curve(anEllipse2));
168   double aDistance = extrema(anExtema, thePointOnEllipse, thePointOnMe);
169   delete anExtema;
170   return aDistance;
171 }