]> SALOME platform Git repositories - modules/shaper.git/blob - src/GeomAPI/GeomAPI_Circ2d.cpp
Salome HOME
GeomAPI_Circ2d: correct checking of parameter on periodic tangent curve
[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 (isParamOnCurve(aPonTgCurve, aCurve)) {
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 = isParamOnCurve(aPonTgCurve, myTangentShapes[0]);
320       }
321       if (myTangentShapes.size() >= 2 && isApplicable) {
322         theBuilder->Tangency2(i, aParSol, aPonTgCurve, aTgPnt);
323         isApplicable = isParamOnCurve(aPonTgCurve, myTangentShapes[1]);
324       }
325       if (myTangentShapes.size() >= 3 && isApplicable) {
326         theBuilder->Tangency3(i, aParSol, aPonTgCurve, aTgPnt);
327         isApplicable = isParamOnCurve(aPonTgCurve, myTangentShapes[2]);
328       }
329
330       if (isApplicable) {
331         aResult = new gp_Circ2d(theBuilder->ThisSolution(i));
332         break;
333       }
334     }
335     // unable to build circle passing through the tangent curve => get any tangent point
336     if (!aResult && aNbSol > 0)
337       aResult =  new gp_Circ2d(theBuilder->ThisSolution(1));
338     return aResult;
339   }
340
341
342   gp_Circ2d* circleByRadiusAndTwoTangentCurves()
343   {
344     VectorOfGccCirc aTgCirc;
345     VectorOfGccLine aTgLine;
346     convertTangentCurvesToGccEnt(aTgCirc, aTgLine);
347
348     if (aTgCirc.size() + aTgLine.size() != 2)
349       return 0;
350
351     std::shared_ptr<GccAna_Circ2d2TanRad> aCircleBuilder;
352     switch (aTgLine.size()) {
353     case 0:
354       aCircleBuilder = std::shared_ptr<GccAna_Circ2d2TanRad>(new GccAna_Circ2d2TanRad(
355           *aTgCirc[0], *aTgCirc[1], myRadius, Precision::Confusion()));
356       break;
357     case 1:
358       aCircleBuilder = std::shared_ptr<GccAna_Circ2d2TanRad>(new GccAna_Circ2d2TanRad(
359           *aTgCirc[0], *aTgLine[0], myRadius, Precision::Confusion()));
360       break;
361     case 2:
362       aCircleBuilder = std::shared_ptr<GccAna_Circ2d2TanRad>(new GccAna_Circ2d2TanRad(
363           *aTgLine[0], *aTgLine[1], myRadius, Precision::Confusion()));
364       break;
365     default:
366       break;
367     }
368
369     return getProperCircle(aCircleBuilder);
370   }
371
372   gp_Circ2d* getProperCircle(const std::shared_ptr<GccAna_Circ2d2TanRad>& theBuilder) const
373   {
374     if (!theBuilder)
375       return 0;
376
377     gp_Circ2d* aResult = 0;
378     int aNbSol = theBuilder->NbSolutions();
379     double aParSol, aPonTgCurve;
380     gp_Pnt2d aTgPnt;
381     for (int i = 1; i <= aNbSol; ++i) {
382       bool isApplicable = false;
383       if (myTangentShapes.size() >= 1) {
384         theBuilder->Tangency1(i, aParSol, aPonTgCurve, aTgPnt);
385         isApplicable = isParamInCurve(aPonTgCurve, myTangentShapes[0]);
386       }
387       if (myTangentShapes.size() >= 2 && isApplicable) {
388         theBuilder->Tangency2(i, aParSol, aPonTgCurve, aTgPnt);
389         isApplicable = isParamInCurve(aPonTgCurve, myTangentShapes[1]);
390       }
391
392       if (isApplicable) {
393         aResult = new gp_Circ2d(theBuilder->ThisSolution(i));
394         break;
395       }
396     }
397     // unable to build circle passing through the tangent curve => get any tangent point
398     if (!aResult && aNbSol > 0)
399       aResult =  new gp_Circ2d(theBuilder->ThisSolution(1));
400     return aResult;
401   }
402
403
404   void convertTangentCurvesToGccEnt(VectorOfGccCirc& theTangentCircles,
405                                     VectorOfGccLine& theTangentLines)
406   {
407     theTangentCircles.reserve(3);
408     theTangentLines.reserve(3);
409
410     std::vector<CurveAdaptorPtr>::iterator anIt = myTangentShapes.begin();
411     for (; anIt != myTangentShapes.end(); ++anIt) {
412       switch ((*anIt)->GetType()) {
413       case GeomAbs_Line:
414         theTangentLines.push_back(
415             std::shared_ptr<GccEnt_QualifiedLin>(
416             new GccEnt_QualifiedLin((*anIt)->Line(), GccEnt_unqualified))
417         );
418         break;
419       case GeomAbs_Circle:
420         theTangentCircles.push_back(
421             std::shared_ptr<GccEnt_QualifiedCirc>(
422             new GccEnt_QualifiedCirc((*anIt)->Circle(), GccEnt_unqualified))
423         );
424         break;
425       default:
426         break;
427       }
428     }
429   }
430
431
432   // boundary parameters of curve are NOT applied
433   static bool isParamInCurve(double& theParameter, const CurveAdaptorPtr& theCurve)
434   {
435     if (theCurve->Curve()->IsPeriodic()) {
436       theParameter = ElCLib::InPeriod(theParameter,
437                                       theCurve->FirstParameter(),
438                                       theCurve->FirstParameter() + theCurve->Period());
439     }
440     return theParameter > theCurve->FirstParameter() &&
441            theParameter < theCurve->LastParameter();
442   }
443
444   // boundary parameters of curve are applied too
445   static bool isParamOnCurve(double& theParameter, const CurveAdaptorPtr& theCurve)
446   {
447     if (theCurve->IsPeriodic()) {
448       theParameter = ElCLib::InPeriod(theParameter,
449                                       theCurve->FirstParameter(),
450                                       theCurve->FirstParameter() + theCurve->Period());
451     }
452     return theParameter >= theCurve->FirstParameter() &&
453            theParameter <= theCurve->LastParameter();
454   }
455
456 private:
457   Handle(Geom_Plane) myPlane;
458   std::shared_ptr<GeomAPI_Pnt2d> myCenter;
459   std::vector<gp_Pnt2d> myPassingPoints;
460   std::vector<CurveAdaptorPtr> myTangentShapes;
461   double myRadius;
462 };
463
464 typedef std::shared_ptr<CircleBuilder> CircleBuilderPtr;
465
466
467 static gp_Circ2d* newCirc2d(const double theCenterX, const double theCenterY, const gp_Dir2d theDir,
468                             const double theRadius)
469 {
470   gp_Pnt2d aCenter(theCenterX, theCenterY);
471   return new gp_Circ2d(gp_Ax2d(aCenter, theDir), theRadius);
472 }
473
474 static gp_Circ2d* newCirc2d(const double theCenterX, const double theCenterY,
475                             const double thePointX, const double thePointY)
476 {
477   gp_Pnt2d aCenter(theCenterX, theCenterY);
478   gp_Pnt2d aPoint(thePointX, thePointY);
479
480   double aRadius = aCenter.Distance(aPoint);
481
482   if (aCenter.IsEqual(aPoint, Precision::Confusion()))
483     return NULL;
484
485   gp_Dir2d aDir(thePointX - theCenterX, thePointY - theCenterY);
486
487   return newCirc2d(theCenterX, theCenterY, aDir, aRadius);
488 }
489
490 static gp_Circ2d* newCirc2d(const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
491                             const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint,
492                             const std::shared_ptr<GeomAPI_Pnt2d>& theThirdPoint)
493 {
494   gp_XY aFirstPnt(theFirstPoint->x(), theFirstPoint->y());
495   gp_XY aSecondPnt(theSecondPoint->x(), theSecondPoint->y());
496   gp_XY aThirdPnt(theThirdPoint->x(), theThirdPoint->y());
497
498   gp_XY aVec12 = aSecondPnt - aFirstPnt;
499   gp_XY aVec23 = aThirdPnt - aSecondPnt;
500   gp_XY aVec31 = aFirstPnt - aThirdPnt;
501
502   // coefficients to calculate center
503   double aCoeff1, aCoeff2, aCoeff3;
504
505   // square of parallelogram
506   double aSquare2 = aVec12.Crossed(aVec23);
507   aSquare2 *= aSquare2 * 2.0;
508   if (aSquare2 < 1.e-20) {
509     // if two points are equal, build a circle on two different points as on diameter
510     double aSqLen12 = aVec12.SquareModulus();
511     double aSqLen23 = aVec23.SquareModulus();
512     double aSqLen31 = aVec31.SquareModulus();
513     if (aSqLen12 < Precision::SquareConfusion() &&
514         aSqLen23 < Precision::SquareConfusion() &&
515         aSqLen31 < Precision::SquareConfusion())
516       return NULL;
517     aCoeff1 = aCoeff2 = aCoeff3 = 1.0 / 3.0;
518   }
519   else {
520     aCoeff1 = aVec23.Dot(aVec23) / aSquare2 * aVec12.Dot(aVec31.Reversed());
521     aCoeff2 = aVec31.Dot(aVec31) / aSquare2 * aVec23.Dot(aVec12.Reversed());
522     aCoeff3 = aVec12.Dot(aVec12) / aSquare2 * aVec31.Dot(aVec23.Reversed());
523   }
524   // center
525   gp_XY aCenter = aFirstPnt * aCoeff1 + aSecondPnt * aCoeff2 + aThirdPnt * aCoeff3;
526   // radius
527   double aRadius = (aFirstPnt - aCenter).Modulus();
528
529   gp_Dir2d aDir(aFirstPnt - aCenter);
530   return newCirc2d(aCenter.X(), aCenter.Y(), aDir, aRadius);
531 }
532
533
534
535 GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
536                                const std::shared_ptr<GeomAPI_Pnt2d>& theCirclePoint)
537     : GeomAPI_Interface(
538         newCirc2d(theCenter->x(), theCenter->y(), theCirclePoint->x(), theCirclePoint->y()))
539 {
540 }
541
542 GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
543                                const std::shared_ptr<GeomAPI_Dir2d>& theDir, double theRadius)
544     : GeomAPI_Interface(
545         newCirc2d(theCenter->x(), theCenter->y(), theDir->impl<gp_Dir2d>(), theRadius))
546 {
547 }
548
549 GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
550                                const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint,
551                                const std::shared_ptr<GeomAPI_Pnt2d>& theThirdPoint)
552     : GeomAPI_Interface(newCirc2d(theFirstPoint, theSecondPoint, theThirdPoint))
553 {
554 }
555
556 GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
557                                const std::shared_ptr<GeomAPI_Shape>& theTangent,
558                                const std::shared_ptr<GeomAPI_Ax3>&   thePlane)
559 {
560   CircleBuilderPtr aBuilder(new CircleBuilder(thePlane));
561   aBuilder->addCenter(theCenter);
562   aBuilder->addTangentCurve(theTangent);
563   setImpl(aBuilder->circle());
564 }
565
566 GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Interface>& theEntity1,
567                                const std::shared_ptr<GeomAPI_Interface>& theEntity2,
568                                const std::shared_ptr<GeomAPI_Interface>& theEntity3,
569                                const std::shared_ptr<GeomAPI_Ax3>&       thePlane)
570 {
571   CircleBuilderPtr aBuilder(new CircleBuilder(thePlane));
572   aBuilder->addPassingEntity(theEntity1);
573   aBuilder->addPassingEntity(theEntity2);
574   aBuilder->addPassingEntity(theEntity3);
575   setImpl(aBuilder->circle());
576 }
577
578 GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Interface>& theEntity1,
579                                const std::shared_ptr<GeomAPI_Interface>& theEntity2,
580                                const double                              theRadius,
581                                const std::shared_ptr<GeomAPI_Ax3>&       thePlane)
582 {
583   CircleBuilderPtr aBuilder(new CircleBuilder(thePlane));
584   aBuilder->addPassingEntity(theEntity1);
585   aBuilder->addPassingEntity(theEntity2);
586   aBuilder->setRadius(theRadius);
587   setImpl(aBuilder->circle());
588 }
589
590
591
592 const std::shared_ptr<GeomAPI_Pnt2d> GeomAPI_Circ2d::project(
593     const std::shared_ptr<GeomAPI_Pnt2d>& thePoint) const
594 {
595   std::shared_ptr<GeomAPI_Pnt2d> aResult;
596   if (!MY_CIRC2D)
597     return aResult;
598
599   const gp_Pnt2d& aCenter = MY_CIRC2D->Location();
600   const gp_Pnt2d& aPoint = thePoint->impl<gp_Pnt2d>();
601
602   double aDist = aCenter.Distance(aPoint);
603   if (aDist < Precision::Confusion())
604     return aResult;
605
606   if (Abs(aDist - MY_CIRC2D->Radius()) < Precision::Confusion()) {
607     // Point on the circle
608     aResult = std::shared_ptr<GeomAPI_Pnt2d>(
609         new GeomAPI_Pnt2d(thePoint->x(), thePoint->y()));
610   } else {
611     gp_Dir2d aDir(aPoint.XY() - aCenter.XY());
612     gp_XY aNewPoint = aCenter.XY() + aDir.XY() * MY_CIRC2D->Radius();
613     aResult = std::shared_ptr<GeomAPI_Pnt2d>(
614         new GeomAPI_Pnt2d(aNewPoint.X(), aNewPoint.Y()));
615   }
616
617   return aResult;
618 }
619
620 const std::shared_ptr<GeomAPI_Pnt2d> GeomAPI_Circ2d::center() const
621 {
622   if (!MY_CIRC2D)
623     return std::shared_ptr<GeomAPI_Pnt2d>();
624   const gp_Pnt2d& aCenter = MY_CIRC2D->Location();
625   return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aCenter.X(), aCenter.Y()));
626 }
627
628 double GeomAPI_Circ2d::radius() const
629 {
630   if (!MY_CIRC2D)
631     return 0.0;
632   return MY_CIRC2D->Radius();
633 }
634
635 //=================================================================================================
636 const bool GeomAPI_Circ2d::parameter(const std::shared_ptr<GeomAPI_Pnt2d> thePoint,
637                                    const double theTolerance,
638                                    double& theParameter) const
639 {
640   Handle(Geom2d_Circle) aCurve = new Geom2d_Circle(*MY_CIRC2D);
641   return GeomLib_Tool::Parameter(aCurve, thePoint->impl<gp_Pnt2d>(),
642                                  theTolerance, theParameter) == Standard_True;
643 }
644
645 //=================================================================================================
646 void GeomAPI_Circ2d::D0(const double theU, std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
647 {
648   Handle(Geom2d_Circle) aCurve = new Geom2d_Circle(*MY_CIRC2D);
649   gp_Pnt2d aPnt;
650   aCurve->D0(theU, aPnt);
651   thePoint.reset(new GeomAPI_Pnt2d(aPnt.X(), aPnt.Y()));
652 }
653