From a61dd97a28b53099635016ed1effd070cc60d0de Mon Sep 17 00:00:00 2001 From: abk Date: Wed, 1 Jul 2015 21:21:56 +0300 Subject: [PATCH] Algorithms to merge sections were created. --- src/HYDROData/HYDROData_PolylineOperator.cxx | 356 ++++++++++++++++--- src/HYDROData/HYDROData_PolylineOperator.h | 8 - 2 files changed, 303 insertions(+), 61 deletions(-) diff --git a/src/HYDROData/HYDROData_PolylineOperator.cxx b/src/HYDROData/HYDROData_PolylineOperator.cxx index acec03bc..ac75dcd8 100644 --- a/src/HYDROData/HYDROData_PolylineOperator.cxx +++ b/src/HYDROData/HYDROData_PolylineOperator.cxx @@ -20,14 +20,20 @@ #include #include #include +#include #include +#include #include #include #include +#include #include #include #include #include +#include +#include +#include #include #include #include @@ -68,9 +74,10 @@ static TopoDS_Edge ReplaceVertex( return TopoDS::Edge(aNewEdge.Oriented(aOrient)); } +template static Standard_Boolean WireToCurve( const TopoDS_Wire& theWire, - NCollection_Vector& 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& theEdges, TopoDS_Wire& theWire) +template +static void CurveToWire(const TCurveType& theCurve, TopoDS_Wire& theWire) { BRep_Builder aBulder; aBulder.MakeWire(theWire); - NCollection_Vector::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& 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& theCurve) +{ + return TopExp::FirstVertex(theCurve.First(), Standard_True). + IsSame(TopExp::LastVertex(theCurve.Last(), Standard_True)); +} + +static void ExtendCurve( + const Standard_Integer thePosition, + NCollection_Sequence& theCurve, + NCollection_Sequence& 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& theCurve) +{ + NCollection_Sequence 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 >& theMergedCurves) +{ + NCollection_Sequence 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* aCurves[] = {NULL, NULL}; + Standard_Integer aOrder = 0; + for (NCollection_Vector >::Iterator + aCIt(theMergedCurves); aCIt.More(); aCIt.Next()) + { + NCollection_Sequence& 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 >& theMergedCurves) +{ + NCollection_Sequence 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 >::Iterator + aCIt(theMergedCurves); aCIt.More(); aCIt.Next()) + { + NCollection_Sequence& 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 > aMergedCurves; + HYDROData_SequenceOfObjects::Iterator aPIt(thePolylines); + for (; aPIt.More(); aPIt.Next()) { - Handle( HYDROData_PolylineXY ) aPolyline = Handle( HYDROData_PolylineXY )::DownCast( thePolylines.Value( i ) ); - std::vector aCurves = GetWires( aPolyline ); - for( int j=0, m=aCurves.size(); j aWires = GetWires(aPolyline); + for (std::vector::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 aShapes( 1 ); - aShapes[0] = aMergedPolyline; - CreatePolylines( theDoc, theName, aShapes, false ); - - return true; -} + TopoDS_Compound aWireSet; + BRep_Builder aBuilder; + aBuilder.MakeCompound(aWireSet); + for (NCollection_Vector >::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 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 > aParams; - aParams.SetValue(aPSCount - 1, NCollection_Sequence()); + aParams.SetValue(aCurve.Size() - 1, NCollection_Sequence()); for (int aTSI = 0; aTSI < aTSCount; ++aTSI) { IntersectCurve(aCurve, aToolCurves[aTSI], aParams); @@ -715,32 +991,6 @@ std::vector HYDROData_PolylineOperator::Split( const TopoDS_Wire& return aResult; } -std::vector HYDROData_PolylineOperator::Split( const TopoDS_Wire& theWire, - const TopoDS_Wire& theTool, - double theTolerance ) -{ - std::vector aResult; - NCollection_Vector aWEdges, aTEdges; - Standard_Boolean aIsWClosed, aIsTClosed; - if (!WireToCurve(theWire, aWEdges, aIsWClosed) || - !WireToCurve(theTool, aTEdges, aIsTClosed)) - { - return aResult; - } - - - //TODO - return aResult; -} - -std::vector HYDROData_PolylineOperator::Split( const std::vector& theWires, - double theTolerance ) -{ - std::vector aResult; - //TODO - return aResult; -} - bool HYDROData_PolylineOperator::CreatePolylines( const Handle( HYDROData_Document )& theDoc, const QString& theNamePrefix, const std::vector& theShapes, diff --git a/src/HYDROData/HYDROData_PolylineOperator.h b/src/HYDROData/HYDROData_PolylineOperator.h index 3f92f0be..0b0fdcee 100644 --- a/src/HYDROData/HYDROData_PolylineOperator.h +++ b/src/HYDROData/HYDROData_PolylineOperator.h @@ -58,14 +58,6 @@ protected: static std::vector Split( const TopoDS_Wire& theWire, const gp_Pnt2d& thePoint, double theTolerance ); - static std::vector Split( const TopoDS_Wire& theWire, - const TopoDS_Wire& theTool, - double theTolerance ); - static std::vector Split( const std::vector& 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, -- 2.39.2