Salome HOME
updated copyright message
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_Circ2dBuilder.cpp
1 // Copyright (C) 2014-2023  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 #include <GeomAlgoAPI_Circ2dBuilder.h>
21 #include <GeomAPI_Ax3.h>
22 #include <GeomAPI_Circ2d.h>
23 #include <GeomAPI_Pnt2d.h>
24 #include <GeomAPI_Dir2d.h>
25 #include <GeomAPI_Shape.h>
26
27 #include <BRep_Tool.hxx>
28 #include <ElCLib.hxx>
29 #include <GccAna_Circ2d2TanOn.hxx>
30 #include <GccAna_Circ2d2TanRad.hxx>
31 #include <GccAna_Circ2d3Tan.hxx>
32 #include <GccAna_Circ2dTanCen.hxx>
33 #include <GccEnt.hxx>
34 #include <GccEnt_QualifiedCirc.hxx>
35 #include <GccEnt_QualifiedLin.hxx>
36 #include <Geom2dAdaptor_Curve.hxx>
37 #include <Geom_Plane.hxx>
38 #include <TopoDS.hxx>
39 #include <TopoDS_Edge.hxx>
40
41 #include <cmath>
42
43 typedef std::shared_ptr<gp_Circ2d> Circ2dPtr;
44 typedef std::shared_ptr<Geom2dAdaptor_Curve> CurveAdaptorPtr;
45 typedef std::vector< std::shared_ptr<GccEnt_QualifiedCirc> > VectorOfGccCirc;
46 typedef std::vector< std::shared_ptr<GccEnt_QualifiedLin> >  VectorOfGccLine;
47
48
49 // Provide different mechanisms to create circle:
50 // * by passing points
51 // * by tangent edges
52 // * by transversal line
53 // * with specified radius
54 // * etc.
55 class CircleBuilder
56 {
57 public:
58   CircleBuilder(const std::shared_ptr<GeomAPI_Ax3>& theBasePlane)
59     : myPlane(new Geom_Plane(theBasePlane->impl<gp_Ax3>())),
60       myRadius(0.0)
61   {}
62
63   void setRadius(const double theRadius)
64   { myRadius = theRadius; }
65
66   void setCenter(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter)
67   { myCenter = theCenter; }
68
69   void setTangentCurves(const std::vector< std::shared_ptr<GeomAPI_Shape> >& theEdges)
70   {
71     std::vector< std::shared_ptr<GeomAPI_Shape> >::const_iterator anEdgeIt;
72     for (anEdgeIt = theEdges.begin(); anEdgeIt != theEdges.end(); ++anEdgeIt) {
73       const TopoDS_Edge& anEdge = TopoDS::Edge((*anEdgeIt)->impl<TopoDS_Shape>());
74
75       double aFirst, aLast;
76       TopLoc_Location aLoc;
77       Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface(anEdge, myPlane, aLoc, aFirst, aLast);
78       CurveAdaptorPtr aCurveAdaptor(new Geom2dAdaptor_Curve(aCurve, aFirst, aLast));
79
80       // sort curves (circles should become first)
81       if (aCurveAdaptor->GetType() == GeomAbs_Circle)
82         myTangentShapes.insert(myTangentShapes.begin(), aCurveAdaptor);
83       else
84         myTangentShapes.push_back(aCurveAdaptor);
85     }
86   }
87
88   void setTransversalLine(const std::shared_ptr<GeomAPI_Shape>& theLine)
89   {
90     if (!theLine)
91       return;
92
93     const TopoDS_Edge& anEdge = TopoDS::Edge(theLine->impl<TopoDS_Shape>());
94
95     double aFirst, aLast;
96     TopLoc_Location aLoc;
97     Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface(anEdge, myPlane, aLoc, aFirst, aLast);
98     myTransversalLine = CurveAdaptorPtr(new Geom2dAdaptor_Curve(aCurve, aFirst, aLast));
99   }
100
101   void setPassingPoints(const std::vector< std::shared_ptr<GeomAPI_Pnt2d> >& thePoints)
102   {
103     std::vector< std::shared_ptr<GeomAPI_Pnt2d> >::const_iterator aPIt;
104     for (aPIt = thePoints.begin(); aPIt != thePoints.end(); ++aPIt)
105       myPassingPoints.push_back((*aPIt)->impl<gp_Pnt2d>());
106   }
107
108   void setClosestPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
109   { myClosestPoint = thePoint; }
110
111
112   Circ2dPtr circle()
113   {
114     Circ2dPtr aResult;
115     if (myCenter) {
116       if (myPassingPoints.size() == 1)
117         aResult = circleByCenterAndPassingPoint();
118       else if (myTangentShapes.size() == 1)
119         aResult = circleByCenterAndTangent();
120       else if (myRadius > 0.0)
121         aResult = circleByCenterAndRadius();
122     } else if (myRadius > 0.0) {
123       if (myTangentShapes.size() == 2)
124         aResult = circleByRadiusAndTwoTangentCurves();
125     } else {
126       switch (myPassingPoints.size()) {
127       case 0:
128         aResult = circleByThreeTangentCurves();
129         break;
130       case 1:
131         aResult = circleByPointAndTwoTangentCurves();
132         break;
133       case 2: {
134         if (myTransversalLine)
135           aResult = circleByTwoPointsAndTransversalLine();
136         else
137           aResult = circleByTwoPointsAndTangentCurve();
138         break;
139       }
140       case 3:
141         aResult = circleByThreePassingPoints();
142         break;
143       default:
144         break;
145       }
146     }
147     return aResult;
148   }
149
150 private:
151   Circ2dPtr circleByCenterAndRadius()
152   {
153     const gp_Pnt2d& aCenter = myCenter->impl<gp_Pnt2d>();
154     return Circ2dPtr(new gp_Circ2d(gp_Ax2d(aCenter, gp::DX2d()), myRadius));
155   }
156
157   Circ2dPtr circleByCenterAndPassingPoint()
158   {
159     const gp_Pnt2d& aCenter = myCenter->impl<gp_Pnt2d>();
160     if (aCenter.SquareDistance(myPassingPoints[0]) > Precision::SquareConfusion()) {
161       GccAna_Circ2dTanCen aBuilder(myPassingPoints[0], aCenter);
162       if (aBuilder.NbSolutions() > 0)
163         return Circ2dPtr(new gp_Circ2d(aBuilder.ThisSolution(1)));
164     }
165     return Circ2dPtr();
166   }
167
168   Circ2dPtr circleByCenterAndTangent()
169   {
170     const gp_Pnt2d& aCenter = myCenter->impl<gp_Pnt2d>();
171     CurveAdaptorPtr aCurve = myTangentShapes[0];
172
173     std::shared_ptr<GccAna_Circ2dTanCen> aCircleBuilder;
174     if (aCurve->GetType() == GeomAbs_Line &&
175         aCurve->Line().Distance(aCenter) > Precision::Confusion()) {
176       aCircleBuilder = std::shared_ptr<GccAna_Circ2dTanCen>(
177           new GccAna_Circ2dTanCen(aCurve->Line(), aCenter));
178     } else if (aCurve->GetType() == GeomAbs_Circle) {
179       aCircleBuilder = std::shared_ptr<GccAna_Circ2dTanCen>(new GccAna_Circ2dTanCen(
180           GccEnt::Unqualified(aCurve->Circle()), aCenter, Precision::Confusion()));
181     }
182
183     return getProperCircle(aCircleBuilder);
184   }
185
186   Circ2dPtr getProperCircle(const std::shared_ptr<GccAna_Circ2dTanCen>& theBuilder) const
187   {
188     if (!theBuilder)
189       return Circ2dPtr();
190
191     CurveAdaptorPtr aCurve = myTangentShapes[0];
192
193     int aNbSol = theBuilder->NbSolutions();
194     if (aNbSol == 0)
195       return Circ2dPtr();
196
197     int anAppropriateSolution = 1;
198     double aMinDist = Precision::Infinite();
199
200     double aParSol, aPonTgCurve;
201     gp_Pnt2d aTgPnt;
202     for (int i = 1; i <= aNbSol && aNbSol > 1 && aCurve; ++i) {
203       theBuilder->Tangency1(i, aParSol, aPonTgCurve, aTgPnt);
204       if (isParamOnCurve(aPonTgCurve, aCurve)) {
205         double aDist = distanceToClosestPoint(theBuilder->ThisSolution(i));
206         if (aDist < aMinDist) {
207           anAppropriateSolution = i;
208           aMinDist = aDist;
209         }
210       }
211     }
212
213     return Circ2dPtr(new gp_Circ2d(theBuilder->ThisSolution(anAppropriateSolution)));
214   }
215
216   double distanceToClosestPoint(const gp_Circ2d& theCirc) const
217   {
218     if (myClosestPoint) {
219       double aDist = myClosestPoint->impl<gp_Pnt2d>().Distance(theCirc.Location());
220       return fabs(aDist - theCirc.Radius());
221     }
222     return 0.0;
223   }
224
225
226   Circ2dPtr circleByThreeTangentCurves()
227   {
228     VectorOfGccCirc aTgCirc;
229     VectorOfGccLine aTgLine;
230     convertTangentCurvesToGccEnt(aTgCirc, aTgLine);
231
232     std::shared_ptr<GccAna_Circ2d3Tan> aCircleBuilder;
233     if (aTgCirc.size() + aTgLine.size() == 3) {
234       switch (aTgLine.size()) {
235       case 0:
236         aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
237             *aTgCirc[0], *aTgCirc[1], *aTgCirc[2], Precision::Confusion()));
238         break;
239       case 1:
240         aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
241             *aTgCirc[0], *aTgCirc[1], *aTgLine[0], Precision::Confusion()));
242         break;
243       case 2:
244         aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
245             *aTgCirc[0], *aTgLine[0], *aTgLine[1], Precision::Confusion()));
246         break;
247       case 3:
248         aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
249             *aTgLine[0], *aTgLine[1], *aTgLine[2], Precision::Confusion()));
250         break;
251       default:
252         break;
253       }
254     }
255
256     return getProperCircle(aCircleBuilder);
257   }
258
259   Circ2dPtr circleByPointAndTwoTangentCurves()
260   {
261     const gp_Pnt2d& aPoint = myPassingPoints[0];
262
263     VectorOfGccCirc aTgCirc;
264     VectorOfGccLine aTgLine;
265     convertTangentCurvesToGccEnt(aTgCirc, aTgLine);
266
267     std::shared_ptr<GccAna_Circ2d3Tan> aCircleBuilder;
268     if (aTgCirc.size() + aTgLine.size() == 2) {
269       switch (aTgLine.size()) {
270       case 0:
271         aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
272             *aTgCirc[0], *aTgCirc[1], aPoint, Precision::Confusion()));
273         break;
274       case 1:
275         aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
276             *aTgCirc[0], *aTgLine[0], aPoint, Precision::Confusion()));
277         break;
278       case 2:
279         aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
280             *aTgLine[0], *aTgLine[1], aPoint, Precision::Confusion()));
281         break;
282       default:
283         break;
284       }
285     }
286
287     return getProperCircle(aCircleBuilder);
288   }
289
290   Circ2dPtr circleByTwoPointsAndTangentCurve()
291   {
292     const gp_Pnt2d& aPoint1 = myPassingPoints[0];
293     const gp_Pnt2d& aPoint2 = myPassingPoints[1];
294     CurveAdaptorPtr aCurve = myTangentShapes[0];
295
296     std::shared_ptr<GccAna_Circ2d3Tan> aCircleBuilder;
297     if (aCurve) {
298       if (aCurve->GetType() == GeomAbs_Line) {
299         aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
300             GccEnt::Unqualified(aCurve->Line()), aPoint1, aPoint2, Precision::Confusion()));
301       }
302       else if (aCurve->GetType() == GeomAbs_Circle) {
303         aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
304             GccEnt::Unqualified(aCurve->Circle()), aPoint1, aPoint2, Precision::Confusion()));
305       }
306     }
307
308     return getProperCircle(aCircleBuilder);
309   }
310
311   Circ2dPtr circleByThreePassingPoints()
312   {
313     GccAna_Circ2d3Tan aCircleBuilder(myPassingPoints[0],
314                                      myPassingPoints[1],
315                                      myPassingPoints[2],
316                                      Precision::Confusion());
317     if (aCircleBuilder.NbSolutions() > 0)
318       return Circ2dPtr(new gp_Circ2d(aCircleBuilder.ThisSolution(1)));
319     return Circ2dPtr();
320   }
321
322   Circ2dPtr getProperCircle(const std::shared_ptr<GccAna_Circ2d3Tan>& theBuilder) const
323   {
324     if (!theBuilder)
325       return Circ2dPtr();
326
327     int aNbSol = theBuilder->NbSolutions();
328     if (aNbSol == 0)
329       return Circ2dPtr();
330
331     int anAppropriateSolution = 1;
332     double aMinDist = Precision::Infinite();
333
334     double aParSol, aPonTgCurve;
335     gp_Pnt2d aTgPnt;
336     for (int i = 1; i <= aNbSol && aNbSol > 1; ++i) {
337       bool isApplicable = false;
338       if (myTangentShapes.size() >= 1) {
339         theBuilder->Tangency1(i, aParSol, aPonTgCurve, aTgPnt);
340         isApplicable = isParamOnCurve(aPonTgCurve, myTangentShapes[0]);
341       }
342       if (myTangentShapes.size() >= 2 && isApplicable) {
343         theBuilder->Tangency2(i, aParSol, aPonTgCurve, aTgPnt);
344         isApplicable = isParamOnCurve(aPonTgCurve, myTangentShapes[1]);
345       }
346       if (myTangentShapes.size() >= 3 && isApplicable) {
347         theBuilder->Tangency3(i, aParSol, aPonTgCurve, aTgPnt);
348         isApplicable = isParamOnCurve(aPonTgCurve, myTangentShapes[2]);
349       }
350
351       if (isApplicable) {
352         double aDist = distanceToClosestPoint(theBuilder->ThisSolution(i));
353         if (aDist < aMinDist) {
354           anAppropriateSolution = i;
355           aMinDist = aDist;
356         }
357       }
358     }
359
360     return Circ2dPtr(new gp_Circ2d(theBuilder->ThisSolution(anAppropriateSolution)));
361   }
362
363
364   Circ2dPtr circleByTwoPointsAndTransversalLine()
365   {
366     const gp_Pnt2d& aPoint1 = myPassingPoints[0];
367     const gp_Pnt2d& aPoint2 = myPassingPoints[1];
368
369     if (myTransversalLine && myTransversalLine->GetType() == GeomAbs_Line) {
370       GccAna_Circ2d2TanOn aCircleBuilder(aPoint1, aPoint2, myTransversalLine->Line(),
371                                          Precision::Confusion());
372       if (aCircleBuilder.NbSolutions() > 0)
373         return Circ2dPtr(new gp_Circ2d(aCircleBuilder.ThisSolution(1)));
374     }
375
376     return Circ2dPtr();
377   }
378
379
380   Circ2dPtr circleByRadiusAndTwoTangentCurves()
381   {
382     VectorOfGccCirc aTgCirc;
383     VectorOfGccLine aTgLine;
384     convertTangentCurvesToGccEnt(aTgCirc, aTgLine);
385
386     std::shared_ptr<GccAna_Circ2d2TanRad> aCircleBuilder;
387     if (aTgCirc.size() + aTgLine.size() == 2) {
388       switch (aTgLine.size()) {
389       case 0:
390         aCircleBuilder = std::shared_ptr<GccAna_Circ2d2TanRad>(new GccAna_Circ2d2TanRad(
391             *aTgCirc[0], *aTgCirc[1], myRadius, Precision::Confusion()));
392         break;
393       case 1:
394         aCircleBuilder = std::shared_ptr<GccAna_Circ2d2TanRad>(new GccAna_Circ2d2TanRad(
395             *aTgCirc[0], *aTgLine[0], myRadius, Precision::Confusion()));
396         break;
397       case 2:
398         aCircleBuilder = std::shared_ptr<GccAna_Circ2d2TanRad>(new GccAna_Circ2d2TanRad(
399             *aTgLine[0], *aTgLine[1], myRadius, Precision::Confusion()));
400         break;
401       default:
402         break;
403       }
404     }
405
406     return getProperCircle(aCircleBuilder);
407   }
408
409   Circ2dPtr getProperCircle(const std::shared_ptr<GccAna_Circ2d2TanRad>& theBuilder) const
410   {
411     if (!theBuilder)
412       return Circ2dPtr();
413
414     int aNbSol = theBuilder->NbSolutions();
415     if (aNbSol == 0)
416       return Circ2dPtr();
417
418     int anAppropriateSolution = 1;
419     double aMinDist = Precision::Infinite();
420
421     double aParSol, aPonTgCurve;
422     gp_Pnt2d aTgPnt;
423     for (int i = 1; i <= aNbSol && aNbSol > 1; ++i) {
424       bool isApplicable = false;
425       if (myTangentShapes.size() >= 1) {
426         theBuilder->Tangency1(i, aParSol, aPonTgCurve, aTgPnt);
427         isApplicable = isParamInCurve(aPonTgCurve, myTangentShapes[0]);
428       }
429       if (myTangentShapes.size() >= 2 && isApplicable) {
430         theBuilder->Tangency2(i, aParSol, aPonTgCurve, aTgPnt);
431         isApplicable = isParamInCurve(aPonTgCurve, myTangentShapes[1]);
432       }
433
434       if (isApplicable) {
435         double aDist = distanceToClosestPoint(theBuilder->ThisSolution(i));
436         if (aDist < aMinDist) {
437           anAppropriateSolution = i;
438           aMinDist = aDist;
439         }
440       }
441     }
442
443     return Circ2dPtr(new gp_Circ2d(theBuilder->ThisSolution(anAppropriateSolution)));
444   }
445
446
447   void convertTangentCurvesToGccEnt(VectorOfGccCirc& theTangentCircles,
448                                     VectorOfGccLine& theTangentLines)
449   {
450     theTangentCircles.reserve(3);
451     theTangentLines.reserve(3);
452
453     std::vector<CurveAdaptorPtr>::iterator anIt = myTangentShapes.begin();
454     for (; anIt != myTangentShapes.end(); ++anIt) {
455       switch ((*anIt)->GetType()) {
456       case GeomAbs_Line:
457         theTangentLines.push_back(
458             std::shared_ptr<GccEnt_QualifiedLin>(
459             new GccEnt_QualifiedLin((*anIt)->Line(), GccEnt_unqualified))
460         );
461         break;
462       case GeomAbs_Circle:
463         theTangentCircles.push_back(
464             std::shared_ptr<GccEnt_QualifiedCirc>(
465             new GccEnt_QualifiedCirc((*anIt)->Circle(), GccEnt_unqualified))
466         );
467         break;
468       default:
469         break;
470       }
471     }
472   }
473
474
475   static void adjustPeriod(double& theParameter, const CurveAdaptorPtr& theCurve)
476   {
477     if (theCurve->Curve()->IsPeriodic()) {
478       theParameter = ElCLib::InPeriod(theParameter,
479                                       theCurve->FirstParameter(),
480                                       theCurve->FirstParameter() + theCurve->Period());
481     }
482   }
483
484   // boundary parameters of curve are NOT applied
485   static bool isParamInCurve(double& theParameter, const CurveAdaptorPtr& theCurve)
486   {
487     adjustPeriod(theParameter, theCurve);
488     return theParameter > theCurve->FirstParameter() &&
489            theParameter < theCurve->LastParameter();
490   }
491
492   // boundary parameters of curve are applied too
493   static bool isParamOnCurve(double& theParameter, const CurveAdaptorPtr& theCurve)
494   {
495     adjustPeriod(theParameter, theCurve);
496     return theParameter >= theCurve->FirstParameter() &&
497            theParameter <= theCurve->LastParameter();
498   }
499
500 private:
501   Handle(Geom_Plane) myPlane;
502   std::shared_ptr<GeomAPI_Pnt2d> myCenter;
503   std::vector<gp_Pnt2d> myPassingPoints;
504   std::vector<CurveAdaptorPtr> myTangentShapes;
505   CurveAdaptorPtr myTransversalLine;
506   double myRadius;
507   std::shared_ptr<GeomAPI_Pnt2d> myClosestPoint;
508 };
509
510
511
512
513
514 GeomAlgoAPI_Circ2dBuilder::GeomAlgoAPI_Circ2dBuilder(const std::shared_ptr<GeomAPI_Ax3>& thePlane)
515   : myPlane(thePlane),
516     myRadius(0.)
517 {
518 }
519
520 void GeomAlgoAPI_Circ2dBuilder::setRadius(const double theRadius)
521 {
522   myRadius = theRadius;
523 }
524
525 void GeomAlgoAPI_Circ2dBuilder::setCenter(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter)
526 {
527   myCenter = theCenter;
528 }
529
530 void GeomAlgoAPI_Circ2dBuilder::addTangentCurve(const std::shared_ptr<GeomAPI_Shape>& theEdge)
531 {
532   if (theEdge->isEdge())
533     myTangentShapes.push_back(theEdge);
534 }
535
536 void GeomAlgoAPI_Circ2dBuilder::setTransversalLine(const std::shared_ptr<GeomAPI_Shape>& theEdge)
537 {
538   if (theEdge->isEdge())
539     myTransversalLine = theEdge;
540 }
541
542 void GeomAlgoAPI_Circ2dBuilder::addPassingPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
543 {
544   myPassingPoints.push_back(thePoint);
545 }
546
547 void GeomAlgoAPI_Circ2dBuilder::setClosestPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
548 {
549   myClosestPoint = thePoint;
550 }
551
552 std::shared_ptr<GeomAPI_Circ2d> GeomAlgoAPI_Circ2dBuilder::circle(
553     const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
554     const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint,
555     const std::shared_ptr<GeomAPI_Pnt2d>& theThirdPoint)
556 {
557   std::shared_ptr<GeomAPI_Ax3> aPlane(new GeomAPI_Ax3);
558
559   GeomAlgoAPI_Circ2dBuilder aBuilder(aPlane);
560   aBuilder.addPassingPoint(theFirstPoint);
561   aBuilder.addPassingPoint(theSecondPoint);
562   aBuilder.addPassingPoint(theThirdPoint);
563   return aBuilder.circle();
564 }
565
566 std::shared_ptr<GeomAPI_Circ2d> GeomAlgoAPI_Circ2dBuilder::circle()
567 {
568   CircleBuilder aCircleBuilder(myPlane);
569   aCircleBuilder.setCenter(myCenter);
570   aCircleBuilder.setTangentCurves(myTangentShapes);
571   aCircleBuilder.setTransversalLine(myTransversalLine);
572   aCircleBuilder.setPassingPoints(myPassingPoints);
573   aCircleBuilder.setClosestPoint(myClosestPoint);
574   aCircleBuilder.setRadius(myRadius);
575   Circ2dPtr aCirc2d = aCircleBuilder.circle();
576
577   std::shared_ptr<GeomAPI_Circ2d> aCircle;
578   if (aCirc2d) {
579     const gp_Pnt2d& aCenter = aCirc2d->Location();
580     const gp_Dir2d& aXAxis = aCirc2d->Position().XDirection();
581
582     std::shared_ptr<GeomAPI_Pnt2d> aCircleCenter(new GeomAPI_Pnt2d(aCenter.X(), aCenter.Y()));
583     std::shared_ptr<GeomAPI_Dir2d> aCircleDir(new GeomAPI_Dir2d(aXAxis.X(), aXAxis.Y()));
584
585     aCircle = std::shared_ptr<GeomAPI_Circ2d>(
586         new GeomAPI_Circ2d(aCircleCenter, aCircleDir, aCirc2d->Radius()));
587   }
588   return aCircle;
589 }