1 // Copyright (C) 2019-2020 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include <PlaneGCSSolver_GeoExtensions.h>
21 #include <PlaneGCSSolver_Tools.h>
23 #include <GeomAPI_BSpline2d.h>
24 #include <GeomAPI_Pnt2d.h>
25 #include <GeomAPI_XY.h>
32 DeriVector2 BSplineImpl::Value(double u, double du, double* derivparam)
37 std::shared_ptr<GeomAPI_Pnt2d> aValue;
38 std::shared_ptr<GeomAPI_XY> aDeriv;
39 myCurve->D1(u, aValue, aDeriv);
41 return DeriVector2(aValue->x(), aValue->y(), aDeriv->x() * du, aDeriv->y() * du);
44 DeriVector2 BSplineImpl::CalculateNormal(Point &p, double* derivparam)
50 if (!myCurve->parameter(GeomPnt2dPtr(new GeomAPI_Pnt2d(*p.x, *p.y)), 1e100, u)) {
51 // Sometimes OCCT's Extrema algorithm cannot find the parameter on B-spline curve
52 // (usually, if the point is near the curve extremity).
53 // Workaround: compute distance to each boundary point
54 double aDistPS = PlaneGCSSolver_Tools::distance(p, poles.front());
55 double aDistPE = PlaneGCSSolver_Tools::distance(p, poles.back());
56 static const double THE_TOLERANCE = 1.e-6;
57 if (aDistPS < aDistPE && aDistPS < THE_TOLERANCE)
59 else if (aDistPE < aDistPS && aDistPE < THE_TOLERANCE)
65 std::shared_ptr<GeomAPI_Pnt2d> aValue;
66 std::shared_ptr<GeomAPI_XY> aDeriv;
67 myCurve->D1(u, aValue, aDeriv);
69 DeriVector2 norm(aDeriv->x(), aDeriv->y(), 0.0, 0.0);
70 return norm.rotate90ccw();
73 BSplineImpl* BSplineImpl::Copy()
75 return new BSplineImpl(*this);
79 bool BSplineImpl::isCacheValid() const
81 // curve has to be initialized
82 bool isValid = myCurve.get() && !myCurve->isNull();
84 static const double THE_TOLERANCE = 1.e-7;
86 isValid = isValid && poles.size() == myCachedPoles.size();
87 std::list<GeomPnt2dPtr>::const_iterator aCachePIt = myCachedPoles.begin();
88 GCS::VEC_P::const_iterator aPolesIt = poles.begin();
89 for (; isValid && aPolesIt != poles.end(); ++aPolesIt, ++aCachePIt) {
90 isValid = isValid && fabs((*aCachePIt)->x() - *aPolesIt->x) < THE_TOLERANCE
91 && fabs((*aCachePIt)->y() - *aPolesIt->y) < THE_TOLERANCE;
95 isValid = isValid && weights.size() == myCachedWeights.size();
96 std::list<double>::const_iterator aCacheWIt = myCachedWeights.begin();
97 GCS::VEC_pD::const_iterator aWeightsIt = weights.begin();
98 for (; isValid && aWeightsIt != weights.end(); ++aWeightsIt, ++aCacheWIt)
99 isValid = isValid && fabs(*aCacheWIt - **aWeightsIt) < THE_TOLERANCE;
104 void BSplineImpl::rebuildCache()
106 myCachedPoles.clear();
107 myCachedWeights.clear();
108 myCachedKnots.clear();
109 myCachedMultiplicities.clear();
111 for (GCS::VEC_P::iterator anIt = poles.begin(); anIt != poles.end(); ++anIt)
112 myCachedPoles.push_back(GeomPnt2dPtr(new GeomAPI_Pnt2d(*anIt->x, *anIt->y)));
113 for (GCS::VEC_pD::iterator anIt = weights.begin(); anIt != weights.end(); ++anIt)
114 myCachedWeights.push_back(**anIt);
115 for (GCS::VEC_pD::iterator anIt = knots.begin(); anIt != knots.end(); ++anIt)
116 myCachedKnots.push_back(**anIt);
117 myCachedMultiplicities.assign(mult.begin(), mult.end());
119 myCurve.reset(new GeomAPI_BSpline2d(degree, myCachedPoles, myCachedWeights,
120 myCachedKnots, myCachedMultiplicities, periodic));