Salome HOME
Task 2.12. New entities: ellipses and arcs of ellipses (issue #3003)
[modules/shaper.git] / src / GeomAPI / GeomAPI_Ellipse2d.cpp
index 7db3ef8a4461f0329cc9004e8ee002d34331efce..92c16886f728d03d4c047c7c38fd8f8c9ae2817d 100644 (file)
@@ -35,6 +35,8 @@
 #include <GeomLib_Tool.hxx>
 #include <gp_Ax22d.hxx>
 #include <gp_Elips2d.hxx>
+#include <IntAna2d_AnaIntersection.hxx>
+#include <IntAna2d_Conic.hxx>
 #include <Precision.hxx>
 
 #define MY_ELLIPSE implPtr<gp_Elips2d>()
@@ -121,20 +123,42 @@ double GeomAPI_Ellipse2d::majorRadius() const
   return MY_ELLIPSE->MajorRadius();
 }
 
+// theArrangePoint is used to select the nearest solution point if intersection is detected
 template <typename EXTREMAPTR>
-static double extrema(EXTREMAPTR theAlgo,
+static double extrema(IntAna2d_AnaIntersection* theIntersectionAlgo,
+                      EXTREMAPTR theExtremaAlgo,
+                      GeomPnt2dPtr theArrangePoint,
                       GeomPnt2dPtr& thePoint1,
                       GeomPnt2dPtr& thePoint2)
 {
   double aDistance = Precision::Infinite();
-  if (theAlgo->IsDone() && theAlgo->NbExt() > 0) {
-    Extrema_POnCurv2d aP1, aP2;
-    for (int i = 1; i <= theAlgo->NbExt(); ++i)
-      if (theAlgo->SquareDistance(i) < aDistance) {
-        aDistance = Sqrt(theAlgo->SquareDistance(i));
-        theAlgo->Points(i, aP1, aP2);
+  if (theIntersectionAlgo->IsDone() && theIntersectionAlgo->NbPoints() > 0) {
+    gp_Pnt2d anArrangePoint(theArrangePoint->x(), theArrangePoint->y());
+    gp_Pnt2d anInterPnt = theIntersectionAlgo->Point(1).Value();
+    aDistance = anArrangePoint.SquareDistance(anInterPnt);
+    // get solution nearest to theArrangePoint
+    for (int i = 2; i <= theIntersectionAlgo->NbPoints(); ++i) {
+      const IntAna2d_IntPoint& aPnt = theIntersectionAlgo->Point(i);
+      double aSqDist = aPnt.Value().SquareDistance(anArrangePoint);
+      if (aSqDist < aDistance) {
+        aDistance = aSqDist;
+        anInterPnt = aPnt.Value();
       }
+    }
 
+    aDistance = 0.0; // curves are intersected
+    thePoint1 = GeomPnt2dPtr(new GeomAPI_Pnt2d(anInterPnt.X(), anInterPnt.Y()));
+    thePoint2 = GeomPnt2dPtr(new GeomAPI_Pnt2d(anInterPnt.X(), anInterPnt.Y()));
+  }
+  else if (theExtremaAlgo->IsDone() && theExtremaAlgo->NbExt() > 0) {
+    Extrema_POnCurv2d aP1, aP2;
+    for (int i = 1; i <= theExtremaAlgo->NbExt(); ++i) {
+      double aSqDist = theExtremaAlgo->SquareDistance(i);
+      if (aSqDist < aDistance) {
+        aDistance = aSqDist;
+        theExtremaAlgo->Points(i, aP1, aP2);
+      }
+    }
     aDistance = Sqrt(aDistance);
     thePoint1 = GeomPnt2dPtr(new GeomAPI_Pnt2d(aP1.Value().X(), aP1.Value().Y()));
     thePoint2 = GeomPnt2dPtr(new GeomAPI_Pnt2d(aP2.Value().X(), aP2.Value().Y()));
@@ -146,16 +170,20 @@ double GeomAPI_Ellipse2d::distance(const std::shared_ptr<GeomAPI_Lin2d>& theLine
                                    std::shared_ptr<GeomAPI_Pnt2d>& thePointOnMe,
                                    std::shared_ptr<GeomAPI_Pnt2d>& thePointOnLine)
 {
+  IntAna2d_AnaIntersection anInter(theLine->impl<gp_Lin2d>(), IntAna2d_Conic(*MY_ELLIPSE));
   Extrema_ExtElC2d anExtema(theLine->impl<gp_Lin2d>(), *MY_ELLIPSE);
-  return extrema(&anExtema, thePointOnLine, thePointOnMe);
+  return extrema(&anInter, &anExtema, theLine->location(), thePointOnLine, thePointOnMe);
 }
 
 double GeomAPI_Ellipse2d::distance(const std::shared_ptr<GeomAPI_Circ2d>& theCircle,
                                    std::shared_ptr<GeomAPI_Pnt2d>& thePointOnMe,
                                    std::shared_ptr<GeomAPI_Pnt2d>& thePointOnCircle)
 {
+  IntAna2d_AnaIntersection anInter(theCircle->impl<gp_Circ2d>(), IntAna2d_Conic(*MY_ELLIPSE));
   Extrema_ExtElC2d anExtema(theCircle->impl<gp_Circ2d>(), *MY_ELLIPSE);
-  return extrema(&anExtema, thePointOnCircle, thePointOnMe);
+  GeomPnt2dPtr aCircleStart;
+  theCircle->D0(0.0, aCircleStart);
+  return extrema(&anInter, &anExtema, aCircleStart, thePointOnCircle, thePointOnMe);
 }
 
 double GeomAPI_Ellipse2d::distance(const std::shared_ptr<GeomAPI_Ellipse2d>& theEllipse,
@@ -165,9 +193,10 @@ double GeomAPI_Ellipse2d::distance(const std::shared_ptr<GeomAPI_Ellipse2d>& the
   Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(theEllipse->impl<gp_Elips2d>());
   Handle(Geom2d_Ellipse) anEllipse2 = new Geom2d_Ellipse(*MY_ELLIPSE);
 
+  IntAna2d_AnaIntersection anInter(theEllipse->impl<gp_Elips2d>(), IntAna2d_Conic(*MY_ELLIPSE));
   Extrema_ExtCC2d* anExtema =
       new Extrema_ExtCC2d(Geom2dAdaptor_Curve(anEllipse1), Geom2dAdaptor_Curve(anEllipse2));
-  double aDistance = extrema(anExtema, thePointOnEllipse, thePointOnMe);
+  double aDistance = extrema(&anInter, anExtema, theEllipse->firstFocus(), thePointOnEllipse, thePointOnMe);
   delete anExtema;
   return aDistance;
 }