]> SALOME platform Git repositories - modules/hydro.git/commitdiff
Salome HOME
Algorithms to split open section by a point were written.
authorabk <abk@opencascade.com>
Fri, 26 Jun 2015 12:26:49 +0000 (15:26 +0300)
committerabk <abk@opencascade.com>
Mon, 29 Jun 2015 12:28:16 +0000 (15:28 +0300)
src/HYDROData/HYDROData_PolylineOperator.cxx
src/HYDROGUI/HYDROGUI_CurveCreatorProfile.cxx

index 757805c153a54f82611f58dbcb8cdc296f1fbeac..6f8ef42ac5bcdc33645a111730ddf758d00227b7 100644 (file)
 
 #include <HYDROData_PolylineOperator.h>
 #include <HYDROData_Document.h>
+#include <BRepAdaptor_Curve.hxx>
+#include <BRep_Builder.hxx>
 #include <BRepBuilderAPI_MakeEdge2d.hxx>
 #include <BRepBuilderAPI_MakeWire.hxx>
+#include <Extrema_ExtPC.hxx>
+#include <NCollection_Vector.hxx>
+#include <Precision.hxx>
+#include <ShapeAnalysis_TransferParametersProj.hxx>
+#include <ShapeBuild_Edge.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Edge.hxx>
 #include <TopoDS_Wire.hxx>
+#include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
 #include <QString>
 
 template<class T> void append( std::vector<T>& theList, const std::vector<T>& theList2 )
@@ -173,12 +182,282 @@ std::vector<TopoDS_Wire> HYDROData_PolylineOperator::GetWires( const Handle( HYD
   return aResult;
 }
 
+static Standard_Boolean OrderCurveEdges(
+  const TopoDS_Wire& theWire,
+  NCollection_Vector<TopoDS_Edge>& 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<TopoDS_Edge>& theEdges,
+  const Standard_Integer theEdgeIndex,
+  const Standard_Real theParameter,
+  NCollection_Vector<TopoDS_Edge>& theEdges1,
+  NCollection_Vector<TopoDS_Edge>& 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<TopoDS_Edge>* 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<TopoDS_Edge>& theEdges, TopoDS_Wire& theWire)
+{
+  BRep_Builder aBulder;
+  aBulder.MakeWire(theWire);
+  NCollection_Vector<TopoDS_Edge>::Iterator aEIt(theEdges);
+  for (; aEIt.More(); aEIt.Next())
+  {
+    aBulder.Add(theWire, aEIt.Value());
+  }
+}
+
 std::vector<TopoDS_Shape> HYDROData_PolylineOperator::Split( const TopoDS_Wire& theWire,
                                                              const gp_Pnt2d& thePoint,
                                                              double theTolerance )
 {
   std::vector<TopoDS_Shape> aResult;
-  //TODO
+  NCollection_Vector<TopoDS_Edge> 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<TopoDS_Edge> 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;
 }
 
index 8468d483137494b0b1bf5596c668dd94d0381e85..072567cfc67edd471c99f5c822fa7949fa4dcae9 100644 (file)
@@ -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;