//
#include <HYDROData_PolylineOperator.h>
-#include <HYDROData_TopoCurve.h>
#include <HYDROData_Document.h>
+#include <HYDROData_TopoCurve.h>
+
+#include <CurveCreator_Utils.hxx>
+
#include <BRepAdaptor_Curve.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
}
return true;
}
+
+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;
+}
#include <vector>
class Handle( HYDROData_Document );
+class HYDROData_TopoCurve;
class HYDRODATA_EXPORT HYDROData_PolylineOperator
{
const Handle( HYDROData_PolylineXY )& thePolyline,
std::vector<TopoDS_Wire>& theWires);
+ //! The method is intended to approximate the B-spline edge curve
+ //! by a 'Hydro' spline section.
+ //! Inserts the knot in the middle of each such B-spline piece that
+ //! the middle deflection is more than the required deflection and
+ //! more than the half of the maximal middle deflection.
+ //! Returns the initial maximal middle deflection.
+ //! Returns a negative value in the case of any erorr.
+ static double ReduceDeflection(
+ const double theDeflection,
+ HYDROData_TopoCurve& theCurve,
+ int& thePieceCount);
+
protected:
bool split( const Handle( HYDROData_Document )& theDoc,
const Handle( HYDROData_PolylineXY )& thePolyline,
return true;
}
-bool HYDROData_TopoCurve::BSplinePiecewiseCurve(
+int HYDROData_TopoCurve::BSplinePiecewiseCurve(
const double theDeflection, HYDROData_TopoCurve& theCurve) const
{
+ int aPieceCount = 0;
std::list<TopoDS_Edge>::const_iterator aLastEIt = myEdges.end();
std::list<TopoDS_Edge>::const_iterator aEIt = myEdges.begin();
TopoDS_Vertex aEndVertex;
::BSpline(BRepAdaptor_Curve(*aEIt), theDeflection);
if (aBSpline.IsNull())
{
- return false;
+ return 0;
}
if (aEIt->Orientation() == TopAbs_REVERSED)
}
BRep_Builder().Add(aEdge, aVertex);
theCurve.myEdges.push_back(aEdge);
+ aPieceCount += aBSpline->NbKnots() - 1;
aPrevEdge = aEdge;
}
aCurve.Value(aCurve.LastParameter()), Precision::Confusion());
}
BRep_Builder().Add(aPrevEdge, aEndVertex.Oriented(TopAbs_REVERSED));
- return true;
+ return aPieceCount;
}
-bool HYDROData_TopoCurve::ValuesInKnots(std::deque<gp_XYZ>& theValues) const
+bool HYDROData_TopoCurve::ValuesInKnots(std::list<gp_XYZ>& theValues) const
{
std::list<TopoDS_Edge>::const_iterator aLastEIt = myEdges.end();
std::list<TopoDS_Edge>::const_iterator aEIt = myEdges.begin();
//! Returns the curve edges.
const std::list<TopoDS_Edge>& Edges() const {return myEdges;}
+ //! Returns the curve edges.
+ std::list<TopoDS_Edge>& Edges() {return myEdges;}
+
//! Cuts the curve in the given parameter of the given edge and
//! fills the cut part.
HYDRODATA_EXPORT void Cut(
//! Creates a B-spline piecewise curve corresponding to the curve
//! and using the deflection.
- HYDRODATA_EXPORT bool BSplinePiecewiseCurve(
+ //! Returns the piece count.
+ //! Returns 0 in the case of any error.
+ HYDRODATA_EXPORT int BSplinePiecewiseCurve(
const double theDeflection, HYDROData_TopoCurve& theCurve) const;
//! Calculates the values of the curve in its knots.
//! Returns 'false' if a curve edge has a nonidentity location or a nonforward
//! orientation or has no a B-spline representation.
- HYDRODATA_EXPORT bool ValuesInKnots(std::deque<gp_XYZ>& theValues) const;
+ HYDRODATA_EXPORT bool ValuesInKnots(std::list<gp_XYZ>& theValues) const;
private:
//! Transfers the edges of the parameter to this curve end.
#include <TopoDS_Wire.hxx>
//static int ZValueIncrement = 0;
+static const double HYDROGUI_MAXIMAL_DEFLECTION = 1e-2;
HYDROGUI_PolylineOp::HYDROGUI_PolylineOp( HYDROGUI_Module* theModule, bool theIsEdit )
: HYDROGUI_Operation( theModule ),
for (int aSI = 0; aSI < aSCount; ++aSI)
{
HYDROData_TopoCurve aCurve, aCurve2;
- std::deque<gp_XYZ> aPs2;
+ std::list<gp_XYZ> aPs2;
+ int aMaxPieceCount;
if (!aCurve.Initialize(aWires[aSI]) ||
- !aCurve.BSplinePiecewiseCurve(Precision::Confusion(), aCurve2) ||
- !aCurve2.ValuesInKnots(aPs2))
+ (aMaxPieceCount = aCurve.BSplinePiecewiseCurve(
+ HYDROGUI_MAXIMAL_DEFLECTION * 0.1, aCurve2)) == 0)
+ {
+ isError = true;
+ break;
+ }
+
+ double aDefl;
+ aMaxPieceCount *= 100;
+ int aPieceCount = 0;
+ while (aPieceCount < aMaxPieceCount &&
+ (aDefl = HYDROData_PolylineOperator::ReduceDeflection(
+ HYDROGUI_MAXIMAL_DEFLECTION, aCurve2, aPieceCount)) >
+ HYDROGUI_MAXIMAL_DEFLECTION);
+ if (aDefl < 0 || !aCurve2.ValuesInKnots(aPs2))
{
isError = true;
break;
aPs.push_back(CurveCreator::Coordinates());
CurveCreator::Coordinates& aPs3 = aPs.back();
- const Standard_Integer aPCount = aPs2.size();
- for (Standard_Integer aPI = 0; aPI < aPCount; ++aPI)
+ std::list<gp_XYZ>::const_iterator aLastPIt = aPs2.end();
+ std::list<gp_XYZ>::const_iterator aPIt = aPs2.begin();
+ for (; aPIt != aLastPIt; ++aPIt)
{
- const gp_XYZ aP = aPs2[aPI];
+ const gp_XYZ aP = *aPIt;
aPs3.push_back(aP.X());
aPs3.push_back(aP.Y());
}