]> SALOME platform Git repositories - modules/hydro.git/commitdiff
Salome HOME
A functionality to control the conversion deflection was created.
authorabk <abk@opencascade.com>
Thu, 9 Jul 2015 17:40:37 +0000 (20:40 +0300)
committerabk <abk@opencascade.com>
Thu, 9 Jul 2015 17:42:40 +0000 (20:42 +0300)
src/HYDROData/HYDROData_PolylineOperator.cxx
src/HYDROData/HYDROData_PolylineOperator.h
src/HYDROData/HYDROData_TopoCurve.cxx
src/HYDROData/HYDROData_TopoCurve.h
src/HYDROGUI/HYDROGUI_PolylineOp.cxx

index 4326e5254186a3d8d7c5a9961dd638e57ede02ee..612d24f985e09c6dc764661df0e5ce9cfe4b2ada 100644 (file)
 //
 
 #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>
@@ -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<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;
+}
index ed658ffbadb1c1c412c183022fec1add7d9b8896..7740bf5ed3977d3a7f13ffa842df76c93a1b73d8 100644 (file)
@@ -25,6 +25,7 @@
 #include <vector>
 
 class Handle( HYDROData_Document );
+class HYDROData_TopoCurve;
 
 class HYDRODATA_EXPORT HYDROData_PolylineOperator
 {
@@ -50,6 +51,18 @@ public:
     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,
index 705b1b2bb521ec68a532fee813c5c2704043a50a..9183b3556aa1361eccec6806b5e1b92d8ecc5b29 100644 (file)
@@ -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<TopoDS_Edge>::const_iterator aLastEIt = myEdges.end();
   std::list<TopoDS_Edge>::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<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();
index abafe899c66d5ae0a2b91a4f5de3d4394d30c5fa..f7439467086a4a39a294bc60e69b75848e28545b 100644 (file)
@@ -66,6 +66,9 @@ public:
   //! 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(
@@ -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<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.
index 31c3ab2de5a44174b2acaaf9b324f5e7840040d4..486b182e5d150c5ddac9831350c8fb08cd2bc4a1 100755 (executable)
@@ -50,6 +50,7 @@
 #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 ), 
@@ -192,10 +193,24 @@ void HYDROGUI_PolylineOp::startOperation()
       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;
@@ -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<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());
         }