X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FHYDROData%2FHYDROData_PolylineOperator.cxx;h=b991bf7f6992a0728f13c55e2e93e11940eb3cea;hb=cde2ec476486fcd7c9b7b38ce814c648d73e7fd3;hp=ac75dcd8dc2f9e0a453219a1d0937777355f9b6e;hpb=a61dd97a28b53099635016ed1effd070cc60d0de;p=modules%2Fhydro.git diff --git a/src/HYDROData/HYDROData_PolylineOperator.cxx b/src/HYDROData/HYDROData_PolylineOperator.cxx index ac75dcd8..b991bf7f 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,9 @@ #include #include #include -#include +#include +#include +#include template void append( std::vector& theList, const std::vector& theList2 ) { @@ -55,696 +64,27 @@ 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) -{ - 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 -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& 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 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& theEdges, - const Standard_Integer theEdgeIndex, - const Standard_Real theParameter, - NCollection_Vector& theEdges1, - NCollection_Vector& 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* 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& 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()) - { - 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& 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) - { - 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; -} - -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, double theTolerance ) const { + if (thePolyline.IsNull()) + { + return false; + } + std::vector aPointsList( 1 ); aPointsList[0] = thePoint; - std::vector aCurves = GetWires( thePolyline ); + std::vector aCurves; + GetWires(thePolyline, aCurves); 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 ); + std::vector aCurvesList; + Split( aCurves[i], thePoint, theTolerance, aCurvesList ); + bool isLocalOK = CreatePolylines( theDoc, thePolyline->GetName(), + aCurvesList, true, thePolyline->GetWireColor() ); isOK = isOK && isLocalOK; } return isOK; @@ -753,11 +93,17 @@ bool HYDROData_PolylineOperator::Split( const Handle( HYDROData_Document )& theD bool HYDROData_PolylineOperator::Split( const Handle( HYDROData_Document )& theDoc, const Handle( HYDROData_PolylineXY )& thePolyline, const Handle( HYDROData_PolylineXY )& theTool, - double theTolerance ) const + double theTolerance, + bool& theIsIntersected) const { + if (thePolyline.IsNull() || theTool.IsNull()) + { + return false; + } + HYDROData_SequenceOfObjects aSeq; aSeq.Append( theTool ); - return split( theDoc, thePolyline, aSeq, theTolerance, -1 ); + return split( theDoc, thePolyline, aSeq, theTolerance, -1, theIsIntersected); } bool HYDROData_PolylineOperator::Split( const Handle( HYDROData_Document )& theDoc, @@ -768,7 +114,8 @@ bool HYDROData_PolylineOperator::Split( const Handle( HYDROData_Document )& theD 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 ) ) + bool isIntersected; + if( !split( theDoc, aPolyline, thePolylines, theTolerance, i, isIntersected) ) return false; } return true; @@ -780,19 +127,20 @@ bool HYDROData_PolylineOperator::Merge( const Handle( HYDROData_Document )& theD bool isConnectByNewSegment, double theTolerance ) { - NCollection_Vector > aMergedCurves; + std::deque aMergedCurves; HYDROData_SequenceOfObjects::Iterator aPIt(thePolylines); for (; aPIt.More(); aPIt.Next()) { Handle(HYDROData_PolylineXY) aPolyline = Handle(HYDROData_PolylineXY)::DownCast(aPIt.Value()); - std::vector aWires = GetWires(aPolyline); + std::vector aWires; + GetWires(aPolyline, aWires); 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); + HYDROData_TopoCurve::Merge(theTolerance, *aWIt, aMergedCurves) : + HYDROData_TopoCurve::Connect(theTolerance, *aWIt, aMergedCurves); if (!aResult) { return false; @@ -803,20 +151,22 @@ bool HYDROData_PolylineOperator::Merge( const Handle( HYDROData_Document )& theD TopoDS_Compound aWireSet; BRep_Builder aBuilder; aBuilder.MakeCompound(aWireSet); - for (NCollection_Vector >::Iterator - aCIt(aMergedCurves); aCIt.More(); aCIt.Next()) + std::deque::iterator aCIt = aMergedCurves.begin(); + std::deque::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()); } } std::vector aPolylines(1); aPolylines[0] = aWireSet; - CreatePolylines(theDoc, theName, aPolylines, false); + QString aName = theName; + if( aName.isEmpty() ) + aName = "merged"; + CreatePolylines( theDoc, aName, aPolylines, true, QColor() ); return true; } @@ -824,177 +174,120 @@ bool HYDROData_PolylineOperator::split( const Handle( HYDROData_Document )& theD const Handle( HYDROData_PolylineXY )& thePolyline, const HYDROData_SequenceOfObjects& theTools, double theTolerance, - int theIgnoreIndex ) const + int theIgnoreIndex, + bool& theIsIntersected) const { - std::vector aCurves = GetWires( thePolyline ); + theIsIntersected = false; + + if (thePolyline.IsNull()) + { + return false; + } + + std::vector aCurves; + GetWires(thePolyline, aCurves); 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 ) ); + if (!aToolPolyline.IsNull()) + { + std::vector aTCurves; + GetWires(aToolPolyline, aTCurves); + append( aToolCurves, aTCurves); + } } + if (aToolCurves.empty()) + { + return false; + } + 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)) + HYDROData_TopoCurve aCurve; + if (!aCurve.Initialize(aCurves[aPSI])) { continue; } - NCollection_Vector > aParams; - aParams.SetValue(aCurve.Size() - 1, NCollection_Sequence()); + std::deque > aParams; 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; + aCurve.Intersect(aToolCurves[aTSI], aParams); } - for (Standard_Integer aSCI = aFSCI; aSCI <= aLSCI; ++aSCI) + std::deque aSplitCurves; + theIsIntersected |= aCurve.Cut(aParams, aSplitCurves); + std::deque::const_iterator aCIt = + aSplitCurves.begin(); + std::deque::const_iterator aLastCIt = + aSplitCurves.end(); + for (; aCIt != aLastCIt; ++aCIt) { - TopoDS_Wire aWire; - CurveToWire(aSplittedCurves(aSCI), aWire); - aResult.push_back(aWire); + aResult.push_back(aCIt->Wire()); } } - CreatePolylines(theDoc, thePolyline->GetName(), aResult, true); + CreatePolylines( theDoc, thePolyline->GetName(), aResult, true, thePolyline->GetWireColor() ); return true; } -std::vector HYDROData_PolylineOperator::GetWires( const Handle( HYDROData_PolylineXY )& thePolyline ) +void HYDROData_PolylineOperator::GetWires( + const Handle( HYDROData_PolylineXY )& thePolyline, + std::vector& theWires) { - std::vector 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 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& theWires) { - std::vector aResult; - NCollection_Vector 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 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::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, const QString& theNamePrefix, const std::vector& theShapes, - bool isUseIndices ) + bool isUseIndices, + const QColor& theColor ) { if( theDoc.IsNull() ) return false; @@ -1013,14 +306,162 @@ bool HYDROData_PolylineOperator::CreatePolylines( const Handle( HYDROData_Docume if( isUseIndices ) { QString aNewName = theNamePrefix + "_" + QString::number( anIndex ); - if( theDoc->FindObjectByName( aNewName ).IsNull() ) // the object with such a name is not found - aPolyline->SetName( aNewName ); - anIndex++; + while( !theDoc->FindObjectByName( aNewName ).IsNull() ) // the object with such a name is not found + { + anIndex++; + aNewName = theNamePrefix + "_" + QString::number( anIndex ); + } + aPolyline->SetName( aNewName ); } else { aPolyline->SetName( theNamePrefix ); } + + if( theColor.isValid() ) + aPolyline->SetWireColor( theColor ); + } + return true; +} + +double HYDROData_PolylineOperator::ReduceDeflection( + const double theDeflection, + HYDROData_TopoCurve& theCurve, + int& thePieceCount) +{ + // Construct the approximating B-spline. + std::list aPs; + if (!theCurve.ValuesInKnots(aPs)) + { + return -1; + } + + Handle(TColgp_HArray1OfPnt) aPs2 = new TColgp_HArray1OfPnt(1, aPs.size()); + { + std::list::const_iterator aLastPIt = aPs.end(); + std::list::const_iterator aPIt = aPs.begin(); + for (int aPN = 1; aPIt != aLastPIt; ++aPN, ++aPIt) + { + aPs2->SetValue(aPN, *aPIt); + } + } + Handle(Geom_BSplineCurve) aBSpline2; + const bool isClosed = theCurve.IsClosed(); +#ifndef LIGHT_MODE + if (!CurveCreator_Utils::constructBSpline(aPs2, isClosed, aBSpline2)) +#endif + { + return -1; + } + + // Calculate the piece deflections. + std::deque aSqDefls; + double aMaxSqDefl = 0; + std::list& aEdges = theCurve.Edges(); + std::list::const_iterator aLastEIt = aEdges.end(); + { + std::list::const_iterator aEIt = aEdges.begin(); + for (int aPrevKCount = 0; aEIt != aLastEIt; ++aEIt) + { + 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 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) + { + aMaxSqDefl = aSqDefl; + } + } + aPrevKCount += aKCount - 1; + } + } + + // Check whether the reducing is necessary. + const double aMaxDefl = Sqrt(aMaxSqDefl); + if (aMaxDefl <= theDeflection) + { + return aMaxDefl; + } + + // 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) + { + 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) + { + 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 aMaxDefl; +} + +bool HYDROData_PolylineOperator::Extract( const Handle(HYDROData_Document)& theDocument, + const Handle(HYDROData_Object)& theObject ) +{ + if( theObject.IsNull() || theDocument.IsNull() ) + return false; + + QList aBoundShapes; + QStringList aBoundNames; + + theObject->GetBoundaries( aBoundShapes, aBoundNames ); + + for( int i=0, n=aBoundShapes.size(); iCreateObject( KIND_POLYLINEXY ) ); + + if( aPolyline.IsNull() ) + return false; + + aPolyline->SetShape( aShape ); + + int anIndex = 0; + QString aName = aBoundName; + while( !theDocument->FindObjectByName( aName ).IsNull() ) + { + anIndex++; + aName = aBoundName + "_" + QString::number( anIndex ); + } + aPolyline->SetName( aName ); } + return true; }