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