From de96a647cbb315cf07287cf903bd01282dbcc0fd Mon Sep 17 00:00:00 2001 From: abk Date: Fri, 26 Jun 2015 15:26:49 +0300 Subject: [PATCH] Algorithms to split open section by a point were written. --- src/HYDROData/HYDROData_PolylineOperator.cxx | 281 +++++++++++++++++- src/HYDROGUI/HYDROGUI_CurveCreatorProfile.cxx | 6 +- 2 files changed, 283 insertions(+), 4 deletions(-) diff --git a/src/HYDROData/HYDROData_PolylineOperator.cxx b/src/HYDROData/HYDROData_PolylineOperator.cxx index 757805c1..6f8ef42a 100644 --- a/src/HYDROData/HYDROData_PolylineOperator.cxx +++ b/src/HYDROData/HYDROData_PolylineOperator.cxx @@ -18,12 +18,21 @@ #include #include +#include +#include #include #include +#include +#include +#include +#include +#include #include #include #include +#include #include +#include #include template void append( std::vector& theList, const std::vector& theList2 ) @@ -173,12 +182,282 @@ std::vector HYDROData_PolylineOperator::GetWires( const Handle( HYD return aResult; } +static Standard_Boolean OrderCurveEdges( + const TopoDS_Wire& theWire, + NCollection_Vector& theEdges, + 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(); + theEdges.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 && theEdges.Size() == aVCount - 1) || + (theIsClosed && theEdges.Size() == aVCount); +} + +static Standard_Real ProjectPointToEdge( + const gp_Pnt& thePoint, + const TopoDS_Edge& theEdge, + Standard_Real& theParameter) +{ + BRepAdaptor_Curve aECurve(theEdge); + Extrema_ExtPC aAlgo(thePoint, aECurve); + 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) + { + 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[] = + {aECurve.FirstParameter(), aECurve.LastParameter()}; + const gp_Pnt aEnds[] = {aECurve.Value(aParams[0]), aECurve.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 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 aECurve(aEdge); + Standard_Integer aParamI = -1; + const Standard_Real aEdgeEndParams[] = + {aECurve.FirstParameter(), aECurve.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; + } + + const Standard_Integer aECount = theEdges.Size(); + if (aParamI == 0) + { + NCollection_Vector* aEdges = (theEdgeIndex != 0) ? &theEdges1 : &theEdges2; + for (Standard_Integer aEI = theEdgeIndex; aEI < aECount; ++aEI) + { + aEdges->Append(theEdges(aEI)); + } + } + else if (aParamI == 1) + { + theEdges1.Append(aEdge); + for (Standard_Integer aEI = theEdgeIndex; aEI < aECount; ++aEI) + { + theEdges2.Append(theEdges(aEI)); + } + } + else + { + TopoDS_Edge aFE = TopoDS::Edge(aEdge.Oriented(TopAbs_FORWARD)); + ShapeAnalysis_TransferParametersProj aSATPP(aFE, TopoDS_Face()); + aSATPP.SetMaxTolerance(Precision::Confusion()); + TopoDS_Vertex aSplitV; + BRep_Builder().MakeVertex( + aSplitV, aECurve.Value(theParameter), Precision::Confusion()); + + TopoDS_Edge aEParts[] = { + ShapeBuild_Edge().CopyReplaceVertices(aFE, TopoDS_Vertex(), + TopoDS::Vertex(aSplitV.Oriented(TopAbs_REVERSED))), + ShapeBuild_Edge().CopyReplaceVertices(aFE, aSplitV, 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) + { + theEdges2.Append(theEdges(aEI)); + } + } +} + +static void CollectCurveWire( + 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()); + } +} + std::vector HYDROData_PolylineOperator::Split( const TopoDS_Wire& theWire, const gp_Pnt2d& thePoint, double theTolerance ) { std::vector aResult; - //TODO + NCollection_Vector aEdges; + Standard_Boolean isClosed; + if (!OrderCurveEdges(theWire, aEdges, isClosed)) + { + 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; + } + } + + NCollection_Vector aEdges1, aEdges2; + SplitCurveByPoint(aEdges, aSEI, aSParam, aEdges1, aEdges2); + TopoDS_Wire aWire; + CollectCurveWire(aEdges1, aWire); + aResult.push_back(aWire); + if (!aEdges2.IsEmpty()) + { + CollectCurveWire(aEdges2, aWire); + aResult.push_back(aWire); + } + return aResult; } diff --git a/src/HYDROGUI/HYDROGUI_CurveCreatorProfile.cxx b/src/HYDROGUI/HYDROGUI_CurveCreatorProfile.cxx index 8468d483..072567cf 100644 --- a/src/HYDROGUI/HYDROGUI_CurveCreatorProfile.cxx +++ b/src/HYDROGUI/HYDROGUI_CurveCreatorProfile.cxx @@ -54,7 +54,7 @@ bool HYDROGUI_CurveCreatorProfile::clearInternal() myDisplayer->eraseAll( true ); // Delete all allocated data. - CurveCreator_Section* aSection = getSection( 0 ); + CurveCreator_Section* aSection = (CurveCreator_Section*)getSection( 0 ); if ( aSection ) aSection->myPoints.clear(); @@ -118,7 +118,7 @@ bool HYDROGUI_CurveCreatorProfile::addPointsInternal( const CurveCreator::Sectio { bool res = false; - CurveCreator_Section* aSection = getSection( 0 ); + CurveCreator_Section* aSection = (CurveCreator_Section*)getSection( 0 ); if( !aSection ) return res; @@ -192,7 +192,7 @@ bool HYDROGUI_CurveCreatorProfile::setPointInternal( const CurveCreator::Section } int anISection = 0; - CurveCreator_Section* aSection = getSection( anISection ); + CurveCreator_Section* aSection = (CurveCreator_Section*)getSection( anISection ); if( !aSection ) return aRes; -- 2.39.2