]> SALOME platform Git repositories - modules/hydro.git/commitdiff
Salome HOME
Algorithms to merge sections were created.
authorabk <abk@opencascade.com>
Wed, 1 Jul 2015 18:21:56 +0000 (21:21 +0300)
committerabk <abk@opencascade.com>
Wed, 1 Jul 2015 18:21:56 +0000 (21:21 +0300)
src/HYDROData/HYDROData_PolylineOperator.cxx
src/HYDROData/HYDROData_PolylineOperator.h

index acec03bc92e29fc11ce8ba12797f2a41b99bdb54..ac75dcd8dc2f9e0a453219a1d0937777355f9b6e 100644 (file)
 #include <HYDROData_Document.h>
 #include <BRepAdaptor_Curve.hxx>
 #include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
 #include <BRepBuilderAPI_MakeEdge2d.hxx>
+#include <BRepBuilderAPI_MakeEdge.hxx>
 #include <BRepBuilderAPI_MakeWire.hxx>
 #include <Extrema_ExtCC.hxx>
 #include <Extrema_ExtPC.hxx>
+#include <GeomAPI_Interpolate.hxx>
 #include <NCollection_Vector.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 <TopoDS.hxx>
 #include <TopoDS_Edge.hxx>
 #include <TopoDS_Wire.hxx>
@@ -68,9 +74,10 @@ static TopoDS_Edge ReplaceVertex(
   return TopoDS::Edge(aNewEdge.Oriented(aOrient));
 }
 
