From: abk Date: Tue, 30 Jun 2015 10:28:19 +0000 (+0300) Subject: Algorithms to cut and split each polyline section by all other polyline sections... X-Git-Tag: v1.4.2~2 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=1a9c7614390a6224d2824852e6cfd33389ec2d12;p=modules%2Fhydro.git Algorithms to cut and split each polyline section by all other polyline sections were written. --- diff --git a/src/HYDROData/HYDROData_PolylineOperator.cxx b/src/HYDROData/HYDROData_PolylineOperator.cxx index ed7a4a93..81ca954e 100644 --- a/src/HYDROData/HYDROData_PolylineOperator.cxx +++ b/src/HYDROData/HYDROData_PolylineOperator.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -48,141 +49,7 @@ template void append( std::vector& theList, const std::vector& th theList[i] = theList2[j]; } -bool HYDROData_PolylineOperator::Split( const Handle( HYDROData_Document )& theDoc, - const Handle( HYDROData_PolylineXY )& thePolyline, - const gp_Pnt2d& thePoint, - double theTolerance ) const -{ - std::vector aPointsList( 1 ); - aPointsList[0] = thePoint; - std::vector aCurves = GetWires( thePolyline ); - bool isOK = true; - for( int i=0, n=aCurves.size(); i aCurvesList = Split( aCurves[i], thePoint, theTolerance ); - bool isLocalOK = CreatePolylines( theDoc, thePolyline->GetName(), aCurvesList, true ); - isOK = isOK && isLocalOK; - } - return isOK; -} - -bool HYDROData_PolylineOperator::Split( const Handle( HYDROData_Document )& theDoc, - const Handle( HYDROData_PolylineXY )& thePolyline, - const Handle( HYDROData_PolylineXY )& theTool, - double theTolerance ) const -{ - HYDROData_SequenceOfObjects aSeq; - aSeq.Append( theTool ); - return split( theDoc, thePolyline, aSeq, theTolerance, -1 ); -} - -bool HYDROData_PolylineOperator::Split( const Handle( HYDROData_Document )& theDoc, - const HYDROData_SequenceOfObjects& thePolylines, - double theTolerance ) -{ - int f = thePolylines.Lower(), l = thePolylines.Upper(); - for( int i=f; i<=l; i++ ) - { - Handle( HYDROData_PolylineXY ) aPolyline = Handle( HYDROData_PolylineXY )::DownCast( thePolylines.Value( i ) ); - if( !split( theDoc, aPolyline, thePolylines, theTolerance, i ) ) - return false; - } - return true; -} - -bool HYDROData_PolylineOperator::Merge( const Handle( HYDROData_Document )& theDoc, - const QString& theName, - const HYDROData_SequenceOfObjects& thePolylines, - bool isConnectByNewSegment, - double theTolerance ) -{ - TopoDS_Shape aMergedPolyline; - - int f = thePolylines.Lower(), l = thePolylines.Upper(); - for( int i=f; i<=l; i++ ) - { - Handle( HYDROData_PolylineXY ) aPolyline = Handle( HYDROData_PolylineXY )::DownCast( thePolylines.Value( i ) ); - std::vector aCurves = GetWires( aPolyline ); - for( int j=0, m=aCurves.size(); j aShapes( 1 ); - aShapes[0] = aMergedPolyline; - CreatePolylines( theDoc, theName, aShapes, false ); - - return true; -} - -bool HYDROData_PolylineOperator::Merge( TopoDS_Shape& theShape, const TopoDS_Wire& theWire, - bool isConnectByNewSegment, double theTolerance ) -{ - //TODO - return true; -} - -bool HYDROData_PolylineOperator::split( const Handle( HYDROData_Document )& theDoc, - const Handle( HYDROData_PolylineXY )& thePolyline, - const HYDROData_SequenceOfObjects& theTools, - double theTolerance, - int theIgnoreIndex ) const -{ - std::vector aCurves = GetWires( thePolyline ); - std::vector 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 ) ); - } - - bool isOK = true; - - int n = aCurves.size(); - std::vector aResults( n ); - for( int i=0; i aNewResults; - for( int k=0, q=aResults.size(); k aCurvesList = Split( TopoDS::Wire( aResults[k] ), aToolCurves[j], theTolerance ); - append( aNewResults, aCurvesList ); - } - aResults = aNewResults; - } - - CreatePolylines( theDoc, thePolyline->GetName(), aResults, true ); - - return isOK; -} - -std::vector HYDROData_PolylineOperator::GetWires( const Handle( HYDROData_PolylineXY )& thePolyline ) -{ - std::vector aResult; - - TopoDS_Shape aShape = thePolyline->GetShape(); - - if( aShape.ShapeType()==TopAbs_WIRE ) - { - aResult.push_back( TopoDS::Wire( aShape ) ); - } - else - { - TopExp_Explorer anExp( aShape, TopAbs_WIRE ); - for( ; anExp.More(); anExp.Next() ) - { - aResult.push_back( TopoDS::Wire( anExp.Current() ) ); - } - } - return aResult; -} - -static Standard_Boolean OrderCurveEdges( +static Standard_Boolean WireToCurve( const TopoDS_Wire& theWire, NCollection_Vector& theEdges, Standard_Boolean& theIsClosed) @@ -258,36 +125,63 @@ static Standard_Boolean OrderCurveEdges( (theIsClosed && theEdges.Size() == aVCount); } -static Standard_Real ProjectPointToEdge( +static void CurveToWire( + const NCollection_Vector& theEdges, TopoDS_Wire& theWire) +{ + BRep_Builder aBulder; + aBulder.MakeWire(theWire); + NCollection_Vector::Iterator aEIt(theEdges); + for (; aEIt.More(); aEIt.Next()) + { + aBulder.Add(theWire, aEIt.Value()); + } +} + +static void CurveToWire( + const NCollection_Vector& theEdges1, + const NCollection_Vector& theEdges2, + TopoDS_Wire& theWire) +{ + BRep_Builder aBulder; + aBulder.MakeWire(theWire); + const NCollection_Vector* aEdges[] = {&theEdges1, &theEdges2}; + for (Standard_Integer aEI = 0; aEI < 2; ++aEI) + { + NCollection_Vector::Iterator aEIt(*aEdges[aEI]); + for (; aEIt.More(); aEIt.Next()) + { + aBulder.Add(theWire, aEIt.Value()); + } + } +} + +static Standard_Real ProjectPointToCurve( const gp_Pnt& thePoint, - const TopoDS_Edge& theEdge, + const Adaptor3d_Curve& theCurve, Standard_Real& theParameter) { - BRepAdaptor_Curve aECurve(theEdge); - Extrema_ExtPC aAlgo(thePoint, aECurve); + Extrema_ExtPC aAlgo(thePoint, theCurve); Standard_Integer aMinEN = -2; Standard_Real aMinSqDist = DBL_MAX; if (aAlgo.IsDone()) { const Standard_Integer aECount = aAlgo.NbExt(); - if (aECount != 0) + for (Standard_Integer aEN = 1; aEN <= aECount; ++aEN) { - 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) { - const gp_Pnt& aP = aAlgo.Point(aEN).Value(); - const Standard_Real aSqDist = thePoint.SquareDistance(aP); - if (aMinSqDist > aSqDist) - { - aMinSqDist = aSqDist; - aMinEN = aEN; - } + aMinSqDist = aSqDist; + aMinEN = aEN; } } } const Standard_Real aParams[] = - {aECurve.FirstParameter(), aECurve.LastParameter()}; - const gp_Pnt aEnds[] = {aECurve.Value(aParams[0]), aECurve.Value(aParams[1])}; + {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) @@ -319,6 +213,14 @@ static Standard_Real ProjectPointToEdge( 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& theEdges, const Standard_Integer theEdgeIndex, @@ -332,10 +234,10 @@ static void SplitCurveByPoint( } const TopoDS_Edge& aEdge = theEdges(theEdgeIndex); - BRepAdaptor_Curve aECurve(aEdge); + BRepAdaptor_Curve aCurve(aEdge); Standard_Integer aParamI = -1; const Standard_Real aEdgeEndParams[] = - {aECurve.FirstParameter(), aECurve.LastParameter()}; + {aCurve.FirstParameter(), aCurve.LastParameter()}; if (Abs(theParameter - aEdgeEndParams[0]) < Precision::PConfusion()) { aParamI = 0; @@ -375,7 +277,7 @@ static void SplitCurveByPoint( aSATPP.SetMaxTolerance(Precision::Confusion()); TopoDS_Vertex aSplitV; BRep_Builder().MakeVertex( - aSplitV, aECurve.Value(theParameter), Precision::Confusion()); + aSplitV, aCurve.Value(theParameter), Precision::Confusion()); TopoDS_Edge aEParts[] = { ShapeBuild_Edge().CopyReplaceVertices(aFE, TopoDS_Vertex(), @@ -405,34 +307,342 @@ static void SplitCurveByPoint( } } -static void CollectCurveWire( - const NCollection_Vector& theEdges, TopoDS_Wire& theWire) +static void SplitCurveByPoints( + const NCollection_Vector& theCurve, + const NCollection_Vector >& theParameters, + NCollection_Vector >& theSplittedCurves) { - BRep_Builder aBulder; - aBulder.MakeWire(theWire); - NCollection_Vector::Iterator aEIt(theEdges); - for (; aEIt.More(); aEIt.Next()) + NCollection_Vector aCurves[3]; + aCurves[0] = theCurve; + Standard_Integer aCI = 0, aEI = 0; + NCollection_Vector::Iterator aEIt(theCurve); + for (NCollection_Vector >::Iterator + aPLIt(theParameters); aPLIt.More(); ++aEI, aEIt.Next(), aPLIt.Next()) { - aBulder.Add(theWire, aEIt.Value()); + const Standard_Boolean isForward = + (aEIt.Value().Orientation() != TopAbs_REVERSED); + for (NCollection_Sequence::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 void CollectCurveWire( - const NCollection_Vector& theEdges1, - const NCollection_Vector& theEdges2, - TopoDS_Wire& theWire) +static Standard_Integer AppendIntersectionPoint( + const Adaptor3d_Curve& theCurve, + const Standard_Real theParameter, + NCollection_Sequence& theParameters) { - BRep_Builder aBulder; - aBulder.MakeWire(theWire); - const NCollection_Vector* aEdges[] = {&theEdges1, &theEdges2}; - for (Standard_Integer aEI = 0; aEI < 2; ++aEI) + // Check the coincidence. + NCollection_Sequence aEndParams; + aEndParams.Append(theCurve.FirstParameter()); + aEndParams.Append(theCurve.LastParameter()); + NCollection_Sequence* aParams[] = + {&theParameters, &aEndParams}; + const gp_Pnt aPoint = theCurve.Value(theParameter); + for (Standard_Integer aLI = 0; aLI < 2; ++aLI) { - NCollection_Vector::Iterator aEIt(*aEdges[aEI]); - for (; aEIt.More(); aEIt.Next()) + NCollection_Sequence::Iterator aPIt(*aParams[aLI]); + for (Standard_Integer aPI = 0; aPIt.More(); aPIt.Next(), ++aPI) { - aBulder.Add(theWire, aEIt.Value()); + 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::Iterator aPIt(theParameters); + if (aPIt.More() && aPIt.Value() < theParameter) + { + NCollection_Sequence::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& 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& theEdges, + const TopoDS_Wire& theWire, + NCollection_Vector >& 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; +} + +bool HYDROData_PolylineOperator::Split( const Handle( HYDROData_Document )& theDoc, + const Handle( HYDROData_PolylineXY )& thePolyline, + const gp_Pnt2d& thePoint, + double theTolerance ) const +{ + std::vector aPointsList( 1 ); + aPointsList[0] = thePoint; + std::vector aCurves = GetWires( thePolyline ); + bool isOK = true; + for( int i=0, n=aCurves.size(); i aCurvesList = Split( aCurves[i], thePoint, theTolerance ); + bool isLocalOK = CreatePolylines( theDoc, thePolyline->GetName(), aCurvesList, true ); + isOK = isOK && isLocalOK; + } + return isOK; +} + +bool HYDROData_PolylineOperator::Split( const Handle( HYDROData_Document )& theDoc, + const Handle( HYDROData_PolylineXY )& thePolyline, + const Handle( HYDROData_PolylineXY )& theTool, + double theTolerance ) const +{ + HYDROData_SequenceOfObjects aSeq; + aSeq.Append( theTool ); + return split( theDoc, thePolyline, aSeq, theTolerance, -1 ); +} + +bool HYDROData_PolylineOperator::Split( const Handle( HYDROData_Document )& theDoc, + const HYDROData_SequenceOfObjects& thePolylines, + double theTolerance ) +{ + int f = thePolylines.Lower(), l = thePolylines.Upper(); + for( int i=f; i<=l; i++ ) + { + Handle( HYDROData_PolylineXY ) aPolyline = Handle( HYDROData_PolylineXY )::DownCast( thePolylines.Value( i ) ); + if( !split( theDoc, aPolyline, thePolylines, theTolerance, i ) ) + return false; + } + return true; +} + +bool HYDROData_PolylineOperator::Merge( const Handle( HYDROData_Document )& theDoc, + const QString& theName, + const HYDROData_SequenceOfObjects& thePolylines, + bool isConnectByNewSegment, + double theTolerance ) +{ + TopoDS_Shape aMergedPolyline; + + int f = thePolylines.Lower(), l = thePolylines.Upper(); + for( int i=f; i<=l; i++ ) + { + Handle( HYDROData_PolylineXY ) aPolyline = Handle( HYDROData_PolylineXY )::DownCast( thePolylines.Value( i ) ); + std::vector aCurves = GetWires( aPolyline ); + for( int j=0, m=aCurves.size(); j aShapes( 1 ); + aShapes[0] = aMergedPolyline; + CreatePolylines( theDoc, theName, aShapes, false ); + + return true; +} + +bool HYDROData_PolylineOperator::Merge( TopoDS_Shape& theShape, const TopoDS_Wire& theWire, + bool isConnectByNewSegment, double theTolerance ) +{ + //TODO + return true; +} + +bool HYDROData_PolylineOperator::split( const Handle( HYDROData_Document )& theDoc, + const Handle( HYDROData_PolylineXY )& thePolyline, + const HYDROData_SequenceOfObjects& theTools, + double theTolerance, + int theIgnoreIndex ) const +{ + std::vector aCurves = GetWires( thePolyline ); + std::vector 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 ) ); + } + + const int aPSCount = aCurves.size(); + const int aTSCount = aToolCurves.size(); + std::vector aResult; + for (int aPSI = 0; aPSI < aPSCount; ++aPSI) + { + NCollection_Vector aCurve; + Standard_Boolean aIsClosed; + if (!WireToCurve(aCurves[aPSI], aCurve, aIsClosed)) + { + continue; + } + + NCollection_Vector > aParams; + aParams.SetValue(aPSCount - 1, NCollection_Sequence()); + for (int aTSI = 0; aTSI < aTSCount; ++aTSI) + { + IntersectCurve(aCurve, aToolCurves[aTSI], aParams); + } + + NCollection_Vector > aSplittedCurves; + SplitCurveByPoints(aCurve, aParams, aSplittedCurves); + + Standard_Boolean aIsClosed2 = aIsClosed; + if (aIsClosed2) + { + const NCollection_Sequence& 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& 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); + } + } + + CreatePolylines(theDoc, thePolyline->GetName(), aResult, true); + return true; +} + +std::vector HYDROData_PolylineOperator::GetWires( const Handle( HYDROData_PolylineXY )& thePolyline ) +{ + std::vector aResult; + + TopoDS_Shape aShape = thePolyline->GetShape(); + + if( aShape.ShapeType()==TopAbs_WIRE ) + { + aResult.push_back( TopoDS::Wire( aShape ) ); + } + else + { + TopExp_Explorer anExp( aShape, TopAbs_WIRE ); + for( ; anExp.More(); anExp.Next() ) + { + aResult.push_back( TopoDS::Wire( anExp.Current() ) ); } } + return aResult; } std::vector HYDROData_PolylineOperator::Split( const TopoDS_Wire& theWire, @@ -442,7 +652,7 @@ std::vector HYDROData_PolylineOperator::Split( const TopoDS_Wire& std::vector aResult; NCollection_Vector aEdges; Standard_Boolean isClosed; - if (!OrderCurveEdges(theWire, aEdges, isClosed)) + if (!WireToCurve(theWire, aEdges, isClosed)) { aResult.push_back(theWire); return aResult; @@ -470,16 +680,23 @@ std::vector HYDROData_PolylineOperator::Split( const TopoDS_Wire& TopoDS_Wire aWire; if (!isClosed) { - CollectCurveWire(aEdges1, aWire); + CurveToWire(aEdges1, aWire); if (!aEdges2.IsEmpty()) { aResult.push_back(aWire); - CollectCurveWire(aEdges2, aWire); + CurveToWire(aEdges2, aWire); } } else { - CollectCurveWire(aEdges2, aEdges1, aWire); + if (!aEdges2.IsEmpty()) + { + CurveToWire(aEdges2, aEdges1, aWire); + } + else + { + CurveToWire(aEdges1, aWire); + } } aResult.push_back(aWire); return aResult; @@ -490,6 +707,15 @@ std::vector HYDROData_PolylineOperator::Split( const TopoDS_Wire& 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; }