]> SALOME platform Git repositories - modules/shaper.git/blob - src/GeomAPI/GeomAPI_Circ2d.cpp
Salome HOME
Cleanup code of SketchPlugin_Fillet feature. Move calculation of tangent circle to...
[modules/shaper.git] / src / GeomAPI / GeomAPI_Circ2d.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        GeomAPI_Circ2d.cpp
4 // Created:     29 May 2014
5 // Author:      Artem ZHIDKOV
6
7 #include <GeomAPI_Circ2d.h>
8 #include <GeomAPI_Ax3.h>
9 #include <GeomAPI_Pnt2d.h>
10 #include <GeomAPI_Dir2d.h>
11 #include <GeomAPI_Shape.h>
12
13 #include <BRep_Tool.hxx>
14 #include <ElCLib.hxx>
15 #include <gp_Dir2d.hxx>
16 #include <gp_Circ2d.hxx>
17 #include <gp_Lin2d.hxx>
18 #include <gp_Pnt2d.hxx>
19 #include <gp_Ax2d.hxx>
20 #include <GccAna_Circ2d2TanRad.hxx>
21 #include <GccAna_Circ2d3Tan.hxx>
22 #include <GccAna_Circ2dTanCen.hxx>
23 #include <GccEnt.hxx>
24 #include <GccEnt_QualifiedCirc.hxx>
25 #include <GccEnt_QualifiedLin.hxx>
26 #include <GeomLib_Tool.hxx>
27 #include <Geom2d_Circle.hxx>
28 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
29 #include <Geom_Plane.hxx>
30 #include <IntAna2d_AnaIntersection.hxx>
31 #include <Precision.hxx>
32 #include <TopoDS.hxx>
33 #include <TopoDS_Edge.hxx>
34
35 #include <vector>
36
37 #define MY_CIRC2D implPtr<gp_Circ2d>()
38
39 typedef std::shared_ptr<Geom2dAdaptor_Curve>  CurveAdaptorPtr;
40 typedef std::vector< std::shared_ptr<GccEnt_QualifiedCirc> > VectorOfGccCirc;
41 typedef std::vector< std::shared_ptr<GccEnt_QualifiedLin> >  VectorOfGccLine;
42
43 // Provide different mechanisms to create circle:
44 // * by passing points
45 // * by tangent edges
46 // * with specified radius
47 // * etc.
48 class CircleBuilder
49 {
50 public:
51   CircleBuilder(const std::shared_ptr<GeomAPI_Ax3>& theBasePlane)
52     : myPlane(new Geom_Plane(theBasePlane->impl<gp_Ax3>())),
53       myRadius(0.0)
54   {}
55
56   void setRadius(const double theRadius)
57   { myRadius = theRadius; }
58
59   void addCenter(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter)
60   { myCenter = theCenter; }
61
62   void addPassingEntity(const std::shared_ptr<GeomAPI_Interface>& theEntity)
63   {
64     std::shared_ptr<GeomAPI_Pnt2d> aPoint = std::dynamic_pointer_cast<GeomAPI_Pnt2d>(theEntity);
65     if (aPoint)
66       addPassingPoint(aPoint);
67     else {
68       std::shared_ptr<GeomAPI_Shape> aShape = std::dynamic_pointer_cast<GeomAPI_Shape>(theEntity);
69       if (aShape)
70         addTangentCurve(aShape);
71     }
72   }
73
74   void addTangentCurve(const std::shared_ptr<GeomAPI_Shape>& theEdge)
75   {
76     if (!theEdge->isEdge())
77       return;
78
79     const TopoDS_Edge& anEdge = TopoDS::Edge(theEdge->impl<TopoDS_Shape>());
80
81     double aFirst, aLast;
82     TopLoc_Location aLoc;
83     Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface(anEdge, myPlane, aLoc, aFirst, aLast);
84     CurveAdaptorPtr aCurveAdaptor(new Geom2dAdaptor_Curve(aCurve, aFirst, aLast));
85
86     myTangentShapes.push_back(aCurveAdaptor);
87   }
88
89   void addPassingPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
90   {
91     myPassingPoints.push_back(thePoint->impl<gp_Pnt2d>());
92   }
93
94   gp_Circ2d* circle()
95   {
96     if (myTangentShapes.size() > 1)
97       sortTangentShapes();
98
99     gp_Circ2d* aResult = 0;
100     if (myCenter) {
101       if (myPassingPoints.size() == 1)
102         aResult = circleByCenterAndPassingPoint();
103       else if (myTangentShapes.size() == 1)
104         aResult = circleByCenterAndTangent();
105       else if (myRadius > 0.0)
106         aResult = circleByCenterAndRadius();
107     } else if (myRadius > 0.0) {
108       if (myTangentShapes.size() == 2)
109         aResult = circleByRadiusAndTwoTangentCurves();
110     } else {
111       switch (myPassingPoints.size()) {
112       case 0:
113         aResult = circleByThreeTangentCurves();
114         break;
115       case 1:
116         aResult = circleByPointAndTwoTangentCurves();
117         break;
118       case 2:
119         aResult = circleByTwoPointsAndTangentCurve();
120         break;
121       case 3:
122         aResult = circleByThreePassingPoints();
123         break;
124       default:
125         break;
126       }
127     }
128     return aResult;
129   }
130
131 private:
132   void sortTangentShapes()
133   {
134     // sort tangent shapes, so circles go before lines
135     int aSize = (int)myTangentShapes.size();
136     for (int i = 1; i < aSize; ++i) {
137       if (myTangentShapes[i]->GetType() != GeomAbs_Circle)
138         continue;
139
140       for (int j = i - 1; j >= 0 && myTangentShapes[j]->GetType() == GeomAbs_Line; --j)
141         std::swap(myTangentShapes[j], myTangentShapes[j+1]);
142     }
143   }
144
145   gp_Circ2d* circleByCenterAndRadius()
146   {
147     const gp_Pnt2d& aCenter = myCenter->impl<gp_Pnt2d>();
148     return new gp_Circ2d(gp_Ax2d(aCenter, gp::DX2d()), myRadius);
149   }
150
151   gp_Circ2d* circleByCenterAndPassingPoint()
152   {
153     const gp_Pnt2d& aCenter = myCenter->impl<gp_Pnt2d>();
154     GccAna_Circ2dTanCen aBuilder(myPassingPoints[0], aCenter);
155     if (aBuilder.NbSolutions() > 0)
156       return new gp_Circ2d(aBuilder.ThisSolution(1));
157     return 0;
158   }
159
160   gp_Circ2d* circleByCenterAndTangent()
161   {
162     const gp_Pnt2d& aCenter = myCenter->impl<gp_Pnt2d>();
163     CurveAdaptorPtr aCurve = myTangentShapes[0];
164
165     std::shared_ptr<GccAna_Circ2dTanCen> aCircleBuilder;
166     if (aCurve->GetType() == GeomAbs_Line) {
167       aCircleBuilder = std::shared_ptr<GccAna_Circ2dTanCen>(
168           new GccAna_Circ2dTanCen(aCurve->Line(), aCenter));
169     } else if (aCurve->GetType() == GeomAbs_Circle) {
170       aCircleBuilder = std::shared_ptr<GccAna_Circ2dTanCen>(new GccAna_Circ2dTanCen(
171           GccEnt::Unqualified(aCurve->Circle()), aCenter, Precision::Confusion()));
172     }
173
174     return getProperCircle(aCircleBuilder);
175   }
176
177   gp_Circ2d* getProperCircle(const std::shared_ptr<GccAna_Circ2dTanCen>& theBuilder) const
178   {
179     if (!theBuilder)
180       return 0;
181
182     CurveAdaptorPtr aCurve = myTangentShapes[0];
183
184     gp_Circ2d* aResult = 0;
185     int aNbSol = theBuilder->NbSolutions();
186     double aParSol, aPonTgCurve;
187     gp_Pnt2d aTgPnt;
188     for (int i = 1; i <= aNbSol && aCurve; ++i) {
189       theBuilder->Tangency1(i, aParSol, aPonTgCurve, aTgPnt);
190       if (aPonTgCurve >= aCurve->FirstParameter() && aPonTgCurve <= aCurve->LastParameter()) {
191         aResult = new gp_Circ2d(theBuilder->ThisSolution(i));
192         break;
193       }
194     }
195     // unable to build circle passing through the tangent curve,
196     // so get a circle passing any tangent point
197     if (!aResult && aNbSol > 0)
198       aResult =  new gp_Circ2d(theBuilder->ThisSolution(1));
199     return aResult;
200   }
201
202
203   gp_Circ2d* circleByThreeTangentCurves()
204   {
205     VectorOfGccCirc aTgCirc;
206     VectorOfGccLine aTgLine;
207     convertTangentCurvesToGccEnt(aTgCirc, aTgLine);
208
209     if (aTgCirc.size() + aTgLine.size() != 3)
210       return 0;
211
212     std::shared_ptr<GccAna_Circ2d3Tan> aCircleBuilder;
213     switch (aTgLine.size()) {
214     case 0:
215       aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
216           *aTgCirc[0], *aTgCirc[1], *aTgCirc[2], Precision::Confusion()));
217       break;
218     case 1:
219       aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
220           *aTgCirc[0], *aTgCirc[1], *aTgLine[0], Precision::Confusion()));
221       break;
222     case 2:
223       aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
224           *aTgCirc[0], *aTgLine[0], *aTgLine[1], Precision::Confusion()));
225       break;
226     case 3:
227       aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
228           *aTgLine[0], *aTgLine[1], *aTgLine[0], Precision::Confusion()));
229       break;
230     default:
231       break;
232     }
233
234     return getProperCircle(aCircleBuilder);
235   }
236
237   gp_Circ2d* circleByPointAndTwoTangentCurves()
238   {
239     const gp_Pnt2d& aPoint = myPassingPoints[0];
240     CurveAdaptorPtr aCurve1 = myTangentShapes[0];
241     CurveAdaptorPtr aCurve2 = myTangentShapes[1];
242     if (!aCurve1 || !aCurve2)
243       return 0;
244
245     std::shared_ptr<GccAna_Circ2d3Tan> aCircleBuilder;
246     if (aCurve1->GetType() == GeomAbs_Line) {
247       if (aCurve2->GetType() == GeomAbs_Line) {
248         aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(
249             new GccAna_Circ2d3Tan(GccEnt::Unqualified(aCurve1->Line()),
250                                   GccEnt::Unqualified(aCurve2->Line()),
251                                   aPoint, Precision::Confusion()));
252       } else if (aCurve2->GetType() == GeomAbs_Circle) {
253         aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(
254             new GccAna_Circ2d3Tan(GccEnt::Unqualified(aCurve2->Circle()),
255                                   GccEnt::Unqualified(aCurve1->Line()),
256                                   aPoint, Precision::Confusion()));
257       }
258     } else if (aCurve1->GetType() == GeomAbs_Circle) {
259       if (aCurve2->GetType() == GeomAbs_Line) {
260         aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(
261             new GccAna_Circ2d3Tan(GccEnt::Unqualified(aCurve1->Circle()),
262                                   GccEnt::Unqualified(aCurve2->Line()),
263                                   aPoint, Precision::Confusion()));
264       } else if (aCurve2->GetType() == GeomAbs_Circle) {
265         aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(
266             new GccAna_Circ2d3Tan(GccEnt::Unqualified(aCurve2->Circle()),
267                                   GccEnt::Unqualified(aCurve1->Circle()),
268                                   aPoint, Precision::Confusion()));
269       }
270     }
271
272     return getProperCircle(aCircleBuilder);
273   }
274
275   gp_Circ2d* circleByTwoPointsAndTangentCurve()
276   {
277     const gp_Pnt2d& aPoint1 = myPassingPoints[0];
278     const gp_Pnt2d& aPoint2 = myPassingPoints[1];
279     CurveAdaptorPtr aCurve = myTangentShapes[0];
280     if (!aCurve)
281       return 0;
282
283     std::shared_ptr<GccAna_Circ2d3Tan> aCircleBuilder;
284     if (aCurve->GetType() == GeomAbs_Line) {
285       aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
286         GccEnt::Unqualified(aCurve->Line()), aPoint1, aPoint2, Precision::Confusion()));
287     } else if (aCurve->GetType() == GeomAbs_Circle) {
288       aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
289           GccEnt::Unqualified(aCurve->Circle()), aPoint1, aPoint2, Precision::Confusion()));
290     }
291
292     return getProperCircle(aCircleBuilder);
293   }
294
295   gp_Circ2d* circleByThreePassingPoints()
296   {
297     GccAna_Circ2d3Tan aCircleBuilder(myPassingPoints[0],
298                                      myPassingPoints[1],
299                                      myPassingPoints[2],
300                                      Precision::Confusion());
301     if (aCircleBuilder.NbSolutions() > 0)
302       return new gp_Circ2d(aCircleBuilder.ThisSolution(1));
303     return 0;
304   }
305
306   gp_Circ2d* getProperCircle(const std::shared_ptr<GccAna_Circ2d3Tan>& theBuilder) const
307   {
308     if (!theBuilder)
309       return 0;
310
311     gp_Circ2d* aResult = 0;
312     int aNbSol = theBuilder->NbSolutions();
313     double aParSol, aPonTgCurve;
314     gp_Pnt2d aTgPnt;
315     for (int i = 1; i <= aNbSol; ++i) {
316       bool isApplicable = false;
317       if (myTangentShapes.size() >= 1) {
318         theBuilder->Tangency1(i, aParSol, aPonTgCurve, aTgPnt);
319         isApplicable = aPonTgCurve >= myTangentShapes[0]->FirstParameter() &&
320                        aPonTgCurve <= myTangentShapes[0]->LastParameter();
321       }
322       if (myTangentShapes.size() >= 2 && isApplicable) {
323         theBuilder->Tangency2(i, aParSol, aPonTgCurve, aTgPnt);
324         isApplicable = aPonTgCurve >= myTangentShapes[1]->FirstParameter() &&
325                        aPonTgCurve <= myTangentShapes[1]->LastParameter();
326       }
327       if (myTangentShapes.size() >= 3 && isApplicable) {
328         theBuilder->Tangency3(i, aParSol, aPonTgCurve, aTgPnt);
329         isApplicable = aPonTgCurve >= myTangentShapes[2]->FirstParameter() &&
330                        aPonTgCurve <= myTangentShapes[2]->LastParameter();
331       }
332
333       if (isApplicable) {
334         aResult = new gp_Circ2d(theBuilder->ThisSolution(i));
335         break;
336       }
337     }
338     // unable to build circle passing through the tangent curve => get any tangent point
339     if (!aResult && aNbSol > 0)
340       aResult =  new gp_Circ2d(theBuilder->ThisSolution(1));
341     return aResult;
342   }
343
344
345   gp_Circ2d* circleByRadiusAndTwoTangentCurves()
346   {
347     VectorOfGccCirc aTgCirc;
348     VectorOfGccLine aTgLine;
349     convertTangentCurvesToGccEnt(aTgCirc, aTgLine);
350
351     if (aTgCirc.size() + aTgLine.size() != 2)
352       return 0;
353
354     std::shared_ptr<GccAna_Circ2d2TanRad> aCircleBuilder;
355     switch (aTgLine.size()) {
356     case 0:
357       aCircleBuilder = std::shared_ptr<GccAna_Circ2d2TanRad>(new GccAna_Circ2d2TanRad(
358           *aTgCirc[0], *aTgCirc[1], myRadius, Precision::Confusion()));
359       break;
360     case 1:
361       aCircleBuilder = std::shared_ptr<GccAna_Circ2d2TanRad>(new GccAna_Circ2d2TanRad(
362           *aTgCirc[0], *aTgLine[0], myRadius, Precision::Confusion()));
363       break;
364     case 2:
365       aCircleBuilder = std::shared_ptr<GccAna_Circ2d2TanRad>(new GccAna_Circ2d2TanRad(
366           *aTgLine[0], *aTgLine[1], myRadius, Precision::Confusion()));
367       break;
368     default:
369       break;
370     }
371
372     return getProperCircle(aCircleBuilder);
373   }
374
375   gp_Circ2d* getProperCircle(const std::shared_ptr<GccAna_Circ2d2TanRad>& theBuilder) const
376   {
377     if (!theBuilder)
378       return 0;
379
380     gp_Circ2d* aResult = 0;
381     int aNbSol = theBuilder->NbSolutions();
382     double aParSol, aPonTgCurve;
383     gp_Pnt2d aTgPnt;
384     for (int i = 1; i <= aNbSol; ++i) {
385       bool isApplicable = false;
386       if (myTangentShapes.size() >= 1) {
387         theBuilder->Tangency1(i, aParSol, aPonTgCurve, aTgPnt);
388         isApplicable = isParamInCurve(aPonTgCurve, myTangentShapes[0]);
389       }
390       if (myTangentShapes.size() >= 2 && isApplicable) {
391         theBuilder->Tangency2(i, aParSol, aPonTgCurve, aTgPnt);
392         isApplicable = isParamInCurve(aPonTgCurve, myTangentShapes[1]);
393       }
394
395       if (isApplicable) {
396         aResult = new gp_Circ2d(theBuilder->ThisSolution(i));
397         break;
398       }
399     }
400     // unable to build circle passing through the tangent curve => get any tangent point
401     if (!aResult && aNbSol > 0)
402       aResult =  new gp_Circ2d(theBuilder->ThisSolution(1));
403     return aResult;
404   }
405
406
407   void convertTangentCurvesToGccEnt(VectorOfGccCirc& theTangentCircles,
408                                     VectorOfGccLine& theTangentLines)
409   {
410     theTangentCircles.reserve(3);
411     theTangentLines.reserve(3);
412
413     std::vector<CurveAdaptorPtr>::iterator anIt = myTangentShapes.begin();
414     for (; anIt != myTangentShapes.end(); ++anIt) {
415       switch ((*anIt)->GetType()) {
416       case GeomAbs_Line:
417         theTangentLines.push_back(
418             std::shared_ptr<GccEnt_QualifiedLin>(
419             new GccEnt_QualifiedLin((*anIt)->Line(), GccEnt_unqualified))
420         );
421         break;
422       case GeomAbs_Circle:
423         theTangentCircles.push_back(
424             std::shared_ptr<GccEnt_QualifiedCirc>(
425             new GccEnt_QualifiedCirc((*anIt)->Circle(), GccEnt_unqualified))
426         );
427         break;
428       default:
429         break;
430       }
431     }
432   }
433
434
435   // boundary parameters of curve are NOT applied
436   static bool isParamInCurve(double& theParameter, const CurveAdaptorPtr& theCurve)
437   {
438     if (theCurve->Curve()->IsPeriodic()) {
439       theParameter = ElCLib::InPeriod(theParameter,
440                                       theCurve->FirstParameter(),
441                                       theCurve->FirstParameter() + theCurve->Period());
442     }
443     return theParameter > theCurve->FirstParameter() &&
444            theParameter < theCurve->LastParameter();
445   }
446
447   // boundary parameters of curve are applied too
448   static bool isParamOnCurve(double& theParameter, const CurveAdaptorPtr& theCurve)
449   {
450     if (theCurve->IsPeriodic()) {
451       theParameter = ElCLib::InPeriod(theParameter,
452                                       theCurve->FirstParameter(),
453                                       theCurve->FirstParameter() + theCurve->Period());
454     }
455     return theParameter >= theCurve->FirstParameter() &&
456            theParameter <= theCurve->LastParameter();
457   }
458
459 private:
460   Handle(Geom_Plane) myPlane;
461   std::shared_ptr<GeomAPI_Pnt2d> myCenter;
462   std::vector<gp_Pnt2d> myPassingPoints;
463   std::vector<CurveAdaptorPtr> myTangentShapes;
464   double myRadius;
465 };
466
467 typedef std::shared_ptr<CircleBuilder> CircleBuilderPtr;
468
469
470 static gp_Circ2d* newCirc2d(const double theCenterX, const double theCenterY, const gp_Dir2d theDir,
471                             const double theRadius)
472 {
473   gp_Pnt2d aCenter(theCenterX, theCenterY);
474   return new gp_Circ2d(gp_Ax2d(aCenter, theDir), theRadius);
475 }
476
477 static gp_Circ2d* newCirc2d(const double theCenterX, const double theCenterY,
478                             const double thePointX, const double thePointY)
479 {
480   gp_Pnt2d aCenter(theCenterX, theCenterY);
481   gp_Pnt2d aPoint(thePointX, thePointY);
482
483   double aRadius = aCenter.Distance(aPoint);
484
485   if (aCenter.IsEqual(aPoint, Precision::Confusion()))
486     return NULL;
487
488   gp_Dir2d aDir(thePointX - theCenterX, thePointY - theCenterY);
489
490   return newCirc2d(theCenterX, theCenterY, aDir, aRadius);
491 }
492
493 static gp_Circ2d* newCirc2d(const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
494                             const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint,
495                             const std::shared_ptr<GeomAPI_Pnt2d>& theThirdPoint)
496 {
497   gp_XY aFirstPnt(theFirstPoint->x(), theFirstPoint->y());
498   gp_XY aSecondPnt(theSecondPoint->x(), theSecondPoint->y());
499   gp_XY aThirdPnt(theThirdPoint->x(), theThirdPoint->y());
500
501   gp_XY aVec12 = aSecondPnt - aFirstPnt;
502   gp_XY aVec23 = aThirdPnt - aSecondPnt;
503   gp_XY aVec31 = aFirstPnt - aThirdPnt;
504
505   // coefficients to calculate center
506   double aCoeff1, aCoeff2, aCoeff3;
507
508   // square of parallelogram
509   double aSquare2 = aVec12.Crossed(aVec23);
510   aSquare2 *= aSquare2 * 2.0;
511   if (aSquare2 < 1.e-20) {
512     // if two points are equal, build a circle on two different points as on diameter
513     double aSqLen12 = aVec12.SquareModulus();
514     double aSqLen23 = aVec23.SquareModulus();
515     double aSqLen31 = aVec31.SquareModulus();
516     if (aSqLen12 < Precision::SquareConfusion() &&
517         aSqLen23 < Precision::SquareConfusion() &&
518         aSqLen31 < Precision::SquareConfusion())
519       return NULL;
520     aCoeff1 = aCoeff2 = aCoeff3 = 1.0 / 3.0;
521   }
522   else {
523     aCoeff1 = aVec23.Dot(aVec23) / aSquare2 * aVec12.Dot(aVec31.Reversed());
524     aCoeff2 = aVec31.Dot(aVec31) / aSquare2 * aVec23.Dot(aVec12.Reversed());
525     aCoeff3 = aVec12.Dot(aVec12) / aSquare2 * aVec31.Dot(aVec23.Reversed());
526   }
527   // center
528   gp_XY aCenter = aFirstPnt * aCoeff1 + aSecondPnt * aCoeff2 + aThirdPnt * aCoeff3;
529   // radius
530   double aRadius = (aFirstPnt - aCenter).Modulus();
531
532   gp_Dir2d aDir(aFirstPnt - aCenter);
533   return newCirc2d(aCenter.X(), aCenter.Y(), aDir, aRadius);
534 }
535
536
537
538 GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
539                                const std::shared_ptr<GeomAPI_Pnt2d>& theCirclePoint)
540     : GeomAPI_Interface(
541         newCirc2d(theCenter->x(), theCenter->y(), theCirclePoint->x(), theCirclePoint->y()))
542 {
543 }
544
545 GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
546                                const std::shared_ptr<GeomAPI_Dir2d>& theDir, double theRadius)
547     : GeomAPI_Interface(
548         newCirc2d(theCenter->x(), theCenter->y(), theDir->impl<gp_Dir2d>(), theRadius))
549 {
550 }
551
552 GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
553                                const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint,
554                                const std::shared_ptr<GeomAPI_Pnt2d>& theThirdPoint)
555     : GeomAPI_Interface(newCirc2d(theFirstPoint, theSecondPoint, theThirdPoint))
556 {
557 }
558
559 GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
560                                const std::shared_ptr<GeomAPI_Shape>& theTangent,
561                                const std::shared_ptr<GeomAPI_Ax3>&   thePlane)
562 {
563   CircleBuilderPtr aBuilder(new CircleBuilder(thePlane));
564   aBuilder->addCenter(theCenter);
565   aBuilder->addTangentCurve(theTangent);
566   setImpl(aBuilder->circle());
567 }
568
569 GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Interface>& theEntity1,
570                                const std::shared_ptr<GeomAPI_Interface>& theEntity2,
571                                const std::shared_ptr<GeomAPI_Interface>& theEntity3,
572                                const std::shared_ptr<GeomAPI_Ax3>&       thePlane)
573 {
574   CircleBuilderPtr aBuilder(new CircleBuilder(thePlane));
575   aBuilder->addPassingEntity(theEntity1);
576   aBuilder->addPassingEntity(theEntity2);
577   aBuilder->addPassingEntity(theEntity3);
578   setImpl(aBuilder->circle());
579 }
580
581 GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Interface>& theEntity1,
582                                const std::shared_ptr<GeomAPI_Interface>& theEntity2,
583                                const double                              theRadius,
584                                const std::shared_ptr<GeomAPI_Ax3>&       thePlane)
585 {
586   CircleBuilderPtr aBuilder(new CircleBuilder(thePlane));
587   aBuilder->addPassingEntity(theEntity1);
588   aBuilder->addPassingEntity(theEntity2);
589   aBuilder->setRadius(theRadius);
590   setImpl(aBuilder->circle());
591 }
592
593
594
595 const std::shared_ptr<GeomAPI_Pnt2d> GeomAPI_Circ2d::project(
596     const std::shared_ptr<GeomAPI_Pnt2d>& thePoint) const
597 {
598   std::shared_ptr<GeomAPI_Pnt2d> aResult;
599   if (!MY_CIRC2D)
600     return aResult;
601
602   const gp_Pnt2d& aCenter = MY_CIRC2D->Location();
603   const gp_Pnt2d& aPoint = thePoint->impl<gp_Pnt2d>();
604
605   double aDist = aCenter.Distance(aPoint);
606   if (aDist < Precision::Confusion())
607     return aResult;
608
609   if (Abs(aDist - MY_CIRC2D->Radius()) < Precision::Confusion()) {
610     // Point on the circle
611     aResult = std::shared_ptr<GeomAPI_Pnt2d>(
612         new GeomAPI_Pnt2d(thePoint->x(), thePoint->y()));
613   } else {
614     gp_Dir2d aDir(aPoint.XY() - aCenter.XY());
615     gp_XY aNewPoint = aCenter.XY() + aDir.XY() * MY_CIRC2D->Radius();
616     aResult = std::shared_ptr<GeomAPI_Pnt2d>(
617         new GeomAPI_Pnt2d(aNewPoint.X(), aNewPoint.Y()));
618   }
619
620   return aResult;
621 }
622
623 const std::shared_ptr<GeomAPI_Pnt2d> GeomAPI_Circ2d::center() const
624 {
625   if (!MY_CIRC2D)
626     return std::shared_ptr<GeomAPI_Pnt2d>();
627   const gp_Pnt2d& aCenter = MY_CIRC2D->Location();
628   return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aCenter.X(), aCenter.Y()));
629 }
630
631 double GeomAPI_Circ2d::radius() const
632 {
633   if (!MY_CIRC2D)
634     return 0.0;
635   return MY_CIRC2D->Radius();
636 }
637
638 //=================================================================================================
639 const bool GeomAPI_Circ2d::parameter(const std::shared_ptr<GeomAPI_Pnt2d> thePoint,
640                                    const double theTolerance,
641                                    double& theParameter) const
642 {
643   Handle(Geom2d_Circle) aCurve = new Geom2d_Circle(*MY_CIRC2D);
644   return GeomLib_Tool::Parameter(aCurve, thePoint->impl<gp_Pnt2d>(),
645                                  theTolerance, theParameter) == Standard_True;
646 }
647
648 //=================================================================================================
649 void GeomAPI_Circ2d::D0(const double theU, std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
650 {
651   Handle(Geom2d_Circle) aCurve = new Geom2d_Circle(*MY_CIRC2D);
652   gp_Pnt2d aPnt;
653   aCurve->D0(theU, aPnt);
654   thePoint.reset(new GeomAPI_Pnt2d(aPnt.X(), aPnt.Y()));
655 }
656