Salome HOME
Extract ShapeHierarchy as a separate object
[modules/shaper.git] / src / GeomAPI / GeomAPI_BSpline2d.cpp
index de07f9299e1437c93baffa05d0c254cf61268d5b..f702a278a0bf1248ceebfb56ddba1ab74a31e312 100644 (file)
 #include <GeomAPI_XY.h>
 
 #include <Geom2d_BSplineCurve.hxx>
+#include <Geom2dAPI_ProjectPointOnCurve.hxx>
+#include <GeomLib_Tool.hxx>
+#include <Precision.hxx>
 
 #define MY_BSPLINE (*(implPtr<Handle_Geom2d_BSplineCurve>()))
 
 
+static Handle_Geom2d_BSplineCurve* newBSpline2d(
+  const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
+  const std::list<double>& theWeights,
+  const int theDegree,
+  const bool thePeriodic);
+
+
 static Handle_Geom2d_BSplineCurve* newBSpline2d(
     const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
     const std::list<double>& theWeights,
@@ -34,19 +44,26 @@ static Handle_Geom2d_BSplineCurve* newBSpline2d(
     const int theDegree,
     const bool thePeriodic)
 {
+  if (theKnots.empty() || theMults.empty())
+    return newBSpline2d(thePoles, theWeights, theDegree, thePeriodic);
+
+  int anAuxPole = 0;
+  if (thePeriodic && thePoles.front()->distance(thePoles.back()) < Precision::Confusion())
+    anAuxPole = -1;
+
   // collect arrays of poles, weights, knots and multiplicities
-  TColgp_Array1OfPnt2d aPoles(1, (int)thePoles.size());
-  TColStd_Array1OfReal aWeights(1, (int)theWeights.size());
+  TColgp_Array1OfPnt2d aPoles(1, (int)thePoles.size() + anAuxPole);
+  TColStd_Array1OfReal aWeights(1, (int)theWeights.size() + anAuxPole);
   TColStd_Array1OfReal aKnots(1, (int)theKnots.size());
   TColStd_Array1OfInteger aMults(1, (int)theMults.size());
 
   int anIndex = 1;
   for (std::list<GeomPnt2dPtr>::const_iterator aPIt = thePoles.begin();
-       aPIt != thePoles.end(); ++aPIt, ++anIndex)
+       aPIt != thePoles.end() && anIndex <= aPoles.Upper(); ++aPIt, ++anIndex)
     aPoles.SetValue(anIndex, gp_Pnt2d((*aPIt)->x(), (*aPIt)->y()));
   anIndex = 1;
   for (std::list<double>::const_iterator aWIt = theWeights.begin();
-       aWIt != theWeights.end(); ++aWIt, ++anIndex)
+       aWIt != theWeights.end() && anIndex <= aWeights.Upper(); ++aWIt, ++anIndex)
     aWeights.SetValue(anIndex, *aWIt);
   anIndex = 1;
   for (std::list<double>::const_iterator aKIt = theKnots.begin();
@@ -62,13 +79,25 @@ static Handle_Geom2d_BSplineCurve* newBSpline2d(
   return new Handle_Geom2d_BSplineCurve(aCurve);
 }
 
-static Handle_Geom2d_BSplineCurve* newBSpline2d(
+Handle_Geom2d_BSplineCurve* newBSpline2d(
     const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
     const std::list<double>& theWeights,
     const int theDegree,
     const bool thePeriodic)
 {
+  std::list<std::shared_ptr<GeomAPI_Pnt2d> > aPoles = thePoles;
+  std::list<double> aWeights = theWeights;
+  int aMult = theDegree + 1;
   int aNbKnots = (int)thePoles.size() - theDegree + 1;
+  if (thePeriodic) {
+    if (aPoles.front()->distance(aPoles.back()) < Precision::Confusion()) {
+      aPoles.pop_back();
+      aWeights.pop_back();
+    }
+    aMult = 1;
+    aNbKnots = (int)aPoles.size() + 1;
+  }
+
   if (aNbKnots < 2)
     return new Handle_Geom2d_BSplineCurve();
 
@@ -82,10 +111,10 @@ static Handle_Geom2d_BSplineCurve* newBSpline2d(
   aKnots.push_back(aEndParam);
 
   std::list<int> aMults(aNbKnots - 2, 1);
-  aMults.push_front(theDegree + 1);
-  aMults.push_back(theDegree + 1);
+  aMults.push_front(aMult);
+  aMults.push_back(aMult);
 
-  return newBSpline2d(thePoles, theWeights, aKnots, aMults, theDegree, thePeriodic);
+  return newBSpline2d(aPoles, aWeights, aKnots, aMults, theDegree, thePeriodic);
 }
 
 static Handle_Geom2d_BSplineCurve* newBSpline2d(
@@ -146,6 +175,14 @@ std::list<int> GeomAPI_BSpline2d::mults() const
   return std::list<int>(aBSplMults.begin(), aBSplMults.end());
 }
 
+const bool GeomAPI_BSpline2d::parameter(const std::shared_ptr<GeomAPI_Pnt2d> thePoint,
+                                        const double theTolerance,
+                                        double& theParameter) const
+{
+  return GeomLib_Tool::Parameter(MY_BSPLINE, thePoint->impl<gp_Pnt2d>(),
+                                 theTolerance, theParameter) == Standard_True;
+}
+
 void GeomAPI_BSpline2d::D0(const double theU, std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
 {
   gp_Pnt2d aPnt;