X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2FHYDROData%2FHYDROData_PolylineOperator.cxx;h=07387a6e9d0cf085fba22e6aca6e2ee26cee61fc;hb=ab379d017642b11cd02612d46372a23842937ddf;hp=ae9a70f944d8c98bbd066e73bde5da0ddb585537;hpb=058fcba8376e80a53b920bc79b832a8df2080b0c;p=modules%2Fhydro.git diff --git a/src/HYDROData/HYDROData_PolylineOperator.cxx b/src/HYDROData/HYDROData_PolylineOperator.cxx index ae9a70f9..07387a6e 100644 --- a/src/HYDROData/HYDROData_PolylineOperator.cxx +++ b/src/HYDROData/HYDROData_PolylineOperator.cxx @@ -18,6 +18,13 @@ #include #include +#include +#include + +#ifndef LIGHT_MODE +#include +#endif + #include #include #include @@ -40,7 +47,16 @@ #include #include #include -#include +#include +#include +#include +#include +#include + +#define _DEVDEBUG_ +#include "HYDRO_trace.hxx" +#include +#include template void append( std::vector& theList, const std::vector& theList2 ) { @@ -55,972 +71,456 @@ template void append( std::vector& theList, const std::vector& 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 -static Standard_Boolean WireToCurve( - const TopoDS_Wire& theWire, - TCurveType& theCurve, - Standard_Boolean& theIsClosed) +bool HYDROData_PolylineOperator::Split( const Handle( HYDROData_Document )& theDoc, + const Handle( HYDROData_PolylineXY )& thePolyline, + const gp_Pnt2d& thePoint, + double theTolerance ) const { - TopTools_IndexedDataMapOfShapeListOfShape aVertexToEdges; - TopExp::MapShapesAndAncestors(theWire, - TopAbs_VERTEX, TopAbs_EDGE, aVertexToEdges); - const Standard_Integer aVCount = aVertexToEdges.Extent(); - if (aVCount == 0) - { - return Standard_False; - } - + if (thePolyline.IsNull()) { - 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; - } + return false; } - TopTools_ListOfShape* aEdges = &aVertexToEdges.ChangeFromIndex(aVN); - while (!aEdges->IsEmpty()) + std::vector aPointsList( 1 ); + aPointsList[0] = thePoint; + std::vector aCurves; + GetWires(thePolyline, aCurves); + bool isOK = true; + for( int i=0, n=aCurves.size(); iFirst()); - 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); - } + std::vector aCurvesList; + Split( aCurves[i], thePoint, theTolerance, aCurvesList ); + bool isLocalOK = CreatePolylines( theDoc, thePolyline, aCurvesList, true ); + isOK = isOK && isLocalOK; } - return (!theIsClosed && theCurve.Size() == aVCount - 1) || - (theIsClosed && theCurve.Size() == aVCount); + return isOK; } -template -static void CurveToWire(const TCurveType& theCurve, TopoDS_Wire& theWire) +bool HYDROData_PolylineOperator::Split( const Handle( HYDROData_Document )& theDoc, + const Handle( HYDROData_PolylineXY )& thePolyline, + const Handle( HYDROData_PolylineXY )& theTool, + double theTolerance, + bool& theIsIntersected) const { - BRep_Builder aBulder; - aBulder.MakeWire(theWire); - for (typename TCurveType::Iterator aEIt(theCurve); aEIt.More(); aEIt.Next()) + if (thePolyline.IsNull() || theTool.IsNull()) { - aBulder.Add(theWire, aEIt.Value()); + return false; } -} -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()); - } - } + HYDROData_SequenceOfObjects aSeq; + aSeq.Append( theTool ); + return split( theDoc, thePolyline, aSeq, theTolerance, -1, theIsIntersected); } -static Standard_Real ProjectPointToCurve( - const gp_Pnt& thePoint, - const Adaptor3d_Curve& theCurve, - Standard_Real& theParameter) +bool HYDROData_PolylineOperator::Split( const Handle( HYDROData_Document )& theDoc, + const HYDROData_SequenceOfObjects& thePolylines, + double theTolerance ) { - 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) + int f = thePolylines.Lower(), l = thePolylines.Upper(); + for( int i=f; i<=l; i++ ) { - if (Abs(theParameter - aParams[aEI]) < Precision::PConfusion() || - aPoint.SquareDistance(aEnds[aEI]) < Precision::SquareConfusion()) - { - theParameter = aParams[aEI]; - } + Handle( HYDROData_PolylineXY ) aPolyline = Handle( HYDROData_PolylineXY )::DownCast( thePolylines.Value( i ) ); + bool isIntersected; + if( !split( theDoc, aPolyline, thePolylines, theTolerance, i, isIntersected) ) + return false; } - return aMinSqDist; -} - -static Standard_Real ProjectPointToEdge( - const gp_Pnt& thePoint, - const TopoDS_Edge& theEdge, - Standard_Real& theParameter) -{ - return ProjectPointToCurve(thePoint, BRepAdaptor_Curve(theEdge), theParameter); + return true; } -static void SplitCurveByPoint( - const NCollection_Vector& theEdges, - const Standard_Integer theEdgeIndex, - const Standard_Real theParameter, - NCollection_Vector& theEdges1, - NCollection_Vector& theEdges2) +bool HYDROData_PolylineOperator::Merge( const Handle( HYDROData_Document )& theDoc, + const QString& theName, + const HYDROData_SequenceOfObjects& thePolylines, + bool isConnectByNewSegment, + double theTolerance ) { - for (Standard_Integer aEI = 0; aEI < theEdgeIndex; ++aEI) - { - theEdges1.Append(theEdges(aEI)); - } + Handle( HYDROData_PolylineXY ) aNewPolyline = + Handle( HYDROData_PolylineXY )::DownCast( theDoc->CreateObject( KIND_POLYLINEXY ) ); + int ins =0; - 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* 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); + HYDROData_SequenceOfObjects::Iterator aPIt(thePolylines); - 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) + for (int ip=1; aPIt.More(); aPIt.Next(), ip++) { - aEdges->Append(theEdges(aEI)); - } -} + Handle(HYDROData_PolylineXY) aPolyline = + Handle(HYDROData_PolylineXY)::DownCast(aPIt.Value()); + NCollection_Sequence aSectNames; + NCollection_Sequence aSectTypes; + NCollection_Sequence aSectClosures; + aPolyline->GetSections( aSectNames, aSectTypes, aSectClosures ); -static void SplitCurveByPoints( - const NCollection_Vector& theCurve, - const NCollection_Vector >& theParameters, - NCollection_Vector >& theSplittedCurves) -{ - 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()) - { - const Standard_Boolean isForward = - (aEIt.Value().Orientation() != TopAbs_REVERSED); - for (NCollection_Sequence::Iterator - aPIt(aPLIt.Value(), isForward); aPIt.More(); aPIt.Next()) + for ( int i = 1, n = aSectNames.Size(); i <= n; ++i ) { - 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(); + const TCollection_AsciiString& aSectName = aSectNames.Value( i ) + "_" + ip; + const HYDROData_PolylineXY::SectionType& aSectType = aSectTypes.Value( i ); + bool aSectClosure = aSectClosures.Value( i ); + aNewPolyline->AddSection(aSectName, aSectType, aSectClosure); + HYDROData_PolylineXY::PointsList aPointsList = aPolyline->GetPoints(i-1, false); + aNewPolyline->SetPoints(ins++, aPointsList); } } - theSplittedCurves.Append(aCurves[aCI]); -} - -static Standard_Integer AppendIntersectionPoint( - const Adaptor3d_Curve& theCurve, - const Standard_Real theParameter, - NCollection_Sequence& theParameters) -{ - // 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_Sequence::Iterator aPIt(*aParams[aLI]); - for (Standard_Integer aPI = 0; aPIt.More(); aPIt.Next(), ++aPI) + QString aName = theName; + if( aName.isEmpty() ) { - 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) + aName = "merged"; + int anIndex = 1; + QString aNewName = aName + "_" + QString::number(anIndex); + while (!theDoc->FindObjectByName(aNewName).IsNull()) // the object with such a name is not found { - if (aPI == 0) - { - theParameters.Prepend(aEndParams.First()); - } - else - { - theParameters.Append(aEndParams.Last()); - } - ++aIntCount; + anIndex++; + aNewName = aName + "_" + QString::number(anIndex); } - return aIntCount; - } + aName = aNewName; } - } - // 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; + aNewPolyline->SetName(aName); + aNewPolyline->Update(); + return true; } -static Standard_Integer IntersectEdge( - const TopoDS_Edge& theEdge1, - const TopoDS_Edge& theEdge2, - NCollection_Sequence& theParameters) +bool HYDROData_PolylineOperator::split( const Handle( HYDROData_Document )& theDoc, + const Handle( HYDROData_PolylineXY )& thePolyline, + const HYDROData_SequenceOfObjects& theTools, + double theTolerance, + int theIgnoreIndex, + bool& theIsIntersected) const { - // 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) + theIsIntersected = false; + + if (thePolyline.IsNull()) { - Standard_Real aParameter; - if (ProjectPointToCurve(aEndPs[aPI], aCurve1, aParameter) <= - Precision::SquareConfusion()) - { - AppendIntersectionPoint(aCurve1, aParameter, theParameters); - } + return false; } - // 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) + std::vector aCurves; + GetWires(thePolyline, aCurves); + std::vector aToolCurves; + for( int i=theTools.Lower(), n=theTools.Upper(); i<=n; i++ ) + if( i!=theIgnoreIndex ) { - Extrema_POnCurv aP1, aP2; - aAlgo.Points(aEN, aP1, aP2); - if (aP1.Value().SquareDistance(aP2.Value()) <= - Precision::SquareConfusion()) + Handle( HYDROData_PolylineXY ) aToolPolyline = + Handle( HYDROData_PolylineXY )::DownCast( theTools.Value( i ) ); + if (!aToolPolyline.IsNull()) { - AppendIntersectionPoint(aCurve1, aP1.Parameter(), theParameters); + std::vector aTCurves; + GetWires(aToolPolyline, aTCurves); + append( aToolCurves, aTCurves); } } - } - 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; -} - -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) + if (aToolCurves.empty()) { - 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; + return false; } - NCollection_Sequence* aCurves[] = {NULL, NULL}; - Standard_Integer aOrder = 0; - for (NCollection_Vector >::Iterator - aCIt(theMergedCurves); aCIt.More(); aCIt.Next()) + const int aPSCount = aCurves.size(); + const int aTSCount = aToolCurves.size(); + std::vector aResult; + for (int aPSI = 0; aPSI < aPSCount; ++aPSI) { - NCollection_Sequence& aC = aCIt.ChangeValue(); - if (aC.IsEmpty() || IsClosed(aC)) + HYDROData_TopoCurve aCurve; + //DEBTRACE("Initialize curve " << aPSI); + if (!aCurve.Initialize(aCurves[aPSI])) { continue; } - const gp_Pnt aP1 = - BRep_Tool::Pnt(TopExp::FirstVertex(aC.First(), Standard_True)); - if (aCurves[0] == NULL && aP1.SquareDistance(aPs[1]) <= aSqTol) + std::deque > aParams; + for (int aTSI = 0; aTSI < aTSCount; ++aTSI) { - aCurves[0] = &aC; + aCurve.Intersect(aToolCurves[aTSI], aParams); } - const gp_Pnt aP2 = - BRep_Tool::Pnt(TopExp::LastVertex(aC.Last(), Standard_True)); - if (aCurves[1] == NULL && aP2.SquareDistance(aPs[0]) <= aSqTol) + std::deque aSplitCurves; + theIsIntersected |= aCurve.Cut(aParams, aSplitCurves); + std::deque::const_iterator aCIt = + aSplitCurves.begin(); + std::deque::const_iterator aLastCIt = + aSplitCurves.end(); + for (int iw=0; aCIt != aLastCIt; ++aCIt, iw++) { - aCurves[1] = &aC; - aOrder = (aCurves[0] == NULL) ? 1 : 0; + /*std::stringstream brepName; + brepName << "theSplitWire_"; + brepName << iw; + brepName << ".brep"; + BRepTools::Write(aCIt->Wire() , brepName.str().c_str() );*/ + aResult.push_back(aCIt->Wire()); } } - 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) + CreatePolylines( theDoc, thePolyline, aResult, true ); + return true; +} + +void HYDROData_PolylineOperator::GetWires( + const Handle( HYDROData_PolylineXY )& thePolyline, + std::vector& theWires) +{ + TopoDS_Shape aShape = thePolyline->GetShape(); + if( aShape.ShapeType()==TopAbs_WIRE ) { - ExtendCurve(1, *aCurves[1], aCurve); + theWires.push_back( TopoDS::Wire( aShape ) ); } else { - ExtendCurve(aOrder, *aCurves[aOrder], aCurve); - if (aCurves[0] != aCurves[1]) - { - ExtendCurve(aOrder, *aCurves[aOrder], *aCurves[1 - aOrder]); - } - else + TopExp_Explorer anExp( aShape, TopAbs_WIRE ); + for( ; anExp.More(); anExp.Next() ) { - CloseCurve(*aCurves[aOrder]); + theWires.push_back( TopoDS::Wire( anExp.Current() ) ); } } - return Standard_True; } -static Standard_Boolean Connect( +void HYDROData_PolylineOperator::Split( const TopoDS_Wire& theWire, - const Standard_Real theTolerance, - NCollection_Vector >& theMergedCurves) + const gp_Pnt2d& thePoint, + double theTolerance, + std::vector& theWires) { - NCollection_Sequence aCurve; - Standard_Boolean isClosed; - if (!WireToCurve(theWire, aCurve, isClosed)) + HYDROData_TopoCurve aCurve; + if (!aCurve.Initialize(theWire)) { - return Standard_False; + theWires.push_back(theWire); + return; } - if (isClosed) + const gp_XYZ aP(thePoint.X(), thePoint.Y(), 0); + std::list::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()) { - theMergedCurves.Append(aCurve); - return Standard_True; + theWires.push_back(aCurve2.Wire()); } +} - 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; - } +bool HYDROData_PolylineOperator::CreatePolylines( const Handle( HYDROData_Document )& theDoc, + const Handle( HYDROData_PolylineXY )& theOldPolyline, + const std::vector& theShapes, + bool isUseIndices ) +{ + if( theDoc.IsNull() ) + return false; + + if ( theOldPolyline.IsNull() ) + return false; + const QString& theNamePrefix = theOldPolyline->GetName(); + const QColor& theColor = theOldPolyline->GetWireColor(); - for (NCollection_Vector >::Iterator - aCIt(theMergedCurves); aCIt.More(); aCIt.Next()) + int n = theShapes.size(); + //DEBTRACE("theShapes.size() "<< n); + int anIndex = 1; + for( int i=0; i& aCurve2 = aCIt.ChangeValue(); - if (aCurve2.IsEmpty() || IsClosed(aCurve2)) - { - continue; - } + Handle( HYDROData_PolylineXY ) aPolyline = + Handle( HYDROData_PolylineXY )::DownCast( theDoc->CreateObject( KIND_POLYLINEXY ) ); + if( aPolyline.IsNull() ) + return false; + + aPolyline->ImportShape(theShapes[i], false, theOldPolyline, false); - 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) + if( isUseIndices ) { - 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)) + QString aNewName = theNamePrefix + "_" + QString::number( anIndex ); + while( !theDoc->FindObjectByName( aNewName ).IsNull() ) // the object with such a name is not found { - return Standard_False; + anIndex++; + aNewName = theNamePrefix + "_" + QString::number( anIndex ); } - - ExtendCurve(aOrder, BRepBuilderAPI_MakeEdge(aBSpline), aCurve2); + aPolyline->SetName( aNewName ); } - ExtendCurve(aOrder, aCurve2, aCurve); - if (aSqDists[1 - aOrder] <= aSqTol) + else { - CloseCurve(aCurve2); + aPolyline->SetName( theNamePrefix ); } - 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, - 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; + if( theColor.isValid() ) + aPolyline->SetWireColor( theColor ); } - 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 ); + return true; } -bool HYDROData_PolylineOperator::Split( const Handle( HYDROData_Document )& theDoc, - const HYDROData_SequenceOfObjects& thePolylines, - double theTolerance ) +double HYDROData_PolylineOperator::ReduceDeflection( + const double theDeflection, + HYDROData_TopoCurve& theCurve, + int& thePieceCount) { - int f = thePolylines.Lower(), l = thePolylines.Upper(); - for( int i=f; i<=l; i++ ) + // Construct the approximating B-spline. + std::list aPs; + if (!theCurve.ValuesInKnots(aPs)) { - Handle( HYDROData_PolylineXY ) aPolyline = Handle( HYDROData_PolylineXY )::DownCast( thePolylines.Value( i ) ); - if( !split( theDoc, aPolyline, thePolylines, theTolerance, i ) ) - return false; + return -1; } - return true; -} -bool HYDROData_PolylineOperator::Merge( const Handle( HYDROData_Document )& theDoc, - const QString& theName, - const HYDROData_SequenceOfObjects& thePolylines, - bool isConnectByNewSegment, - double theTolerance ) -{ - NCollection_Vector > aMergedCurves; - HYDROData_SequenceOfObjects::Iterator aPIt(thePolylines); - for (; aPIt.More(); aPIt.Next()) + Handle(TColgp_HArray1OfPnt) aPs2 = new TColgp_HArray1OfPnt(1, aPs.size()); { - Handle(HYDROData_PolylineXY) aPolyline = - Handle(HYDROData_PolylineXY)::DownCast(aPIt.Value()); - std::vector aWires = GetWires(aPolyline); - for (std::vector::const_iterator aWIt = aWires.begin(), - aLastWIt = aWires.end(); aWIt != aLastWIt; ++aWIt) + std::list::const_iterator aLastPIt = aPs.end(); + std::list::const_iterator aPIt = aPs.begin(); + for (int aPN = 1; aPIt != aLastPIt; ++aPN, ++aPIt) { - const Standard_Boolean aResult = !isConnectByNewSegment ? - ::Merge(*aWIt, theTolerance, aMergedCurves) : - Connect(*aWIt, theTolerance, aMergedCurves); - if (!aResult) - { - return false; - } + aPs2->SetValue(aPN, *aPIt); } } - - TopoDS_Compound aWireSet; - BRep_Builder aBuilder; - aBuilder.MakeCompound(aWireSet); - for (NCollection_Vector >::Iterator - aCIt(aMergedCurves); aCIt.More(); aCIt.Next()) + Handle(Geom_BSplineCurve) aBSpline2; + const bool isClosed = theCurve.IsClosed(); +#ifndef LIGHT_MODE + if (!CurveCreator_Utils::constructBSpline(aPs2, isClosed, aBSpline2)) +#endif { - if (!aCIt.Value().IsEmpty()) - { - TopoDS_Wire aWire; - CurveToWire(aCIt.Value(), aWire); - aBuilder.Add(aWireSet, aWire); - } + return -1; } - std::vector aPolylines(1); - aPolylines[0] = aWireSet; - CreatePolylines(theDoc, theName, aPolylines, false); - 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) + // Calculate the piece deflections. + std::deque aSqDefls; + double aMaxSqDefl = 0; + std::list& aEdges = theCurve.Edges(); + std::list::const_iterator aLastEIt = aEdges.end(); { - NCollection_Vector aCurve; - Standard_Boolean aIsClosed; - if (!WireToCurve(aCurves[aPSI], aCurve, aIsClosed)) + std::list::const_iterator aEIt = aEdges.begin(); + for (int aPrevKCount = 0; aEIt != aLastEIt; ++aEIt) { - continue; - } - - NCollection_Vector > aParams; - aParams.SetValue(aCurve.Size() - 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) + TopLoc_Location aLoc; + double aParams[2]; + Handle(Geom_BSplineCurve) aBSpline = Handle(Geom_BSplineCurve)::DownCast( + BRep_Tool::Curve(*aEIt, aLoc, aParams[0], aParams[1])); + const int aKCount = aBSpline->NbKnots(); + for (int aKN = 1; aKN < aKCount; ++aKN) { - const NCollection_Sequence& aPs = aParams.Last(); - if (!aPs.IsEmpty()) + const double aParam = + (aBSpline->Knot(aKN) + aBSpline->Knot(aKN + 1)) * 0.5; + const double aParam2 = (aBSpline2->Knot(aPrevKCount + aKN) + + aBSpline2->Knot(aPrevKCount + aKN + 1)) * 0.5; + const double aSqDefl = Abs(aBSpline->Value(aParam). + SquareDistance(aBSpline2->Value(aParam2))); + aSqDefls.push_back(aSqDefl); + if (aMaxSqDefl < aSqDefl) { - 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()); + aMaxSqDefl = aSqDefl; } } - } - - 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); + aPrevKCount += aKCount - 1; } } - 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 ) + // Check whether the reducing is necessary. + const double aMaxDefl = Sqrt(aMaxSqDefl); + if (aMaxDefl <= theDeflection) { - aResult.push_back( TopoDS::Wire( aShape ) ); + return aMaxDefl; } - else + + // Reduce the deflections. + const double aThresSqDefl = + Max(aMaxSqDefl * 0.25, theDeflection * theDeflection); + std::list::iterator aEIt = aEdges.begin(); + std::deque::const_iterator aSqDIt = aSqDefls.begin(); + thePieceCount = 0; + for (; aEIt != aLastEIt; ++aEIt) { - TopExp_Explorer anExp( aShape, TopAbs_WIRE ); - for( ; anExp.More(); anExp.Next() ) + TopLoc_Location aLoc; + double aParams[2]; + Handle(Geom_BSplineCurve) aBSpline = Handle(Geom_BSplineCurve)::DownCast( + BRep_Tool::Curve(*aEIt, aLoc, aParams[0], aParams[1])); + Handle(Geom_BSplineCurve) aBSpline2 = + Handle(Geom_BSplineCurve)::DownCast(aBSpline->Copy()); + const int aKCount = aBSpline->NbKnots(); + for (int aKN = 1; aKN < aKCount; ++aSqDIt, ++aKN) { - aResult.push_back( TopoDS::Wire( anExp.Current() ) ); + if (*aSqDIt > aThresSqDefl) + { + aBSpline2->InsertKnot( + (aBSpline->Knot(aKN) + aBSpline->Knot(aKN + 1)) * 0.5); + } } + TopoDS_Edge aEdge; + BRep_Builder().MakeEdge(aEdge, aBSpline2, Precision::Confusion()); + BRep_Builder().Add(aEdge, TopExp::FirstVertex(*aEIt)); + BRep_Builder().Add(aEdge, TopExp::LastVertex(*aEIt)); + thePieceCount += aBSpline2->NbKnots() - 1; + *aEIt = aEdge; } - return aResult; + return aMaxDefl; } -std::vector HYDROData_PolylineOperator::Split( const TopoDS_Wire& theWire, - const gp_Pnt2d& thePoint, - double theTolerance ) +bool HYDROData_PolylineOperator::Extract( const Handle(HYDROData_Document)& theDocument, + const Handle(HYDROData_Object)& theObject ) { - std::vector aResult; - NCollection_Vector aEdges; - Standard_Boolean isClosed; - if (!WireToCurve(theWire, aEdges, isClosed)) - { - aResult.push_back(theWire); - return aResult; - } + if( theObject.IsNull() || theDocument.IsNull() ) + return false; + + QList aBoundShapes; + QStringList aBoundNames; + QMap aNameToShMap; + + theObject->GetBoundaries( aBoundShapes, aBoundNames ); - 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) + for( int i=0, n=aBoundShapes.size(); i aSqDist) + TopoDS_Shape aShape = aBoundShapes[i]; + if( aShape.IsNull() ) + continue; + + QString aBoundName = i aEdges1, aEdges2; - SplitCurveByPoint(aEdges, aSEI, aSParam, aEdges1, aEdges2); - TopoDS_Wire aWire; - if (!isClosed) + foreach( QString K, aNameToShMap.keys() ) { - CurveToWire(aEdges1, aWire); - if (!aEdges2.IsEmpty()) + const TopTools_IndexedMapOfShape& IM = aNameToShMap.value(K); + TopTools_ListOfShape LSE; + for (int i = 1; i <= IM.Extent(); i++) { - aResult.push_back(aWire); - CurveToWire(aEdges2, aWire); + const TopoDS_Edge& E = TopoDS::Edge(IM(i)); + if (E.IsNull()) + continue; + LSE.Append(E); } - } - else - { - if (!aEdges2.IsEmpty()) + + + TopoDS_Shape aShapeOut; + if (LSE.Extent() == 1) { - CurveToWire(aEdges2, aEdges1, aWire); + aShapeOut = LSE.First(); } - else + else if (LSE.Extent() > 1) { - CurveToWire(aEdges1, aWire); + BRepLib_MakeWire WM; + WM.Add(LSE); + if (WM.IsDone()) + aShapeOut = WM.Wire(); + else + continue; } - } - aResult.push_back(aWire); - return aResult; -} - -bool HYDROData_PolylineOperator::CreatePolylines( const Handle( HYDROData_Document )& theDoc, - const QString& theNamePrefix, - const std::vector& theShapes, - bool isUseIndices ) -{ - if( theDoc.IsNull() ) - return false; + else continue; - int n = theShapes.size(); - int anIndex = 1; - for( int i=0; iCreateObject( KIND_POLYLINEXY ) ); + Handle( HYDROData_PolylineXY )::DownCast( theDocument->CreateObject( KIND_POLYLINEXY ) ); + if( aPolyline.IsNull() ) return false; - aPolyline->SetShape( theShapes[i] ); + aPolyline->SetShape( aShapeOut ); - if( isUseIndices ) + int anIndex = 0; + QString aName = K; + while( !theDocument->FindObjectByName( aName ).IsNull() ) { - QString aNewName = theNamePrefix + "_" + QString::number( anIndex ); - if( theDoc->FindObjectByName( aNewName ).IsNull() ) // the object with such a name is not found - aPolyline->SetName( aNewName ); anIndex++; + aName = K + "_" + QString::number( anIndex ); } - else - { - aPolyline->SetName( theNamePrefix ); - } + aPolyline->SetName( aName ); } + return true; }