#include <HYDROData_Document.h>
#include <BRepAdaptor_Curve.hxx>
#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
#include <BRepBuilderAPI_MakeEdge2d.hxx>
+#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <Extrema_ExtCC.hxx>
#include <Extrema_ExtPC.hxx>
+#include <GeomAPI_Interpolate.hxx>
#include <NCollection_Vector.hxx>
#include <Precision.hxx>
#include <ShapeAnalysis_TransferParametersProj.hxx>
#include <ShapeBuild_Edge.hxx>
+#include <TColgp_Array1OfVec.hxx>
+#include <TColgp_HArray1OfPnt.hxx>
+#include <TColStd_HArray1OfBoolean.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Wire.hxx>
return TopoDS::Edge(aNewEdge.Oriented(aOrient));
}
+template<typename TCurveType>
static Standard_Boolean WireToCurve(
const TopoDS_Wire& theWire,
- NCollection_Vector<TopoDS_Edge>& theEdges,
+ TCurveType& theCurve,
Standard_Boolean& theIsClosed)
{
TopTools_IndexedDataMapOfShapeListOfShape aVertexToEdges;
{
const TopoDS_Edge aEdge = TopoDS::Edge(aEdges->First());
aEdges->RemoveFirst();
- theEdges.Append(aEdge);
+ theCurve.Append(aEdge);
Standard_Integer aVN2 =
aVertexToEdges.FindIndex(TopExp::FirstVertex(aEdge));
if (aVN2 == aVN)
aEdges->Append(aEdge);
}
}
- return (!theIsClosed && theEdges.Size() == aVCount - 1) ||
- (theIsClosed && theEdges.Size() == aVCount);
+ return (!theIsClosed && theCurve.Size() == aVCount - 1) ||
+ (theIsClosed && theCurve.Size() == aVCount);
}
-static void CurveToWire(
- const NCollection_Vector<TopoDS_Edge>& theEdges, TopoDS_Wire& theWire)
+template<typename TCurveType>
+static void CurveToWire(const TCurveType& theCurve, TopoDS_Wire& theWire)
{
BRep_Builder aBulder;
aBulder.MakeWire(theWire);
- NCollection_Vector<TopoDS_Edge>::Iterator aEIt(theEdges);
- for (; aEIt.More(); aEIt.Next())
+ for (TCurveType::Iterator aEIt(theCurve); aEIt.More(); aEIt.Next())
{
aBulder.Add(theWire, aEIt.Value());
}
return aIntCount;
}
+static void CloseCurve(NCollection_Sequence<TopoDS_Edge>& 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<TopoDS_Edge>& theCurve)
+{
+ return TopExp::FirstVertex(theCurve.First(), Standard_True).
+ IsSame(TopExp::LastVertex(theCurve.Last(), Standard_True));
+}
+
+static void ExtendCurve(
+ const Standard_Integer thePosition,
+ NCollection_Sequence<TopoDS_Edge>& theCurve,
+ NCollection_Sequence<TopoDS_Edge>& 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<TopoDS_Edge>& theCurve)
+{
+ NCollection_Sequence<TopoDS_Edge> 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<NCollection_Sequence<TopoDS_Edge> >& theMergedCurves)
+{
+ NCollection_Sequence<TopoDS_Edge> 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<TopoDS_Edge>* aCurves[] = {NULL, NULL};
+ Standard_Integer aOrder = 0;
+ for (NCollection_Vector<NCollection_Sequence<TopoDS_Edge> >::Iterator
+ aCIt(theMergedCurves); aCIt.More(); aCIt.Next())
+ {
+ NCollection_Sequence<TopoDS_Edge>& 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<NCollection_Sequence<TopoDS_Edge> >& theMergedCurves)
+{
+ NCollection_Sequence<TopoDS_Edge> 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<NCollection_Sequence<TopoDS_Edge> >::Iterator
+ aCIt(theMergedCurves); aCIt.More(); aCIt.Next())
+ {
+ NCollection_Sequence<TopoDS_Edge>& 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,
bool isConnectByNewSegment,
double theTolerance )
{
- TopoDS_Shape aMergedPolyline;
-
- int f = thePolylines.Lower(), l = thePolylines.Upper();
- for( int i=f; i<=l; i++ )
+ NCollection_Vector<NCollection_Sequence<TopoDS_Edge> > aMergedCurves;
+ HYDROData_SequenceOfObjects::Iterator aPIt(thePolylines);
+ for (; aPIt.More(); aPIt.Next())
{
- Handle( HYDROData_PolylineXY ) aPolyline = Handle( HYDROData_PolylineXY )::DownCast( thePolylines.Value( i ) );
- std::vector<TopoDS_Wire> aCurves = GetWires( aPolyline );
- for( int j=0, m=aCurves.size(); j<m; j++ )
- if( !Merge( aMergedPolyline, aCurves[j], isConnectByNewSegment, theTolerance ) )
+ Handle(HYDROData_PolylineXY) aPolyline =
+ Handle(HYDROData_PolylineXY)::DownCast(aPIt.Value());
+ std::vector<TopoDS_Wire> aWires = GetWires(aPolyline);
+ for (std::vector<TopoDS_Wire>::const_iterator aWIt = aWires.begin(),
+ aLastWIt = aWires.end(); aWIt != aLastWIt; ++aWIt)
+ {
+ const Standard_Boolean aResult = !isConnectByNewSegment ?
+ ::Merge(*aWIt, theTolerance, aMergedCurves) :
+ Connect(*aWIt, theTolerance, aMergedCurves);
+ if (!aResult)
+ {
return false;
+ }
+ }
}
- std::vector<TopoDS_Shape> aShapes( 1 );
- aShapes[0] = aMergedPolyline;
- CreatePolylines( theDoc, theName, aShapes, false );
-
- return true;
-}
+ TopoDS_Compound aWireSet;
+ BRep_Builder aBuilder;
+ aBuilder.MakeCompound(aWireSet);
+ for (NCollection_Vector<NCollection_Sequence<TopoDS_Edge> >::Iterator
+ aCIt(aMergedCurves); aCIt.More(); aCIt.Next())
+ {
+ if (!aCIt.Value().IsEmpty())
+ {
+ TopoDS_Wire aWire;
+ CurveToWire(aCIt.Value(), aWire);
+ aBuilder.Add(aWireSet, aWire);
+ }
+ }
-bool HYDROData_PolylineOperator::Merge( TopoDS_Shape& theShape, const TopoDS_Wire& theWire,
- bool isConnectByNewSegment, double theTolerance )
-{
- //TODO
+ std::vector<TopoDS_Shape> aPolylines(1);
+ aPolylines[0] = aWireSet;
+ CreatePolylines(theDoc, theName, aPolylines, false);
return true;
}
}
NCollection_Vector<NCollection_Sequence<Standard_Real> > aParams;
- aParams.SetValue(aPSCount - 1, NCollection_Sequence<Standard_Real>());
+ aParams.SetValue(aCurve.Size() - 1, NCollection_Sequence<Standard_Real>());
for (int aTSI = 0; aTSI < aTSCount; ++aTSI)
{
IntersectCurve(aCurve, aToolCurves[aTSI], aParams);
return aResult;
}
-std::vector<TopoDS_Shape> HYDROData_PolylineOperator::Split( const TopoDS_Wire& theWire,
- const TopoDS_Wire& theTool,
- double theTolerance )
-{
- std::vector<TopoDS_Shape> aResult;
- NCollection_Vector<TopoDS_Edge> aWEdges, aTEdges;
- Standard_Boolean aIsWClosed, aIsTClosed;
- if (!WireToCurve(theWire, aWEdges, aIsWClosed) ||
- !WireToCurve(theTool, aTEdges, aIsTClosed))
- {
- return aResult;
- }
-
-
- //TODO
- return aResult;
-}
-
-std::vector<TopoDS_Shape> HYDROData_PolylineOperator::Split( const std::vector<TopoDS_Wire>& theWires,
- double theTolerance )
-{
- std::vector<TopoDS_Shape> aResult;
- //TODO
- return aResult;
-}
-
bool HYDROData_PolylineOperator::CreatePolylines( const Handle( HYDROData_Document )& theDoc,
const QString& theNamePrefix,
const std::vector<TopoDS_Shape>& theShapes,