+
+double HYDROData_PolylineOperator::ReduceDeflection(
+ const double theDeflection,
+ HYDROData_TopoCurve& theCurve,
+ int& thePieceCount)
+{
+ // Construct the approximating B-spline.
+ std::list<gp_XYZ> aPs;
+ if (!theCurve.ValuesInKnots(aPs))
+ {
+ return -1;
+ }
+
+ Handle(TColgp_HArray1OfPnt) aPs2 = new TColgp_HArray1OfPnt(1, aPs.size());
+ {
+ std::list<gp_XYZ>::const_iterator aLastPIt = aPs.end();
+ std::list<gp_XYZ>::const_iterator aPIt = aPs.begin();
+ for (int aPN = 1; aPIt != aLastPIt; ++aPN, ++aPIt)
+ {
+ aPs2->SetValue(aPN, *aPIt);
+ }
+ }
+ Handle(Geom_BSplineCurve) aBSpline2;
+ const bool isClosed = theCurve.IsClosed();
+ if (!CurveCreator_Utils::constructBSpline(aPs2, isClosed, aBSpline2))
+ {
+ return -1;
+ }
+
+ // Calculate the piece deflections.
+ std::deque<double> aSqDefls;
+ double aMaxSqDefl = 0;
+ std::list<TopoDS_Edge>& aEdges = theCurve.Edges();
+ std::list<TopoDS_Edge>::const_iterator aLastEIt = aEdges.end();
+ {
+ std::list<TopoDS_Edge>::const_iterator aEIt = aEdges.begin();
+ for (int aPrevKCount = 0; aEIt != aLastEIt; ++aEIt)
+ {
+ TopLoc_Location aLoc;
+ double aParams[2];
+ Handle(Geom_BSplineCurve) aBSpline = Handle(Geom_BSplineCurve)::DownCast(
+ BRep_Tool::Curve(*aEIt, aLoc, aParams[0], aParams[1]));
+ const int aKCount = aBSpline->NbKnots();
+ for (int aKN = 1; aKN < aKCount; ++aKN)
+ {
+ const double aParam =
+ (aBSpline->Knot(aKN) + aBSpline->Knot(aKN + 1)) * 0.5;
+ const double aParam2 = (aBSpline2->Knot(aPrevKCount + aKN) +
+ aBSpline2->Knot(aPrevKCount + aKN + 1)) * 0.5;
+ const double aSqDefl = Abs(aBSpline->Value(aParam).
+ SquareDistance(aBSpline2->Value(aParam2)));
+ aSqDefls.push_back(aSqDefl);
+ if (aMaxSqDefl < aSqDefl)
+ {
+ aMaxSqDefl = aSqDefl;
+ }
+ }
+ aPrevKCount += aKCount - 1;
+ }
+ }
+
+ // Check whether the reducing is necessary.
+ const double aMaxDefl = Sqrt(aMaxSqDefl);
+ if (aMaxDefl <= theDeflection)
+ {
+ return aMaxDefl;
+ }
+
+ // Reduce the deflections.
+ const double aThresSqDefl =
+ Max(aMaxSqDefl * 0.25, theDeflection * theDeflection);
+ std::list<TopoDS_Edge>::iterator aEIt = aEdges.begin();
+ std::deque<double>::const_iterator aSqDIt = aSqDefls.begin();
+ thePieceCount = 0;
+ for (; aEIt != aLastEIt; ++aEIt)
+ {
+ TopLoc_Location aLoc;
+ double aParams[2];
+ Handle(Geom_BSplineCurve) aBSpline = Handle(Geom_BSplineCurve)::DownCast(
+ BRep_Tool::Curve(*aEIt, aLoc, aParams[0], aParams[1]));
+ Handle(Geom_BSplineCurve) aBSpline2 =
+ Handle(Geom_BSplineCurve)::DownCast(aBSpline->Copy());
+ const int aKCount = aBSpline->NbKnots();
+ for (int aKN = 1; aKN < aKCount; ++aSqDIt, ++aKN)
+ {
+ if (*aSqDIt > aThresSqDefl)
+ {
+ aBSpline2->InsertKnot(
+ (aBSpline->Knot(aKN) + aBSpline->Knot(aKN + 1)) * 0.5);
+ }
+ }
+ TopoDS_Edge aEdge;
+ BRep_Builder().MakeEdge(aEdge, aBSpline2, Precision::Confusion());
+ BRep_Builder().Add(aEdge, TopExp::FirstVertex(*aEIt));
+ BRep_Builder().Add(aEdge, TopExp::LastVertex(*aEIt));
+ thePieceCount += aBSpline2->NbKnots() - 1;
+ *aEIt = aEdge;
+ }
+ return aMaxDefl;
+}