+template<typename TCurveType>
 static Standard_Boolean WireToCurve(
   const TopoDS_Wire& theWire,
-  NCollection_Vector<TopoDS_Edge>& theEdges,
+  TCurveType& theCurve,
   Standard_Boolean& theIsClosed)
 {
   TopTools_IndexedDataMapOfShapeListOfShape aVertexToEdges;
@@ -119,7 +126,7 @@ static Standard_Boolean WireToCurve(
   {
     const TopoDS_Edge aEdge = TopoDS::Edge(aEdges->First());
     aEdges->RemoveFirst();
-    theEdges.Append(aEdge);
+    theCurve.Append(aEdge);
     Standard_Integer aVN2 =
       aVertexToEdges.FindIndex(TopExp::FirstVertex(aEdge));
     if (aVN2 == aVN)
@@ -140,17 +147,16 @@ static Standard_Boolean WireToCurve(
       aEdges->Append(aEdge);
     }
   }
-  return (!theIsClosed && theEdges.Size() == aVCount - 1) ||
-    (theIsClosed && theEdges.Size() == aVCount);
+  return (!theIsClosed && theCurve.Size() == aVCount - 1) ||
+    (theIsClosed && theCurve.Size() == aVCount);
 }
 
-static void CurveToWire(
-  const NCollection_Vector<TopoDS_Edge>& theEdges, TopoDS_Wire& theWire)
+template<typename TCurveType>
+static void CurveToWire(const TCurveType& theCurve, TopoDS_Wire& theWire)
 {
   BRep_Builder aBulder;
   aBulder.MakeWire(theWire);
-  NCollection_Vector<TopoDS_Edge>::Iterator aEIt(theEdges);
-  for (; aEIt.More(); aEIt.Next())
+  for (TCurveType::Iterator aEIt(theCurve); aEIt.More(); aEIt.Next())
   {
     aBulder.Add(theWire, aEIt.Value());
   }
@@ -470,6 +476,262 @@ static Standard_Integer IntersectCurve(
   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,
@@ -518,29 +780,43 @@ bool HYDROData_PolylineOperator::Merge( const Handle( HYDROData_Document )& theD
                                         bool isConnectByNewSegment,
                                         double theTolerance )
 {
-  TopoDS_Shape aMergedPolyline;
-
-  int f = thePolylines.Lower(), l = thePolylines.Upper();
-  for( int i=f; i<=l; i++ )
+  NCollection_Vector<NCollection_Sequence<TopoDS_Edge> > aMergedCurves;
+  HYDROData_SequenceOfObjects::Iterator aPIt(thePolylines);
+  for (; aPIt.More(); aPIt.Next())
   {
-    Handle( HYDROData_PolylineXY ) aPolyline = Handle( HYDROData_PolylineXY )::DownCast( thePolylines.Value( i ) );
-    std::vector<TopoDS_Wire> aCurves = GetWires( aPolyline );
-    for( int j=0, m=aCurves.size(); j<m; j++ )
-      if( !Merge( aMergedPolyline, aCurves[j], isConnectByNewSegment, theTolerance ) )
+    Handle(HYDROData_PolylineXY) aPolyline =
+      Handle(HYDROData_PolylineXY)::DownCast(aPIt.Value());
+    std::vector<TopoDS_Wire> aWires = GetWires(aPolyline);
+    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);
+      if (!aResult)
+      {
         return false;
+      }
+    }
   }
 
-  std::vector<TopoDS_Shape> aShapes( 1 );
-  aShapes[0] = aMergedPolyline;
-  CreatePolylines( theDoc, theName, aShapes, false );
-
-  return true;
-}
+  TopoDS_Compound aWireSet;
+  BRep_Builder aBuilder;
+  aBuilder.MakeCompound(aWireSet);
+  for (NCollection_Vector<NCollection_Sequence<TopoDS_Edge> >::Iterator
+    aCIt(aMergedCurves); aCIt.More(); aCIt.Next())
+  {
+    if (!aCIt.Value().IsEmpty())
+    {
+      TopoDS_Wire aWire;
+      CurveToWire(aCIt.Value(), aWire);
+      aBuilder.Add(aWireSet, aWire);
+    }
+  }
 
-bool HYDROData_PolylineOperator::Merge( TopoDS_Shape& theShape, const TopoDS_Wire& theWire, 
-                                        bool isConnectByNewSegment, double theTolerance )
-{
-  //TODO
+  std::vector<TopoDS_Shape> aPolylines(1);
+  aPolylines[0] = aWireSet;
+  CreatePolylines(theDoc, theName, aPolylines, false);
   return true;
 }
 
@@ -573,7 +849,7 @@ bool HYDROData_PolylineOperator::split( const Handle( HYDROData_Document )& theD
     }
 
     NCollection_Vector<NCollection_Sequence<Standard_Real> > aParams;
-    aParams.SetValue(aPSCount - 1, NCollection_Sequence<Standard_Real>());
+    aParams.SetValue(aCurve.Size() - 1, NCollection_Sequence<Standard_Real>());
     for (int aTSI = 0; aTSI < aTSCount; ++aTSI)
     {
       IntersectCurve(aCurve, aToolCurves[aTSI], aParams);
@@ -715,32 +991,6 @@ std::vector<TopoDS_Shape> HYDROData_PolylineOperator::Split( const TopoDS_Wire&
   return aResult;
 }
 
-std::vector<TopoDS_Shape> HYDROData_PolylineOperator::Split( const TopoDS_Wire& theWire,
-                                                             const TopoDS_Wire& theTool,
-                                                             double theTolerance )
-{
-  std::vector<TopoDS_Shape> aResult;
-  NCollection_Vector<TopoDS_Edge> aWEdges, aTEdges;
-  Standard_Boolean aIsWClosed, aIsTClosed;
-  if (!WireToCurve(theWire, aWEdges, aIsWClosed) ||
-    !WireToCurve(theTool, aTEdges, aIsTClosed))
-  {
-    return aResult;
-  }
-
-
-  //TODO
-  return aResult;
-}
-
-std::vector<TopoDS_Shape> HYDROData_PolylineOperator::Split( const std::vector<TopoDS_Wire>& theWires,
-                                                             double theTolerance )
-{
-  std::vector<TopoDS_Shape> aResult;
-  //TODO
-  return aResult;
-}
-
 bool HYDROData_PolylineOperator::CreatePolylines( const Handle( HYDROData_Document )& theDoc,
                                                   const QString& theNamePrefix,
                                                   const std::vector<TopoDS_Shape>& theShapes,
index 3f92f0befff43394b0cdf9c4223241bcbdac71f7..0b0fdceeba7e2220c21eb097dbcb4f26a5723c48 100644 (file)
@@ -58,14 +58,6 @@ protected:
   static std::vector<TopoDS_Shape> Split( const TopoDS_Wire& theWire,
                                           const gp_Pnt2d& thePoint,
                                           double theTolerance );
-  static std::vector<TopoDS_Shape> Split( const TopoDS_Wire& theWire,
-                                          const TopoDS_Wire& theTool,
-                                          double theTolerance );
-  static std::vector<TopoDS_Shape> Split( const std::vector<TopoDS_Wire>& theWires,
-                                          double theTolerance );
-
-  static bool Merge( TopoDS_Shape& theShape, const TopoDS_Wire& theWire, 
-                     bool isConnectByNewSegment, double theTolerance );
 
   static bool CreatePolylines( const Handle( HYDROData_Document )& theDoc,
                                const QString& theNamePrefix,