From: abk Date: Thu, 9 Jul 2015 17:40:37 +0000 (+0300) Subject: A functionality to control the conversion deflection was created. X-Git-Tag: BR_quadtree_20150925~2^2~4^2~3 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=2c701f7ccb7e83e06eb3ed6af61739ee46c07392;p=modules%2Fhydro.git A functionality to control the conversion deflection was created. --- diff --git a/src/HYDROData/HYDROData_PolylineOperator.cxx b/src/HYDROData/HYDROData_PolylineOperator.cxx index 4326e525..612d24f9 100644 --- a/src/HYDROData/HYDROData_PolylineOperator.cxx +++ b/src/HYDROData/HYDROData_PolylineOperator.cxx @@ -17,8 +17,11 @@ // #include -#include #include +#include + +#include + #include #include #include @@ -276,3 +279,103 @@ bool HYDROData_PolylineOperator::CreatePolylines( const Handle( HYDROData_Docume } return true; } + +double HYDROData_PolylineOperator::ReduceDeflection( + const double theDeflection, + HYDROData_TopoCurve& theCurve, + int& thePieceCount) +{ + // Construct the approximating B-spline. + std::list aPs; + if (!theCurve.ValuesInKnots(aPs)) + { + return -1; + } + + Handle(TColgp_HArray1OfPnt) aPs2 = new TColgp_HArray1OfPnt(1, aPs.size()); + { + std::list::const_iterator aLastPIt = aPs.end(); + std::list::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 aSqDefls; + double aMaxSqDefl = 0; + std::list& aEdges = theCurve.Edges(); + std::list::const_iterator aLastEIt = aEdges.end(); + { + std::list::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::iterator aEIt = aEdges.begin(); + std::deque::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; +} diff --git a/src/HYDROData/HYDROData_PolylineOperator.h b/src/HYDROData/HYDROData_PolylineOperator.h index ed658ffb..7740bf5e 100644 --- a/src/HYDROData/HYDROData_PolylineOperator.h +++ b/src/HYDROData/HYDROData_PolylineOperator.h @@ -25,6 +25,7 @@ #include class Handle( HYDROData_Document ); +class HYDROData_TopoCurve; class HYDRODATA_EXPORT HYDROData_PolylineOperator { @@ -50,6 +51,18 @@ public: const Handle( HYDROData_PolylineXY )& thePolyline, std::vector& 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, diff --git a/src/HYDROData/HYDROData_TopoCurve.cxx b/src/HYDROData/HYDROData_TopoCurve.cxx index 705b1b2b..9183b355 100644 --- a/src/HYDROData/HYDROData_TopoCurve.cxx +++ b/src/HYDROData/HYDROData_TopoCurve.cxx @@ -808,9 +808,10 @@ bool HYDROData_TopoCurve::Connect( return true; } -bool HYDROData_TopoCurve::BSplinePiecewiseCurve( +int HYDROData_TopoCurve::BSplinePiecewiseCurve( const double theDeflection, HYDROData_TopoCurve& theCurve) const { + int aPieceCount = 0; std::list::const_iterator aLastEIt = myEdges.end(); std::list::const_iterator aEIt = myEdges.begin(); TopoDS_Vertex aEndVertex; @@ -821,7 +822,7 @@ bool HYDROData_TopoCurve::BSplinePiecewiseCurve( ::BSpline(BRepAdaptor_Curve(*aEIt), theDeflection); if (aBSpline.IsNull()) { - return false; + return 0; } if (aEIt->Orientation() == TopAbs_REVERSED) @@ -844,6 +845,7 @@ bool HYDROData_TopoCurve::BSplinePiecewiseCurve( } BRep_Builder().Add(aEdge, aVertex); theCurve.myEdges.push_back(aEdge); + aPieceCount += aBSpline->NbKnots() - 1; aPrevEdge = aEdge; } @@ -854,10 +856,10 @@ bool HYDROData_TopoCurve::BSplinePiecewiseCurve( aCurve.Value(aCurve.LastParameter()), Precision::Confusion()); } BRep_Builder().Add(aPrevEdge, aEndVertex.Oriented(TopAbs_REVERSED)); - return true; + return aPieceCount; } -bool HYDROData_TopoCurve::ValuesInKnots(std::deque& theValues) const +bool HYDROData_TopoCurve::ValuesInKnots(std::list& theValues) const { std::list::const_iterator aLastEIt = myEdges.end(); std::list::const_iterator aEIt = myEdges.begin(); diff --git a/src/HYDROData/HYDROData_TopoCurve.h b/src/HYDROData/HYDROData_TopoCurve.h index abafe899..f7439467 100644 --- a/src/HYDROData/HYDROData_TopoCurve.h +++ b/src/HYDROData/HYDROData_TopoCurve.h @@ -66,6 +66,9 @@ public: //! Returns the curve edges. const std::list& Edges() const {return myEdges;} + //! Returns the curve edges. + std::list& Edges() {return myEdges;} + //! Cuts the curve in the given parameter of the given edge and //! fills the cut part. HYDRODATA_EXPORT void Cut( @@ -156,13 +159,15 @@ public: //! 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& theValues) const; + HYDRODATA_EXPORT bool ValuesInKnots(std::list& theValues) const; private: //! Transfers the edges of the parameter to this curve end. diff --git a/src/HYDROGUI/HYDROGUI_PolylineOp.cxx b/src/HYDROGUI/HYDROGUI_PolylineOp.cxx index 31c3ab2d..486b182e 100755 --- a/src/HYDROGUI/HYDROGUI_PolylineOp.cxx +++ b/src/HYDROGUI/HYDROGUI_PolylineOp.cxx @@ -50,6 +50,7 @@ #include //static int ZValueIncrement = 0; +static const double HYDROGUI_MAXIMAL_DEFLECTION = 1e-2; HYDROGUI_PolylineOp::HYDROGUI_PolylineOp( HYDROGUI_Module* theModule, bool theIsEdit ) : HYDROGUI_Operation( theModule ), @@ -192,10 +193,24 @@ void HYDROGUI_PolylineOp::startOperation() for (int aSI = 0; aSI < aSCount; ++aSI) { HYDROData_TopoCurve aCurve, aCurve2; - std::deque aPs2; + std::list 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; @@ -203,10 +218,11 @@ void HYDROGUI_PolylineOp::startOperation() 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::const_iterator aLastPIt = aPs2.end(); + std::list::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()); }