]> SALOME platform Git repositories - modules/hydro.git/commitdiff
Salome HOME
Algorithms to convert 'TopoDS_Wire' object to a wire composed of B-spline edges were...
authorabk <abk@opencascade.com>
Tue, 7 Jul 2015 12:17:54 +0000 (15:17 +0300)
committerabk <abk@opencascade.com>
Thu, 9 Jul 2015 12:06:03 +0000 (15:06 +0300)
An automatic conversion of each complex polyline to polyline composed of spline section was created based on these algorithms.
The deflection of the conversion is uncontrolled now.
The data structures and the algorithms to work with the topological curves were formed as class 'HYDROData_TopoCurve'.

src/HYDROData/CMakeLists.txt
src/HYDROData/HYDROData_PolylineOperator.cxx
src/HYDROData/HYDROData_PolylineOperator.h
src/HYDROData/HYDROData_TopoCurve.cxx [new file with mode: 0644]
src/HYDROData/HYDROData_TopoCurve.h [new file with mode: 0644]
src/HYDROGUI/HYDROGUI_PolylineOp.cxx

index dfa8bf1b60f328b2e636f145988c43f20780aa0c..fd9899d428291a90221b1dbe83b150ef2d6c409a 100644 (file)
@@ -43,8 +43,9 @@ set(PROJECT_HEADERS
     HYDROData_Stream.h
     HYDROData_StreamAltitude.h
     HYDROData_StricklerTable.h
-       HYDROData_LandCover.h
+    HYDROData_LandCover.h
     HYDROData_Tool.h
+    HYDROData_TopoCurve.h
     HYDROData_Transform.h
     HYDROData_VisualState.h
     HYDROData_Warning.h
@@ -99,8 +100,9 @@ set(PROJECT_SOURCES
     HYDROData_Stream.cxx
     HYDROData_StreamAltitude.cxx
     HYDROData_StricklerTable.cxx
-       HYDROData_LandCover.cxx
+    HYDROData_LandCover.cxx
     HYDROData_Tool.cxx
+    HYDROData_TopoCurve.cxx
     HYDROData_Transform.cxx
     HYDROData_VisualState.cxx
     HYDROData_Zone.cxx
index ac75dcd8dc2f9e0a453219a1d0937777355f9b6e..4326e5254186a3d8d7c5a9961dd638e57ede02ee 100644 (file)
@@ -17,6 +17,7 @@
 //
 
 #include <HYDROData_PolylineOperator.h>
+#include <HYDROData_TopoCurve.h>
 #include <HYDROData_Document.h>
 #include <BRepAdaptor_Curve.hxx>
 #include <BRep_Builder.hxx>
@@ -55,683 +56,6 @@ template<class T> void append( std::vector<T>& theList, const std::vector<T>& th
     theList[i] = theList2[j];
 }
 
-static TopoDS_Edge ReplaceVertex(
-  const TopoDS_Edge& theEdge, Standard_Integer theVertexIndex)
-{
-  TopoDS_Vertex aVertices[] =
-    {TopExp::FirstVertex(theEdge), TopExp::LastVertex(theEdge)};
-  const TopAbs_Orientation aOrient = theEdge.Orientation();
-  if (aOrient == TopAbs_REVERSED)
-  {
-    theVertexIndex ^= 1;
-  }
-  aVertices[theVertexIndex].EmptyCopy();
-  aVertices[0].Orientation(TopAbs_FORWARD);
-  aVertices[1].Orientation(TopAbs_REVERSED);
-  TopoDS_Edge aFE = TopoDS::Edge(theEdge.Oriented(TopAbs_FORWARD));
-  TopoDS_Edge aNewEdge =
-    ShapeBuild_Edge().CopyReplaceVertices(aFE, aVertices[0], aVertices[1]);
-  return TopoDS::Edge(aNewEdge.Oriented(aOrient));
-}
-
-template<typename TCurveType>
-static Standard_Boolean WireToCurve(
-  const TopoDS_Wire& theWire,
-  TCurveType& theCurve,
-  Standard_Boolean& theIsClosed)
-{
-  TopTools_IndexedDataMapOfShapeListOfShape aVertexToEdges;
-  TopExp::MapShapesAndAncestors(theWire,
-    TopAbs_VERTEX, TopAbs_EDGE, aVertexToEdges);
-  const Standard_Integer aVCount = aVertexToEdges.Extent();
-  if (aVCount == 0)
-  {
-    return Standard_False;
-  }
-
-  {
-    Standard_Integer aEndCount = 0;
-    for (Standard_Integer aVN = 1; aVN <= aVCount; ++aVN)
-    {
-      const Standard_Integer aEdgeCount =
-        aVertexToEdges.FindFromIndex(aVN).Extent();
-      if (aEdgeCount == 1)
-      {
-        ++aEndCount;
-      }
-      if (aEdgeCount > 2)
-      {
-        return Standard_False;
-      }
-    }
-    theIsClosed = (aEndCount == 0);
-    if (!theIsClosed && aEndCount != 2)
-    {
-      return Standard_False;
-    }
-  }
-
-  Standard_Integer aVN = 1;
-  if (!theIsClosed)
-  {
-    while (aVN <= aVCount &&
-      aVertexToEdges.FindFromIndex(aVN).Extent() == 2)
-    {
-      ++aVN;
-    }
-  }
-
-  TopTools_ListOfShape* aEdges = &aVertexToEdges.ChangeFromIndex(aVN);
-  while (!aEdges->IsEmpty())
-  {
-    const TopoDS_Edge aEdge = TopoDS::Edge(aEdges->First());
-    aEdges->RemoveFirst();
-    theCurve.Append(aEdge);
-    Standard_Integer aVN2 =
-      aVertexToEdges.FindIndex(TopExp::FirstVertex(aEdge));
-    if (aVN2 == aVN)
-    {
-      aVN2 = aVertexToEdges.FindIndex(TopExp::LastVertex(aEdge));
-    }
-    aVN = aVN2;
-
-    aEdges = &aVertexToEdges.ChangeFromIndex(aVN2);
-    if (aEdges->First().IsEqual(aEdge))
-    {
-      aEdges->RemoveFirst();
-    }
-    else
-    {
-      const TopoDS_Edge aEdge = TopoDS::Edge(aEdges->First());
-      aEdges->Clear();
-      aEdges->Append(aEdge);
-    }
-  }
-  return (!theIsClosed && theCurve.Size() == aVCount - 1) ||
-    (theIsClosed && theCurve.Size() == aVCount);
-}
-
-template<typename TCurveType>
-static void CurveToWire(const TCurveType& theCurve, TopoDS_Wire& theWire)
-{
-  BRep_Builder aBulder;
-  aBulder.MakeWire(theWire);
-  for (TCurveType::Iterator aEIt(theCurve); aEIt.More(); aEIt.Next())
-  {
-    aBulder.Add(theWire, aEIt.Value());
-  }
-}
-
-static void CurveToWire(
-  const NCollection_Vector<TopoDS_Edge>& theEdges1,
-  const NCollection_Vector<TopoDS_Edge>& theEdges2,
-  TopoDS_Wire& theWire)
-{
-  BRep_Builder aBulder;
-  aBulder.MakeWire(theWire);
-  const NCollection_Vector<TopoDS_Edge>* aEdges[] = {&theEdges1, &theEdges2};
-  for (Standard_Integer aEI = 0; aEI < 2; ++aEI)
-  {
-    NCollection_Vector<TopoDS_Edge>::Iterator aEIt(*aEdges[aEI]);
-    for (; aEIt.More(); aEIt.Next())
-    {
-      aBulder.Add(theWire, aEIt.Value());
-    }
-  }
-}
-
-static Standard_Real ProjectPointToCurve(
-  const gp_Pnt& thePoint,
-  const Adaptor3d_Curve& theCurve,
-  Standard_Real& theParameter)
-{
-  Extrema_ExtPC aAlgo(thePoint, theCurve);
-  Standard_Integer aMinEN = -2;
-  Standard_Real aMinSqDist = DBL_MAX;
-  if (aAlgo.IsDone())
-  {
-    const Standard_Integer aECount = aAlgo.NbExt();
-    for (Standard_Integer aEN = 1; aEN <= aECount; ++aEN)
-    {
-      const gp_Pnt& aP = aAlgo.Point(aEN).Value();
-      const Standard_Real aSqDist = thePoint.SquareDistance(aP);
-      if (aMinSqDist > aSqDist)
-      {
-        aMinSqDist = aSqDist;
-        aMinEN = aEN;
-      }
-    }
-  }
-
-  const Standard_Real aParams[] =
-    {theCurve.FirstParameter(), theCurve.LastParameter()};
-  const gp_Pnt aEnds[] =
-    {theCurve.Value(aParams[0]), theCurve.Value(aParams[1])};
-  const Standard_Real aSqDists[] =
-    {thePoint.SquareDistance(aEnds[0]), thePoint.SquareDistance(aEnds[1])};
-  for (Standard_Integer aEI = 0; aEI < 2; ++aEI)
-  {
-    if (aMinSqDist > aSqDists[aEI])
-    {
-      aMinSqDist = aSqDists[aEI];
-      aMinEN = -aEI;
-    }
-  }
-
-  if (aMinEN <= 0)
-  {
-    theParameter = aParams[-aMinEN];
-    return aMinSqDist;
-  }
-
-  const Extrema_POnCurv& aPOnC = aAlgo.Point(aMinEN);
-  const gp_Pnt& aPoint = aPOnC.Value();
-  theParameter = aPOnC.Parameter();
-  for (Standard_Integer aEI = 0; aEI < 2; ++aEI)
-  {
-    if (Abs(theParameter - aParams[aEI]) < Precision::PConfusion() ||
-      aPoint.SquareDistance(aEnds[aEI]) < Precision::SquareConfusion())
-    {
-      theParameter = aParams[aEI];
-    }
-  }
-  return aMinSqDist;
-}
-
-static Standard_Real ProjectPointToEdge(
-  const gp_Pnt& thePoint,
-  const TopoDS_Edge& theEdge,
-  Standard_Real& theParameter)
-{
-  return ProjectPointToCurve(thePoint, BRepAdaptor_Curve(theEdge), theParameter);
-}
-
-static void SplitCurveByPoint(
-  const NCollection_Vector<TopoDS_Edge>& theEdges,
-  const Standard_Integer theEdgeIndex,
-  const Standard_Real theParameter,
-  NCollection_Vector<TopoDS_Edge>& theEdges1,
-  NCollection_Vector<TopoDS_Edge>& theEdges2)
-{
-  for (Standard_Integer aEI = 0; aEI < theEdgeIndex; ++aEI)
-  {
-    theEdges1.Append(theEdges(aEI));
-  }
-
-  const TopoDS_Edge& aEdge = theEdges(theEdgeIndex);
-  BRepAdaptor_Curve aCurve(aEdge);
-  Standard_Integer aParamI = -1;
-  const Standard_Real aEdgeEndParams[] =
-    {aCurve.FirstParameter(), aCurve.LastParameter()};
-  if (Abs(theParameter - aEdgeEndParams[0]) < Precision::PConfusion())
-  {
-    aParamI = 0;
-  }
-  else if (Abs(theParameter - aEdgeEndParams[1]) < Precision::PConfusion())
-  {
-    aParamI = 1;
-  }
-
-  const TopAbs_Orientation aOrient = aEdge.Orientation();
-  if (aOrient == TopAbs_REVERSED)
-  {
-    aParamI ^= 1;
-  }
-
-  NCollection_Vector<TopoDS_Edge>* aEdges = &theEdges2;
-  const Standard_Integer aECount = theEdges.Size();
-  if (aParamI == 0)
-  {
-    aEdges = (theEdgeIndex == 0) ? &theEdges1 : &theEdges2;
-    aEdges->Append(ReplaceVertex(aEdge, 0));
-  }
-  else if (aParamI == 1)
-  {
-    theEdges1.Append(ReplaceVertex(aEdge, 1));
-  }
-  else
-  {
-    TopoDS_Edge aFE = TopoDS::Edge(aEdge.Oriented(TopAbs_FORWARD));
-    ShapeAnalysis_TransferParametersProj aSATPP(aFE, TopoDS_Face());
-    aSATPP.SetMaxTolerance(Precision::Confusion());
-    TopoDS_Vertex aSplitV1, aSplitV2;
-    BRep_Builder().MakeVertex(
-      aSplitV1, aCurve.Value(theParameter), Precision::Confusion());
-    BRep_Builder().MakeVertex(
-      aSplitV2, aCurve.Value(theParameter), Precision::Confusion());
-    TopoDS_Edge aEParts[] = {
-      ShapeBuild_Edge().CopyReplaceVertices(aFE, TopoDS_Vertex(),
-        TopoDS::Vertex(aSplitV1.Oriented(TopAbs_REVERSED))),
-      ShapeBuild_Edge().CopyReplaceVertices(aFE, aSplitV2, TopoDS_Vertex())};
-    ShapeBuild_Edge().CopyPCurves(aEParts[0], aFE);
-    ShapeBuild_Edge().CopyPCurves(aEParts[1], aFE);
-    BRep_Builder().SameRange(aEParts[0], Standard_False);
-    BRep_Builder().SameRange(aEParts[1], Standard_False);
-    BRep_Builder().SameParameter(aEParts[0], Standard_False);
-    BRep_Builder().SameParameter(aEParts[1], Standard_False);
-    aSATPP.TransferRange(aEParts[0],
-      aEdgeEndParams[0], theParameter, Standard_False);
-    aSATPP.TransferRange(aEParts[1],
-      theParameter, aEdgeEndParams[1], Standard_False);
-    aEParts[0].Orientation(aOrient);
-    aEParts[1].Orientation(aOrient);
-
-    const Standard_Integer aFirstPI = (aOrient != TopAbs_REVERSED) ? 0 : 1;
-    theEdges1.Append(aEParts[aFirstPI]);
-    theEdges2.Append(aEParts[1 - aFirstPI]);
-  }
-  for (Standard_Integer aEI = theEdgeIndex + 1; aEI < aECount; ++aEI)
-  {
-    aEdges->Append(theEdges(aEI));
-  }
-}
-
-static void SplitCurveByPoints(
-  const NCollection_Vector<TopoDS_Edge>& theCurve,
-  const NCollection_Vector<NCollection_Sequence<Standard_Real> >& theParameters,
-  NCollection_Vector<NCollection_Vector<TopoDS_Edge> >& theSplittedCurves)
-{
-  NCollection_Vector<TopoDS_Edge> aCurves[3];
-  aCurves[0] = theCurve;
-  Standard_Integer aCI = 0, aEI = 0;
-  NCollection_Vector<TopoDS_Edge>::Iterator aEIt(theCurve);
-  for (NCollection_Vector<NCollection_Sequence<Standard_Real> >::Iterator
-    aPLIt(theParameters); aPLIt.More(); ++aEI, aEIt.Next(), aPLIt.Next())
-  {
-    const Standard_Boolean isForward =
-      (aEIt.Value().Orientation() != TopAbs_REVERSED);
-    for (NCollection_Sequence<Standard_Real>::Iterator
-      aPIt(aPLIt.Value(), isForward); aPIt.More(); aPIt.Next())
-    {
-      const Standard_Integer aCI1 = (aCI + 1) % 3, aCI2 = (aCI + 2) % 3;
-      SplitCurveByPoint(aCurves[aCI], aEI,
-        aPIt.Value(), aCurves[aCI1], aCurves[aCI2]);
-      if (!aCurves[aCI2].IsEmpty())
-      {
-        theSplittedCurves.Append(aCurves[aCI1]);
-        aCurves[aCI].Clear();
-        aCI = aCI2;
-        aEI = 0;
-      }
-      aCurves[aCI1].Clear();
-    }
-  }
-  theSplittedCurves.Append(aCurves[aCI]);
-}
-
-static Standard_Integer AppendIntersectionPoint(
-  const Adaptor3d_Curve& theCurve,
-  const Standard_Real theParameter,
-  NCollection_Sequence<Standard_Real>& theParameters)
-{
-  // Check the coincidence.
-  NCollection_Sequence<Standard_Real> aEndParams;
-  aEndParams.Append(theCurve.FirstParameter());
-  aEndParams.Append(theCurve.LastParameter());
-  NCollection_Sequence<Standard_Real>* aParams[] =
-    {&theParameters, &aEndParams};
-  const gp_Pnt aPoint = theCurve.Value(theParameter);
-  for (Standard_Integer aLI = 0; aLI < 2; ++aLI)
-  {
-    NCollection_Sequence<Standard_Real>::Iterator aPIt(*aParams[aLI]);
-    for (Standard_Integer aPI = 0; aPIt.More(); aPIt.Next(), ++aPI)
-    {
-      const Standard_Real aParam = aPIt.Value();
-      if (Abs(theParameter - aParam) < Precision::PConfusion() ||
-        aPoint.SquareDistance(theCurve.Value(aParam)) <=
-          Precision::SquareConfusion())
-      {
-        Standard_Integer aIntCount = 0;
-        if (aLI != 0)
-        {
-          if (aPI == 0)
-          {
-            theParameters.Prepend(aEndParams.First());
-          }
-          else
-          {
-            theParameters.Append(aEndParams.Last());
-          }
-          ++aIntCount;
-        }
-        return aIntCount;
-      }
-    }
-  }
-
-  // Calculate the position to insert.
-  NCollection_Sequence<Standard_Real>::Iterator aPIt(theParameters);
-  if (aPIt.More() && aPIt.Value() < theParameter)
-  {
-    NCollection_Sequence<Standard_Real>::Iterator aPIt2 = aPIt;
-    aPIt2.Next();
-    for (; aPIt2.More() && aPIt2.Value() < theParameter;
-      aPIt.Next(), aPIt2.Next());
-    theParameters.InsertAfter(aPIt, theParameter);
-  }
-  else
-  {
-    theParameters.Prepend(theParameter);
-  }
-  return 1;
-}
-
-static Standard_Integer IntersectEdge(
-  const TopoDS_Edge& theEdge1,
-  const TopoDS_Edge& theEdge2,
-  NCollection_Sequence<Standard_Real>& theParameters)
-{
-  // Process the ends.
-  Standard_Integer aIntCount = 0;
-  BRepAdaptor_Curve aCurve1 = BRepAdaptor_Curve(theEdge1);
-  BRepAdaptor_Curve aCurve2 = BRepAdaptor_Curve(theEdge2);
-  const gp_Pnt aEndPs[] = {aCurve2.Value(aCurve2.FirstParameter()),
-    aCurve2.Value(aCurve2.LastParameter())};
-  for (Standard_Integer aPI = 0; aPI < 2; ++aPI)
-  {
-    Standard_Real aParameter;
-    if (ProjectPointToCurve(aEndPs[aPI], aCurve1, aParameter) <=
-      Precision::SquareConfusion())
-    {
-      AppendIntersectionPoint(aCurve1, aParameter, theParameters);
-    }
-  }
-
-  // Process the internal extrema.
-  Extrema_ExtCC aAlgo(aCurve1, aCurve2);
-  if (aAlgo.IsDone())
-  {
-    const Standard_Integer aECount = aAlgo.NbExt();
-    for (Standard_Integer aEN = 1; aEN <= aECount; ++aEN)
-    {
-      Extrema_POnCurv aP1, aP2;
-      aAlgo.Points(aEN, aP1, aP2);
-      if (aP1.Value().SquareDistance(aP2.Value()) <=
-        Precision::SquareConfusion())
-      {
-        AppendIntersectionPoint(aCurve1, aP1.Parameter(), theParameters);
-      }
-    }
-  }
-  return aIntCount;
-}
-
-static Standard_Integer IntersectCurve(
-  const NCollection_Vector<TopoDS_Edge>& theEdges,
-  const TopoDS_Wire& theWire,
-  NCollection_Vector<NCollection_Sequence<Standard_Real> >& theParameters)
-{
-  Standard_Integer aIntCount = 0;
-  const Standard_Integer aECount1 = theEdges.Size();
-  for (Standard_Integer aEI1 = 0; aEI1 < aECount1; ++aEI1)
-  {
-    const TopoDS_Edge& aEdge1 = theEdges(aEI1);
-    TopExp_Explorer aEIt2(theWire, TopAbs_EDGE);
-    for (; aEIt2.More(); aEIt2.Next())
-    {
-      aIntCount += IntersectEdge(aEdge1,
-        TopoDS::Edge(aEIt2.Current()), theParameters(aEI1));
-    }
-  }
-  return aIntCount;
-}
-
-static void CloseCurve(NCollection_Sequence<TopoDS_Edge>& theCurve)
-{
-  const TopoDS_Vertex aVertex = TopoDS::Vertex(TopExp::LastVertex(
-    theCurve.Last(), Standard_True).Oriented(TopAbs_FORWARD));
-  const TopoDS_Edge& aEdge = theCurve.First();
-  const TopoDS_Edge aForwardEdge = TopoDS::Edge(aEdge.Oriented(TopAbs_FORWARD));
-  theCurve.ChangeFirst() = TopoDS::Edge(ShapeBuild_Edge().CopyReplaceVertices(
-    aForwardEdge, aVertex, TopoDS_Vertex()).Oriented(aEdge.Orientation()));
-}
-
-static Standard_Boolean IsClosed(
-  const NCollection_Sequence<TopoDS_Edge>& theCurve)
-{
-  return TopExp::FirstVertex(theCurve.First(), Standard_True).
-    IsSame(TopExp::LastVertex(theCurve.Last(), Standard_True));
-}
-
-static void ExtendCurve(
-  const Standard_Integer thePosition,
-  NCollection_Sequence<TopoDS_Edge>& theCurve,
-  NCollection_Sequence<TopoDS_Edge>& theExtension)
-{
-  if (thePosition == 0)
-  {
-    const TopoDS_Vertex aVertex = TopoDS::Vertex(TopExp::LastVertex(
-      theExtension.Last(), Standard_True).Oriented(TopAbs_FORWARD));
-    TopoDS_Edge& aEdge = theCurve.ChangeFirst();
-    aEdge = TopoDS::Edge(ShapeBuild_Edge().CopyReplaceVertices(
-        TopoDS::Edge(aEdge.Oriented(TopAbs_FORWARD)), aVertex, TopoDS_Vertex()).
-      Oriented(aEdge.Orientation()));
-    theCurve.Prepend(theExtension);
-  }
-  else
-  {
-    const TopoDS_Vertex aVertex = TopoDS::Vertex(TopExp::FirstVertex(
-      theExtension.First(), Standard_True).Oriented(TopAbs_REVERSED));
-    TopoDS_Edge& aEdge = theCurve.ChangeLast();
-    aEdge = TopoDS::Edge(ShapeBuild_Edge().CopyReplaceVertices(
-        TopoDS::Edge(aEdge.Oriented(TopAbs_FORWARD)), TopoDS_Vertex(), aVertex).
-      Oriented(aEdge.Orientation()));
-    theCurve.Append(theExtension);
-  }
-}
-
-static void ExtendCurve(
-  const Standard_Integer thePosition,
-  const TopoDS_Edge& theExtension,
-  NCollection_Sequence<TopoDS_Edge>& theCurve)
-{
-  NCollection_Sequence<TopoDS_Edge> aExtension;
-  aExtension.Append(theExtension);
-  ExtendCurve(thePosition, theCurve, aExtension);
-}
-
-static gp_XYZ Tangent(
-  const Adaptor3d_Curve& theCurve, const Standard_Integer thePosition)
-{
-  const Standard_Real aParam = (thePosition == 0) ?
-    theCurve.FirstParameter() : theCurve.LastParameter();
-  gp_Pnt aP;
-  gp_Vec aV;
-  theCurve.D1(aParam, aP, aV);
-  Standard_Real aNorm = aV.Magnitude();
-  aNorm = (aNorm >= Precision::PConfusion()) ? aNorm : 0;
-  return ((1 / aNorm) * aV).XYZ();
-}
-
-static gp_XYZ Tangent(
-  const TopoDS_Edge& theEdge, const Standard_Integer thePosition)
-{
-  BRepAdaptor_Curve aCurve(theEdge);
-  return Tangent(BRepAdaptor_Curve(theEdge), thePosition);
-}
-
-static Standard_Boolean Interpolate(
-  const gp_Pnt thePoint1,
-  const gp_Pnt thePoint2,
-  const gp_Vec theTangent1,
-  const gp_Vec theTangent2,
-  Handle(Geom_BSplineCurve)& theBSpline)
-{
-  Handle(TColgp_HArray1OfPnt) aPs = new TColgp_HArray1OfPnt(1, 2);
-  TColgp_Array1OfVec aTs(1, 2);
-  Handle(TColStd_HArray1OfBoolean) aTFs = new TColStd_HArray1OfBoolean(1, 2);
-  aPs->SetValue(1, thePoint1);
-  aPs->SetValue(2, thePoint2);
-  aTs.SetValue(1, theTangent1);
-  aTs.SetValue(2, theTangent2);
-  aTFs->SetValue(1, Standard_True);
-  aTFs->SetValue(2, Standard_True);
-  GeomAPI_Interpolate aInterpolator(aPs, Standard_False, 0);
-  aInterpolator.Load(aTs, aTFs, Standard_False);
-  aInterpolator.Perform();
-  const Standard_Boolean aResult = (aInterpolator.IsDone() == Standard_True);
-  if (aResult)
-  {
-    theBSpline = aInterpolator.Curve();
-  }
-  return aResult;
-}
-
-static Standard_Boolean Merge(
-  const TopoDS_Wire& theWire,
-  const Standard_Real theTolerance,
-  NCollection_Vector<NCollection_Sequence<TopoDS_Edge> >& theMergedCurves)
-{
-  NCollection_Sequence<TopoDS_Edge> aCurve;
-  Standard_Boolean isClosed;
-  if (!WireToCurve(theWire, aCurve, isClosed))
-  {
-    return Standard_False;
-  }
-
-  if (isClosed)
-  {
-    theMergedCurves.Append(aCurve);
-    return Standard_True;
-  }
-
-  const Standard_Real aSqTol = theTolerance * theTolerance;
-  const gp_Pnt aPs[] = {
-    BRep_Tool::Pnt(TopExp::FirstVertex(aCurve.First(), Standard_True)),
-    BRep_Tool::Pnt(TopExp::LastVertex(aCurve.Last(), Standard_True))};
-  if (!isClosed && aPs[0].SquareDistance(aPs[1]) <= aSqTol)
-  {
-    CloseCurve(aCurve);
-    theMergedCurves.Append(aCurve);
-    return Standard_True;
-  }
-
-  NCollection_Sequence<TopoDS_Edge>* aCurves[] = {NULL, NULL};
-  Standard_Integer aOrder = 0;
-  for (NCollection_Vector<NCollection_Sequence<TopoDS_Edge> >::Iterator
-    aCIt(theMergedCurves); aCIt.More(); aCIt.Next())
-  {
-    NCollection_Sequence<TopoDS_Edge>& aC = aCIt.ChangeValue();
-    if (aC.IsEmpty() || IsClosed(aC))
-    {
-      continue;
-    }
-
-    const gp_Pnt aP1 =
-      BRep_Tool::Pnt(TopExp::FirstVertex(aC.First(), Standard_True));
-    if (aCurves[0] == NULL && aP1.SquareDistance(aPs[1]) <= aSqTol)
-    {
-      aCurves[0] = &aC;
-    }
-
-    const gp_Pnt aP2 =
-      BRep_Tool::Pnt(TopExp::LastVertex(aC.Last(), Standard_True));
-    if (aCurves[1] == NULL && aP2.SquareDistance(aPs[0]) <= aSqTol)
-    {
-      aCurves[1] = &aC;
-      aOrder = (aCurves[0] == NULL) ? 1 : 0;
-    }
-  }
-
-  if (aCurves[0] == NULL && aCurves[1] == NULL)
-  {
-    theMergedCurves.Append(aCurve);
-  }
-  else if (aCurves[1] == NULL)
-  {
-    ExtendCurve(0, *aCurves[0], aCurve);
-  }
-  else if (aCurves[0] == NULL)
-  {
-    ExtendCurve(1, *aCurves[1], aCurve);
-  }
-  else
-  {
-    ExtendCurve(aOrder, *aCurves[aOrder], aCurve);
-    if (aCurves[0] != aCurves[1])
-    {
-      ExtendCurve(aOrder, *aCurves[aOrder], *aCurves[1 - aOrder]);
-    }
-    else
-    {
-      CloseCurve(*aCurves[aOrder]);
-    }
-  }
-  return Standard_True;
-}
-
-static Standard_Boolean Connect(
-  const TopoDS_Wire& theWire,
-  const Standard_Real theTolerance,
-  NCollection_Vector<NCollection_Sequence<TopoDS_Edge> >& theMergedCurves)
-{
-  NCollection_Sequence<TopoDS_Edge> aCurve;
-  Standard_Boolean isClosed;
-  if (!WireToCurve(theWire, aCurve, isClosed))
-  {
-    return Standard_False;
-  }
-
-  if (isClosed)
-  {
-    theMergedCurves.Append(aCurve);
-    return Standard_True;
-  }
-
-  const Standard_Real aSqTol = theTolerance * theTolerance;
-  const gp_Pnt aPs[] = {
-    BRep_Tool::Pnt(TopExp::FirstVertex(aCurve.First(), Standard_True)),
-    BRep_Tool::Pnt(TopExp::LastVertex(aCurve.Last(), Standard_True))};
-  if (!isClosed && aPs[0].SquareDistance(aPs[1]) <= aSqTol)
-  {
-    CloseCurve(aCurve);
-    theMergedCurves.Append(aCurve);
-    return Standard_True;
-  }
-
-  for (NCollection_Vector<NCollection_Sequence<TopoDS_Edge> >::Iterator
-    aCIt(theMergedCurves); aCIt.More(); aCIt.Next())
-  {
-    NCollection_Sequence<TopoDS_Edge>& aCurve2 = aCIt.ChangeValue();
-    if (aCurve2.IsEmpty() || IsClosed(aCurve2))
-    {
-      continue;
-    }
-
-    const TopoDS_Edge* aEdges2[] = {&aCurve2.First(), &aCurve2.Last()};
-    const gp_Pnt aPs2[] = {
-      BRep_Tool::Pnt(TopExp::FirstVertex(*aEdges2[0], Standard_True)),
-      BRep_Tool::Pnt(TopExp::LastVertex(*aEdges2[1], Standard_True))};
-    const Standard_Real aSqDists[] =
-      {aPs2[0].SquareDistance(aPs[1]), aPs2[1].SquareDistance(aPs[0])};
-    const Standard_Integer aOrder = (aSqDists[0] <= aSqDists[1]) ? 0 : 1;
-    if (aSqDists[aOrder] > aSqTol)
-    {
-      const TopoDS_Edge& aEdge = (aOrder == 0) ? aCurve.Last() : aCurve.First();
-      const gp_Pnt aPs3[] = {aPs[1 - aOrder], aPs2[aOrder]};
-      const gp_XYZ aTs[] =
-        {Tangent(aEdge, 1 - aOrder), Tangent(*aEdges2[aOrder], aOrder)};
-      Handle(Geom_BSplineCurve) aBSpline;
-      if (!Interpolate(aPs3[aOrder], aPs3[1 - aOrder],
-        aTs[aOrder], aTs[1 - aOrder], aBSpline))
-      {
-        return Standard_False;
-      }
-
-      ExtendCurve(aOrder, BRepBuilderAPI_MakeEdge(aBSpline), aCurve2);
-    }
-    ExtendCurve(aOrder, aCurve2, aCurve);
-    if (aSqDists[1 - aOrder] <= aSqTol)
-    {
-      CloseCurve(aCurve2);
-    }
-    return Standard_True;
-  }
-
-  theMergedCurves.Append(aCurve);
-  return Standard_True;
-}
-
 bool HYDROData_PolylineOperator::Split( const Handle( HYDROData_Document )& theDoc,
                                         const Handle( HYDROData_PolylineXY )& thePolyline,
                                         const gp_Pnt2d& thePoint,
@@ -739,11 +63,13 @@ bool HYDROData_PolylineOperator::Split( const Handle( HYDROData_Document )& theD
 {
   std::vector<gp_Pnt2d> aPointsList( 1 );
   aPointsList[0] = thePoint;
-  std::vector<TopoDS_Wire> aCurves = GetWires( thePolyline );
+  std::vector<TopoDS_Wire> aCurves;
+  GetWires(thePolyline, aCurves);
   bool isOK = true;
   for( int i=0, n=aCurves.size(); i<n; i++ )
   {
-    std::vector<TopoDS_Shape> aCurvesList = Split( aCurves[i], thePoint, theTolerance );
+    std::vector<TopoDS_Shape> aCurvesList;
+    Split(aCurves[i], thePoint, theTolerance, aCurvesList);
     bool isLocalOK = CreatePolylines( theDoc, thePolyline->GetName(), aCurvesList, true );
     isOK = isOK && isLocalOK;
   }
@@ -780,19 +106,20 @@ bool HYDROData_PolylineOperator::Merge( const Handle( HYDROData_Document )& theD
                                         bool isConnectByNewSegment,
                                         double theTolerance )
 {
-  NCollection_Vector<NCollection_Sequence<TopoDS_Edge> > aMergedCurves;
+  std::deque<HYDROData_TopoCurve> aMergedCurves;
   HYDROData_SequenceOfObjects::Iterator aPIt(thePolylines);
   for (; aPIt.More(); aPIt.Next())
   {
     Handle(HYDROData_PolylineXY) aPolyline =
       Handle(HYDROData_PolylineXY)::DownCast(aPIt.Value());
-    std::vector<TopoDS_Wire> aWires = GetWires(aPolyline);
+    std::vector<TopoDS_Wire> aWires;
+    GetWires(aPolyline, aWires);
     for (std::vector<TopoDS_Wire>::const_iterator aWIt = aWires.begin(),
       aLastWIt = aWires.end(); aWIt != aLastWIt; ++aWIt)
     {
       const Standard_Boolean aResult = !isConnectByNewSegment ?
-        ::Merge(*aWIt, theTolerance, aMergedCurves) :
-        Connect(*aWIt, theTolerance, aMergedCurves);
+        HYDROData_TopoCurve::Merge(theTolerance, *aWIt, aMergedCurves) :
+        HYDROData_TopoCurve::Connect(theTolerance, *aWIt, aMergedCurves);
       if (!aResult)
       {
         return false;
@@ -803,14 +130,13 @@ bool HYDROData_PolylineOperator::Merge( const Handle( HYDROData_Document )& theD
   TopoDS_Compound aWireSet;
   BRep_Builder aBuilder;
   aBuilder.MakeCompound(aWireSet);
-  for (NCollection_Vector<NCollection_Sequence<TopoDS_Edge> >::Iterator
-    aCIt(aMergedCurves); aCIt.More(); aCIt.Next())
+  std::deque<HYDROData_TopoCurve>::iterator aCIt = aMergedCurves.begin();
+  std::deque<HYDROData_TopoCurve>::iterator aLastCIt = aMergedCurves.end();
+  for (; aCIt != aLastCIt; ++aCIt)
   {
-    if (!aCIt.Value().IsEmpty())
+    if (!aCIt->IsEmpty())
     {
-      TopoDS_Wire aWire;
-      CurveToWire(aCIt.Value(), aWire);
-      aBuilder.Add(aWireSet, aWire);
+      aBuilder.Add(aWireSet, aCIt->Wire());
     }
   }
 
@@ -826,14 +152,17 @@ bool HYDROData_PolylineOperator::split( const Handle( HYDROData_Document )& theD
                                         double theTolerance,
                                         int theIgnoreIndex ) const
 {
-  std::vector<TopoDS_Wire> aCurves = GetWires( thePolyline );
+  std::vector<TopoDS_Wire> aCurves;
+  GetWires(thePolyline, aCurves);
   std::vector<TopoDS_Wire> aToolCurves;
   for( int i=theTools.Lower(), n=theTools.Upper(); i<=n; i++ )
     if( i!=theIgnoreIndex )
     {
       Handle( HYDROData_PolylineXY ) aToolPolyline = 
         Handle( HYDROData_PolylineXY )::DownCast( theTools.Value( i ) );
-      append( aToolCurves, GetWires( aToolPolyline ) );
+      std::vector<TopoDS_Wire> aTCurves;
+      GetWires(aToolPolyline, aTCurves);
+      append( aToolCurves, aTCurves);
     }
 
   const int aPSCount = aCurves.size();
@@ -841,71 +170,27 @@ bool HYDROData_PolylineOperator::split( const Handle( HYDROData_Document )& theD
   std::vector<TopoDS_Shape> aResult;
   for (int aPSI = 0; aPSI < aPSCount; ++aPSI)
   {
-    NCollection_Vector<TopoDS_Edge> aCurve;
-    Standard_Boolean aIsClosed;
-    if (!WireToCurve(aCurves[aPSI], aCurve, aIsClosed))
+    HYDROData_TopoCurve aCurve;
+    if (!aCurve.Initialize(aCurves[aPSI]))
     {
       continue;
     }
 
-    NCollection_Vector<NCollection_Sequence<Standard_Real> > aParams;
-    aParams.SetValue(aCurve.Size() - 1, NCollection_Sequence<Standard_Real>());
+    std::deque<std::list<double> > aParams;
     for (int aTSI = 0; aTSI < aTSCount; ++aTSI)
     {
-      IntersectCurve(aCurve, aToolCurves[aTSI], aParams);
+      aCurve.Intersect(aToolCurves[aTSI], aParams);
     }
 
-    NCollection_Vector<NCollection_Vector<TopoDS_Edge> > aSplittedCurves;
-    SplitCurveByPoints(aCurve, aParams, aSplittedCurves);
-
-    Standard_Boolean aIsClosed2 = aIsClosed;
-    if (aIsClosed2)
+    std::deque<HYDROData_TopoCurve> aSplittedCurves;
+    aCurve.Cut(aParams, aSplittedCurves);
+    std::deque<HYDROData_TopoCurve>::const_iterator aCIt =
+      aSplittedCurves.begin();
+    std::deque<HYDROData_TopoCurve>::const_iterator aLastCIt =
+      aSplittedCurves.end();
+    for (; aCIt != aLastCIt; ++aCIt)
     {
-      const NCollection_Sequence<Standard_Real>& aPs = aParams.First();
-      if (!aPs.IsEmpty())
-      {
-        const TopoDS_Edge& aEdge = aCurve.First();
-        const Standard_Boolean isForward =
-          (aEdge.Orientation() != TopAbs_REVERSED);
-        const Standard_Real aParam = isForward ? aPs.First() : aPs.Last();
-        BRepAdaptor_Curve aCurve(aEdge);
-        const Standard_Real aEndParam = isForward ?
-          aCurve.FirstParameter() : aCurve.LastParameter();
-        aIsClosed2 = (Abs(aParam - aEndParam) > Precision::PConfusion());
-      }
-
-      if (aIsClosed2)
-      {
-        const NCollection_Sequence<Standard_Real>& aPs = aParams.Last();
-        if (!aPs.IsEmpty())
-        {
-          const TopoDS_Edge& aEdge = aCurve.Last();
-          const Standard_Boolean isForward =
-            (aEdge.Orientation() != TopAbs_REVERSED);
-          const Standard_Real aParam = isForward ? aPs.Last() : aPs.First();
-          BRepAdaptor_Curve aCurve(aEdge);
-          const Standard_Real aEndParam = isForward ?
-            aCurve.LastParameter() : aCurve.FirstParameter();
-          aIsClosed2 = (Abs(aParam - aEndParam) >= Precision::PConfusion());
-        }
-      }
-    }
-
-    Standard_Integer aFSCI = 0, aLSCI = aSplittedCurves.Size() - 1;
-    if (aIsClosed2 && aFSCI < aLSCI)
-    {
-      TopoDS_Wire aWire;
-      CurveToWire(aSplittedCurves(aLSCI), aSplittedCurves(aFSCI), aWire);
-      aResult.push_back(aWire);
-      ++aFSCI;
-      --aLSCI;
-    }
-
-    for (Standard_Integer aSCI = aFSCI; aSCI <= aLSCI; ++aSCI)
-    {
-      TopoDS_Wire aWire;
-      CurveToWire(aSplittedCurves(aSCI), aWire);
-      aResult.push_back(aWire);
+      aResult.push_back(aCIt->Wire());
     }
   }
 
@@ -913,82 +198,49 @@ bool HYDROData_PolylineOperator::split( const Handle( HYDROData_Document )& theD
   return true;
 }
 
-std::vector<TopoDS_Wire> HYDROData_PolylineOperator::GetWires( const Handle( HYDROData_PolylineXY )& thePolyline )
+void HYDROData_PolylineOperator::GetWires(
+  const Handle( HYDROData_PolylineXY )& thePolyline,
+  std::vector<TopoDS_Wire>& theWires)
 {
-  std::vector<TopoDS_Wire> aResult;
-
   TopoDS_Shape aShape = thePolyline->GetShape();
-
   if( aShape.ShapeType()==TopAbs_WIRE )
   {
-    aResult.push_back( TopoDS::Wire( aShape ) );
+    theWires.push_back( TopoDS::Wire( aShape ) );
   }
   else
   {
     TopExp_Explorer anExp( aShape, TopAbs_WIRE );
     for( ; anExp.More(); anExp.Next() )
     {
-      aResult.push_back( TopoDS::Wire( anExp.Current() ) );
+      theWires.push_back( TopoDS::Wire( anExp.Current() ) );
     }
   }
-  return aResult;
 }
 
-std::vector<TopoDS_Shape> HYDROData_PolylineOperator::Split( const TopoDS_Wire& theWire,
-                                                             const gp_Pnt2d& thePoint,
-                                                             double theTolerance )
+void HYDROData_PolylineOperator::Split(
+  const TopoDS_Wire& theWire,
+  const gp_Pnt2d& thePoint,
+  double theTolerance,
+  std::vector<TopoDS_Shape>& theWires)
 {
-  std::vector<TopoDS_Shape> aResult;
-  NCollection_Vector<TopoDS_Edge> aEdges;
-  Standard_Boolean isClosed;
-  if (!WireToCurve(theWire, aEdges, isClosed))
+  HYDROData_TopoCurve aCurve;
+  if (!aCurve.Initialize(theWire))
   {
-    aResult.push_back(theWire);
-    return aResult;
-  }
-
-  const gp_Pnt aP(thePoint.X(), thePoint.Y(), 0);
-  Standard_Real aMinSqDist = DBL_MAX;
-  int aSEI = -1;
-  Standard_Real aSParam;
-  for (int aECount = aEdges.Size(), aEI = 0; aEI < aECount; ++aEI)
-  {
-    Standard_Real aParam;
-    const Standard_Real aSqDist =
-      ProjectPointToEdge(aP, aEdges(aEI), aParam);
-    if (aMinSqDist > aSqDist)
-    {
-      aMinSqDist = aSqDist;
-      aSEI = aEI;
-      aSParam = aParam;
-    }
+    theWires.push_back(theWire);
+    return;
   }
 
-  NCollection_Vector<TopoDS_Edge> aEdges1, aEdges2;
-  SplitCurveByPoint(aEdges, aSEI, aSParam, aEdges1, aEdges2);
-  TopoDS_Wire aWire;
-  if (!isClosed)
-  {
-    CurveToWire(aEdges1, aWire);
-    if (!aEdges2.IsEmpty())
-    {
-      aResult.push_back(aWire);
-      CurveToWire(aEdges2, aWire);
-    }
-  }
-  else
+  const gp_XYZ aP(thePoint.X(), thePoint.Y(), 0);
+  std::list<TopoDS_Edge>::const_iterator aEPos;
+  double aParam;
+  aCurve.Project(aP, aEPos, aParam);
+  HYDROData_TopoCurve aCurve1, aCurve2;
+  aCurve.Cut(aEPos, aParam, aCurve1, aCurve2);
+  theWires.push_back(aCurve1.Wire());
+  if (!aCurve2.IsEmpty())
   {
-    if (!aEdges2.IsEmpty())
-    {
-      CurveToWire(aEdges2, aEdges1, aWire);
-    }
-    else
-    {
-      CurveToWire(aEdges1, aWire);
-    }
+    theWires.push_back(aCurve2.Wire());
   }
-  aResult.push_back(aWire);
-  return aResult;
 }
 
 bool HYDROData_PolylineOperator::CreatePolylines( const Handle( HYDROData_Document )& theDoc,
index 0b0fdceeba7e2220c21eb097dbcb4f26a5723c48..ed658ffbadb1c1c412c183022fec1add7d9b8896 100644 (file)
@@ -46,6 +46,10 @@ public:
               bool isConnectByNewSegment,
               double theTolerance );
 
+  static void GetWires(
+    const Handle( HYDROData_PolylineXY )& thePolyline,
+    std::vector<TopoDS_Wire>& theWires);
+
 protected:
   bool split( const Handle( HYDROData_Document )& theDoc,
               const Handle( HYDROData_PolylineXY )& thePolyline,
@@ -53,11 +57,11 @@ protected:
               double theTolerance,
               int theIgnoreIndex ) const;
 
-  static std::vector<TopoDS_Wire> GetWires( const Handle( HYDROData_PolylineXY )& thePolyline );
-
-  static std::vector<TopoDS_Shape> Split( const TopoDS_Wire& theWire,
-                                          const gp_Pnt2d& thePoint,
-                                          double theTolerance );
+  static void Split(
+    const TopoDS_Wire& theWire,
+    const gp_Pnt2d& thePoint,
+    double theTolerance,
+    std::vector<TopoDS_Shape>& theWires);
 
   static bool CreatePolylines( const Handle( HYDROData_Document )& theDoc,
                                const QString& theNamePrefix,
diff --git a/src/HYDROData/HYDROData_TopoCurve.cxx b/src/HYDROData/HYDROData_TopoCurve.cxx
new file mode 100644 (file)
index 0000000..449db4c
--- /dev/null
@@ -0,0 +1,894 @@
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include <HYDROData_TopoCurve.h>
+
+#include <Approx_Curve3d.hxx>
+#include <BRep_Builder.hxx>
+#include <BRepAdaptor_Curve.hxx>
+#include <BRepAdaptor_HCurve.hxx>
+#include <BRepBuilderAPI_MakeEdge.hxx>
+#include <Extrema_ExtCC.hxx>
+#include <Extrema_ExtPC.hxx>
+#include <GeomAPI_Interpolate.hxx>
+#include <Geom_BSplineCurve.hxx>
+#include <Precision.hxx>
+#include <ShapeAnalysis_TransferParametersProj.hxx>
+#include <ShapeBuild_Edge.hxx>
+#include <TColgp_Array1OfVec.hxx>
+#include <TColgp_HArray1OfPnt.hxx>
+#include <TColStd_HArray1OfBoolean.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Wire.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
+
+//! The type is intended to traverse the container
+//! either from the begin to the end or vice versa.
+template<typename ContainerType, typename IteratorType>
+class Iterator
+{
+private:
+  IteratorType myIterator; //!< The iterator.
+  IteratorType myIteratorLimit; //!< The iterator limit.
+
+  //! The pointer to the method to traverse the next item.
+  IteratorType& (IteratorType::*myNext)();
+
+public:
+  //! The constructor.
+  Iterator(
+    const ContainerType& theContainer,
+    const bool theIsForward)
+  {
+    if (theIsForward)
+    {
+      myIterator = theContainer.begin();
+      myIteratorLimit = theContainer.end();
+      myNext = &IteratorType::operator++;
+    }
+    else
+    {
+      myIterator = --theContainer.end();
+      myIteratorLimit = --theContainer.begin();
+      myNext = &IteratorType::operator--;
+    }
+  }
+
+  //! Returna 'true' if the container contains not yet traversed item.
+  bool More() const
+  {
+    return myIterator != myIteratorLimit;
+  }
+
+  //! Traverses to the next item.
+  IteratorType& operator ++()
+  {
+    return (myIterator.*myNext)();
+  }
+
+  //! Returns the iterator.
+  IteratorType& operator *() {return myIterator;}
+};
+
+// Inserts the value after the position.
+template<typename ItemType> static void InsertAfter(
+  const typename std::list<ItemType>::iterator& thePosition,
+  const ItemType& theValue,
+  std::list<ItemType>& theList)
+{
+  std::list<ItemType>::iterator aEIt2 = thePosition;
+  if (++aEIt2 != theList.end())
+  {
+    theList.insert(aEIt2, theValue);
+  }
+  else
+  {
+    theList.push_back(theValue);
+  }
+}
+
+// Converts the curve to a smooth cubic B-spline using the deflection.
+static Handle(Geom_BSplineCurve) BSpline(
+  const BRepAdaptor_Curve& theCurve, const double theDeflection)
+{
+  Handle(BRepAdaptor_HCurve) aCurve = new BRepAdaptor_HCurve(theCurve);
+  Approx_Curve3d aConverter(aCurve, theDeflection, GeomAbs_C1, 4, 3);
+  Handle(Geom_BSplineCurve) aBSpline;
+  return aConverter.HasResult() ? aConverter.Curve() : aBSpline;
+}
+
+// Replaces the vertex of the edge considering the edge orientation.
+static TopoDS_Edge ReplaceVertex(
+  const TopoDS_Edge& theEdge, const bool theIsEndVertex)
+{
+  TopoDS_Vertex aVertices[] = {
+    TopExp::FirstVertex(theEdge, Standard_True),
+    TopExp::LastVertex(theEdge, Standard_True)};
+  aVertices[theIsEndVertex ? 1 : 0].EmptyCopy();
+  TopoDS_Edge aNewEdge = TopoDS::Edge(theEdge.Oriented(TopAbs_FORWARD));
+  aNewEdge =
+    ShapeBuild_Edge().CopyReplaceVertices(aNewEdge, aVertices[0], aVertices[1]);
+  aNewEdge.Orientation(theEdge.Orientation());
+  return aNewEdge;
+}
+
+// Projects the point to the curve.
+static double ProjectPointToCurve(
+  const gp_XYZ& thePoint,
+  const Adaptor3d_Curve& theCurve,
+  double& theParameter)
+{
+  // Calculate the nearest curve internal extremum.
+  Extrema_ExtPC aAlgo(thePoint, theCurve);
+  int aMinEN = -2;
+  double aMinSqDist = DBL_MAX;
+  if (aAlgo.IsDone())
+  {
+    const int aECount = aAlgo.NbExt();
+    for (int aEN = 1; aEN <= aECount; ++aEN)
+    {
+      const gp_XYZ& aP = aAlgo.Point(aEN).Value().XYZ();
+      const double aSqDist = (thePoint - aP).SquareModulus();
+      if (aMinSqDist > aSqDist)
+      {
+        aMinSqDist = aSqDist;
+        aMinEN = aEN;
+      }
+    }
+  }
+
+  // Calculate the nearest curve end extremum.
+  const double aParams[] =
+    {theCurve.FirstParameter(), theCurve.LastParameter()};
+  const gp_XYZ aEnds[] =
+    {theCurve.Value(aParams[0]).XYZ(), theCurve.Value(aParams[1]).XYZ()};
+  const double aSqDists[] = {
+    (thePoint - aEnds[0]).SquareModulus(),
+    (thePoint - aEnds[1]).SquareModulus()};
+  for (int aEI = 0; aEI < 2; ++aEI)
+  {
+    if (aMinSqDist > aSqDists[aEI])
+    {
+      aMinSqDist = aSqDists[aEI];
+      aMinEN = -aEI;
+    }
+  }
+
+  if (aMinEN <= 0)
+  {
+    theParameter = aParams[-aMinEN];
+    return aMinSqDist;
+  }
+
+  const Extrema_POnCurv& aPOnC = aAlgo.Point(aMinEN);
+  const gp_XYZ& aP = aPOnC.Value().XYZ();
+  theParameter = aPOnC.Parameter();
+  for (int aEI = 0; aEI < 2; ++aEI)
+  {
+    if (Abs(theParameter - aParams[aEI]) < Precision::PConfusion() ||
+      (aP - aEnds[aEI]).SquareModulus() < Precision::SquareConfusion())
+    {
+      theParameter = aParams[aEI];
+    }
+  }
+  return aMinSqDist;
+}
+
+// Projects the point to the edge.
+static double ProjectPointToEdge(
+  const gp_XYZ& thePoint, const TopoDS_Edge& theEdge, double& theParameter)
+{
+  return ProjectPointToCurve(thePoint, BRepAdaptor_Curve(theEdge), theParameter);
+}
+
+// Adds the parameter to the curve parameter list.
+static int AddParameter(
+  const Adaptor3d_Curve& theCurve,
+  const double theParameter,
+  std::list<double>& theParameters)
+{
+  // Check the coincidence.
+  std::list<double> aEndParams;
+  aEndParams.push_back(theCurve.FirstParameter());
+  aEndParams.push_back(theCurve.LastParameter());
+  std::list<double>* aParams[] = {&theParameters, &aEndParams};
+  const gp_XYZ aPoint = theCurve.Value(theParameter).XYZ();
+  for (int aLI = 0; aLI < 2; ++aLI)
+  {
+    std::list<double>::iterator aPIt = aParams[aLI]->begin();
+    std::list<double>::iterator aLastPIt = aParams[aLI]->end();
+    for (int aPI = 0; aPIt != aLastPIt; ++aPI, ++aPIt)
+    {
+      const double aParam = *aPIt;
+      if (Abs(theParameter - aParam) < Precision::PConfusion() ||
+        (theCurve.Value(aParam).XYZ() - aPoint).SquareModulus() <=
+          Precision::SquareConfusion())
+      {
+        int aIntCount = 0;
+        if (aLI != 0)
+        {
+          if (aPI == 0)
+          {
+            theParameters.push_front(aEndParams.front());
+          }
+          else
+          {
+            theParameters.push_back(aEndParams.back());
+          }
+          ++aIntCount;
+        }
+        return aIntCount;
+      }
+    }
+  }
+
+  // Calculate the position to insert.
+  std::list<double>::iterator aPIt = theParameters.begin();
+  std::list<double>::iterator aLastPIt = theParameters.end();
+  if (aPIt != aLastPIt && *aPIt < theParameter)
+  {
+    for (++aPIt; aPIt != aLastPIt && *aPIt < theParameter; ++aPIt);
+    if (aPIt != aLastPIt)
+    {
+      theParameters.insert(aPIt, theParameter);
+    }
+    else
+    {
+      theParameters.push_back(theParameter);
+    }
+  }
+  else
+  {
+    theParameters.push_front(theParameter);
+  }
+  return 1;
+}
+
+// Intersects the first curve by the second one and
+// adds the intersection parameters to the ordered list.
+static int IntersectCurve(
+  const Adaptor3d_Curve& theCurve1,
+  const Adaptor3d_Curve& theCurve2,
+  std::list<double>& theParameters)
+{
+  // Process the ends.
+  int aIntCount = 0;
+  const gp_XYZ aEndPs[] = {
+    theCurve2.Value(theCurve2.FirstParameter()).XYZ(),
+    theCurve2.Value(theCurve2.LastParameter()).XYZ()};
+  for (int aPI = 0; aPI < 2; ++aPI)
+  {
+    double aParameter;
+    if (ProjectPointToCurve(aEndPs[aPI], theCurve1, aParameter) <=
+      Precision::SquareConfusion())
+    {
+      aIntCount += AddParameter(theCurve1, aParameter, theParameters);
+    }
+  }
+
+  // Process the internal extremums.
+  Extrema_ExtCC aAlgo(theCurve1, theCurve2);
+  if (aAlgo.IsDone())
+  {
+    const int aECount = aAlgo.NbExt();
+    for (int aEN = 1; aEN <= aECount; ++aEN)
+    {
+      Extrema_POnCurv aP1, aP2;
+      aAlgo.Points(aEN, aP1, aP2);
+      if (aP1.Value().SquareDistance(aP2.Value()) <=
+        Precision::SquareConfusion())
+      {
+        aIntCount += AddParameter(theCurve1, aP1.Parameter(), theParameters);
+      }
+    }
+  }
+  return aIntCount;
+}
+
+// Intersects the first edge by the second one and
+// adds the intersection parameters to the ordered list.
+static int IntersectEdge(
+  const TopoDS_Edge& theEdge1,
+  const TopoDS_Edge& theEdge2,
+  std::list<double>& theParameters)
+{
+  BRepAdaptor_Curve aCurve1 = BRepAdaptor_Curve(theEdge1);
+  BRepAdaptor_Curve aCurve2 = BRepAdaptor_Curve(theEdge2);
+  return IntersectCurve(aCurve1, aCurve2, theParameters);
+}
+
+// Returns the curve tangent in the position: 0 - start, 1 - end.
+static gp_XYZ Tangent(const Adaptor3d_Curve& theCurve, const int thePosition)
+{
+  const Standard_Real aParam = (thePosition == 0) ?
+    theCurve.FirstParameter() : theCurve.LastParameter();
+  gp_Pnt aP;
+  gp_Vec aV;
+  theCurve.D1(aParam, aP, aV);
+  Standard_Real aNorm = aV.Magnitude();
+  aNorm = (aNorm >= Precision::PConfusion()) ? aNorm : 0;
+  return ((1 / aNorm) * aV).XYZ();
+}
+
+// Returns the edge tangent in the position: 0 - start, 1 - end.
+static gp_XYZ Tangent(const TopoDS_Edge& theEdge, const int thePosition)
+{
+  BRepAdaptor_Curve aCurve(theEdge);
+  return Tangent(BRepAdaptor_Curve(theEdge), thePosition);
+}
+
+static bool Interpolate(
+  const gp_XYZ thePoint1,
+  const gp_XYZ thePoint2,
+  const gp_XYZ theTangent1,
+  const gp_XYZ theTangent2,
+  Handle(Geom_BSplineCurve)& theBSpline)
+{
+  Handle(TColgp_HArray1OfPnt) aPs = new TColgp_HArray1OfPnt(1, 2);
+  TColgp_Array1OfVec aTs(1, 2);
+  Handle(TColStd_HArray1OfBoolean) aTFs = new TColStd_HArray1OfBoolean(1, 2);
+  aPs->SetValue(1, thePoint1);
+  aPs->SetValue(2, thePoint2);
+  aTs.SetValue(1, theTangent1);
+  aTs.SetValue(2, theTangent2);
+  aTFs->SetValue(1, Standard_True);
+  aTFs->SetValue(2, Standard_True);
+  GeomAPI_Interpolate aInterpolator(aPs, Standard_False, 0);
+  aInterpolator.Load(aTs, aTFs, Standard_False);
+  aInterpolator.Perform();
+  const bool aResult = (aInterpolator.IsDone() == Standard_True);
+  if (aResult)
+  {
+    theBSpline = aInterpolator.Curve();
+  }
+  return aResult;
+}
+
+bool HYDROData_TopoCurve::Initialize(const TopoDS_Wire& theWire)
+{
+  // Check for nonemptiness.
+  myEdges.clear();
+  TopTools_IndexedDataMapOfShapeListOfShape aVertexToEdges;
+  TopExp::MapShapesAndAncestors(theWire,
+    TopAbs_VERTEX, TopAbs_EDGE, aVertexToEdges);
+  const int aVCount = aVertexToEdges.Extent();
+  if (aVCount == 0)
+  {
+    return false;
+  }
+
+  // Check for 1 manifoldness.
+  bool isClosed = false;
+  {
+    int aEndCount = 0;
+    for (int aVN = 1; aVN <= aVCount; ++aVN)
+    {
+      const int aEdgeCount = aVertexToEdges.FindFromIndex(aVN).Extent();
+      if (aEdgeCount == 1)
+      {
+        ++aEndCount;
+      }
+      if (aEdgeCount > 2)
+      {
+        return false;
+      }
+    }
+    isClosed = (aEndCount == 0);
+    if (!isClosed && aEndCount != 2)
+    {
+      return false;
+    }
+  }
+
+  // Find the start.
+  int aVN = 1;
+  if (!isClosed)
+  {
+    for (; aVertexToEdges.FindFromIndex(aVN).Extent() == 2; ++aVN);
+    if (!aVertexToEdges.FindKey(aVN).IsEqual(TopExp::FirstVertex(
+      TopoDS::Edge(aVertexToEdges.FindFromIndex(aVN).First()), Standard_True)))
+    {
+      for (; aVertexToEdges.FindFromIndex(aVN).Extent() == 2; ++aVN);
+    }
+  }
+  else
+  {
+    TopTools_ListOfShape& aEdges = aVertexToEdges.ChangeFromIndex(1);
+    if (!aVertexToEdges.FindKey(aVN).IsEqual(
+      TopExp::FirstVertex(TopoDS::Edge(aEdges.First()), Standard_True)))
+    {
+      const TopoDS_Shape aEdge = aEdges.First();
+      aEdges.First() = aEdges.Last();
+      aEdges.Last() = aEdge;
+    }
+  }
+
+  // Calculate the edge order.
+  TopTools_ListOfShape* aEdges = &aVertexToEdges.ChangeFromIndex(aVN);
+  while (!aEdges->IsEmpty())
+  {
+    const TopoDS_Edge aEdge = TopoDS::Edge(aEdges->First());
+    aEdges->RemoveFirst();
+    myEdges.push_back(aEdge);
+    int aVN2 = aVertexToEdges.FindIndex(TopExp::FirstVertex(aEdge));
+    if (aVN2 == aVN)
+    {
+      aVN2 = aVertexToEdges.FindIndex(TopExp::LastVertex(aEdge));
+    }
+    aVN = aVN2;
+
+    aEdges = &aVertexToEdges.ChangeFromIndex(aVN2);
+    const TopoDS_Edge aEdge2 = TopoDS::Edge(aEdges->First());
+    if (aEdge2.IsEqual(aEdge))
+    {
+      aEdges->RemoveFirst();
+    }
+    else
+    {
+      aEdges->Clear();
+      aEdges->Append(aEdge2);
+    }
+  }
+
+  // Check for connectedness and free vertex.
+  return aVCount - myEdges.size() == (isClosed ? 0 : 1);
+}
+
+TopoDS_Wire HYDROData_TopoCurve::Wire() const
+{
+  TopoDS_Wire aWire;
+  BRep_Builder aBulder;
+  aBulder.MakeWire(aWire);
+  std::list<TopoDS_Edge>::const_iterator aEItLast = myEdges.end();
+  std::list<TopoDS_Edge>::const_iterator aEIt = myEdges.begin();
+  for (; aEIt != aEItLast; ++aEIt)
+  {
+    aBulder.Add(aWire, *aEIt);
+  }
+  return aWire;
+}
+
+void HYDROData_TopoCurve::Cut(
+  const std::list<TopoDS_Edge>::iterator& theEdgePosition,
+  const double theParameter,
+  HYDROData_TopoCurve& theCurve)
+{
+  // Locate the edge.
+  std::list<TopoDS_Edge>::iterator aFirstEIt = myEdges.begin();
+  std::list<TopoDS_Edge>::iterator aEIt = aFirstEIt;
+  for (; aEIt != theEdgePosition; ++aEIt);
+
+  // Cut the edge.
+  TopoDS_Edge aEdge = *aEIt;
+  BRepAdaptor_Curve aCurve(aEdge);
+  int aParamI = -1;
+  const double aEdgeEndParams[] =
+    {aCurve.FirstParameter(), aCurve.LastParameter()};
+  if (Abs(theParameter - aEdgeEndParams[0]) < Precision::PConfusion())
+  {
+    aParamI = 0;
+  }
+  else if (Abs(theParameter - aEdgeEndParams[1]) < Precision::PConfusion())
+  {
+    aParamI = 1;
+  }
+  const TopAbs_Orientation aOrient = aEdge.Orientation();
+  if (aOrient == TopAbs_REVERSED)
+  {
+    aParamI ^= 1;
+  }
+  if (aParamI < 0)
+  {
+    aEdge.Orientation(TopAbs_FORWARD);
+    TopoDS_Vertex aSplitV1, aSplitV2;
+    BRep_Builder().MakeVertex(
+      aSplitV1, aCurve.Value(theParameter), Precision::Confusion());
+    BRep_Builder().MakeVertex(
+      aSplitV2, aCurve.Value(theParameter), Precision::Confusion());
+    TopoDS_Edge aEParts[] = {
+      ShapeBuild_Edge().CopyReplaceVertices(aEdge, TopoDS_Vertex(),
+        TopoDS::Vertex(aSplitV1.Oriented(TopAbs_REVERSED))),
+      ShapeBuild_Edge().CopyReplaceVertices(aEdge, aSplitV2, TopoDS_Vertex())};
+    ShapeBuild_Edge().CopyPCurves(aEParts[0], aEdge);
+    ShapeBuild_Edge().CopyPCurves(aEParts[1], aEdge);
+    BRep_Builder().SameRange(aEParts[0], Standard_False);
+    BRep_Builder().SameRange(aEParts[1], Standard_False);
+    BRep_Builder().SameParameter(aEParts[0], Standard_False);
+    BRep_Builder().SameParameter(aEParts[1], Standard_False);
+    ShapeAnalysis_TransferParametersProj aSATPP(aEdge, TopoDS_Face());
+    aSATPP.SetMaxTolerance(Precision::Confusion());
+    aSATPP.TransferRange(aEParts[0],
+      aEdgeEndParams[0], theParameter, Standard_False);
+    aSATPP.TransferRange(aEParts[1],
+      theParameter, aEdgeEndParams[1], Standard_False);
+    aEParts[0].Orientation(aOrient);
+    aEParts[1].Orientation(aOrient);
+
+    const int aFirstPI = (aOrient != TopAbs_REVERSED) ? 0 : 1;
+    *aEIt = aEParts[aFirstPI];
+    InsertAfter(aEIt, aEParts[1 - aFirstPI], myEdges);
+    ++aEIt;
+  }
+  else if (aParamI > 0)
+  {
+    ++aEIt;
+  }
+
+  // Calculate the curve parts.
+  std::list<TopoDS_Edge>::iterator aLastEIt = myEdges.end();
+  if (aEIt != aFirstEIt && aEIt != aLastEIt)
+  {
+    std::list<TopoDS_Edge>* aEdges = !IsClosed() ? &theCurve.myEdges : &myEdges;
+    aEdges->splice(aEdges->begin(), myEdges, aEIt, aLastEIt);
+  }
+}
+
+void HYDROData_TopoCurve::Cut(
+  const std::list<TopoDS_Edge>::const_iterator& theEdgePosition,
+  const double theParameter,
+  HYDROData_TopoCurve& theCurve1,
+  HYDROData_TopoCurve& theCurve2) const
+{
+  theCurve1 = *this;
+  std::list<TopoDS_Edge>::const_iterator aEPos = myEdges.begin();
+  std::list<TopoDS_Edge>::iterator aEPos1 = theCurve1.myEdges.begin();
+  for (; aEPos != theEdgePosition; ++aEPos1, ++aEPos);
+  theCurve1.Cut(aEPos1, theParameter, theCurve2);
+}
+
+void HYDROData_TopoCurve::Cut(
+  const std::deque<std::list<double> >& theParameters,
+  std::deque<HYDROData_TopoCurve>& theCurves) const
+{
+  HYDROData_TopoCurve aCurves[2];
+  aCurves[0] = *this;
+  int aCI = 0;
+  std::list<TopoDS_Edge>::iterator aEIt = aCurves[0].myEdges.begin();
+  std::deque<std::list<double> >::const_iterator aPLIt = theParameters.begin();
+  for (std::deque<std::list<double> >::const_iterator aLastPLIt =
+    theParameters.end(); aPLIt != aLastPLIt; ++aEIt, ++aPLIt)
+  {
+    for (Iterator<std::list<double>, std::list<double>::const_iterator> aPIt(
+      *aPLIt, (aEIt->Orientation() != TopAbs_REVERSED)); aPIt.More(); ++aPIt)
+    {
+      const int aCI1 = 1 - aCI;
+      aCurves[aCI].Cut(aEIt, **aPIt, aCurves[aCI1]);
+      if (!aCurves[aCI1].IsEmpty())
+      {
+        theCurves.push_back(HYDROData_TopoCurve());
+        theCurves.back().append(aCurves[aCI]);
+        aEIt = aCurves[aCI1].myEdges.begin();
+        aCI = aCI1;
+      }
+      else
+      {
+        aEIt = aCurves[aCI].myEdges.begin();
+      }
+    }
+  }
+  theCurves.push_back(aCurves[aCI]);
+}
+
+double HYDROData_TopoCurve::Project(
+  const gp_XYZ& thePoint,
+  std::list<TopoDS_Edge>::const_iterator& theEdgeIterator,
+  double& theParameter) const
+{
+  double aMinSqDist = DBL_MAX;
+  std::list<TopoDS_Edge>::const_iterator aEIt = myEdges.begin();
+  std::list<TopoDS_Edge>::const_iterator aLastEIt = myEdges.end();
+  for (; aEIt != aLastEIt; ++aEIt)
+  {
+    double aParam;
+    const double aSqDist = ProjectPointToEdge(thePoint, *aEIt, aParam);
+    if (aMinSqDist > aSqDist)
+    {
+      aMinSqDist = aSqDist;
+      theEdgeIterator = aEIt;
+      theParameter = aParam;
+    }
+  }
+  return aMinSqDist;
+}
+
+int HYDROData_TopoCurve::Intersect(
+  const TopoDS_Wire& theWire,
+  std::deque<std::list<double> >& theParameters) const
+{
+  int aIntCount = 0;
+  theParameters.resize(myEdges.size());
+  std::list<TopoDS_Edge>::const_iterator aEIt = myEdges.begin();
+  std::list<TopoDS_Edge>::const_iterator aLastEIt = myEdges.end();
+  std::deque<std::list<double> >::iterator aPIt = theParameters.begin();
+  for (; aEIt != aLastEIt; ++aPIt, ++aEIt)
+  {
+    const TopoDS_Edge& aEdge = *aEIt;
+    std::list<double>& aParams = *aPIt;
+    TopExp_Explorer aEIt2(theWire, TopAbs_EDGE);
+    for (; aEIt2.More(); aEIt2.Next())
+    {
+      aIntCount += IntersectEdge(aEdge,TopoDS::Edge(aEIt2.Current()), aParams);
+    }
+  }
+  return aIntCount;
+}
+
+void HYDROData_TopoCurve::CloseCurve()
+{
+  const TopoDS_Vertex aVertex = TopoDS::Vertex(TopExp::LastVertex(
+    myEdges.back(), Standard_True).Oriented(TopAbs_FORWARD));
+  TopoDS_Edge& aEdge = myEdges.front();
+  const TopoDS_Edge aForwardEdge = TopoDS::Edge(aEdge.Oriented(TopAbs_FORWARD));
+  aEdge = TopoDS::Edge(ShapeBuild_Edge().CopyReplaceVertices(
+    aForwardEdge, aVertex, TopoDS_Vertex()).Oriented(aEdge.Orientation()));
+}
+
+void HYDROData_TopoCurve::Merge(
+  const int thePosition, HYDROData_TopoCurve& theCurve)
+{
+  if (thePosition == 0)
+  {
+    const TopoDS_Vertex aVertex = TopoDS::Vertex(TopExp::LastVertex(
+      theCurve.myEdges.back(), Standard_True).Oriented(TopAbs_FORWARD));
+    TopoDS_Edge& aEdge = myEdges.front();
+    aEdge = TopoDS::Edge(ShapeBuild_Edge().CopyReplaceVertices(
+        TopoDS::Edge(aEdge.Oriented(TopAbs_FORWARD)), aVertex, TopoDS_Vertex()).
+      Oriented(aEdge.Orientation()));
+    prepend(theCurve);
+  }
+  else
+  {
+    const TopoDS_Vertex aVertex = TopoDS::Vertex(TopExp::FirstVertex(
+      theCurve.myEdges.front(), Standard_True).Oriented(TopAbs_REVERSED));
+    TopoDS_Edge& aEdge = myEdges.back();
+    aEdge = TopoDS::Edge(ShapeBuild_Edge().CopyReplaceVertices(
+        TopoDS::Edge(aEdge.Oriented(TopAbs_FORWARD)), TopoDS_Vertex(), aVertex).
+      Oriented(aEdge.Orientation()));
+    append(theCurve);
+  }
+}
+
+void HYDROData_TopoCurve::Merge(
+  const double theTolerance, std::deque<HYDROData_TopoCurve>& theCurves)
+{
+  // Process the curve closeness.
+  const double aSqTol = theTolerance * theTolerance;
+  const gp_XYZ aPs[] = {
+    BRep_Tool::Pnt(TopExp::FirstVertex(myEdges.front(), Standard_True)).XYZ(),
+    BRep_Tool::Pnt(TopExp::LastVertex(myEdges.back(), Standard_True)).XYZ()};
+  bool isClosed = IsClosed();
+  if (!isClosed && (aPs[0] - aPs[1]).SquareModulus() <= aSqTol)
+  {
+    CloseCurve();
+    isClosed = true;
+  }
+
+  // Find the merge places.
+  HYDROData_TopoCurve* aCurves[] = {NULL, NULL};
+  int aOrder = 0;
+  if (!isClosed)
+  {
+    std::deque<HYDROData_TopoCurve>::iterator aCIt = theCurves.begin();
+    std::deque<HYDROData_TopoCurve>::iterator aLastCIt = theCurves.end();
+    for (; aCIt != aLastCIt; ++aCIt)
+    {
+      HYDROData_TopoCurve& aCurve = *aCIt;
+      if (aCurve.IsEmpty() || aCurve.IsClosed())
+      {
+        continue;
+      }
+
+      const gp_XYZ aP1 = BRep_Tool::Pnt(
+        TopExp::FirstVertex(aCurve.myEdges.front(), Standard_True)).XYZ();
+      if (aCurves[0] == NULL && (aPs[1] - aP1).SquareModulus() <= aSqTol)
+      {
+        aCurves[0] = &aCurve;
+      }
+
+      const gp_XYZ aP2 = BRep_Tool::Pnt(
+        TopExp::LastVertex(aCurve.myEdges.back(), Standard_True)).XYZ();
+      if (aCurves[1] == NULL && (aPs[0] - aP2).SquareModulus() <= aSqTol)
+      {
+        aCurves[1] = &aCurve;
+        aOrder = (aCurves[0] == NULL) ? 1 : 0;
+      }
+    }
+  }
+
+  if (aCurves[0] == NULL && aCurves[1] == NULL)
+  {
+    theCurves.push_back(HYDROData_TopoCurve());
+    theCurves.back().append(*this);
+  }
+  else if (aCurves[1] == NULL)
+  {
+    aCurves[0]->Merge(0, *this);
+  }
+  else if (aCurves[0] == NULL)
+  {
+    aCurves[1]->Merge(1, *this);
+  }
+  else
+  {
+    aCurves[aOrder]->Merge(aOrder, *this);
+    if (aCurves[0] != aCurves[1])
+    {
+      aCurves[aOrder]->Merge(aOrder, *aCurves[1 - aOrder]);
+    }
+    else
+    {
+      aCurves[aOrder]->CloseCurve();
+    }
+  }
+}
+
+bool HYDROData_TopoCurve::Connect(
+  const Standard_Real theTolerance, std::deque<HYDROData_TopoCurve>& theCurves)
+{
+  const double aSqTol = theTolerance * theTolerance;
+  const gp_XYZ aPs[] = {
+    BRep_Tool::Pnt(TopExp::FirstVertex(myEdges.front(), Standard_True)).XYZ(),
+    BRep_Tool::Pnt(TopExp::LastVertex(myEdges.back(), Standard_True)).XYZ()};
+  bool isClosed = IsClosed();
+  if (!isClosed && (aPs[0] - aPs[1]).SquareModulus() <= aSqTol)
+  {
+    CloseCurve();
+    isClosed = true;
+  }
+
+  if (!isClosed)
+  {
+    std::deque<HYDROData_TopoCurve>::iterator aCIt = theCurves.begin();
+    std::deque<HYDROData_TopoCurve>::iterator aLastCIt = theCurves.end();
+    for (; aCIt != aLastCIt; ++aCIt)
+    {
+      HYDROData_TopoCurve& aCurve2 = *aCIt;
+      if (aCurve2.IsEmpty() || aCurve2.IsClosed())
+      {
+        continue;
+      }
+
+      const TopoDS_Edge* aEdges2[] =
+        {&aCurve2.myEdges.front(), &aCurve2.myEdges.back()};
+      const gp_XYZ aPs2[] = {
+        BRep_Tool::Pnt(TopExp::FirstVertex(*aEdges2[0], Standard_True)).XYZ(),
+        BRep_Tool::Pnt(TopExp::LastVertex(*aEdges2[1], Standard_True)).XYZ()};
+      const double aSqDists[] =
+        {(aPs[1] - aPs2[0]).SquareModulus(), (aPs[0] - aPs2[1]).SquareModulus()};
+      const int aOrder = (aSqDists[0] <= aSqDists[1]) ? 0 : 1;
+      if (aSqDists[aOrder] > aSqTol)
+      {
+        const TopoDS_Edge& aEdge =
+          (aOrder == 0) ? myEdges.back() : myEdges.front();
+        const gp_XYZ aPs3[] = {aPs[1 - aOrder], aPs2[aOrder]};
+        const gp_XYZ aTs[] =
+          {Tangent(aEdge, 1 - aOrder), Tangent(*aEdges2[aOrder], aOrder)};
+        Handle(Geom_BSplineCurve) aBSpline;
+        if (!Interpolate(aPs3[aOrder], aPs3[1 - aOrder],
+          aTs[aOrder], aTs[1 - aOrder], aBSpline))
+        {
+          return false;
+        }
+
+        HYDROData_TopoCurve aECurve = BRepBuilderAPI_MakeEdge(aBSpline);
+        aCurve2.Merge(aOrder, aECurve);
+      }
+      aCurve2.Merge(aOrder, *this);
+      if (aSqDists[1 - aOrder] <= aSqTol)
+      {
+        aCurve2.CloseCurve();
+      }
+      return true;
+    }
+  }
+
+  theCurves.push_back(HYDROData_TopoCurve());
+  theCurves.back().append(*this);
+  return true;
+}
+
+bool HYDROData_TopoCurve::BSplinePiecewiseCurve(
+  const double theDeflection, HYDROData_TopoCurve& theCurve) const
+{
+  std::list<TopoDS_Edge>::const_iterator aLastEIt = myEdges.end();
+  std::list<TopoDS_Edge>::const_iterator aEIt = myEdges.begin();
+  TopoDS_Vertex aEndVertex;
+  TopoDS_Edge aPrevEdge;
+  for (; aEIt != aLastEIt; ++aEIt)
+  {
+    Handle(Geom_BSplineCurve) aBSpline =
+      ::BSpline(BRepAdaptor_Curve(*aEIt), theDeflection);
+    if (aBSpline.IsNull())
+    {
+      return false;
+    }
+
+    if (aEIt->Orientation() == TopAbs_REVERSED)
+    {
+      aBSpline->Reverse();
+    }
+
+    TopoDS_Edge aEdge;
+    BRep_Builder().MakeEdge(aEdge, aBSpline, Precision::Confusion());
+    TopoDS_Vertex aVertex;
+    BRep_Builder().MakeVertex(aVertex,
+      aBSpline->Value(aBSpline->FirstParameter()), Precision::Confusion());
+    if (!aPrevEdge.IsNull())
+    {
+      BRep_Builder().Add(aPrevEdge, aVertex.Oriented(TopAbs_REVERSED));
+    }
+    else
+    {
+      aEndVertex = aVertex;
+    }
+    BRep_Builder().Add(aEdge, aVertex);
+    theCurve.myEdges.push_back(aEdge);
+    aPrevEdge = aEdge;
+  }
+
+  if (!IsClosed())
+  {
+    BRepAdaptor_Curve aCurve(aPrevEdge);
+    BRep_Builder().MakeVertex(aEndVertex,
+      aCurve.Value(aCurve.LastParameter()), Precision::Confusion());
+  }
+  BRep_Builder().Add(aPrevEdge, aEndVertex.Oriented(TopAbs_REVERSED));
+  return true;
+}
+
+bool HYDROData_TopoCurve::ValuesInKnots(std::deque<gp_XYZ>& theValues) const
+{
+  std::list<TopoDS_Edge>::const_iterator aLastEIt = myEdges.end();
+  std::list<TopoDS_Edge>::const_iterator aEIt = myEdges.begin();
+  for (; aEIt != aLastEIt; ++aEIt)
+  {
+    Handle(Geom_BSplineCurve) aCurve;
+    {
+      TopLoc_Location aLoc;
+      double aParams[2];
+      aCurve = Handle(Geom_BSplineCurve)::
+        DownCast(BRep_Tool::Curve(*aEIt, aLoc, aParams[0], aParams[1]));
+      if (!aLoc.IsIdentity() || aEIt->Orientation() != TopAbs_FORWARD ||
+        aCurve.IsNull())
+      {
+        return false;
+      }
+    }
+
+    for (int aNbKnots = aCurve->NbKnots(), aKN = 1; aKN < aNbKnots; ++aKN)
+    {
+      theValues.push_back(aCurve->Value(aCurve->Knot(aKN)).XYZ());
+    }
+  }
+
+  if (!IsClosed())
+  {
+    TopLoc_Location aLoc;
+    double aParams[2];
+    Handle(Geom_Curve) aCurve =
+      BRep_Tool::Curve(myEdges.back(), aLoc, aParams[0], aParams[1]);
+    theValues.push_back(aCurve->Value(aParams[1]).XYZ());
+  }
+  return true;
+}
diff --git a/src/HYDROData/HYDROData_TopoCurve.h b/src/HYDROData/HYDROData_TopoCurve.h
new file mode 100644 (file)
index 0000000..abafe89
--- /dev/null
@@ -0,0 +1,179 @@
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef HYDRODATA_TOPOCURVE_H
+#define HYDRODATA_TOPOCURVE_H
+
+#include <deque>
+#include <Handle_Geom_BSplineCurve.hxx>
+#include <HYDROData.h>
+#include <list>
+#include <TopExp.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Vertex.hxx>
+
+class TopoDS_Wire;
+
+//! The type represents a 1 monifold connected topo curve
+//! with forward orientation.
+class HYDROData_TopoCurve
+{
+public:
+  //! The default computer.
+  HYDROData_TopoCurve() {}
+
+  //! Constructs the curve from the edge.
+  HYDROData_TopoCurve(const TopoDS_Edge& theEdge) {myEdges.push_back(theEdge);}
+
+  //! Initializes the curve by the wire.
+  //! Returns 'false' if the wire is not 1 monifold or
+  //! is disconnected or is empty.
+  HYDRODATA_EXPORT bool Initialize(const TopoDS_Wire& theWire);
+
+  //! Converts the curve to the wire.
+  HYDRODATA_EXPORT TopoDS_Wire Wire() const;
+
+  //! Returns 'true' if the curve has no edges.
+  bool IsEmpty() const {return myEdges.empty();}
+
+  //! Returns 'true' whether the curve is closed.
+  bool IsClosed() const
+  {
+    return TopExp::LastVertex(myEdges.back(), Standard_True).
+        IsSame(TopExp::FirstVertex(myEdges.front(), Standard_True)) ==
+      Standard_True;
+  }
+
+  //! Returns the curve edges.
+  const std::list<TopoDS_Edge>& Edges() const {return myEdges;}
+
+  //! Cuts the curve in the given parameter of the given edge and
+  //! fills the cut part.
+  HYDRODATA_EXPORT void Cut(
+    const std::list<TopoDS_Edge>::iterator& theEdgePosition,
+    const double theParameter,
+    HYDROData_TopoCurve& theCurve);
+
+  //! Cuts the curve in the given parameter of the given edge and
+  //! fills the cut parts.
+  HYDRODATA_EXPORT void Cut(
+      const std::list<TopoDS_Edge>::const_iterator& theEdgePosition,
+      const double theParameter,
+      HYDROData_TopoCurve& theCurve1,
+      HYDROData_TopoCurve& theCurve2) const;
+
+  //! Cuts the curve at the parameters.
+  //! Each parameter vector list corresponds to the curve edge and
+  //! is ordered in the ascending order.
+  HYDRODATA_EXPORT void Cut(
+    const std::deque<std::list<double> >& theParameters,
+    std::deque<HYDROData_TopoCurve>& theCurves) const;
+
+  //! Projects the point to the nearest point of the curve.
+  //! Fills the iterator of the edge and
+  //! the parameter on the edge for the projection.
+  //! Returns the square distance from the point to the projection.
+  HYDRODATA_EXPORT double Project(
+    const gp_XYZ& thePoint,
+    std::list<TopoDS_Edge>::const_iterator& theEdgeIterator,
+    double& theParameter) const;
+
+  //! Adds the intersection parameters of the curve with the wire to the vector.
+  HYDRODATA_EXPORT int Intersect(
+    const TopoDS_Wire& theWire,
+    std::deque<std::list<double> >& theParameters) const;
+
+  //! Replaces the first vertex by the last one.
+  HYDRODATA_EXPORT void CloseCurve();
+
+  //! Topologically extends the curve by the parameter at the position:
+  //! 0 - start, 1 - end.
+  HYDRODATA_EXPORT void Merge(
+    const int thePosition, HYDROData_TopoCurve& theCurve);
+
+  //! Topologically merges the curve to the curves.
+  HYDRODATA_EXPORT void Merge(
+    const double theTolerance, std::deque<HYDROData_TopoCurve>& theCurves);
+
+  //! Topologically merges the wire curve to the curves.
+  //! Returns 'false' if the wire is not a curve.
+  static bool Merge(
+    const double theTolerance,
+    const TopoDS_Wire& theWire,
+    std::deque<HYDROData_TopoCurve>& theCurves)
+  {
+    HYDROData_TopoCurve aCurve;
+    const bool aResult = aCurve.Initialize(theWire);
+    if (aResult)
+    {
+      aCurve.Merge(theTolerance, theCurves);
+    }
+    return aResult;
+  }
+
+  //! Topologically connects the curve to the first open one of the curves.
+  //! If the gap between the curve and the first open curve is more than the
+  //! tolerance then the gap is smoothly filled by a curve.
+  //! It is assumed that only one of the parameter curves may be open.
+  //! If the curve is closed then it is added to the curves.
+  HYDRODATA_EXPORT bool Connect(
+    const Standard_Real theTolerance,
+    std::deque<HYDROData_TopoCurve>& theCurves);
+
+  //! Works by the same way as the above method.
+  static bool Connect(
+    const Standard_Real theTolerance,
+    const TopoDS_Wire& theWire,
+    std::deque<HYDROData_TopoCurve>& theCurves)
+  {
+    HYDROData_TopoCurve aCurve;
+    if (!aCurve.Initialize(theWire))
+    {
+      return aCurve.Connect(theTolerance, theCurves);
+    }
+
+    return false;
+  }
+
+  //! Creates a B-spline piecewise curve corresponding to the curve
+  //! and using the deflection.
+  HYDRODATA_EXPORT bool 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;
+
+private:
+  //! Transfers the edges of the parameter to this curve end.
+  void append(HYDROData_TopoCurve& theCurve)
+    {myEdges.splice(myEdges.end(), theCurve.myEdges);}
+
+  //! Transfers the edges of the parameter to this curve start.
+  void prepend(HYDROData_TopoCurve& theCurve)
+    {myEdges.splice(myEdges.begin(), theCurve.myEdges);}
+
+  std::list<TopoDS_Edge> myEdges; //!< The ordered curve edges.
+};
+
+#endif
index 745cf67dc6259e75a94b3978857d41d895e8e577..31c3ab2de5a44174b2acaaf9b324f5e7840040d4 100755 (executable)
@@ -25,6 +25,8 @@
 #include "HYDROGUI_UpdateFlags.h"
 
 #include <HYDROData_Document.h>
+#include <HYDROData_PolylineOperator.h>
+#include <HYDROData_TopoCurve.h>
 
 #include <CurveCreator_Curve.hxx>
 #include <CurveCreator_Displayer.hxx>
@@ -44,6 +46,9 @@
 #include <SUIT_MessageBox.h>
 #include <SUIT_Desktop.h>
 
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_Wire.hxx>
+
 //static int ZValueIncrement = 0;
 
 HYDROGUI_PolylineOp::HYDROGUI_PolylineOp( HYDROGUI_Module* theModule, bool theIsEdit )
@@ -148,27 +153,75 @@ void HYDROGUI_PolylineOp::startOperation()
     NCollection_Sequence<bool>                              aSectClosures;
     myEditedObject->GetSections( aSectNames, aSectTypes, aSectClosures );
 
-    for ( int i = 1, n = aSectNames.Size(); i <= n; ++i )
+    if (!aSectNames.IsEmpty())
     {
-      QString aSectName = HYDROGUI_Tool::ToQString( aSectNames.Value( i ) );
-      HYDROData_PolylineXY::SectionType aSectType = aSectTypes.Value( i );
-      bool aSectClosure = aSectClosures.Value( i );
+      for ( int i = 1, n = aSectNames.Size(); i <= n; ++i )
+      {
+        QString aSectName = HYDROGUI_Tool::ToQString( aSectNames.Value( i ) );
+        HYDROData_PolylineXY::SectionType aSectType = aSectTypes.Value( i );
+        bool aSectClosure = aSectClosures.Value( i );
+
+        CurveCreator::SectionType aCurveType = CurveCreator::Polyline;
+        if( aSectType == HYDROData_PolylineXY::SECTION_SPLINE )
+          aCurveType = CurveCreator::Spline;
 
-      CurveCreator::SectionType aCurveType = CurveCreator::Polyline;
-      if( aSectType == HYDROData_PolylineXY::SECTION_SPLINE )
-        aCurveType = CurveCreator::Spline;
+        CurveCreator::Coordinates aCurveCoords;
 
-      CurveCreator::Coordinates aCurveCoords;
+        HYDROData_PolylineXY::PointsList aSectPointsList =
+          myEditedObject->GetPoints( i - 1 );
+        for (int k = 1, aNbPoints = aSectPointsList.Size(); k <= aNbPoints; ++k)
+        {
+          const HYDROData_PolylineXY::Point& aSectPoint =
+            aSectPointsList.Value( k );
+          aCurveCoords.push_back( aSectPoint.X() );
+          aCurveCoords.push_back( aSectPoint.Y() );
+        }
 
-      HYDROData_PolylineXY::PointsList aSectPointsList = myEditedObject->GetPoints( i - 1 );
-      for ( int k = 1, aNbPoints = aSectPointsList.Size(); k <= aNbPoints; ++k )
+        myCurve->addSectionInternal( aSectName.toStdString(),
+          aCurveType, aSectClosure, aCurveCoords );
+      }
+    }
+    else
+    {
+      std::deque<CurveCreator::Coordinates> aPs;
+      std::deque<bool> isCloseds;
+      std::vector<TopoDS_Wire> aWires;
+      HYDROData_PolylineOperator::GetWires(myEditedObject, aWires);
+      const int aSCount = aWires.size();
+      bool isError = false;
+      for (int aSI = 0; aSI < aSCount; ++aSI)
       {
-        const HYDROData_PolylineXY::Point& aSectPoint = aSectPointsList.Value( k );
-        aCurveCoords.push_back( aSectPoint.X() );
-        aCurveCoords.push_back( aSectPoint.Y() );
+        HYDROData_TopoCurve aCurve, aCurve2;
+        std::deque<gp_XYZ> aPs2;
+        if (!aCurve.Initialize(aWires[aSI]) ||
+          !aCurve.BSplinePiecewiseCurve(Precision::Confusion(), aCurve2) ||
+          !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)
+        {
+          const gp_XYZ aP = aPs2[aPI];
+          aPs3.push_back(aP.X());
+          aPs3.push_back(aP.Y());
+        }
+        isCloseds.push_back(aCurve.IsClosed());
       }
 
-      myCurve->addSectionInternal( aSectName.toStdString(), aCurveType, aSectClosure, aCurveCoords );
+      if (!isError)
+      {
+        const TCollection_AsciiString aNamePrefix = "Section_";
+        for (int aSI = 0; aSI < aSCount; ++aSI)
+        {
+          myCurve->addSectionInternal((aNamePrefix + (aSI + 1)).ToCString(),
+            CurveCreator::Spline, isCloseds[aSI], aPs[aSI]);
+        }
+      }
     }
 
     aPolylineName = myEditedObject->GetName();